OpenGLAppComponent, adding an OpenGLShaderProgram::setUniform(...)


#1

Hi community

I need to add some Uniform variables to a fragment shader. I have started to create a new OpenGl project from Introjucer and, on the other hand, I followed the structure of OpenGL2D example in the demo app.

Further, I have used:

    OpenGLShaderProgram* OpenGLGraphicsContextCustomShader::getProgram ( LowLevelGraphicsContext &  )

inside of paint(Graphics& g) method in order to get a pointer to the shader program and so, to add the uniform variable, according to documentation explanation:

"This can be called when you're about to use fillRect, to set up any uniforms/textures that the program may require."

The paint() code excerpt is this:

    void paint (Graphics& g) override
    {
        String str = file->loadFileAsString();
        shader = new OpenGLGraphicsContextCustomShader(str);
        Result result(shader->checkCompilation(g.getInternalContext()));
        if (result.failed())
        {
            String strErr = result.getErrorMessage();
            shader = nullptr;
        }
        
        if (shader != nullptr)
        {
            OpenGLShaderProgram* pPgm = shader->getProgram(g.getInternalContext());
            pPgm->setUniform("viewSize", (float)getWidth(), (float)getHeight());
            shader->fillRect(g.getInternalContext(), getLocalBounds());
        }
    }

At this point, the code gets a runtime error due to  pPgm->setUniform() insertion.:

JUCE v4.1.0
***** GL_INVALID_OPERATION  at c:\intlaas\00 sdks\juce\modules\juce_opengl\opengl\juce_openglgraphicscontext.cpp : 1293
JUCE Assertion failure in juce_opengl.cpp:153

Being the stack:

juce::checkGLError(const char *, const int) Line 153    C++
     juce::OpenGLRendering::StateHelpers::CurrentShader::setShader(const juce::Rectangle<int> &, juce::OpenGLRendering::StateHelpers::ShaderQuadQueue &, juce::OpenGLRendering::ShaderPrograms::ShaderBase &) Line 1293    C++
     juce::OpenGLRendering::StateHelpers::CurrentShader::setShader(juce::OpenGLRendering::Target &, juce::OpenGLRendering::StateHelpers::ShaderQuadQueue &, juce::OpenGLRendering::ShaderPrograms::ShaderBase &) Line 1305    C++
     juce::OpenGLRendering::GLState::setShader(juce::OpenGLRendering::ShaderPrograms::ShaderBase &) Line 1369    C++
     juce::OpenGLRendering::SavedState::fillRectWithCustomShader(juce::OpenGLRendering::ShaderPrograms::ShaderBase &, const juce::Rectangle<int> &) Line 1691    C++
     juce::OpenGLRendering::ShaderContext::fillRectWithCustomShader(juce::OpenGLRendering::ShaderPrograms::ShaderBase &, const juce::Rectangle<int> &) Line 1724    C++

So, what am I doing wrong? Can I use Uniforms in a OpenGLAppComponent derived component? Have the uniform to be injected in another place or moment?

Thank you for your answers in advance,

Gabriel


#2

1 - Use the OpenGLAppExample in JUCE examples folder

2 - Uniforms can be declared when the OpenGLComponent is defined, but they shoud be updated (set) in the renderOpenGL method

3 - Problem might come from the GLSL (shader ) code itself. Since you didn't give the shader code, it's hard to help...


#3

Thank you Alan for your  answer.

I've used OpenGLAppExample but it has not customizable Uniforms. About point 2, my Uniforms are declared before OpoenGlComponent definition and intended to be updated in renderOpenGL method.

The fragment shader works flawlessly in other environments ad-hoc, nevertheless, here it is the header:


uniform vec2 viewSize = vec2(800.0, 600.0);
float xScale      = 100.0;
float xScale1     = xScale/10.0;
float ySpan       = 0.85; // Upper and lower vertical margins
float yDivisions  = viewSize.y/20.0*ySpan;  // 10 for half upper and 10 for half bottom
float yDivisions1 = viewSize.y/4.0*ySpan;   //  2 for half upper and  2 for half bottom
float pos=-80.0+viewSize.x/2.0;
const int IN=1;
float F(float x)
{
    return  sin(x)/2.0;
}
...

I have a question for you, did you ever use Uniforms on your side?

 

Thank you,

 

Gabriel


#4

Yes of course I use Uniforms. I use them for example as textures and also to generate a timed translation by merely adding a vector. I even use boolean uniforms !

As I said the first thing to do is to compile and run the OpenGLAppExample demo (make sure you have the latest tip). If that works, then modify it gradually with you code and see where the problem arises.

There *ARE* uniforms in this demo to define the projection and the view matrices. You can use those as examples. There is no such thing as a "customizable" uniform. Just apply the same code as the one shown in the demo and adapt it to your case.

OpenGL is not a trivial framework, and there are a LOT of things that can go wrong (starting with the versions you are using)... So you have to be systematic to see where the problems are.


#5

Ok, Alan, just needed the confirmation that you were able to manage Uniforms, what it leads towards I'm doing something wrong. Yes, OpenGL is cumbersome and completely agree that until you manage to establish the bare minimum infrastructure, any minimum and subtle misleading thing can helpless ruin the whole chain.

Thank you!

Gabriel