Extra2D/include/renderer/rhi/opengl/gl_utils.h

308 lines
13 KiB
C++

#pragma once
#include <renderer/rhi/rhi.h>
#include <glad/glad.h>
#include <utils/logger.h>
namespace extra2d {
/**
* @brief OpenGL 错误检查宏
*/
#define GL_CHECK(call) do { \
call; \
GLenum err = glGetError(); \
if (err != GL_NO_ERROR) { \
E2D_LOG_ERROR("OpenGL error in {}: {} ({})", #call, getGLErrorString(err), err); \
} \
} while(0)
/**
* @brief 获取 OpenGL 错误字符串
* @param error OpenGL 错误码
* @return 错误描述字符串
*/
inline const char* getGLErrorString(GLenum error) {
switch (error) {
case GL_NO_ERROR: return "GL_NO_ERROR";
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
default: return "Unknown Error";
}
}
/**
* @brief 将 BufferType 转换为 OpenGL 缓冲区目标
*/
inline GLenum bufferTypeToGL(BufferType type) {
switch (type) {
case BufferType::Vertex: return GL_ARRAY_BUFFER;
case BufferType::Index: return GL_ELEMENT_ARRAY_BUFFER;
case BufferType::Uniform: return GL_UNIFORM_BUFFER;
case BufferType::Storage: return GL_SHADER_STORAGE_BUFFER;
case BufferType::Staging: return GL_ARRAY_BUFFER;
default: return GL_ARRAY_BUFFER;
}
}
/**
* @brief 将 BufferUsage 转换为 OpenGL 使用模式
*/
inline GLenum bufferUsageToGL(BufferUsage usage) {
switch (usage) {
case BufferUsage::Static: return GL_STATIC_DRAW;
case BufferUsage::Dynamic: return GL_DYNAMIC_DRAW;
case BufferUsage::Stream: return GL_STREAM_DRAW;
default: return GL_STATIC_DRAW;
}
}
/**
* @brief 将 TextureFormat 转换为 OpenGL 内部格式
*/
inline GLenum textureFormatToGLInternal(TextureFormat format) {
switch (format) {
case TextureFormat::R8: return GL_R8;
case TextureFormat::RG8: return GL_RG8;
case TextureFormat::RGB8: return GL_RGB8;
case TextureFormat::RGBA8: return GL_RGBA8;
case TextureFormat::RGBA8_SRGB: return GL_SRGB8_ALPHA8;
case TextureFormat::Depth16: return GL_DEPTH_COMPONENT16;
case TextureFormat::Depth24: return GL_DEPTH_COMPONENT24;
case TextureFormat::Depth32F: return GL_DEPTH_COMPONENT32F;
case TextureFormat::Depth24Stencil8: return GL_DEPTH24_STENCIL8;
case TextureFormat::Depth32FStencil8:return GL_DEPTH32F_STENCIL8;
case TextureFormat::BC1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
case TextureFormat::BC3: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
case TextureFormat::BC5: return 0x8DBD; // GL_COMPRESSED_RG_RGTC2
default: return GL_RGBA8;
}
}
/**
* @brief 将 TextureFormat 转换为 OpenGL 格式
*/
inline GLenum textureFormatToGLFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8: return GL_RED;
case TextureFormat::RG8: return GL_RG;
case TextureFormat::RGB8: return GL_RGB;
case TextureFormat::RGBA8:
case TextureFormat::RGBA8_SRGB: return GL_RGBA;
case TextureFormat::Depth16:
case TextureFormat::Depth24:
case TextureFormat::Depth32F: return GL_DEPTH_COMPONENT;
case TextureFormat::Depth24Stencil8:
case TextureFormat::Depth32FStencil8:return GL_DEPTH_STENCIL;
default: return GL_RGBA;
}
}
/**
* @brief 将 TextureFormat 转换为 OpenGL 数据类型
*/
inline GLenum textureFormatToGLType(TextureFormat format) {
switch (format) {
case TextureFormat::R8:
case TextureFormat::RG8:
case TextureFormat::RGB8:
case TextureFormat::RGBA8:
case TextureFormat::RGBA8_SRGB: return GL_UNSIGNED_BYTE;
case TextureFormat::Depth16: return GL_UNSIGNED_SHORT;
case TextureFormat::Depth24: return GL_UNSIGNED_INT;
case TextureFormat::Depth32F: return GL_FLOAT;
case TextureFormat::Depth24Stencil8: return GL_UNSIGNED_INT_24_8;
case TextureFormat::Depth32FStencil8:return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
default: return GL_UNSIGNED_BYTE;
}
}
/**
* @brief 将 TextureFilter 转换为 OpenGL 过滤模式
*/
inline GLenum textureFilterToGLMin(TextureFilter filter) {
switch (filter) {
case TextureFilter::Nearest: return GL_NEAREST;
case TextureFilter::Linear: return GL_LINEAR;
case TextureFilter::NearestMipmapNearest: return GL_NEAREST_MIPMAP_NEAREST;
case TextureFilter::LinearMipmapNearest: return GL_LINEAR_MIPMAP_NEAREST;
case TextureFilter::NearestMipmapLinear: return GL_NEAREST_MIPMAP_LINEAR;
case TextureFilter::LinearMipmapLinear: return GL_LINEAR_MIPMAP_LINEAR;
default: return GL_LINEAR;
}
}
inline GLenum textureFilterToGLMag(TextureFilter filter) {
// Mag filter doesn't support mipmaps
switch (filter) {
case TextureFilter::Nearest:
case TextureFilter::NearestMipmapNearest:
case TextureFilter::NearestMipmapLinear:
return GL_NEAREST;
case TextureFilter::Linear:
case TextureFilter::LinearMipmapNearest:
case TextureFilter::LinearMipmapLinear:
default:
return GL_LINEAR;
}
}
/**
* @brief 将 TextureWrap 转换为 OpenGL 环绕模式
*/
inline GLenum textureWrapToGL(TextureWrap wrap) {
switch (wrap) {
case TextureWrap::Repeat: return GL_REPEAT;
case TextureWrap::ClampToEdge: return GL_CLAMP_TO_EDGE;
case TextureWrap::ClampToBorder: return GL_CLAMP_TO_BORDER;
case TextureWrap::MirroredRepeat: return GL_MIRRORED_REPEAT;
default: return GL_REPEAT;
}
}
/**
* @brief 将 VertexFormat 转换为 OpenGL 格式
*/
inline void vertexFormatToGL(VertexFormat format, GLint& components, GLenum& type, GLboolean& normalized) {
switch (format) {
case VertexFormat::Float1: components = 1; type = GL_FLOAT; normalized = GL_FALSE; break;
case VertexFormat::Float2: components = 2; type = GL_FLOAT; normalized = GL_FALSE; break;
case VertexFormat::Float3: components = 3; type = GL_FLOAT; normalized = GL_FALSE; break;
case VertexFormat::Float4: components = 4; type = GL_FLOAT; normalized = GL_FALSE; break;
case VertexFormat::Int1: components = 1; type = GL_INT; normalized = GL_FALSE; break;
case VertexFormat::Int2: components = 2; type = GL_INT; normalized = GL_FALSE; break;
case VertexFormat::Int3: components = 3; type = GL_INT; normalized = GL_FALSE; break;
case VertexFormat::Int4: components = 4; type = GL_INT; normalized = GL_FALSE; break;
case VertexFormat::UInt1: components = 1; type = GL_UNSIGNED_INT; normalized = GL_FALSE; break;
case VertexFormat::UInt2: components = 2; type = GL_UNSIGNED_INT; normalized = GL_FALSE; break;
case VertexFormat::UInt3: components = 3; type = GL_UNSIGNED_INT; normalized = GL_FALSE; break;
case VertexFormat::UInt4: components = 4; type = GL_UNSIGNED_INT; normalized = GL_FALSE; break;
case VertexFormat::Byte4: components = 4; type = GL_BYTE; normalized = GL_FALSE; break;
case VertexFormat::Byte4Normalized: components = 4; type = GL_BYTE; normalized = GL_TRUE; break;
case VertexFormat::UByte4: components = 4; type = GL_UNSIGNED_BYTE; normalized = GL_FALSE; break;
case VertexFormat::UByte4Normalized:components = 4; type = GL_UNSIGNED_BYTE; normalized = GL_TRUE; break;
default: components = 4; type = GL_FLOAT; normalized = GL_FALSE; break;
}
}
/**
* @brief 将 IndexType 转换为 OpenGL 类型
*/
inline GLenum indexTypeToGL(IndexType type) {
switch (type) {
case IndexType::UInt16: return GL_UNSIGNED_SHORT;
case IndexType::UInt32: return GL_UNSIGNED_INT;
default: return GL_UNSIGNED_SHORT;
}
}
/**
* @brief 将 PrimitiveType 转换为 OpenGL 图元类型
*/
inline GLenum primitiveTypeToGL(PrimitiveType type) {
switch (type) {
case PrimitiveType::Points: return GL_POINTS;
case PrimitiveType::Lines: return GL_LINES;
case PrimitiveType::LineStrip: return GL_LINE_STRIP;
case PrimitiveType::Triangles: return GL_TRIANGLES;
case PrimitiveType::TriangleStrip: return GL_TRIANGLE_STRIP;
case PrimitiveType::TriangleFan: return GL_TRIANGLE_FAN;
default: return GL_TRIANGLES;
}
}
/**
* @brief 将 BlendFactor 转换为 OpenGL 混合因子
*/
inline GLenum blendFactorToGL(BlendFactor factor) {
switch (factor) {
case BlendFactor::Zero: return GL_ZERO;
case BlendFactor::One: return GL_ONE;
case BlendFactor::SrcColor: return GL_SRC_COLOR;
case BlendFactor::OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR;
case BlendFactor::DstColor: return GL_DST_COLOR;
case BlendFactor::OneMinusDstColor: return GL_ONE_MINUS_DST_COLOR;
case BlendFactor::SrcAlpha: return GL_SRC_ALPHA;
case BlendFactor::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
case BlendFactor::DstAlpha: return GL_DST_ALPHA;
case BlendFactor::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA;
default: return GL_ONE;
}
}
/**
* @brief 将 BlendOp 转换为 OpenGL 混合操作
*/
inline GLenum blendOpToGL(BlendOp op) {
switch (op) {
case BlendOp::Add: return GL_FUNC_ADD;
case BlendOp::Subtract: return GL_FUNC_SUBTRACT;
case BlendOp::ReverseSubtract: return GL_FUNC_REVERSE_SUBTRACT;
case BlendOp::Min: return GL_MIN;
case BlendOp::Max: return GL_MAX;
default: return GL_FUNC_ADD;
}
}
/**
* @brief 将 CompareFunc 转换为 OpenGL 比较函数
*/
inline GLenum compareFuncToGL(CompareFunc func) {
switch (func) {
case CompareFunc::Never: return GL_NEVER;
case CompareFunc::Less: return GL_LESS;
case CompareFunc::Equal: return GL_EQUAL;
case CompareFunc::LessEqual: return GL_LEQUAL;
case CompareFunc::Greater: return GL_GREATER;
case CompareFunc::NotEqual: return GL_NOTEQUAL;
case CompareFunc::GreaterEqual: return GL_GEQUAL;
case CompareFunc::Always: return GL_ALWAYS;
default: return GL_LESS;
}
}
/**
* @brief 将 ShaderType 转换为 OpenGL 着色器类型
*/
inline GLenum shaderTypeToGL(ShaderType type) {
switch (type) {
case ShaderType::Vertex: return GL_VERTEX_SHADER;
case ShaderType::Fragment: return GL_FRAGMENT_SHADER;
case ShaderType::Geometry: return GL_GEOMETRY_SHADER;
case ShaderType::Compute: return GL_COMPUTE_SHADER;
default: return GL_VERTEX_SHADER;
}
}
/**
* @brief 获取 VertexFormat 的大小(字节)
*/
inline uint32_t getVertexFormatSize(VertexFormat format) {
switch (format) {
case VertexFormat::Float1: return sizeof(float) * 1;
case VertexFormat::Float2: return sizeof(float) * 2;
case VertexFormat::Float3: return sizeof(float) * 3;
case VertexFormat::Float4: return sizeof(float) * 4;
case VertexFormat::Int1: return sizeof(int32_t) * 1;
case VertexFormat::Int2: return sizeof(int32_t) * 2;
case VertexFormat::Int3: return sizeof(int32_t) * 3;
case VertexFormat::Int4: return sizeof(int32_t) * 4;
case VertexFormat::UInt1: return sizeof(uint32_t) * 1;
case VertexFormat::UInt2: return sizeof(uint32_t) * 2;
case VertexFormat::UInt3: return sizeof(uint32_t) * 3;
case VertexFormat::UInt4: return sizeof(uint32_t) * 4;
case VertexFormat::Byte4:
case VertexFormat::Byte4Normalized: return sizeof(int8_t) * 4;
case VertexFormat::UByte4:
case VertexFormat::UByte4Normalized: return sizeof(uint8_t) * 4;
default: return sizeof(float) * 4;
}
}
} // namespace extra2d