Search code examples
opengltextures

openGL unattached texture refers to other texture


If I've a shader that uses two textures, and one of them is not set for the first few draws (because I'm fetching it over the network), the program will use the second texture for the first one, instead of sampling from a default black.

For instance, if my fragment shader is:

uniform sampler2D texture1;
uniform sampler2D texture2; // this is a color filter

varying mediump vec2 v_textureCoordinate;

void main() {
  mediump vec3 rgb = texture2D(texture1, v_textureCoordinate);
  rgb.r = texture2D(texture2, vec2(rgb.r, 0.5).r);

  gl_FragColor = vec4(rgb, 1.0);
}

and I use it after texture2 is set and before texture1 is set, sampling from texture1 will sample from texture2, instead of from a default empty texture. Why is that?


Solution

  • instead of sampling from a default black

    There is no such thing as an "black default texture". The sampler types do not reference textures in GLSL, but texture units. So either there is some complete texture bound to the (matching target of) that texture unit, or there isn't.

    As Andon M. Coleman pointed out in the comments, there is conceptually no way to have no texture bound, since texture object 0 refers to a valid texture object in the GL, the default texture object. But that does not contain any image data initially, so it is just incomplete.

    UPDATE

    When sampling from an incomplete texture, the return value of your sample operation will be just undefined.

    Actually, as Reto Koradi pointed out in a comment, sampling from an incomplete texture is well-defined in the GL. It will yield (0,0,0,1). However, when using texelFetch on an incomplete texture, the results will be undefined (unless the context was created with robust buffer access behavior).

    But since you use texture2D, you would be safe here. However ,you aren't accessing an incomplete texture. Uniforms are by default initialized to zero. As a result, both texture1 and texture2 will initially refer to texture unit GL_TEXTURE0. If you happen to use that unit for your first usage of texture2, then the texture1 sampler will end up accessing the same texture.