c++ - OpenGL 4 核心配置文件、着色器和 MFC

标签 c++ opengl mfc

我正在尝试让着色器在具有 OpenGL 4 核心配置文件的 MFC 应用程序中工作。

我在 Win32 应用程序中执行此操作以确保其正常工作(确实如此,在窗口的下部绘制了一个三角形):

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   m_hDC = ::GetDC(hWnd);

   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 = 32;
   pfd.cDepthBits = 32;
   pfd.iLayerType = PFD_MAIN_PLANE;

   int nPixelFormat = ChoosePixelFormat(m_hDC, &pfd);

   if (nPixelFormat == 0) return false;

   BOOL bResult = SetPixelFormat(m_hDC, nPixelFormat, &pfd);

   if (!bResult) return false;

   HGLRC tempContext = wglCreateContext(m_hDC);
   wglMakeCurrent(m_hDC, tempContext);

   GLenum err = glewInit();
   if (GLEW_OK != err)
   {
       MessageBox(hWnd, (LPCWSTR)L"Glew not initialized", (LPCWSTR)L"Error", MB_ICONEXCLAMATION);
   }

   //Get a GL 4,2 context
   int attribs[] =
   {
       WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
       WGL_CONTEXT_MINOR_VERSION_ARB, 2,
       WGL_CONTEXT_FLAGS_ARB, 0,
       0
   };

   if (wglewIsSupported("WGL_ARB_create_context") == 1)
   {
       m_hRC = wglCreateContextAttribsARB(m_hDC, 0, attribs);
       wglMakeCurrent(NULL, NULL);
       wglDeleteContext(tempContext);
       wglMakeCurrent(m_hDC, m_hRC);
   }
   else
   {    //It's not possible to make a GL 4.x context. Use the old style context (GL 2.1 and before)
       m_hRC = tempContext;
   }


   if (!m_hRC) return false;

   static const char * vs_source[] =
   {
       "#version 420 core                                                 \n"
       "                                                                  \n"
       "void main(void)                                                   \n"
       "{                                                                 \n"
       "    const vec4 vertices[] = vec4[](vec4( 2.25, -2.25, 0.5, 1.0),  \n"
       "                                   vec4(-2.25, -2.25, 0.5, 1.0),  \n"
       "                                   vec4( 2.25,  2.25, 0.5, 1.0)); \n"
       "                                                                  \n"
       "    gl_Position = vertices[gl_VertexID];                          \n"
       "}                                                                 \n"
   };

   static const char * fs_source[] =
   {
       "#version 420 core                                                 \n"
       "                                                                  \n"
       "out vec4 color;                                                   \n"
       "                                                                  \n"
       "void main(void)                                                   \n"
       "{                                                                 \n"
       "    color = vec4(1.0, 0.8, 1.0, 1.0);                             \n"
       "}                                                                 \n"
   };

   program = glCreateProgram();
   GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
   glShaderSource(fs, 1, fs_source, NULL);
   glCompileShader(fs);

   GLuint vs = glCreateShader(GL_VERTEX_SHADER);
   glShaderSource(vs, 1, vs_source, NULL);
   glCompileShader(vs);

   glAttachShader(program, vs);
   glAttachShader(program, fs);

   glLinkProgram(program);

   glGenVertexArrays(1, &vao);
   glBindVertexArray(vao);

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

   return TRUE;
}


const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        //hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...

        glClearBufferfv(GL_COLOR, 0, green);

        glUseProgram(program);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        SwapBuffers(m_hDC);

        //EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

然后我在 MFC MDI 程序中做了同样的事情,虽然背景被清除为与 Win32 应用程序相同的颜色,但着色器没有绘制任何东西。

为了完成,这是我的 MFC MDI View 类中的相关代码(它与 Win32 应用程序中的代码不同,因为我一直试图找出问题所在,但它曾经与 Win32 应用程序代码相同并且它没有用):

int CMFCApplication2View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    m_hDC = ::GetDC(m_hWnd);

    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 = 32;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int nPixelFormat = ChoosePixelFormat(m_hDC, &pfd);

    if (nPixelFormat == 0) return false;

    BOOL bResult = SetPixelFormat(m_hDC, nPixelFormat, &pfd);

    if (!bResult) return false;

    HGLRC tempContext = wglCreateContext(m_hDC);
    wglMakeCurrent(m_hDC, tempContext);


    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        AfxMessageBox(_T("GLEW is not initialized!"));
    }

    //This is a modern pixel format attribute list.
    //It has an extensible structure. Just add in more argument pairs 
    //befroe the null to request more features.
    const int attribList[] =
    {
        WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
        WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
        WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
        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, 0  //End
    };


    unsigned int numFormats;
    int pixelFormat;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));

    //Select a pixel format number
    wglChoosePixelFormatARB(m_hDC, attribList, NULL, 1, &pixelFormat, &numFormats);

    //Optional: Get the pixel format's description. We must provide a 
    //description to SetPixelFormat(), but its contents mean little.
    //According to MSDN: 
    //  The system's metafile component uses this structure to record the logical
    //  pixel format specification. The structure has no other effect upon the
    //  behavior of the SetPixelFormat function.
    //DescribePixelFormat(m_pDC->GetSafeHdc(), pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);

    //Set it as the current 
    if (FALSE == SetPixelFormat(m_hDC, pixelFormat, &pfd))
    {

    }



    //Get a GL 4,4 context
    int attribs[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
        WGL_CONTEXT_MINOR_VERSION_ARB, 2,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
        0, 0  //End
    };

    if (wglewIsSupported("WGL_ARB_create_context") == 1)
    {
        m_hRC = wglCreateContextAttribsARB(m_hDC, 0, attribs);
        wglMakeCurrent(NULL, NULL);
        wglDeleteContext(tempContext);
        wglMakeCurrent(m_hDC, m_hRC);
    }
    else
    {   //It's not possible to make a GL 4.x context. Use the old style context (GL 2.1 and before)
        m_hRC = tempContext;
    }


    if (!m_hRC) return false;

    static const char * vs_source[] =
    {
        "#version 150 core                                                 \n"
        "                                                                  \n"
        "void main(void)                                                   \n"
        "{                                                                 \n"
        "    const vec4 vertices[] = vec4[](vec4( 2.25, -2.25, 0.5, 1.0),  \n"
        "                                   vec4(-2.25, -2.25, 0.5, 1.0),  \n"
        "                                   vec4( 2.25,  2.25, 0.5, 1.0)); \n"
        "                                                                  \n"
        "    gl_Position = vertices[gl_VertexID];                          \n"
        "}                                                                 \n"
    };

    static const char * fs_source[] =
    {
        "#version 150 core                                                 \n"
        "                                                                  \n"
        "out vec4 color;                                                   \n"
        "                                                                  \n"
        "void main(void)                                                   \n"
        "{                                                                 \n"
        "    color = vec4(1.0, 0.8, 1.0, 1.0);                             \n"
        "}                                                                 \n"
    };

    program = glCreateProgram();
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fs, 1, fs_source, NULL);
    glCompileShader(fs);

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vs, 1, vs_source, NULL);
    glCompileShader(vs);

    glAttachShader(program, vs);
    glAttachShader(program, fs);

    glLinkProgram(program);

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    wglMakeCurrent(NULL, NULL);

    return 0;
}



void CMFCApplication2View::OnDraw(CDC*/* pDC*/)
{
    CMFCApplication2Doc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: add draw code for native data here
    // Make the rendering context current
    wglMakeCurrent(m_hDC, m_hRC);

    // TODO: add draw code for native data here 
    static const GLfloat green[] = { 1.0f, 0.0f, 0.0f, 1.0f };
    glClearBufferfv(GL_COLOR, 0, green);

    glUseProgram(program);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    SwapBuffers(m_hDC);

    // Allow other rendering contexts to coexist
    wglMakeCurrent(NULL, NULL);

}

我通过 AMD 的 GPU Perfstudio 运行了这两个可执行文件。 Win32 框架调试显示一切正常。 MFC 帧调试显示帧缓冲区大小为 0(win32 应用程序的帧缓冲区大小为窗口大小)。两个应用程序 API 跟踪是相同的。

知道会发生什么吗?

最佳答案

显然,MFC 中的 OpenGL 在使用核心配置文件时需要通过 glViewport 设置视口(viewport)。

处理 WM_SIZE 并执行 glViewport(0, 0, (GLsizei)cx, (GLsizei)cy) 解决了这个问题。

请注意,Andon 说我不应该指定像素格式两次是正确的。它没有给出任何错误,这很奇怪,但是当我删除它时,一切都继续工作。

关于c++ - OpenGL 4 核心配置文件、着色器和 MFC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26949823/

相关文章:

c++ - 无故对 glEnd 进行无效操作?

c++ - 该程序运行但不正确;数字不对

opengl - 怎么做对应2D-3D点

c++ - Visual Studio下编译调试GLUT

visual-studio - 无法在动态链接库 msvcrt.dll 中找到过程入口点 _except_handler4_common

c++ - 三角化元组

Qt:如何检测正在使用的 OpenGL 版本?

c++ - 如何开发图像识别程序

c++ - SQL 查询返回 DB_E_NOTABLE

c++ - 有一个dll项目,我可以强制将它链接到一个静态库吗?