0
votes

I'm in GLSL texture hell: I load 4 different textures of the same size in uniform sampler2D variables in my fragment shader and try to access them with different texture coordinates:

uniform sampler2D image0, image1, image2, image3;
varying highp vec2 texCoord;

void main()
{   
highp vec2 tc = vec2(texCoord.x, mod(1.0-texCoord.y, 0.2) + 0.2);

lowp vec4 color0 = texture2D(image0, tc);
lowp vec4 color1 = texture2D(image1, tc);
lowp vec4 color2 = texture2D(image2, tc);
lowp vec4 color3 = texture2D(image3, tc);

if (texCoord.y < 0.2) { gl_FragColor = color0; }
else if (texCoord.y < 0.4) { gl_FragColor = color1; }
else if (texCoord.y < 0.6) { gl_FragColor = color2; }
else if (texCoord.y < 0.8) { gl_FragColor = color3; }
else { gl_FragColor = vec4(0.0); }
}

The texCoord comes from the vertex shader of course:

uniform lowp float ratio;
attribute highp vec4 vertex;
varying highp vec2 texCoord;

void main()
{
gl_Position = vertex;
texCoord.x = ((vertex.x * 0.5) + 0.5) * ratio;
texCoord.y = (vertex.y * 0.5) + 0.5;
}

I get 5 separate slices, from image0, image2 (!! not image1), image3, image3 (again!), and black (this would hold a merge of the various texture, not important in this context, my problem being getting the right textures first). I checked the image loading code multiple times, I do load 4 different images:

- (void)linkTexture:(GLenum)tex image:(Image *)image varName:(const char *)varName
{
GLint texLocation;

texLocation = glGetUniformLocation(program, varName);
glUniform1i(texLocation, tex-GL_TEXTURE0);
glActiveTexture(tex);
glBindTexture(GL_TEXTURE_2D, image->texID);
}

and further down:

    loadTexture("new_york_0.jpg", &image0, &renderer);
    [self linkTexture:GL_TEXTURE0 image:&image0 varName:"image0"];

    loadTexture("new_york_1.jpg", &image1, &renderer);
    [self linkTexture:GL_TEXTURE1 image:&image1 varName:"image1"];

    loadTexture("new_york_2.jpg", &image2, &renderer);
    [self linkTexture:GL_TEXTURE2 image:&image2 varName:"image2"];

    loadTexture("new_york_3.jpg", &image3, &renderer);
    [self linkTexture:GL_TEXTURE3 image:&image3 varName:"image3"];

There must be something very wrong in the way I expect the GPU to lookup textures but I have no clue what it is.

Can someone shine a light?

2

2 Answers

4
votes

Well in the first case of course you get 5 slices from the same texture.

Think about what you are doing.

Take a y coordinate of 0.6.

(1 - 0.6)       = 0.4
mod( 0.4, 0.2 ) = 0.0
0.0 + 0.2       = 0.2

Basically you force the y coordinate to be in the range 0.2 to 0.4 which will always be image1. I'm not sure why you are seeing image2 though ...

As for the 2nd case ... this heavily implies that the texture coord you are receiving is wrong. So .. do you want to show us the vertex shader as well as this fragment shader?

I have to admit, though, I can't understand why you don't just put the 5 slices into a single texture and just render it ...

You may want to check out this:

http://www.vis.uni-stuttgart.de/glsldevil/index.html#downloads

0
votes

glUniform1i modifies the uniform values for the current program. Make sure you are calling glUseProgram(myProgram) before your calls to linkTexture.