|
From: James W. <ja...@fr...> - 2007-12-12 00:17:31
|
I've added support for full-screen antialiasing via the OpenGL multisampling feature. It is implemented for Mac-Carbon and Windows in the OpenGL renderer and derived renderers. However, it's not quite as simple as submitting a kQ3AntiAliasModeMaskFullScreen style object. When setting up the draw context, you must provide a multisample-capable pixel format (by platform-dependent means) as an object property of type kQ3DrawContextPropertyGLPixelFormat. The extra complication is mostly due to Windows. On Windows, in order to get an appropriate function pointer, you must first get a function pointer to wglChoosePixelFormatARB, and in order to get that, you must already have an OpenGL context set up. So the typical routine would involve creating a dummy window, getting the function pointer, destroying the dummy window, and then proceeding to set up the window you really want to use. I didn't want Quesa to get into the business of creating and destroying windows. -- James W. Walker, Innoventive Software LLC <http://www.frameforge3d.com/> |
|
From: James W. W. <os...@jw...> - 2007-12-12 03:44:10
|
On Dec 11, 2007, at 4:17 PM, James Walker wrote: > The extra complication is mostly due to Windows. On Windows, in order > to get an appropriate function pointer, you must first get a function > pointer to wglChoosePixelFormatARB, and in order to get that, you must > already have an OpenGL context set up. Oops, that should say "On Windows, in order to get an appropriate pixel format, you must..." > So the typical routine would > involve creating a dummy window, getting the function pointer, > destroying the dummy window, and then proceeding to set up the window > you really want to use. I didn't want Quesa to get into the > business of > creating and destroying windows. |
|
From: Jose' C. <cru...@ce...> - 2007-12-12 08:06:18
|
Il giorno 12/dic/07, alle ore 01:17, James Walker ha scritto: > > The extra complication is mostly due to Windows. On Windows, in order > to get an appropriate function pointer, you must first get a function > pointer to wglChoosePixelFormatARB, and in order to get that, you must > already have an OpenGL context set up. So the typical routine would > involve creating a dummy window, getting the function pointer, > destroying the dummy window, and then proceeding to set up the window > you really want to use. I didn't want Quesa to get into the =20 > business of > creating and destroying windows. can you please post a code snippet of this, (mostly for documentation =20= purposes) Pax et Bonum # Dott. Jos=E9 Cruanyes Aguilar - C.E. Soft srl # Pzza. Firenze,4 MILANO - XX Settembre 10, CREMONA # 02,3923101 0372,460602 |
|
From: James W. <ja...@fr...> - 2007-12-12 21:37:38
|
Jose' Cruanyes wrote:
> Il giorno 12/dic/07, alle ore 01:17, James Walker ha scritto:
>
>> The extra complication is mostly due to Windows. On Windows, in order
>> to get an appropriate function pointer, you must first get a function
>> pointer to wglChoosePixelFormatARB, and in order to get that, you must
>> already have an OpenGL context set up. So the typical routine would
>> involve creating a dummy window, getting the function pointer,
>> destroying the dummy window, and then proceeding to set up the window
>> you really want to use. I didn't want Quesa to get into the
>> business of
>> creating and destroying windows.
>
>
> can you please post a code snippet of this, (mostly for documentation
> purposes)
OK... I'm not an expert Windows programmer, so I might be doing more
work than necessary.
static const char* kWindowClassName = "dummy";
static HDC theDC = NULL;
static PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB
= NULL;
static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
static void RegisterWindowClass( HINSTANCE inInstance )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = (WNDPROC) DefWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = inInstance;
wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = kWindowClassName;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
}
void SetDummyGLContext()
{
static HGLRC glContext = NULL;
if (glContext == NULL)
{
HINSTANCE theInstance = GetModuleHandle( NULL );
RegisterWindowClass( theInstance );
HWND theWindow = CreateWindow( kWindowClassName, "XDummy",
WS_OVERLAPPEDWINDOW |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
400, 30, 40, 40,
NULL, NULL, theInstance, NULL );
theDC = GetDC((HWND) theWindow);
PIXELFORMATDESCRIPTOR pixelFormatDesc;
pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
pixelFormatDesc.nVersion = 1;
pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
pixelFormatDesc.cColorBits = 0;
pixelFormatDesc.cDepthBits = 24;
pixelFormatDesc.cStencilBits = 8;
pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
int pixelFormat = ChoosePixelFormat( theDC, &pixelFormatDesc );
if (pixelFormat != NULL)
{
if (SetPixelFormat( theDC, pixelFormat, &pixelFormatDesc))
{
glContext = wglCreateContext( theDC );
}
}
}
if (glContext != NULL)
{
wglMakeCurrent( theDC, glContext );
}
}
static bool HasMultisample()
{
std::string theExts(" ");
theExts += (const char*) glGetString( GL_EXTENSIONS );
theExts += ' ';
bool hasExt = theExts.find( " GL_ARB_multisample " ) != std::string::npos;
if (not hasExt)
{
// OpenGL 1.3 incorporates multisampling.
std::string theVers( (const char*) glGetString( GL_VERSION ) );
if ( (theVers[0] > '1') or (theVers[2] >= '3') )
{
hasExt = true;
}
}
return hasExt;
}
static bool IsMultisampleFormat( HDC inDC, int inPixelFormat )
{
bool isMulti = false;
int atts[2] = {
WGL_SAMPLE_BUFFERS_ARB,
WGL_SAMPLES_ARB
};
int values[2];
if (wglGetPixelFormatAttribivARB( inDC, inPixelFormat, 0, 2,
atts, values ))
{
isMulti = (values[0] > 0) and (values[1] > 0);
}
return isMulti;
}
static int ChoosePixelFormatARB( HDC hdc, const int *piAttribIList )
{
UINT numFormats = -1;
int theFormat = 0;
if (wglChoosePixelFormatARB( hdc, piAttribIList, NULL, 1, &theFormat,
&numFormats ))
{
if (numFormats == 0)
{
theFormat = 0;
//DebugMsg("No multisample formats available");
}
else
{
if (not IsMultisampleFormat( hdc, theFormat ))
{
theFormat = 0; // not sure if this can happen
}
}
}
else
{
DWORD err = GetLastError();
char xmsg[100];
std::sprintf( xmsg, "wglChoosePixelFormatARB failed with error %X.",
err );
DebugMsg(xmsg);
}
return theFormat;
}
static int ChooseWinMultisampleFormat()
{
int theFormat = 0;
SetDummyGLContext();
if (not HasMultisample())
{
return theFormat;
}
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
(PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB != NULL)
{
HDC theDC = GetDummyDC();
std::string extStr(" ");
extStr += (char*)wglGetExtensionsStringARB( theDC );
extStr += ' ';
if (extStr.find( " WGL_ARB_pixel_format " ) != std::string::npos)
{
wglChoosePixelFormatARB =
(PFNWGLCHOOSEPIXELFORMATARBPROC)
wglGetProcAddress( "wglChoosePixelFormatARB" );
wglGetPixelFormatAttribivARB =
(PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
int atts[] =
{
WGL_SAMPLES_ARB, 4, // keep this first!
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_SAMPLE_BUFFERS_ARB, 1,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, 0
};
theFormat = ChoosePixelFormatARB( theDC, atts );
if ( theFormat == 0 )
{
atts[1] = 2; // WGL_SAMPLES_ARB value
theFormat = ChoosePixelFormatARB( theDC, atts );
}
}
}
return theFormat;
}
--
James W. Walker, Innoventive Software LLC
<http://www.frameforge3d.com/>
|
|
From: James W. <ja...@fr...> - 2007-12-12 21:56:59
|
Jose' Cruanyes wrote:
> Il giorno 12/dic/07, alle ore 01:17, James Walker ha scritto:
>
>> The extra complication is mostly due to Windows. On Windows, in order
>> to get an appropriate function pointer, you must first get a function
>> pointer to wglChoosePixelFormatARB, and in order to get that, you must
>> already have an OpenGL context set up. So the typical routine would
>> involve creating a dummy window, getting the function pointer,
>> destroying the dummy window, and then proceeding to set up the window
>> you really want to use. I didn't want Quesa to get into the
>> business of
>> creating and destroying windows.
>
>
> can you please post a code snippet of this, (mostly for documentation
> purposes)
OK... I'm not an expert Windows programmer, so I might be doing more
work than necessary.
static const char* kWindowClassName = "dummy";
static HDC theDC = NULL;
static PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB
= NULL;
static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
static void RegisterWindowClass( HINSTANCE inInstance )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = (WNDPROC) DefWindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = inInstance;
wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = kWindowClassName;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
}
void SetDummyGLContext()
{
static HGLRC glContext = NULL;
if (glContext == NULL)
{
HINSTANCE theInstance = GetModuleHandle( NULL );
RegisterWindowClass( theInstance );
HWND theWindow = CreateWindow( kWindowClassName, "XDummy",
WS_OVERLAPPEDWINDOW |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
400, 30, 40, 40,
NULL, NULL, theInstance, NULL );
theDC = GetDC((HWND) theWindow);
PIXELFORMATDESCRIPTOR pixelFormatDesc;
pixelFormatDesc.nSize = sizeof(pixelFormatDesc);
pixelFormatDesc.nVersion = 1;
pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
pixelFormatDesc.cColorBits = 0;
pixelFormatDesc.cDepthBits = 24;
pixelFormatDesc.cStencilBits = 8;
pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
int pixelFormat = ChoosePixelFormat( theDC, &pixelFormatDesc );
if (pixelFormat != NULL)
{
if (SetPixelFormat( theDC, pixelFormat, &pixelFormatDesc))
{
glContext = wglCreateContext( theDC );
}
}
}
if (glContext != NULL)
{
wglMakeCurrent( theDC, glContext );
}
}
static bool HasMultisample()
{
std::string theExts(" ");
theExts += (const char*) glGetString( GL_EXTENSIONS );
theExts += ' ';
bool hasExt = theExts.find( " GL_ARB_multisample " ) != std::string::npos;
if (not hasExt)
{
// OpenGL 1.3 incorporates multisampling.
std::string theVers( (const char*) glGetString( GL_VERSION ) );
if ( (theVers[0] > '1') or (theVers[2] >= '3') )
{
hasExt = true;
}
}
return hasExt;
}
static bool IsMultisampleFormat( HDC inDC, int inPixelFormat )
{
bool isMulti = false;
int atts[2] = {
WGL_SAMPLE_BUFFERS_ARB,
WGL_SAMPLES_ARB
};
int values[2];
if (wglGetPixelFormatAttribivARB( inDC, inPixelFormat, 0, 2,
atts, values ))
{
isMulti = (values[0] > 0) and (values[1] > 0);
}
return isMulti;
}
static int ChoosePixelFormatARB( HDC hdc, const int *piAttribIList )
{
UINT numFormats = -1;
int theFormat = 0;
if (wglChoosePixelFormatARB( hdc, piAttribIList, NULL, 1, &theFormat,
&numFormats ))
{
if (numFormats == 0)
{
theFormat = 0;
//DebugMsg("No multisample formats available");
}
else
{
if (not IsMultisampleFormat( hdc, theFormat ))
{
theFormat = 0; // not sure if this can happen
}
}
}
else
{
DWORD err = GetLastError();
char xmsg[100];
std::sprintf( xmsg, "wglChoosePixelFormatARB failed with error %X.",
err );
DebugMsg(xmsg);
}
return theFormat;
}
static int ChooseWinMultisampleFormat()
{
int theFormat = 0;
SetDummyGLContext();
if (not HasMultisample())
{
return theFormat;
}
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
(PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB != NULL)
{
HDC theDC = GetDummyDC();
std::string extStr(" ");
extStr += (char*)wglGetExtensionsStringARB( theDC );
extStr += ' ';
if (extStr.find( " WGL_ARB_pixel_format " ) != std::string::npos)
{
wglChoosePixelFormatARB =
(PFNWGLCHOOSEPIXELFORMATARBPROC)
wglGetProcAddress( "wglChoosePixelFormatARB" );
wglGetPixelFormatAttribivARB =
(PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
int atts[] =
{
WGL_SAMPLES_ARB, 4, // keep this first!
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_SAMPLE_BUFFERS_ARB, 1,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, 0
};
theFormat = ChoosePixelFormatARB( theDC, atts );
if ( theFormat == 0 )
{
atts[1] = 2; // WGL_SAMPLES_ARB value
theFormat = ChoosePixelFormatARB( theDC, atts );
}
}
}
return theFormat;
}
--
James W. Walker, Innoventive Software LLC
<http://www.frameforge3d.com/>
|