Search code examples
c++opengltexturesshader

Shader texture values not the same as written when creating the texture


I have created a texture and filled it with ones:

size_t size = width * height * 4;
float *pixels = new float[size];
for (size_t i = 0; i < size; ++i) {
    pixels[i] = 1.0f;
}

glTextureStorage2D(texture_id, 1, GL_RGBA16F, width,
                   height);
glTextureSubImage2D(texture_id, 0, 0, 0, width, height, GL_RGBA,
                    GL_FLOAT, pixels);

I use linear filtering (GL_LINEAR) and clamp to border.

But when I draw the image:

color = texture(atlas, uv);

the last row looks like it has alpha values of less than 1. If in the shader I set the alpha to 1:

color.a = 1.0f;

it draws it correctly. What could be the reason for this?


Solution

  • The problem comes from the combination of GL_LINEAR and GL_CLAMP_TO_BORDER:

    • Clamp to border means that every texture coordinate outside of [0, 1] will return the border color. This color can be set with glTexParameterf(..., GL_TEXTURE_BORDER_COLOR, ...) and is black by default.

    • Linear filter will take into account pixels that are adjacent to the sampling location (unless sampling happens exactly at texel centers1), and will thus also read border color texels (which are here black).

    If you don't want this behavior, the simplest solution would be to use GL_CLAMP_TO_EDGE instead which will repeat the last row/column of texels to infinity. The different wrapping modes are explained very well explained at open.gl.

    1) Sampling happens most probably not at pixel centers as explained in this answer.