Difference between revisions of "Multisampling"

From OpenGL.org
Jump to: navigation, search
(New page: Full Scene Anti-Aliasing - also called FSAA<br> The 1995 method of doing AA was to call glEnable(GL_POINT_SMOOTH), glEnable(GL_LINE_SMOOTH), glEnable(GL_POLYGON_SMOOTH) and to enable blend...)
 
(Cross-platform (using GLUT))
(23 intermediate revisions by 4 users not shown)
Line 1: Line 1:
Full Scene Anti-Aliasing - also called FSAA<br>
+
Multisampling, also known as multisample antialiasing (MSAA), is one method for achieving full-screen antialiasing (FSAA). Unlike supersampling (SSAA) which can result in the same pixel being shaded multiple times per pixel, multisampling runs the fragment program just once per pixel rasterized.  However with MSAA multiple depth/stencil comparisons are performed per pixel, one for each of the subsamples, which gives you sub-pixel spatial precision on your geometry and nice, smoothed edges on your polygons.
The 1995 method of doing AA was to call glEnable(GL_POINT_SMOOTH), glEnable(GL_LINE_SMOOTH), glEnable(GL_POLYGON_SMOOTH) and to enable blending with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), glEnable(GL_BLEND). For points and lines, you need to make them a little big, glPointSize(1.1), glLineWidth(1.1).<br>
+
 
<br>
+
== History ==
Since GPUs of the day didn't support it in hw, it would run very slow.<br>
+
Before GL_ARB_multisample extension, the edges of lines, polygons, and points could be selectively antialiased using using glEnable(GL_LINE_SMOOTH), glEnable(GL_POLYGON_SMOOTH), glEnable(GL_POINT_SMOOTH) respectively, combined with a blending function, such as glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). Such features were typically not implemented in hardware in early consumer graphics cards at the time, and were done in software resulting in poor performance. More expensive "workstation" graphics cards from HP, Sun, and SGI at the time did implement these features in hardware. Modern programs should not make use of these features.
<br>
+
 
These days, they still run slow unless you have a workstation GPU.<br>
+
== Rendering with Multisampling ==
For gaming GPUs, you should only use FSAA. You should even give the user the option to turn on and off FSAA.<br>
+
 
== The Procedure ==
+
There are two pieces to rendering with multisampling:
The problem is that this part of OpenGL is platform specific. If you use freeGLUT, SDL or some other library, they hide this platform specific stuff. Here, we will talk about Windows and the platform specific API.<br>
+
 
This is what you must do :<br>
+
# Allocating a multisample render target (window or [[FBO]]), and
1. Start your program, open a dummy window for getting function pointers (CreateWindowEx)<br>
+
# Enabling multisample rasterization (i.e. <code>glEnable( GL_MULTISAMPLE )</code>)
2. Make the window invisible ShowWindow(window.HWnd, SW_HIDE)<br>
+
 
3. You can then SetPixelFormat, create the GL context, make the GL context current (wglMakeCurrent(hdc, glrc))<br>
+
While the second step is standardized across all render target types and platforms, the first is only standardized for [[FBO]]s (as it is totally internal to GL). When rendering to a window, the allocation method depends on the specific platform GL integration layer in-use (e.g. WGL, GLX, AGL, etc.).  GLUT provides a wrapper around some of these so you don't have to care.
4. Now you can get the funcion pointers. If you are using GLEW
+
 
   GLenum err=glewInit();
+
The following sections describe how to perform MSAA render target allocation (#1) for various render target types and platforms.
   if(err!=GLEW_OK)
+
 
 +
== Allocating a Multisample Render Target ==
 +
 
 +
=== Render-to-FBO ===
 +
 
 +
As mentioned, allocation of multisample off-screen [[FBO]]s is platform independent. Here's an example:
 +
 
 +
<pre>
 +
  glGenTextures( 1, &tex );
 +
  glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, tex );
 +
  glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, num_samples, GL_RGBA8, width, height, false );
 +
 
 +
  glGenFramebuffers( 1, &fbo );
 +
  glBindFramebuffer( GL_FRAMEBUFFER, fbo );
 +
  glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0 );
 +
 
 +
  GLenum status = glCheckFramebufferStatus( target );
 +
  ...
 +
</pre>
 +
 
 +
=== Render-to-Window ===
 +
 
 +
==== Microsoft Windows (using wgl) ====
 +
 
 +
The wgl functions required to create a multisampled OpenGL context are not available until a valid OpenGL context is made current to the thread. This leads to a [[Creating_an_OpenGL_Context#Proper_Context_Creation|temporary context]] code path which can get very involved with platform specific detailed. Users of libraries such as GLUT, GLEW, or GLee can significantly reduce the amount of effort required. The rest of this section assumes that valid context is present and all wgl extension function pointers have been obtained, if not, please see how to create a [[Creating_an_OpenGL_Context#Proper_Context_Creation|temporary context]].
 +
 
 +
A valid pixel format for the framebuffer is choose using the wglChoosePixelFormatARB function with a list of attributes to specify the multisampling properties. In order to choose a framebuffer format that incorporates multisampling, you must add it to the list of attributes. For example, this list of attributes ''does not'' select a multisampled pixel format:
 +
 
 +
<code c>
 +
    int attributes[] = {
 +
    WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
 +
    WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
 +
    WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
 +
    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
 +
    WGL_COLOR_BITS_ARB, 32,
 +
    WGL_DEPTH_BITS_ARB, 24,
 +
    WGL_STENCIL_BITS_ARB, 8,
 +
    0
 +
    };
 +
</code>
 +
 
 +
To consider multisampled visuals, the WGL_SAMPLE_BUFFERS_ARB and WGL_SAMPLES_ARB attributes must be present. The WGL_SAMPLE_BUFFERS_ARB must be set to 1, and WGL_SAMPLES_ARB is the number of samples, e.g. for 8x multisampling, WGL_SAMPLES_ARB would be set to 8. This attribute list is the same as above, but considers 4x multisampled pixel formats too:
 +
 
 +
<code c>
 +
    int attributes[] = {
 +
    WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
 +
    WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
 +
    WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
 +
    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
 +
    WGL_COLOR_BITS_ARB, 32,
 +
    WGL_DEPTH_BITS_ARB, 24,
 +
    WGL_STENCIL_BITS_ARB, 8,
 +
    WGL_SAMPLE_BUFFERS_ARB, 1, //Number of buffers (must be 1 at time of writing)
 +
    WGL_SAMPLES_ARB, 4,        //Number of samples
 +
    0
 +
    };
 +
</code c>
 +
 
 +
Once the correct pixel format is found, creating a context proceeds as normal.
 +
 
 +
==== X Windows (using GLX) ====
 +
 
 +
This is the method you'd use on UNIX/Linux if you want to create an X window with multisampling capability. There are a few methods for doing this, but the following locates an MSAA FBConfig, looks up its XVisual, and then creates an X window in that visual.  You'll notice some similarities with the WGL method above.
 +
 
 +
<pre>
 +
  // --- Find a MSAA FBConfig ---
 +
  static const int Visual_attribs[] =
 +
    {
 +
      GLX_X_RENDERABLE    , True,
 +
      GLX_DRAWABLE_TYPE  , GLX_WINDOW_BIT,
 +
      GLX_RENDER_TYPE    , GLX_RGBA_BIT,
 +
      GLX_X_VISUAL_TYPE  , GLX_TRUE_COLOR,
 +
      GLX_RED_SIZE        , 8,
 +
      GLX_GREEN_SIZE      , 8,
 +
      GLX_BLUE_SIZE      , 8,
 +
      GLX_ALPHA_SIZE      , 8,
 +
      GLX_DEPTH_SIZE      , 24,
 +
      GLX_STENCIL_SIZE    , 8,
 +
      GLX_DOUBLEBUFFER    , True,
 +
      GLX_SAMPLE_BUFFERS  , 1,            // <-- MSAA
 +
      GLX_SAMPLES        , 4,            // <-- MSAA
 +
      None
 +
    };
 +
 
 +
  int attribs [ 100 ] ;
 +
  memcpy( attribs, Visual_attribs, sizeof( Visual_attribs ) );
 +
 
 +
   GLXFBConfig fbconfig = 0;
 +
  int        fbcount;
 +
  GLXFBConfig *fbc = glXChooseFBConfig( display, screen, attribs, &fbcount );
 +
   if ( fbc )
 
   {
 
   {
    //Problem: glewInit failed, something is seriously wrong
+
    if ( fbcount >= 1 )
    sprintf(pErrorMessage, "Error: %s", glewGetErrorString(err));
+
      fbconfig = fbc[0];
    return -1;
+
    XFree( fbc );
 
   }
 
   }
  
5. Check to see if function pointer (wglGetExtensionsStringARB) is not NULL. If it is not NULL, call wglGetExtensionsStringARB(hdc) to get a list of WGL extensions supported.<br>
+
  if ( !fbconfig )
6. WGL_ARB_pixel_format and WGL_ARB_multisample should be in the list. If they are, set some variable to TRUE and then make GL context non-current, kill the GL context, destroy the temporary window. <br>
+
  {
7. Now, create your real window. Make it visible.<br>
+
    printf( "Failed to get MSAA GLXFBConfig\n" );
8. Now you must check that variable that you had set. Is it FALSE or TRUE. If it is TRUE, then you can setup a FSAA pixelformat.<br>
+
    exit(1);
9. Since you have already called glewInit, you don't need to call it again. Use wglGetPixelFormatAttribivARB to collect information.<br>
+
  }
10. When you find a pixelformat that you like, call the "tradional" SetPixelFormat. Make a GL context, make context current and now you are ready to render.<br>
+
 
<br>
+
  // --- Get its VisualInfo ---
The most difficult part is choosing a suitable pixelformat. One that has the right color bits, depth bits, stencil bits, the right FSAA level.<br>
+
  XVisualInfo *visinfo = glXGetVisualFromFBConfig( display, fbconfig );
You should also call glEnable(GL_MULTISAMPLE) but in reality this is useless since it is not possible to enable or disable FSAA once you have chosen a FSAA pixelformat.<br>
+
  if ( !visinfo )
In this entire document, we called it FSAA (Full Scene Anti-Aliasing) but it is also called MS (multisampling) since multiple samples are taken in various ways and the samples are blended together to give the resulting pixel. There is also another concept called supersampling and there are also nVidia specific GPU algorithms for sampling (see nVidia's documents on their developer website. http://developer.nvidia.com)
+
  {
 +
    printf( "Failed to get XVisualInfo\n" );
 +
    exit(1);
 +
  }
 +
  printf( "X Visual ID = 0x%.2x\n", int( visinfo->visualid ) );
 +
 
 +
  // --- Now just create an X window in that visual ---
 +
  XSetWindowAttributes winAttr ;
 +
 
 +
  winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
 +
  winAttr.background_pixmap = None ;
 +
  winAttr.background_pixel  = 0    ;
 +
  winAttr.border_pixel      = 0    ;
 +
 
 +
  winAttr.colormap = XCreateColormap( display, root_win,
 +
                                      visinfo->visual, AllocNone );
 +
 
 +
  unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
 +
 
 +
  Window win = XCreateWindow ( display, root_win,
 +
                              WIN_XPOS, WIN_YPOS,
 +
                              WIN_XRES, WIN_YRES, 0,
 +
                              visinfo->depth, InputOutput,
 +
                              visinfo->visual, mask, &winAttr ) ;
 +
 
 +
  XStoreName( display, win, "My GLX Window");
 +
</pre>
 +
 
 +
==== MacOS X (using Cocoa) ====
 +
 
 +
''TBD''
 +
 
 +
==== Cross-platform (using GLUT) ====
 +
 
 +
GLUT is a wrapper around the platform-specific GL integration layers (e.g. WGL, GLX, etc.) which allows you to prototype simple cross-platform GL examples quickly. In GLUT, the key to allocating an MSAA window is this:
 +
 
 +
  glutInitDisplayMode( ... | GLUT_MULTISAMPLE );
 +
 
 +
which directs GLUT to allocate an MSAA-capable window. The following is a complete example showing how to render with multisampling in a simple GLUT test program:
 +
 
 +
<pre>
 +
#include <GL/gl.h>
 +
#include <GL/glut.h>
 +
#include <GL/glu.h>
 +
 
 +
#include <stdio.h>
 +
 
 +
float rotation_angle=0;
 +
int msaa=1;
 +
 
 +
void reshape(int width, int height)
 +
{
 +
  glViewport(0, 0, width, height);
 +
}
 +
 
 +
void mouse(int button, int state, int x, int y)
 +
{
 +
  if (state==GLUT_DOWN)
 +
  {
 +
    msaa = !msaa;
 +
    glutPostRedisplay();
 +
  }
 +
}
 +
 
 +
 
 +
void display()
 +
{
 +
  int err=0;
 +
  glClear(GL_COLOR_BUFFER_BIT);
 +
 
 +
  glMatrixMode(GL_PROJECTION);
 +
  glLoadIdentity();
 +
  glOrtho(-1,1,-1,1,-1,1);
 +
 
 +
  glMatrixMode(GL_MODELVIEW);
 +
  glLoadIdentity();
 +
 
 +
  glRotatef(rotation_angle, 0,0,1);
 +
 
 +
  glColor4f(1,0,0,1);
 +
 
 +
  if (msaa)
 +
  {
 +
    glEnable(GL_MULTISAMPLE_ARB);
 +
    printf("msaa on\n");
 +
  }
 +
  else
 +
  {
 +
    printf("msaa off\n");
 +
    glDisable(GL_MULTISAMPLE_ARB);
 +
  }
 +
 
 +
  glRectf(-.5,-.5,.5,.5);
 +
 
 +
  glutSwapBuffers();
 +
  err = glGetError();
 +
  if (err)
 +
    fprintf(stderr, "%s\n", gluErrorString(err));
 +
}
 +
 
 +
int
 +
main (int argc, char** argv)
 +
{
 +
  glutInit(&argc, argv);
 +
  glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
 +
  glutCreateWindow(argv[0]);
 +
 
 +
  glutDisplayFunc(display);
 +
  glutMouseFunc(mouse);
 +
  glutReshapeFunc(reshape);
 +
 
 +
  glutReshapeWindow(400,400);
 +
 
 +
  printf("%s\n",glGetString(GL_RENDERER));
 +
 
 +
  rotation_angle=30;
 +
 
 +
  glutMainLoop();
 +
  return 0;
 +
}
 +
</pre>
 +
 
 +
== Extension References ==
 +
- http://www.opengl.org/registry/specs/ARB/multisample.txt
 +
 
 +
These might interest you :
 +
- http://www.opengl.org/registry/specs/NV/multisample_filter_hint.txt
 +
- http://www.opengl.org/registry/specs/NV/explicit_multisample.txt
 +
- http://www.opengl.org/registry/specs/NV/multisample_coverage.txt
 +
 
 
== Conclusion ==
 
== Conclusion ==
Setting up FSAA takes a few steps but it is worth it. Todays GPUs are very rapid and the user wants control over the quality of the game's graphics.<br>
+
Setting up FSAA takes a few steps but it is worth it. Today's GPUs are very rapid and the user wants control over the quality of the game's graphics.<br>
 
On Windows, the extension we are interested in are WGL_ARB_extensions_string which defines wglGetExtensionsStringARB, but the only way to check if this is available is to call wglGetExtensionsStringARB. So this is a chicken and egg situation. Just get the function pointer to wglGetExtensionsStringARB and use it to see if you have WGL_ARB_pixel_format and WGL_ARB_multisample.
 
On Windows, the extension we are interested in are WGL_ARB_extensions_string which defines wglGetExtensionsStringARB, but the only way to check if this is available is to call wglGetExtensionsStringARB. So this is a chicken and egg situation. Just get the function pointer to wglGetExtensionsStringARB and use it to see if you have WGL_ARB_pixel_format and WGL_ARB_multisample.
 +
 +
[[Category:Sample Writing]]

Revision as of 23:26, 11 November 2012

Multisampling, also known as multisample antialiasing (MSAA), is one method for achieving full-screen antialiasing (FSAA). Unlike supersampling (SSAA) which can result in the same pixel being shaded multiple times per pixel, multisampling runs the fragment program just once per pixel rasterized. However with MSAA multiple depth/stencil comparisons are performed per pixel, one for each of the subsamples, which gives you sub-pixel spatial precision on your geometry and nice, smoothed edges on your polygons.

History

Before GL_ARB_multisample extension, the edges of lines, polygons, and points could be selectively antialiased using using glEnable(GL_LINE_SMOOTH), glEnable(GL_POLYGON_SMOOTH), glEnable(GL_POINT_SMOOTH) respectively, combined with a blending function, such as glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). Such features were typically not implemented in hardware in early consumer graphics cards at the time, and were done in software resulting in poor performance. More expensive "workstation" graphics cards from HP, Sun, and SGI at the time did implement these features in hardware. Modern programs should not make use of these features.

Rendering with Multisampling

There are two pieces to rendering with multisampling:

  1. Allocating a multisample render target (window or FBO), and
  2. Enabling multisample rasterization (i.e. glEnable( GL_MULTISAMPLE ))

While the second step is standardized across all render target types and platforms, the first is only standardized for FBOs (as it is totally internal to GL). When rendering to a window, the allocation method depends on the specific platform GL integration layer in-use (e.g. WGL, GLX, AGL, etc.). GLUT provides a wrapper around some of these so you don't have to care.

The following sections describe how to perform MSAA render target allocation (#1) for various render target types and platforms.

Allocating a Multisample Render Target

Render-to-FBO

As mentioned, allocation of multisample off-screen FBOs is platform independent. Here's an example:

  glGenTextures( 1, &tex );
  glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, tex );
  glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, num_samples, GL_RGBA8, width, height, false );

  glGenFramebuffers( 1, &fbo );
  glBindFramebuffer( GL_FRAMEBUFFER, fbo );
  glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0 );

  GLenum status = glCheckFramebufferStatus( target );
  ...

Render-to-Window

Microsoft Windows (using wgl)

The wgl functions required to create a multisampled OpenGL context are not available until a valid OpenGL context is made current to the thread. This leads to a temporary context code path which can get very involved with platform specific detailed. Users of libraries such as GLUT, GLEW, or GLee can significantly reduce the amount of effort required. The rest of this section assumes that valid context is present and all wgl extension function pointers have been obtained, if not, please see how to create a temporary context.

A valid pixel format for the framebuffer is choose using the wglChoosePixelFormatARB function with a list of attributes to specify the multisampling properties. In order to choose a framebuffer format that incorporates multisampling, you must add it to the list of attributes. For example, this list of attributes does not select a multisampled pixel format:

   int attributes[] = {
   WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
   WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
   WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
   WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
   WGL_COLOR_BITS_ARB, 32,
   WGL_DEPTH_BITS_ARB, 24,
   WGL_STENCIL_BITS_ARB, 8,
   0
   };

To consider multisampled visuals, the WGL_SAMPLE_BUFFERS_ARB and WGL_SAMPLES_ARB attributes must be present. The WGL_SAMPLE_BUFFERS_ARB must be set to 1, and WGL_SAMPLES_ARB is the number of samples, e.g. for 8x multisampling, WGL_SAMPLES_ARB would be set to 8. This attribute list is the same as above, but considers 4x multisampled pixel formats too:

   int attributes[] = {
   WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
   WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
   WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
   WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
   WGL_COLOR_BITS_ARB, 32,
   WGL_DEPTH_BITS_ARB, 24,
   WGL_STENCIL_BITS_ARB, 8,
   WGL_SAMPLE_BUFFERS_ARB, 1, //Number of buffers (must be 1 at time of writing)
   WGL_SAMPLES_ARB, 4,        //Number of samples
   0
   };

Once the correct pixel format is found, creating a context proceeds as normal.

X Windows (using GLX)

This is the method you'd use on UNIX/Linux if you want to create an X window with multisampling capability. There are a few methods for doing this, but the following locates an MSAA FBConfig, looks up its XVisual, and then creates an X window in that visual. You'll notice some similarities with the WGL method above.

  // --- Find a MSAA FBConfig ---
  static const int Visual_attribs[] =
    {
      GLX_X_RENDERABLE    , True,
      GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
      GLX_RENDER_TYPE     , GLX_RGBA_BIT,
      GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
      GLX_RED_SIZE        , 8,
      GLX_GREEN_SIZE      , 8,
      GLX_BLUE_SIZE       , 8,
      GLX_ALPHA_SIZE      , 8,
      GLX_DEPTH_SIZE      , 24,
      GLX_STENCIL_SIZE    , 8,
      GLX_DOUBLEBUFFER    , True,
      GLX_SAMPLE_BUFFERS  , 1,            // <-- MSAA
      GLX_SAMPLES         , 4,            // <-- MSAA
      None
    };

  int attribs [ 100 ] ;
  memcpy( attribs, Visual_attribs, sizeof( Visual_attribs ) );

  GLXFBConfig fbconfig = 0;
  int         fbcount;
  GLXFBConfig *fbc = glXChooseFBConfig( display, screen, attribs, &fbcount );
  if ( fbc )
  {
    if ( fbcount >= 1 )
      fbconfig = fbc[0];
    XFree( fbc );
  }

  if ( !fbconfig )
  {
    printf( "Failed to get MSAA GLXFBConfig\n" );
    exit(1);
  }

  // --- Get its VisualInfo ---
  XVisualInfo *visinfo = glXGetVisualFromFBConfig( display, fbconfig );
  if ( !visinfo )
  {
    printf( "Failed to get XVisualInfo\n" );
    exit(1);
  }
  printf( "X Visual ID = 0x%.2x\n", int( visinfo->visualid ) );

  // --- Now just create an X window in that visual ---
  XSetWindowAttributes winAttr ;

  winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
  winAttr.background_pixmap = None ;
  winAttr.background_pixel  = 0    ;
  winAttr.border_pixel      = 0    ;

  winAttr.colormap = XCreateColormap( display, root_win,
                                      visinfo->visual, AllocNone );
  
  unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;

  Window win = XCreateWindow ( display, root_win, 
                               WIN_XPOS, WIN_YPOS, 
                               WIN_XRES, WIN_YRES, 0, 
                               visinfo->depth, InputOutput, 
                               visinfo->visual, mask, &winAttr ) ;

  XStoreName( display, win, "My GLX Window");

MacOS X (using Cocoa)

TBD

Cross-platform (using GLUT)

GLUT is a wrapper around the platform-specific GL integration layers (e.g. WGL, GLX, etc.) which allows you to prototype simple cross-platform GL examples quickly. In GLUT, the key to allocating an MSAA window is this:

 glutInitDisplayMode( ... | GLUT_MULTISAMPLE );

which directs GLUT to allocate an MSAA-capable window. The following is a complete example showing how to render with multisampling in a simple GLUT test program:

#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glu.h>

#include <stdio.h>

float rotation_angle=0;
int msaa=1;

void reshape(int width, int height)
{
  glViewport(0, 0, width, height);
}

void mouse(int button, int state, int x, int y)
{
  if (state==GLUT_DOWN) 
  {
    msaa = !msaa;
    glutPostRedisplay();
  }
}


void display()
{
  int err=0;
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-1,1,-1,1,-1,1);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glRotatef(rotation_angle, 0,0,1);

  glColor4f(1,0,0,1);

  if (msaa) 
  {
    glEnable(GL_MULTISAMPLE_ARB);
    printf("msaa on\n");
  } 
  else 
  {
    printf("msaa off\n");
    glDisable(GL_MULTISAMPLE_ARB);
  }

  glRectf(-.5,-.5,.5,.5);
  
  glutSwapBuffers();
  err = glGetError();
  if (err)
    fprintf(stderr, "%s\n", gluErrorString(err));
}

int
main (int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
  glutCreateWindow(argv[0]);

  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  glutReshapeFunc(reshape);
  
  glutReshapeWindow(400,400);

  printf("%s\n",glGetString(GL_RENDERER));

  rotation_angle=30;

  glutMainLoop();
  return 0;
}

Extension References

- http://www.opengl.org/registry/specs/ARB/multisample.txt

These might interest you : - http://www.opengl.org/registry/specs/NV/multisample_filter_hint.txt - http://www.opengl.org/registry/specs/NV/explicit_multisample.txt - http://www.opengl.org/registry/specs/NV/multisample_coverage.txt

Conclusion

Setting up FSAA takes a few steps but it is worth it. Today's GPUs are very rapid and the user wants control over the quality of the game's graphics.
On Windows, the extension we are interested in are WGL_ARB_extensions_string which defines wglGetExtensionsStringARB, but the only way to check if this is available is to call wglGetExtensionsStringARB. So this is a chicken and egg situation. Just get the function pointer to wglGetExtensionsStringARB and use it to see if you have WGL_ARB_pixel_format and WGL_ARB_multisample.