Extra2D/src/renderer/rhi/opengl/gl_pipeline.cpp

117 lines
2.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <renderer/rhi/opengl/gl_pipeline.h>
#include <renderer/rhi/opengl/gl_utils.h>
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<const void *>(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