GL_TEXTURE_2D_MULTISAMPLE with 1 sample vs. GL_TEXTURE_2D

Hello everybody,

I am currently switching an existing OpenGL renderer from regular 2D texture render targets to multisample textures. One requirement of this renderer is that anti-aliasing can be enabled and disabled with a single mouse click. I did not think this would be much of a problem because I could still use the multisample textures with just one sample per pixel. However, this produces unexpected results as shown in the picture below.

Here’s what I do:

  1. Setup three textures:
  • Texture A with target GL_TEXTURE_2D and nearest-neighbor filtering
  • Texture B with target GL_TEXTURE_2D and nearest-neighbor filtering, same size as A
  • Texture C with target GL_TEXTURE_2D_MULTISAMPLE, 1 sample, fixedsamplelocations = true, same size as A and B
  1. Setup framebuffer, attach either B or C as color attachment 0, glEnable(GL_MULTISAMPLE)
  2. Bind framebuffer
  3. Draw the grid as line strips (glLineWidth(1.0f)) into framebuffer
  4. Attach texture A as color attachment 0 to framebuffer
  5. Bind either texture B or C as texture to shader, vertex shader is the same, the fragment shaders are:
// Pass-through fragment shader for regular 2D texture
#version 330

uniform sampler2D sourceTex;

in vec2 texCoord;

out vec4 fragment_color;

void main()
{
    ivec2 scaledTexCoord = ivec2(vec2(textureSize(sourceTex, 0)) * vec2(texCoord.x, 1.0 - texCoord.y));
    fragment_color = texelFetch(sourceTex, scaledTexCoord, 0);
}
// Pass-through fragment shader for multisample texture
#version 330

uniform sampler2DMS sourceTex;

in vec2 texCoord;

out vec4 fragment_color;

void main()
{
    ivec2 scaledTexCoord = ivec2(vec2(textureSize(sourceTex)) * vec2(texCoord.x, 1.0 - texCoord.y));
    fragment_color = texelFetch(sourceTex, scaledTexCoord, 0);
} 

  1. Draw a full-screen quad to copy the contents of either texture B or C into texture A. I do this because the texture is then read back with glReadPixels.

Result of texture B (GL_TEXTURE_2D)

Result of texture C (GL_TEXTURE_2D_MULTISAMPLE)

After this, I get very different results for texture B and C. If you don’t see it at first, open both images in separate tabs and switch between them. The lines in the result with the multisample texture are very rough and bumpy as compared to the common stair-stepping lines, particularly visible in the foreground. To make this clear: This thread is not about how to get anti-aliased lines! It is about why there is a difference between a GL_TEXTURE_2D render target and a GL_TEXTURE_2D_MULTISAMPLE render target with 1 sample per pixel.

I even set fixedsamplelocations = true in glTexImage2DMultisample, so I would expect that the samples are aligned like a regular grid and regular sampling takes place, which should (with an additional, constant offset inside the pixel) look exactly like the result of texture B. Any explanation or educated guess? I use the same drawing for both versions, I use textures of the same size, I fetch the texels the same way, I have the same states enabled at all time, what am I not seeing here? Multisampling in general works very well, it’s just having just one sample (“deactivating anti-aliasing”) that does not produce the results I expected. I expected and want the same, clean stair-stepping lines as in the non-multisample case.

I would really appreciate your help!

Regards,
nostalgic

By the way, I am using a Geforce GTX 680, if this is of any relevance. I’ve read that on previous cards, multisampling has been implemented as a combination of multisampling and supersampling, although this would still not explain the rough lines.