redbook multisample example not work (GL_SAMPLE_BUFFERS = 0)

Hello,

I want to learn some antialiasing effects, and read it in the red book. I tried the sample program, “multisamp.c,” in the book, but I couldn’t see any antialiasing from the results.

The query results from
glGetIntegerv(GL_SAMPLE_BUFFERS) and
glGetIntegerv(GL_SAMPLES) are both zeros. I guess that is the reason because according to the book, if the first value is “1,” and the second value is greater than “1,” then I’ll be able to use multisampling.

I am using a ATI mobility 9600 in my laptop. It supports OpenGL 2.0. I also adjust the settings in the control panel to force OpenGL use 2x antialiasing. But it doesn’t work.

Here is the code. Any ideas?

#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/glut.h>
static int bgtoggle = 1;
void init(void)
{
   static GLint buf[1], sbuf[1];
   int i, j;

   glClearColor(0.0, 0.0, 0.0, 0.0);
   glGetIntegerv (GL_SAMPLE_BUFFERS, buf);
   printf ("number of sample buffers is %d
", buf[0]);
   glGetIntegerv (GL_SAMPLES, sbuf);
   printf ("number of samples is %d
", sbuf[0]);

   glNewList (1, GL_COMPILE);
   for (i = 0; i < 19; i++) {
      glPushMatrix();
      glRotatef(360.0*(float)i/19.0, 0.0, 0.0, 1.0);
      glColor3f (1.0, 1.0, 1.0);
      glLineWidth((i%3)+1.0);
      glBegin (GL_LINES);
         glVertex2f (0.25, 0.05);
         glVertex2f (0.9, 0.2);
      glEnd ();
      glColor3f (0.0, 1.0, 1.0);
      glBegin (GL_TRIANGLES);
         glVertex2f (0.25, 0.0);
         glVertex2f (0.9, 0.0);
         glVertex2f (0.875, 0.10);
      glEnd ();
      glPopMatrix();
   }
   glEndList ();

   glNewList (2, GL_COMPILE);
   glColor3f (1.0, 0.5, 0.0);
   glBegin (GL_QUADS);
   for (i = 0; i < 16; i++) {
      for (j = 0; j < 16; j++) {
         if (((i + j) % 2) == 0) {
            glVertex2f (-2.0 + (i * 0.25), -2.0 + (j * 0.25));
            glVertex2f (-2.0 + (i * 0.25), -1.75 + (j * 0.25));
            glVertex2f (-1.75 + (i * 0.25), -1.75 + (j * 0.25));
            glVertex2f (-1.75 + (i * 0.25), -2.0 + (j * 0.25));
         }
      }
   }
   glEnd ();
   glEndList ();
}


void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT);

   if (bgtoggle) 
      glCallList (2);

   glEnable (GL_MULTISAMPLE);
   glPushMatrix();
   glTranslatef (-1.0, 0.0, 0.0);
   glCallList (1);
   glPopMatrix();

   glDisable (GL_MULTISAMPLE);
   glPushMatrix();
   glTranslatef (1.0, 0.0, 0.0);
   glCallList (1);
   glPopMatrix();
   glutSwapBuffers();
}

void reshape(int w, int h)
{
   glViewport(0, 0, w, h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   if (w <= (2 * h)) 
      gluOrtho2D (-2.0, 2.0, 
         -2.0*(GLfloat)h/(GLfloat)w, 2.0*(GLfloat)h/(GLfloat)w);
   else 
      gluOrtho2D (-2.0*(GLfloat)w/(GLfloat)h, 
         2.0*(GLfloat)w/(GLfloat)h, -2.0, 2.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 'b':
      case 'B':
         bgtoggle = !bgtoggle;
         glutPostRedisplay();
         break;
      case 27:  /*  Escape Key  */
         exit(0);
      default:
         break;
    }
}

int main(int argc, char** argv)
{
	glewInit();
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_MULTISAMPLE);
   glutInitWindowSize (600, 300);
   glutCreateWindow (argv[0]);
   init();
   glutReshapeFunc (reshape);
   glutKeyboardFunc (keyboard);
   glutDisplayFunc (display);
   glutMainLoop();
   return 0;
}

One tip could be to initialize GLEW after you have created the window… like the manual says =)

I believe glut’s multi-sampling relies on the old GLX_SAMPLE_SGIS extension which your ATI card may not support. Your program needs to ask for a multi-sample visual (Linux) or pixel format (Windows). What platform are you using? I have working examples I can post although they are based on glx/glw, not glut.

It also possible that SDL (http://www.libsdl.org/) may support ms out of the box.

Koz

Hi Joel, it doesn’t work.

To koz:
I am under windows.

If I don’t include glew.h, then there are compilor errors:

.\multisamp.c(75) : error C2065: 'GL_SAMPLE_BUFFERS' : undeclared identifier
.\multisamp.c(77) : error C2065: 'GL_SAMPLES' : undeclared identifier
.\multisamp.c(130) : error C2065: 'GL_MULTISAMPLE' : undeclared identifier

So glew takes care of the multi-sampling thing. Am I right?

  
//
//
// fsaa.c - Multi-sample example.
//
// cl fsaa.c opengl32.lib gdi32.lib user32.lib
//
#include <windows.h>   // standard Windows headers
#include <math.h>
#include <GL/gl.h>     // OpenGL interface
#include <GL/glu.h>    // OpenGL utility Library interface
//
// You may need to grab the following headers from 
// http://www.opengl.org/registry/
//
#include <GL/glext.h>
#include <GL/wglext.h>

LONG WINAPI WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawOpenGLScene(void);
HGLRC SetUpOpenGL(HWND hWnd);

int bestFormat = 0;

//
// Check for an OpenGL extension
//
static GLboolean CheckExtension(char *extName, const char *extString)
{
   char *p = (char *)extString;
   char *end;
   int extNameLen;

   extNameLen = strlen(extName);
   end = p + strlen(p);

   while (p < end) {
      int n = strcspn(p, " ");
      if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
	 return GL_TRUE;
      }
      p += (n + 1);
   }
   return GL_FALSE;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpszCmdLine, int nCmdShow) {
   static char szAppName[] = "OpenGL";
   static char szTitle[]="FSAA";
   WNDCLASS wc;   
   MSG      msg;  
   HWND     hWnd; 
   HWND hWndGL;   

   wc.style         =
      CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc   = 
      (WNDPROC)WndProc;      
   wc.cbClsExtra    = 0;     
   wc.cbWndExtra    = 0;     
   wc.hInstance     =
      hInstance;            
   wc.hIcon         = NULL;  
   wc.hCursor       =
      LoadCursor(NULL, IDC_ARROW);
   wc.hbrBackground = 
      (HBRUSH)(COLOR_WINDOW+1);
   wc.lpszMenuName  = NULL;  
   wc.lpszClassName =
      szAppName;            

   RegisterClass( &wc );

   //
   // Create a temporary window so OpenGL can query the pixel formats
   //
   hWndGL = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW | 
	 WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 
	 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWndGL) {
      return (0);
   } else {
      SetUpOpenGL(hWndGL);
   }

   //
   // Create a main window for this application instance.
   //
   hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW | 
	 WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 
	 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if ( !hWnd ) {
      return( 0 );
   }

   ShowWindow( hWnd, nCmdShow );
   UpdateWindow( hWnd );       

   while (GetMessage(&msg, NULL, 0, 0)) {
      TranslateMessage( &msg ); // Translates messages
      DispatchMessage( &msg );  // then dispatches
   }

   return( msg.wParam ); 
}

LONG WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
   HDC hDC;
   static HGLRC hRC; 
   PAINTSTRUCT ps;
   GLdouble gldAspect;
   GLsizei glnWidth, glnHeight;

   switch (msg)
   {
      case WM_CREATE:
	 hDC = GetDC(hWnd);
	 SetPixelFormat(hDC, bestFormat, NULL);
	 hRC = wglCreateContext(hDC);
	 ReleaseDC(hWnd, hDC);
	 return 0;

      case WM_SIZE:
	 hDC = GetDC (hWnd);
	 wglMakeCurrent (hDC, hRC);

	 glnWidth = (GLsizei) LOWORD (lParam);
	 glnHeight = (GLsizei) HIWORD (lParam);
	 gldAspect = 
	    (GLdouble)glnWidth/(GLdouble)glnHeight;

	 glMatrixMode( GL_PROJECTION );
	 glLoadIdentity();
	 gluPerspective( 30.0, gldAspect, 1.0, 10.0 ); 

	 glViewport( 0, 0, glnWidth, glnHeight );
	 wglMakeCurrent( NULL, NULL );
	 ReleaseDC( hWnd, hDC );
	 return 0;

      case WM_PAINT:
	 hDC = BeginPaint( hWnd, &ps );
	 wglMakeCurrent( hDC, hRC );

	 DrawOpenGLScene();
	 SwapBuffers(hDC);

	 wglMakeCurrent( NULL, NULL );

	 EndPaint( hWnd, &ps );
	 return 0;       

      case WM_DESTROY:
	 wglDeleteContext( hRC );
	 PostQuitMessage( 0 );
	 return 0;
   }

   return DefWindowProc( hWnd, msg, wParam, lParam );
}

HGLRC SetUpOpenGL(HWND hWnd) {
   static PIXELFORMATDESCRIPTOR pfd = {
      sizeof (PIXELFORMATDESCRIPTOR), // strcut size 
      1,                              // Version number
      PFD_DRAW_TO_WINDOW |    // Flags, draw to a window,
      PFD_SUPPORT_OPENGL,     // use OpenGL
      PFD_TYPE_RGBA,          // RGBA pixel values
      24,                     // 24-bit color
      0, 0, 0,                // RGB bits & shift sizes.
      0, 0, 0,                // Don't care about them
      0, 0,                   // No alpha buffer info
      0, 0, 0, 0, 0,          // No accumulation buffer
      32,                     // 32-bit depth buffer
      0,                      // No stencil buffer
      0,                      // No auxiliary buffers
      PFD_MAIN_PLANE,         // Layer type
      0,                      // Reserved (must be 0)
      0,                      // No layer mask
      0,                      // No visible mask
      0                       // No damage mask
   };

   int nMyPixelFormatID;
   HDC hDC;
   HGLRC hRC;
   static char myExtension[] = "GL_ARB_multisample";
   static char myWglExtension[] = "WGL_ARB_multisample";
   PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
   PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB = NULL;
   int formatCount = 0; 
   int attrib[] = { WGL_NUMBER_PIXEL_FORMATS_ARB };
   int formatResults[9];
   int formatAttribs[9] = { WGL_SUPPORT_OPENGL_ARB,
      WGL_ACCELERATION_ARB,
      WGL_DRAW_TO_WINDOW_ARB,
      WGL_DOUBLE_BUFFER_ARB,
      WGL_PIXEL_TYPE_ARB,
      WGL_DEPTH_BITS_ARB,
      WGL_STENCIL_BITS_ARB,
      WGL_SAMPLE_BUFFERS_ARB,
      WGL_SAMPLES_ARB };
   int i, j;
   int maxSamples = 0;
   int depth = 0;
   int stencil = 0;

   hDC = GetDC( hWnd );
   nMyPixelFormatID = ChoosePixelFormat( hDC, &pfd );

   SetPixelFormat( hDC, nMyPixelFormatID, &pfd );

   hRC = wglCreateContext( hDC );

   //
   // Extension check
   //
   wglMakeCurrent(hDC, hRC);
   if(CheckExtension(myExtension,
	    glGetString(GL_EXTENSIONS))){
      printf("%s is supported
", myExtension);
   } 
   wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
      wglGetProcAddress("wglGetExtensionsStringARB");

   if(CheckExtension(myWglExtension,
	    wglGetExtensionsStringARB(hDC))){
      printf("%s is supported
", myWglExtension);
   } 
   if(CheckExtension("WGL_ARB_pixel_format", 
	    wglGetExtensionsStringARB(hDC)))
      if(wglGetPixelFormatAttribivARB == NULL)
	 wglGetPixelFormatAttribivARB = 
	    (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
	    wglGetProcAddress("wglGetPixelFormatAttribivARB");

   wglGetPixelFormatAttribivARB(hDC, 1, 0, 1, attrib, &formatCount);

   for(i=0;i<formatCount;i+=1) {
      wglGetPixelFormatAttribivARB(hDC, i+1, 0, 9, 
	    formatAttribs, formatResults);
      //
      // Find the best double buffered fsaa pixel format with z.
      //
      if(formatResults[3] && (formatResults[8] > maxSamples)) {
	 maxSamples = formatResults[8];
	 depth = formatResults[5];
	 stencil = formatResults[6];
	 bestFormat = i+1;
      }
   }
   if(maxSamples > 0) {
      printf("Pixel format: 
 id = %d, z = %d, stencil = %d, samples = %d
", bestFormat, depth, stencil, maxSamples);
      _flushall();
      wglMakeCurrent(hDC, NULL);
      wglDeleteContext(hRC);
   }

   ReleaseDC(hWnd, hDC);
   return hRC;
}

void drawLines() {

   int a;
   float r;

   for(a=0; a<360; a+=8) {
      glBegin(GL_LINES);
      glColor3f(1.0f, 1.0f, 1.0f);
      glVertex3f(0.0f, 0.0f, 0.0f);
      r = 3.1459 * a / 180.0;
      glVertex3f(sin(r), cos(r), 0.0f);
      glEnd();
   }

}

void DrawOpenGLScene( )
{

   glEnable( GL_DEPTH_TEST );
   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();

   glTranslatef( 0.0f, 0.0f, -5.0f );

   drawLines();

   glFlush ();

}

Could I see the GLX code for it?, thank you.

NEHE Lesson 46 is a multsample example.I think you can try it. Since having not encapsulated by glut, maybe it can disclose more detail.

You need to create a window with a gl context and make it current to query the wgl extension to request advanced visuals, because the PFD approach is inherently flawed.

wglChoosePixelFormatARB =
        (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");

Once you have this pointer you can delete your first window and create a new one and request a gl context with multisample attributes.

Yep it’s a pain in the ass but you gotta do it that way to get ChoosePixelFormat and as an API it is inherently useful and brings some normality to visual selection on Windows.