0

I want to set up MSAA on an OpenGL context in win32 API. Everything is working fine, but the MSAA just doesn't want to activate. Here is my code for building the context:

void Display::CreateGLContext(HWND hWND) {
mHDC = GetDC(hWND);  //get current windows device context

int nPixelFormat;

PIXELFORMATDESCRIPTOR pfd; // Create a new PIXELFORMATDESCRIPTOR (PFD)  
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); // Clear our  PFD  
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Set the size of the PFD to the size of the class  
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; // Enable double buffering, opengl support and drawing to a window  
pfd.iPixelType = PFD_TYPE_RGBA; // Set our application to use RGBA pixels  
pfd.cColorBits = 32; // Give us 32 bits of color information (the higher, the more colors)  
pfd.cDepthBits = 16; // Give us 32 bits of depth information (the higher, the more depth levels)  
pfd.iLayerType = PFD_MAIN_PLANE; // Set the layer of the PFD

/*      Choose best matching format*/
nPixelFormat = ChoosePixelFormat(mHDC, &pfd);

/*      Set the pixel format to the device context*/
SetPixelFormat(mHDC, nPixelFormat, &pfd);

HGLRC tempRC = wglCreateContext(mHDC);
wglMakeCurrent(mHDC, tempRC);

if (glewInit() != GLEW_OK) {
    MessageBox(mHWND, "Eroare", "glew", MB_OK);
}
int nPixelFormat2;

BOOL bValidPixFormat;
UINT nMaxFormats = 1;
UINT nNumFormats;
float pfAttribFList[] = { 0, 0 };
int piAttribIList[] = { 
    WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
    WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
    WGL_COLOR_BITS_ARB, 32,
    WGL_RED_BITS_ARB, 8,
    WGL_GREEN_BITS_ARB, 8,
    WGL_BLUE_BITS_ARB, 8,
    WGL_ALPHA_BITS_ARB, 8,
    WGL_DEPTH_BITS_ARB, 16,
    WGL_STENCIL_BITS_ARB, 0,
    WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
    WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
    WGL_SAMPLES_ARB, 16,
    0, 0 };

bValidPixFormat = wglChoosePixelFormatARB(mHDC, piAttribIList, pfAttribFList, nMaxFormats, &nPixelFormat2, &nNumFormats);

if (!bValidPixFormat)
{
    MessageBox(NULL, "Invalid Pixel Format", "Error! (SetupWGLPixelFormat)", MB_OK);
}

SetPixelFormat(mHDC, nPixelFormat2, &pfd);


mGLRenderContext = wglCreateContext(mHDC);

wglMakeCurrent(mHDC, NULL);
wglDeleteContext(tempRC);
wglMakeCurrent(mHDC, mGLRenderContext);

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
}

The code works fine, it is called after creating hWnd in the main class, not in WndProc on the WM_CREATE case... What can be wrong?

dei.andrei98
  • 174
  • 1
  • 2
  • 11
  • Can you try a `glGetIntegerv(GL_SAMPLES, ...)` to double check that you actually got a multisampled framebuffer? Also, you could try a more commonly supported value like 4 for the number of samples. The value for `WGL_COLOR_BITS_ARB` should be 24 (it only counts the RGB bits), but that's probably not doing any harm. – Reto Koradi Jan 21 '16 at 05:02
  • It returns an integer with a value of 0. – dei.andrei98 Jan 21 '16 at 15:20
  • I'm sure I don't create the context ok... but I can't find an example for creating an context with wgl attributes. – dei.andrei98 Jan 21 '16 at 15:20
  • 2
    I know this is an old question but in Windows you can only set the pixelformat once. You have to delete the entire window and create it again after you get a valid nPixelFormat2. – Stefan Agartsson May 31 '18 at 14:01
  • 1
    You are right. You can't get a valid pixel format for multisampling without GLEW, and you can't get GLEW to initialize without having an active opengl context. So you need to firstly create a temporary window, initialize glew in its opengl context, get the pixelformat for multisample ( and other options, if you want them ) and then destroy this window and create another one with a new opengl context based on this pixel format. I know this is old but maybe someone will see this and fix the problems. – dei.andrei98 Jun 01 '18 at 20:13

2 Answers2

3

I see the part where you asked for 16 samples. But I don't see the part where you enabled GL_MULTISAMPLE. Without which, rendering to a multisampled buffer will act no differently from rendering to a single sampled one.

Also, I would advise you to use a framebuffer object for your multisample render target instead of the default framebuffer. Yes, it's nice that the default framebuffer can be resized by the window. But by using a framebuffer object, you can control when multisampling is resolved.

Also, it allows you to keep the driver's pesky control panel options from messing with your sample counts ;)

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks for answering so fast... I added glEnable(GL_MULTISAMPLE) after the last wglMakeCurrent and nothing changed... – dei.andrei98 Jan 20 '16 at 19:42
  • 1
    `GL_MULTISAMPLE` is enabled by default. So unless it was explicitly disabled earlier, calling `glEnable(GL_MULTISAMPLE)` is a no-op. – Reto Koradi Jan 21 '16 at 01:04
1

I have found the problem. Basically you can't call SetPixelFormat on the same window as this article mentions: https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation

The solution is basically to create a dummy window(not visible) enable opengl and delete it. I have copied the code from here and it worked for me Create Modern OpenGL context using WGL?

vlad alex
  • 26
  • 3
  • Yes, this is the answer that made it work years ago. I created a dummy window, as you said, and everything worked as expected. Thanks for this answer. It may save a lot of time for others having this problem. – dei.andrei98 Jun 09 '20 at 19:39