views:

48

answers:

1

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?

+1  A: 

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

Goz
+1, although I'm thinking the image1 not showing is simply a mistake in the sampler setting code (hence why we see image2 in the uncommented code)
Bahbar
Oh my oh my, you're right of course, that is why I'm seeing image1 every time, that was pretty silly of me. I've fixed that part and I do see different images in each slice, but not the right ones, I will edit the question to detail how I load the images.
Guy
An idea why I'm not seeing the right textures? Anyone? I've looked at this code for so long I may be missing another one of those obvious mistakes, but I just can't see it.
Guy