简体   繁体   中英

Software Architecture: OpenGL Shader creation and compilation

I'm about to refactor some parts of a rendering engine, and wonder if a shader should really know it's OpenGL context. Currently, each shader has a bind() and compileShader() method - which do nothing else but call the OpenGL context for the actual task.

It seems common to have these methods implemented in the shader - but is it really good practice? Shouldn't it be better to have the context create, compile and bind a shader? And does a shader necessarily have to know it's context?

Some code snippets below. Here you see that the shader just calls context methods, and therefore compilation could be a concern of the context and not the shader itself.

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);
}

When it comes to OpenGL and OOP programming no clear cut answers can be given. Due to the way the OpenGL API mixes global state, certain object types confined to a single context and other object types shareable among multiple contexts it's very difficult, if not impossible to perfectly map OpenGL into a OOP model.

Shouldn't it be better to have the context create, compile and bind a shader?

Yes! In fact it makes a lot of sense for a OpenGL context to be a factory for OpenGL objects.

And does a shader necessarily have to know it's context?

In fact every OpenGL object should know the contexts it's related to. I recommend to implement this via a dedicated abstract context reference class; from that class derive a single context reference that's instanciated by objects that are not shareable (shaders, programs, framebuffer objects, VAOs, …) and a shared context reference that's instanciated by objects that are shareable (images, textures, buffer objects, …).

And then you somehow should implement a way to track context sharing setup and map this into the shared context reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM