2026-03-03 02:16:29 +08:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include <glad/glad.h>
|
2026-03-03 21:23:54 +08:00
|
|
|
|
#include <renderer/rhi/rhi.h>
|
2026-03-03 02:16:29 +08:00
|
|
|
|
#include <utils/logger.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace extra2d {
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief OpenGL 错误检查宏
|
|
|
|
|
|
*/
|
2026-03-03 21:23:54 +08:00
|
|
|
|
#define GL_CHECK(call) \
|
|
|
|
|
|
do { \
|
|
|
|
|
|
call; \
|
|
|
|
|
|
GLenum err = glGetError(); \
|
|
|
|
|
|
if (err != GL_NO_ERROR) { \
|
|
|
|
|
|
E2D_ERROR("OpenGL 错误在 {}: {} ({})", #call, getGLErrorString(err), \
|
|
|
|
|
|
err); \
|
|
|
|
|
|
} \
|
|
|
|
|
|
} while (0)
|
2026-03-03 02:16:29 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取 OpenGL 错误字符串
|
|
|
|
|
|
* @param error OpenGL 错误码
|
|
|
|
|
|
* @return 错误描述字符串
|
|
|
|
|
|
*/
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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";
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 BufferType 转换为 OpenGL 缓冲区目标
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum bufferTypeToGL(BufferType type) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 BufferUsage 转换为 OpenGL 使用模式
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum bufferUsageToGL(BufferUsage usage) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 TextureFormat 转换为 OpenGL 内部格式
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum textureFormatToGLInternal(TextureFormat format) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 TextureFormat 转换为 OpenGL 格式
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum textureFormatToGLFormat(TextureFormat format) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 TextureFormat 转换为 OpenGL 数据类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum textureFormatToGLType(TextureFormat format) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 TextureFilter 转换为 OpenGL 过滤模式
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum textureFilterToGLMin(TextureFilter filter) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline GLenum textureFilterToGLMag(TextureFilter filter) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
// 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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 TextureWrap 转换为 OpenGL 环绕模式
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum textureWrapToGL(TextureWrap wrap) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 VertexFormat 转换为 OpenGL 格式
|
|
|
|
|
|
*/
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 IndexType 转换为 OpenGL 类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum indexTypeToGL(IndexType type) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
switch (type) {
|
|
|
|
|
|
case IndexType::UInt16:
|
|
|
|
|
|
return GL_UNSIGNED_SHORT;
|
|
|
|
|
|
case IndexType::UInt32:
|
|
|
|
|
|
return GL_UNSIGNED_INT;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return GL_UNSIGNED_SHORT;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 PrimitiveType 转换为 OpenGL 图元类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum primitiveTypeToGL(PrimitiveType type) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 BlendFactor 转换为 OpenGL 混合因子
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum blendFactorToGL(BlendFactor factor) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 BlendOp 转换为 OpenGL 混合操作
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum blendOpToGL(BlendOp op) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 CompareFunc 转换为 OpenGL 比较函数
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum compareFuncToGL(CompareFunc func) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 ShaderType 转换为 OpenGL 着色器类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline GLenum shaderTypeToGL(ShaderType type) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取 VertexFormat 的大小(字节)
|
|
|
|
|
|
*/
|
|
|
|
|
|
inline uint32_t getVertexFormatSize(VertexFormat format) {
|
2026-03-03 21:23:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-03-03 02:16:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace extra2d
|