软件架构:OpenGL着色器创建和编译

Software Architecture: OpenGL Shader creation and compilation

本文关键字:创建 编译 OpenGL 软件架构      更新时间:2023-10-16

我即将重构渲染引擎的某些部分,并且想知道shader是否应该真正知道它的OpenGL上下文。目前,每个着色器都有一个bind()和compileShader()方法——它们除了为实际任务调用OpenGL上下文之外什么都不做。

在着色器中实现这些方法似乎很常见-但这真的是很好的实践吗?让上下文创建、编译和绑定着色器不是更好吗?一个shader必须知道它的上下文吗?

下面是一些代码片段。这里你看到shader只是调用上下文方法,因此编译可能是上下文的关注点,而不是shader本身。

ShaderPtr hdm::shader::fancy_lines_3d_ptr;
fancy_lines_3d_ptr->compileShader( vert_src.c_str(), frag_src.c_str(), vlayout );
void Shader::bind()
{
    assert(_shaderObj);
    _context.bindShader(_shaderObj);
}

void Shader::compileShader(const string &vertexSrc,
                           const string &fragmentSrc,
                           hdm::rendering::VERTEX_LAYOUT vlayout)
{
    _context.compileShader(_shaderObj, vertexSrc.c_str(), vertexSrc.length(), SHADER_TYPE::ST_VERTEX);
    _context.compileShader(_shaderObj, fragmentSrc.c_str(), fragmentSrc.length(), SHADER_TYPE::ST_FRAGMENT);
    _context.bindAttributeLocations(vlayout, _shaderObj);
    _context.linkShader(_shaderObj);
}

说到OpenGL和OOP编程,没有明确的答案。由于OpenGL API混合了全局状态,某些对象类型限制在单一上下文中,而其他对象类型可在多个上下文中共享,因此很难将OpenGL完美地映射到OOP模型中。

让上下文创建、编译和绑定着色器不是更好吗?

是的!事实上,OpenGL上下文作为OpenGL对象的工厂是很有意义的。

一个shader必须知道它的上下文吗?

事实上,每个OpenGL对象都应该知道与它相关的上下文。我建议通过一个专门的抽象上下文引用类来实现这一点;从这个类派生出一个单一上下文引用,它是由不可共享的对象实例化的(着色器,程序,framebuffer对象,VAOs,…)和一个共享上下文引用,它是由共享的对象实例化的(图像,纹理,缓冲区对象,…)。

然后你应该以某种方式实现一种方法来跟踪上下文共享设置并将其映射到共享上下文引用