Hi all,
I’d really like to get some feedback on this. I see that since my post, others have had the same problem (see here) in addition to previous requests by others (here & here).
To elaborate on where I’ve got to, I’ve found a workable solution now with very few changes to the JUCE codebase. In OpenGLGraphicsContextCustomShader
I have added a public member:
std::function<void(OpenGLShaderProgram*)> onSetUniforms;
then in ShaderBase
I have added one of these also.
Then in OpenGLGraphicsContextCustomShader::fillRect
I have added a copy of the std::function - I actually hate this bit and would remove it but I have no idea of the lifetime of objects in this part of JUCE, so a better solution should be found for this…
if (OpenGLRendering::ShaderContext* sc = dynamic_cast<OpenGLRendering::ShaderContext*> (&gc))
if (CustomProgram* c = CustomProgram::getOrCreate (gc, hashName, code, errorMessage))
{
c->onSetUniforms = onSetUniforms;
sc->fillRectWithCustomShader (*c, area);
}
Finally, in CurrentShader::setShader
I have added the following after the call to shader.bindAttributes (context);
:
if (shader.onSetUniforms)
shader.onSetUniforms (&shader.program);
This allows me to use a lambda to set uniforms and do other things at this point, e.g.
shader->onSetUniforms = [&](OpenGLShaderProgram* program)
{
program->setUniform ("myUniform", 0.5f);
};
I am doing this successfully with several uniforms and passing textures to shaders. They render in a way that integrates nicely with other JUCE components.
I can totally see that some other solution might be better - perhaps some virtual function in OpenGLGraphicsContextCustomShader
such as…
virtual void setUniforms (OpenGLShaderProgram* program);
that we could override. But in general, it feels like this is something lots of people keep coming back to and I think a solution to it wouldn’t be too much work (unless I’m overlooking something).
Looking forward to your thoughts,
Adam