116 lines
2.6 KiB
C++
116 lines
2.6 KiB
C++
|
|
#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,因为我们使用动态顶点属性配置
|
|||
|
|
// 顶点属性在 GLCommandList::setVertexBuffer 中配置
|
|||
|
|
|
|||
|
|
// 应用混合状态
|
|||
|
|
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
|