PDA

View Full Version : Set value to uniform int in fragment shader



XavierArias
09-05-2012, 02:42 AM
Hi,

this should be a stupid problem, as i've been setting uniform float and vec2 values without problems, but it seems that i don't set up the int value correctly...

EDIT: I forgot to mention that i'm working with opengl es (for an iPhone game)

Here is the fragment shader:

#ifdef GL_ES
precision mediump float;
#endif

// Texture, coordinates and size
uniform sampler2D u_texture;
varying vec2 v_texCoord;
uniform vec2 textureSize;

// this is the one that i'm trying to set
uniform int lightCount;

struct LightSource
{
vec2 position;
float radius;
float strength;
};

uniform LightSource lights[10];

void main()
{
float alpha = 1.0;

vec2 pos = vec2(v_texCoord.x * textureSize.x, v_texCoord.y * textureSize.y);

// here i try to do 'lightCount' loops. I've set lightCount to 1 from cpp and got terrible performance
// but if i put a break; at the end of the loop the performance increases a lot, so i assume that
// lightCount is a very big value (11215121 for example), like i did not set it...

int i = 0;
while (i < lightCount)
{
LightSource source = lights[i];
float distance = distance(source.position, pos);

if (distance < source.radius)
{
alpha -= source.strength;
}

i++;
}

alpha = max(0.0, alpha);

gl_FragColor = vec4(texture2D(u_texture, v_texCoord).rgb, alpha);
}


This is my c++ code:

// cocos2d-x OpenGl wrapper code has already initialized the shader and all of the following works except the int part

// get program from cocos2d-x wrapper
GLuint glProgramID = sprite->getShaderProgram()->getProgram();

// sets vec2 value correctly
glUniform2f(glGetUniformLocation(glProgramID, "textureSize"), screen.width, screen.height);

// this is the part that's not working
GLint lightCount = 1;
GLint location = glGetUniformLocation(glProgramID, "lightCount");
glUniform1i(location, lightCount);

// overcomplicated code to assign properties to an array of structs
std::string arrayName = "lights[";
std::string lightName;

for (char c = '0'; c - '0' < lightCount && c <= '9'; c++)
{
lightName = arrayName + c + "].";

std::string fieldName = lightName + "position";
glUniform2f(glGetUniformLocation(glProgramID, fieldName.c_str()), screen.width / 2, screen.height / 2);

fieldName = lightName + "radius";
glUniform1f(glGetUniformLocation(glProgramID, fieldName.c_str()), screen.width / 2);

fieldName = lightName + "strength";
glUniform1f(glGetUniformLocation(glProgramID, fieldName.c_str()), 1.0f);
}

// don't know if this is necessary or not
sprite->getShaderProgram()->updateUniforms();


I thought maybe there was a problem with the array of structs or with the struct itself, but i can't see anything out of the ordinary...

Note that if change the lightCount variable in the while for a 1 literal performance increases a lot (like when i put a break statement).

Any idea of how i can see if the lightCount is set correctly?
Anyone has a moment to test if this is working (should get the affected texture with a alpha gap on the middle) and the loop is only looping once?

Thanks for your time

mbentrup
09-05-2012, 02:52 AM
Is your program current at the time you set the uniforms ? Uniforms are not bound to the context, but to the current program object, so you have to make your program current with glUseProgram before you update the uniforms.

XavierArias
09-05-2012, 02:57 AM
i did make a call to glUseProgram using the cocos2d-x wrapper, so i guess that is working correctly.
By now i'm using only one light as i cannot control the number of loops and everything works ok (except that int i guess...)