Shader Uniform not updating with DrawNode

Hi all,

I am currently trying to pass a series of uniform variables into a fragment shader that processes polygons drawn by a cocos2d::DrawNode.

I am doing this using a GLProgramState, initializing it in the Init function of my Layer:

m_visibilityDrawNode = cocos2d::DrawNode::create();
addChild(m_visibilityDrawNode);

cocos2d::GLProgram* lightProgram = cocos2d::GLProgram::createWithFilenames("shaders/light.vertex", "shaders/light.fragment");

cocos2d::GLProgramState* state = cocos2d::GLProgramState::getOrCreateWithGLProgram(lightProgram);
	
m_visibilityDrawNode->setGLProgramState(state);

Then, in my update function I try to update a uniform variable in the fragment shader:

m_visibilityDrawNode->getGLProgramState()->setUniformFloat("a", 2.f);
m_visibilityDrawNode->getGLProgramState()->applyUniforms();

I am calling applyUniforms since this is what actually calls glUniform1fv (for every updated uniform)

In my fragment shader I just check what is the value of the uniform and draw with a color accordingly:

//fragment shader

uniform float a;
void main()
{
    vec4 finalColor;
    if (a == 0.0)
    {
        finalColor = vec4(0.0,0.0,0.0,0.0);
    }
    else
    {
        finalColor = vec4(1.0,1.0,1.0,1.0);
    }
    
    gl_FragColor = finalColor;
}

However, the uniform ‘a’ never changes its value and I always get black color (it’s not a problem with the shader or any other part since I get the right thing when I invert the condition).

Finally, whenever there is a call to glUniform1fv (called by applyUniforms) I end up with a messagethat tells me:

OpenGL error 0x0502 in …\renderer\CCFrameBuffer.cpp cocos2d::experimental::FrameBuffer::applyFBO 445

I have tried several things and I’m running out of ideas. So is there something I’m doing wrong? Or is this a bug?

Note: I am using cocos2d-x 3.10 and trying it on windows

Thank you very much for your help!

Bump
Can anybody put light on this , i’m facing similar issue

Dont know but it works when i write

my_gl_program->use();
before updating uniforms of gl_program_state derived from my_gl_program
i need explanation for that , Thank You

Hi, bbmn16. It’s been a long time and I had abandoned the thing, but I checked back and yes, calling use() every time fixes it. Thanks a lot!

But yes, it needs some explanation.

Solved , found on opengl wiki https://www.opengl.org/wiki/GLSL_:_common_mistakes
glUseProgram
When should you call glUseProgram ?
glUseProgram needs to be called before you setup a uniform (unless you have GL 4.1 or ARB_separate_shader_objects, and can use glProgramUniform ). There are several versions of the glUniform function depending if your variable is a single float, vec2, vec3, vec4, a matrix, etc. Notice that the glUniform functions do not take the program ID (your shader) as a parameter.
Getting the location of a uniform, such as from glGetUniformLocation , does not require calling glUseProgram . glGetUniformLocation already takes the program to get the location from.
glUseProgram is needed for rendering. You must use the program you intend to render with before issuing a rendering call.

I think it is fixed in this PR: https://github.com/cocos2d/cocos2d-x/pull/14005