#include #include namespace extra2d { GLPipeline::GLPipeline(const PipelineDesc &desc) : desc_(desc), vao_(0) {} GLPipeline::~GLPipeline() { destroy(); } bool GLPipeline::create() { // 创建 VAO glGenVertexArrays(1, &vao_); if (vao_ == 0) { return false; } glBindVertexArray(vao_); // 配置顶点属性 const auto &layout = desc_.vertexLayout; for (const auto &attr : layout.attributes) { glEnableVertexAttribArray(attr.location); GLenum type = GL_FLOAT; GLint size = 1; GLboolean normalized = GL_FALSE; switch (attr.format) { case VertexFormat::Float1: size = 1; break; case VertexFormat::Float2: size = 2; break; case VertexFormat::Float3: size = 3; break; case VertexFormat::Float4: size = 4; break; default: break; } glVertexAttribPointer(attr.location, size, type, normalized, layout.stride, reinterpret_cast(attr.offset)); } glBindVertexArray(0); return true; } void GLPipeline::destroy() { if (vao_ != 0) { glDeleteVertexArrays(1, &vao_); vao_ = 0; } } void GLPipeline::bind() { // 绑定着色器程序 if (shaderProgram_ != 0) { glUseProgram(shaderProgram_); } // 注意:VAO 需要与具体的顶点缓冲区绑定才能工作 // 所以我们不在此处绑定 VAO,而是在渲染时动态配置顶点属性 // 这样可以支持不同的 Mesh 使用相同的 Pipeline // 应用混合状态 if (desc_.blendState.enabled) { glEnable(GL_BLEND); glBlendFunc(blendFactorToGL(desc_.blendState.srcFactor), blendFactorToGL(desc_.blendState.dstFactor)); } else { glDisable(GL_BLEND); } // 应用深度状态 if (desc_.depthStencilState.depthTestEnabled) { glEnable(GL_DEPTH_TEST); glDepthFunc(compareFuncToGL(desc_.depthStencilState.depthCompare)); glDepthMask(desc_.depthStencilState.depthWriteEnabled ? GL_TRUE : GL_FALSE); } else { glDisable(GL_DEPTH_TEST); } // 应用光栅化状态 if (desc_.rasterizerState.cullEnabled) { glEnable(GL_CULL_FACE); glCullFace(desc_.rasterizerState.cullFrontFace ? GL_FRONT : GL_BACK); glFrontFace(desc_.rasterizerState.frontCCW ? GL_CCW : GL_CW); } else { glDisable(GL_CULL_FACE); } } void GLPipeline::unbind() { glBindVertexArray(0); } ShaderHandle GLPipeline::getVertexShader() const { return desc_.vertexShader; } ShaderHandle GLPipeline::getFragmentShader() const { return desc_.fragmentShader; } const VertexLayout& GLPipeline::getVertexLayout() const { return desc_.vertexLayout; } bool GLPipeline::isValid() const { return vao_ != 0; } } // namespace extra2d