使用WGL_SAMPLE_BUFFERS_ARB / WGL_SAMPLES_ARB

时间:2016-01-26 07:41:51

标签: c++ opengl

我决定在我的应用程序中添加MSAA支持,因此我检查了要做什么。我发现的例子总是引用pixelformatdescriptor中的WGL_SAMPLE_BUFFERS_ARB / WGL_SAMPLES_ARB来做到这一点。我现在正在使用glew:

int DesiredColorBits   = 32;
int DesiredStencilBits = 0;
int DesiredDepthBits   = 24;
int MajorVersion=3;
int MinorVersion=3;

PIXELFORMATDESCRIPTOR temppfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        DesiredColorBits,
        0, 0, 0, 0, 0, 0,
        0, 0,
        0, 0, 0, 0, 0,
        DesiredDepthBits,
        0,//DesiredStencilBits,
        0,
        PFD_MAIN_PLANE,
        0,
        0, 0, 0
    };

HDC TemphDC;
TemphDC = GetDC( hWnd );
int nPixelFormat = ChoosePixelFormat( TemphDC, &temppfd );
check(nPixelFormat);
verify(SetPixelFormat( TemphDC, nPixelFormat, &temppfd ));

// oldstyle context to init glew.
HGLRC tempContext = wglCreateContext(TemphDC);
wglMakeCurrent(TemphDC, tempContext);

//init glew
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
    errorprintf(TEXT("Error: Init glew failed: %s"), glewGetErrorString(err)));
else debugprintf( TEXT("Glew successfully initialized."));

ReleaseDC(hWnd, TemphDC);

//Now init pure OpenGL >= 3.3 context.
if (WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(tempContext);
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = DesiredColorBits;
    pfd.cDepthBits = DesiredDepthBits;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int iPixelFormatAttribList[30];
    iPixelFormatAttribList[0] = WGL_DRAW_TO_WINDOW_ARB;
    iPixelFormatAttribList[1] = GL_TRUE;
    iPixelFormatAttribList[2] = WGL_SUPPORT_OPENGL_ARB;
    iPixelFormatAttribList[3] = GL_TRUE;
    iPixelFormatAttribList[4] = WGL_DOUBLE_BUFFER_ARB;
    iPixelFormatAttribList[5] = GL_TRUE;
    iPixelFormatAttribList[6] = WGL_PIXEL_TYPE_ARB;
    iPixelFormatAttribList[7] = WGL_TYPE_RGBA_ARB;
    iPixelFormatAttribList[8] = WGL_COLOR_BITS_ARB;
    iPixelFormatAttribList[9] = DesiredColorBits;
    iPixelFormatAttribList[10] = WGL_DEPTH_BITS_ARB;
    iPixelFormatAttribList[11] = DesiredDepthBits;
    iPixelFormatAttribList[12] = WGL_STENCIL_BITS_ARB;
    iPixelFormatAttribList[13] = 0;
    iPixelFormatAttribList[14] = WGL_SAMPLE_BUFFERS_ARB;
    iPixelFormatAttribList[15] = GL_TRUE;
    iPixelFormatAttribList[16] = WGL_SAMPLES_ARB;
    iPixelFormatAttribList[17] = NumAASamples;
    iPixelFormatAttribList[18] = 0;

    int iPixelFormat, iNumFormats;
    wglChoosePixelFormatARB(hDC, iPixelFormatAttribList, NULL, 1, &iPixelFormat, (GLuint*)&iNumFormats);

    if( iNumFormats == 0 )
    {
        debugprintf(TEXT("Couldn't support multisampling"));
    }
    else debugprintf(TEXT("Available formats: %i %i"),iNumFormats,iPixelFormat);

    int iContextAttribs[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB, MajorVersion,
        WGL_CONTEXT_MINOR_VERSION_ARB, MinorVersion,
        WGL_CONTEXT_FLAGS_ARB, ContextFlags,
        0 // End of attributes list
    };

    // pfd oldstyle crap...
    debugprintf(TEXT("DesiredColorBits: %i"), DesiredColorBits);
    debugprintf(TEXT("DesiredDepthBits: %i"), DesiredDepthBits);

    if (!SetPixelFormat(hDC, iPixelFormat, &pfd))
    {
        debugprintf(TEXT("Setting PixelFormat %i failed!"), iPixelFormat);
        iPixelFormat = ChoosePixelFormat(hDC, &pfd); 
        if (!SetPixelFormat(hDC, iPixelFormat, &pfd))
            errorprintf(TEXT("Error: SetPixelFormat %i failed."),iPixelFormat);
    }

    hRC = wglCreateContextAttribsARB(hDC, 0, iContextAttribs);
}
else  errorprintf(TEXT("Error: Init glew failed: %s"), glewGetErrorString(err)));

if(hRC)
{
    MakeCurrent();

    debugprintf( TEXT("GL_VENDOR     : %s"), glGetString(GL_VENDOR));
    debugprintf( TEXT("GL_RENDERER   : %s"), glGetString(GL_RENDERER));
    debugprintf( TEXT("GL_VERSION    : %s"), glGetString(GL_VERSION));
    debugprintf( TEXT("GLEW Version  : %s"), glewGetString(GLEW_VERSION));

    int NumberOfAASamples=0, NumberOfSampleBufers;
    glGetintegerv(GL_SAMPLE_BUFFERS,&NumberOfSampleBufers);
    glGetintegerv(GL_SAMPLES,&NumberOfAASamples);
    debugprintf(TEXT("SampleBuffers: %i, NumAASamples: (%i/%i)"),NumberOfSampleBufers, NumberOfAASamples,NumAASamples);

    int NumberOfExtensions=0;
    glGetintegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions);
    for (int i = 0; i<NumberOfExtensions; i++)
    {
        FString ExtensionString = glGetStringi(GL_EXTENSIONS, i));
        debugprintf(NAME_DevLoad, TEXT("GL_EXTENSIONS(%i) : %s"), i, ExtensionString);
    }
    debugprintf( TEXT("OpenGL %i.%i context initialized!"), MajorVersion,MinorVersion);
}

到目前为止,非常好,我得到了我的tempcontext到init glew,它正确初始化并准备好使用,也没有SetPixelFormat的问题 - 至少没有样本缓冲区。 现在,如果我要添加WGL_SAMPLE_BUFFERS_ARB和WGL_SAMPLES_ARB,我仍然会从wglChoosePixelFormatARB返回一个像素格式(实际上iNumFormats返回32),但SetPixelFormat总是失败并返回从其返回的pixelformat。 我尝试了各种颜色和深度,但无论我做什么,我似乎无法找到一种方法来完成这项工作。我也在我的NVidia和Intel卡上试过这个,没有强制AA预设。

现在 - 有不同的方法来获得这个结果吗?我认为SetPixelformat是&#34;不推荐使用#34;,部分甚至已经过时了,但我似乎需要它来启用MSAA,这是一种有点烦人的依赖。 我错过了什么吗?

1 个答案:

答案 0 :(得分:0)

我通过更改一件事解决了这个问题,我为glew init创建了一个完全独立的窗口,如下所示:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uiMsg)
    {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hWnd, uiMsg, wParam, lParam);
    }

    return 0;
}
PIXELFORMATDESCRIPTOR temppfd =
{
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    DesiredColorBits,
    0, 0, 0, 0, 0, 0,
    0, 0,
    0, 0, 0, 0, 0,
    DesiredDepthBits,
    0,//DesiredStencilBits,
    0,
    PFD_MAIN_PLANE,
    0,
    0, 0, 0
};
DWORD Style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
WNDCLASSEX WndClassEx;
memset(&WndClassEx, 0, sizeof(WNDCLASSEX));

WndClassEx.cbSize = sizeof(WNDCLASSEX);
WndClassEx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClassEx.lpfnWndProc = WndProc;
WndClassEx.hInstance = hInstance;
WndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClassEx.lpszClassName = L"Win32OpenGLWindow";

if(RegisterClassEx(&WndClassEx) == 0)
{
    debugprintf(TEXT("RegisterClassEx failed!"));
}
HWND TemphWnd = CreateWindowEx(WS_EX_APPWINDOW, WndClassEx.lpszClassName,  L"InitWIndow", Style, 0, 0, SizeX, SizeY, NULL, NULL, hInstance, NULL);
HDC TemphDC = GetDC( TemphWnd );
INT nPixelFormat = ChoosePixelFormat( TemphDC, &temppfd );
check(nPixelFormat);
verify(SetPixelFormat( TemphDC, nPixelFormat, &temppfd ));

// oldstyle context to init glew.
HGLRC tempContext = wglCreateContext(TemphDC);
wglMakeCurrent(TemphDC, tempContext);

//init glew
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
    errorprintf(TEXT("Error: Init glew failed: %s"),glewGetErrorString(err));
else debugprintf(TEXT("Glew successfully initialized."));

//Now init pure OpenGL >= 3.3 context.
if (WGLEW_ARB_create_context && WGLEW_ARB_pixel_format)
{
    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(tempContext);
    ReleaseDC(TemphWnd, TemphDC);
    DestroyWindow(TemphWnd);
...

在销毁此临时窗口然后使用上面显示的实际游戏窗口后,可以使用带有新选项的SetPixelFormat。为什么在没有添加WGL_SAMPLE_BUFFERS_ARB / WGL_SAMPLES_ARB时没有造成这样的麻烦我不知道,我认为之后不可能真正改变窗口的pixelformat,与任何hWnd,hDC或上下文无关,如果那些在两者之间被摧毁或更新。网络上的许多示例和教程都不清楚,并且也显示出错误的方式。 简而言之,创建一个tempwindow,temphWnd和temphDC,然后初始化glew,销毁所有临时内容,然后继续用真实窗口,hWnd和hDC创建你真正想要的上下文,否则你会买点麻烦。

是的,我认为在Windows中获取干净的上下文真是一团糟。

无论哪种方式,我希望这会有所帮助。