Search code examples
c++shadersfml

SFML shaders (GLSL) calling texture2D() has side effects?


I am trying to use two textures with different resolutions (and thus different texture coordinates) in my shader. However, if I call texture2D() (or texture(), doesn't matter) on the second texture with anything other than gl_TexCoord[0].xy, the output becomes distorted, even if the result of the lookup is not used anywhere.

First texture, aka texture:

enter image description here

Second texture, aka noise:

enter image description here

Distorted image. The gl_Color passed to the vertex shader is white on the left and black on the right so somehow this image is a result of pixel * gl_Color * some_weird_color_shift

enter image description here

Vertex shader. I just started with copying gl_TexCoord[0] and sending its interpolated value to fragment.

varying vec4 noiseTexCoord;

void main()
{
    // transform the vertex position
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
    noiseTexCoord = gl_TexCoord[0];

    // forward the vertex color
    gl_FrontColor = vec4(gl_Color.z, gl_Color.z, gl_Color.z, 1);
}

Fragment shader. With the bugger commented out, this draws the noise texture.

uniform sampler2D texture;
uniform sampler2D noise;

varying vec4 noiseTexCoord;

void main()
{
    // lookup the pixel in the texture
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);

    // vec4 bugger = texture2D(noise, noiseTexCoord);
    vec4 noise = texture2D(noise, gl_TexCoord[0].xy);
    
    // gl_Color is unused

    gl_FragColor = noise;
}

If I uncomment the bugger variable, the resulting image will be the distorted one, no matter what is written to gl_FragColor. It doesn't matter if I assign a pixel, noise or some hardcoded color to it.

I would not be surprised if noiseTexCoord contained some weird value, but I thought the texture2D is just a lookup without side effects. What is wrong?


Solution

  • The problem was that noiseTexCoord is vec4 that I am trying to pass to texture2D that expects a vec2. Thus the fragment shader failed to compile.

    The proper expression should be:

    vec4 bugger = texture2D(noise, noiseTexCoord.xy);
    

    Which behaves as expected.