Search code examples
openglshadersupersamplingtexel

Why is my GLSL shader causing incorrect edge wrapping


I have been writing my own SSAA fragment shader, so far I am sampling 4 points: top left, top right, bottom left and bottom right.

I am rendering to a small window, I have noticed when I full screen this window I have bars on all side of the screen that repeats what should be on the other side of the screen.

My shader currently calculates if we are looking at an edge pixel like this: TL = TopLeft

if(texCoord.s <= 1 || texCoord.s >= textureWidth - 1)
{
    //dont offset by -x, instead just use the current x and only offset y
    TL = texture2D(texture, vec2(texCoord.s , texCoord.t + y ));
}
else
{
    TL = texture2D(texture, vec2(texCoord.s - x, texCoord.t + y ));
}

Solution

  • Texel coordinates range from 0 to 1 on both axes over the whole texture. Therefore, texture coordinates (0, 0) refers to the bottom-left corner (i.e. not the center) of the bottom-left texel.

    Illustrated:

    d_x = 1 / textureWidth
    d_y = 1 / textureHeight
    
               +-----+-----+-----+
               |     |     |     |
               |     |     |     |
               |     |     |     |
    (-d_x,d_y) +-----+-----+-----+ (2d_x, d_y)
               |     |     |     |
               |     |  A  |     |
               |     |     |     |
               +-----+-----+-----+
        (-d_x,0) (0,0)  (d_x,0)  (2d_x, 0)
    
    A: (d_x/2, d_y/2) <= center of the bottom-left texel
    

    If you sample at point A, linear texture filtering will produce the value of the bottom-left texel exactly. If you sample at (0, 0) however, linear filtering will give the average of all the corners texels.

    This behavior can be controlled by configuring GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T with glTexParameter. In your case, GL_CLAMP_TO_EDGE is probably the right mode to use.