Hello,
This thread is actually a follow-up to an issue initially described in this discussion.
I’m trying to render to multisample textures (ARB_texture_multisample) with multisample disabled through glDisable(GL_MULTISAMPLE). For any given pixel/texel, I expected to get the same color for every sub-sample. However, when fetching individual samples (through texelFetch in GLSL), they don’t always all have the same value.
I developped a small app in order to diagnose the problem.
Code here: http://emmanuel.raulo.free.fr/oglorg/multisamplepb.cpp.
Win32 binaries here (needs VC9 SP1 redist): http://emmanuel.raulo.free.fr/oglorg/multisamplepb-win32.7z
Here is the code in case hosting is too crappy for people to successfully download it (sorry for the long post):
#include <cstdlib>
#include <string>
#include <iostream>
#include <sstream>
#include <GL/glew.h>
#include <GL/glut.h>
#ifndef _WIN32
# include <GL/gl.h>
# include <GL/glu.h>
#endif
//----------------------------------------------------------------------------
// Some global variables...
static GLuint programHandle = 0;
static GLuint samplerLoc = 0;
static GLuint layerLoc = 0;
static GLuint fboHandle = 0;
static GLuint textureHandle = 0;
static GLint layer = 0;
static GLint maxLayers = 0;
static bool multisample=false;
//----------------------------------------------------------------------------
// Shader for displaying multisample buffer content...
static const char* shaderSrc =
"#extension ARB_texture_multisample : enable
"
"uniform sampler2DMS sampler;
"
"uniform int layer;
"
"
"
"void main() {
"
" gl_FragColor = texelFetch( sampler, ivec2(gl_FragCoord.xy), layer );
"
"}
";
//----------------------------------------------------------------------------
// Display callback...
void myDisplay( void )
{
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboHandle );
glDrawBuffer( GL_COLOR_ATTACHMENT0_EXT );
glViewport( 0, 0, 512, 512 );
glClear( GL_COLOR_BUFFER_BIT );
if( multisample )
glEnable( GL_MULTISAMPLE );
else
glDisable( GL_MULTISAMPLE );
glLoadIdentity();
glRotatef( 22.5f, 0.0f, 0.0f, 1.0f );
glRectf( -0.5f, -0.5f, 0.5f, 0.5f );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, textureHandle );
glUseProgram( programHandle );
glUniform1i( samplerLoc, 0 );
glUniform1i( layerLoc, layer );
glLoadIdentity();
glViewport( 0, 0, 512, 512 );
glRecti( -1, -1, 1, 1 );
glUseProgram( 0 );
glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, 0 );
glDisable( GL_TEXTURE_2D );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
// Keyboard callback...
void myKeyboard( unsigned char key, int x, int y )
{
switch( key ) {
case ' ':
layer = (layer+1)%maxLayers;
std::cout << "Now displaying sample " << layer << std::endl;
glutPostRedisplay();
break;
case 'm':
multisample = !multisample;
std::cout
<< "Multisample " << ( multisample? "enabled" : "disabled" )
<< std::endl;
glutPostRedisplay();
break;
case 27:
exit(0);
}
}
//----------------------------------------------------------------------------
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
glutInitWindowSize( 512, 512 );
glutCreateWindow( "multisample test" );
try {
GLenum status = glewInit();
if( status!=GLEW_NO_ERROR )
throw std::string("glewInit error: ")+(const char*)glewGetErrorString(status);
if( !GLEW_VERSION_2_0 )
throw std::string("OpenGL 2.0 not supported");
if( !glewIsExtensionSupported("GL_EXT_framebuffer_object") )
throw std::string("EXT_framebuffer_object not supported");
if( !glewIsExtensionSupported("GL_ARB_texture_multisample") )
throw std::string("ARB_texture_multisample not supported");
GLuint shaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource( shaderHandle, 1, &shaderSrc, 0 );
glCompileShader( shaderHandle );
programHandle = glCreateProgram();
glAttachShader( programHandle, shaderHandle );
glLinkProgram( programHandle );
glUseProgram( programHandle ); // ATi workaround
samplerLoc = glGetUniformLocation( programHandle, "sampler" );
layerLoc = glGetUniformLocation( programHandle, "layer" );
glUseProgram( 0 );
glGenTextures( 1, &textureHandle );
glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, textureHandle );
glGetIntegerv( GL_MAX_SAMPLES, &maxLayers );
glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, maxLayers, GL_RGB8, 512, 512, GL_TRUE );
glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, 0 );
status = glGetError();
if( status!=GL_NO_ERROR )
throw std::string("Failed to allocate texture: ")+(const char*)gluErrorString(status);
glGenFramebuffersEXT( 1, &fboHandle );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboHandle );
glFramebufferTexture2D( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D_MULTISAMPLE, textureHandle, 0 );
status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
if( status!=GL_FRAMEBUFFER_COMPLETE_EXT ) {
std::ostringstream str;
str << "Framebuffer not complete: " << status;
throw str.str();
}
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
}
catch( std::string errString ) {
std::cerr << errString << std::endl;
return -1;
}
glutDisplayFunc( &myDisplay );
glutKeyboardFunc( &myKeyboard );
glutMainLoop();
return 0;
}
Hitting space will cycle through sample indices. Hitting ‘m’ will toggle multisample (initially disabled).
With an nVidia 8800GTX and latest drivers, disabling multisampling will only provide 4 samples with the same value, then 4 other samples with another value, and so on…
I’m looking for a way to broadcast every processed fragment to all of its sub-samples. Is there another way to go?
Can people try this app and tell me if they have more luck (e.g. exact same image for every sample) with some other setup, please?
Help would be greatly appreciated