【问题标题】:Win32 opengl Window creationWin32 opengl 窗口创建
【发布时间】:2011-06-09 03:00:54
【问题描述】:

在 win32 中设置一个集成了 OpenGl(如果需要额外代码才能工作,还有 glsl)的窗口的最佳方法是什么?

我做了一些研究,发现了许多完成这项任务的方法,我想知道最好的方法是什么,或者如果最好的方法没有答案,你最喜欢哪种方法。

我查看了 nehe 的设计以及 OpenGL 超级圣经提供的设计,两者都有完全不同的实现方式(超级圣经也给我错误:()。

任何帮助将不胜感激,包括教程等。

谢谢

【问题讨论】:

    标签: winapi opengl window


    【解决方案1】:

    你所有的“不同方式”并没有那么不同。你必须:

    • 创建您的窗口(以通常的 Win32 方式,使用 RegisterClass(Ex)CreateWindow(Ex)
    • 创建与您的窗口相对应的 GDI 设备上下文 (GetDC)
    • 选择显示器支持的像素格式(可选DescribePixelFormat,然后ChoosePixelFormat
    • 创建您的 OpenGL 上下文 (wglCreateContext)
    • (可选,但需要使用 GLSL)链接 OpenGL 扩展函数(GLee 或 GLEW 助手,或glGetString(GL_EXTENSIONS) 然后wglGetProcAddress
    • (可选)创建 OpenGL 3.x 上下文,释放兼容性上下文 (wglCreateContextAttribs)
    • 激活上下文 (wglMakeCurrent)
    • 开始使用 OpenGL(设置着色器程序、加载纹理、绘制内容等)

    显示这些步骤的代码摘录(不适合复制+粘贴,使用了一堆 RAII 包装器):

    bool Context::attach( HWND hwnd )
    {
        PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1 };
        if (!m_dc) {
            scoped_window_hdc(hwnd).swap(m_dc);
    
            pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION | PFD_DOUBLEBUFFER;
            pfd.iPixelType = PFD_TYPE_RGBA;
            pfd.cColorBits = 32;
            pfd.cAlphaBits = 8;
            pfd.iLayerType = PFD_MAIN_PLANE;
            auto format_index = ::ChoosePixelFormat(m_dc.get(), &pfd);
            if (!format_index)
                return false;
    
            if (!::SetPixelFormat(m_dc.get(), format_index, &pfd))
                return false;
        }
    
        auto active_format_index = ::GetPixelFormat(m_dc.get());
        if (!active_format_index)
            return false;
    
        if (!::DescribePixelFormat(m_dc.get(), active_format_index, sizeof pfd, &pfd))
            return false;
    
        if ((pfd.dwFlags & PFD_SUPPORT_OPENGL) != PFD_SUPPORT_OPENGL)
            return false;
    
        m_render_thread = ::CreateThread(NULL, 0, &RenderThreadProc, this, 0, NULL);
        return m_render_thread != NULL;
    }
    
    DWORD WINAPI Context::RenderThreadProc( LPVOID param )
    {
        Context* const ctx = static_cast<Context*>(param);
        HDC dc = ctx->m_dc.get();
    
        SIZE canvas_size;
        ctx->m_dc.check_resize(&canvas_size);
    
        scoped_hglrc glrc(wglCreateContext(dc));
    
        if (!glrc)
            return EXIT_FAILURE;
    
        if (!glrc.make_current(dc))
            return EXIT_FAILURE;
    
        if (ctx->m_major_version > 2 && GLEE_WGL_ARB_create_context) {
            int const create_attribs[] = {
                WGL_CONTEXT_MAJOR_VERSION_ARB, ctx->m_major_version,
                WGL_CONTEXT_MINOR_VERSION_ARB, ctx->m_minor_version,
                0
            };
            scoped_hglrc advrc(wglCreateContextAttribsARB(dc, 0, create_attribs));
    
            if (advrc) {
                if (!advrc.make_current(dc))
                    return EXIT_FAILURE;
                advrc.swap(glrc);
            }
        }
    
        {
            const char* ver = reinterpret_cast<const char*>(glGetString(GL_VERSION));
            if (ver) {
                OutputDebugStringA("GL_VERSION = \"");
                OutputDebugStringA(ver);
                OutputDebugStringA("\"\n");
            }
        }
    
        glDisable(GL_DITHER);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        glClearColor(0.f, 0.f, 0.f, 1.f);
        if (GLEE_WGL_EXT_swap_control)
            wglSwapIntervalEXT(1);
    
        GLuint vao;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
    
        while (!::InterlockedExchange(&ctx->m_stop_render, 0)) {
            ctx->process_queued_tasks();
    
            if (ctx->m_dc.check_resize(&canvas_size)) {
                glViewport(0, 0, canvas_size.cx, canvas_size.cy);
                ctx->process_on_resize();
            }
            glClear(GL_COLOR_BUFFER_BIT);
    
            glBindVertexArray(vao);
    
            ctx->process_on_render();
    
            BOOL swapped = ::SwapBuffers(dc);
            if (!swapped)
                std::cout << "::SwapBuffers failure, GetLastError() returns " << std::hex << ::GetLastError() << std::endl;
        }
    
        ctx->m_program_db.clear();
    
        return EXIT_SUCCESS;
    }
    

    它也不包括窗口创建,它在现有窗口上启用 OpenGL。

    【讨论】:

    • 非常感谢您对基本设置的帮助,这是nehe.gamedev.net/data/lessons/lesson.asp?lesson=01 一个好的设置吗?然后我需要做的就是添加 3.x 和着色器支持?
    • 是的,就上下文创建而言,这很好。刚开始的时候,我从 NeHe 教程中学到了很多东西。
    • 太棒了:D 现在我将尝试添加额外的东西。
    • 如果你愿意,我可以展示一些来自个人项目的代码。它不是独立的,它使用 GLee 进行扩展访问,但它提供了上述步骤的具体示例。
    • 我有一个关于上述代码的小问题。::DescribePixelFormat 双冒号有什么作用?
    【解决方案2】:

    如果您真的非常想自己动手,您仍然可以看看 GLFW 是如何做到的。在其源目录中,您有一个特定于 win32 的目录,其中有一个特定于窗口的 .c 文件。你应该在这个文件中找到你需要的一切。

    OpenGL Wiki 的This page 也可以为您提供帮助。

    【讨论】:

      【解决方案3】:

      这对我来说差不多:http://nehe.gamedev.net/tutorial/creating_an_opengl_window_%28win32%29/13001/

      编辑:相关代码:

      /*
       *      This Code Was Created By Jeff Molofee 2000
       *      A HUGE Thanks To Fredric Echols For Cleaning Up
       *      And Optimizing This Code, Making It More Flexible!
       *      If You've Found This Code Useful, Please Let Me Know.
       *      Visit My Site At nehe.gamedev.net
       */
      
      #include <windows.h>        // Header File For Windows
      #include <gl\gl.h>          // Header File For The OpenGL32 Library
      #include <gl\glu.h>         // Header File For The GLu32 Library
      #include <gl\glaux.h>       // Header File For The Glaux Library
      
      HDC         hDC=NULL;       // Private GDI Device Context
      HGLRC       hRC=NULL;       // Permanent Rendering Context
      HWND        hWnd=NULL;      // Holds Our Window Handle
      HINSTANCE   hInstance;      // Holds The Instance Of The Application
      
      bool    keys[256];          // Array Used For The Keyboard Routine
      bool    active=TRUE;        // Window Active Flag Set To TRUE By Default
      bool    fullscreen=TRUE;    // Fullscreen Flag Set To Fullscreen Mode By Default
      
      LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // Declaration For WndProc
      
      GLvoid ReSizeGLScene(GLsizei width, GLsizei height)     // Resize And Initialize The GL Window
      {
          if (height==0)                                      // Prevent A Divide By Zero By
          {
              height=1;                                       // Making Height Equal One
          }
      
          glViewport(0,0,width,height);                       // Reset The Current Viewport
      
          glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
          glLoadIdentity();                                   // Reset The Projection Matrix
      
          // Calculate The Aspect Ratio Of The Window
          gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
      
          glMatrixMode(GL_MODELVIEW);                         // Select The Modelview Matrix
          glLoadIdentity();                                   // Reset The Modelview Matrix
      }
      
      int InitGL(GLvoid)                                      // All Setup For OpenGL Goes Here
      {
          glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
          glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
          glClearDepth(1.0f);                                 // Depth Buffer Setup
          glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
          glDepthFunc(GL_LEQUAL);                             // The Type Of Depth Testing To Do
          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations
          return TRUE;                                        // Initialization Went OK
      }
      
      int DrawGLScene(GLvoid)                                 // Here's Where We Do All The Drawing
      {
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
          glLoadIdentity();                                   // Reset The Current Modelview Matrix
          return TRUE;                                        // Everything Went OK
      }
      
      GLvoid KillGLWindow(GLvoid)                             // Properly Kill The Window
      {
          if (fullscreen)                                     // Are We In Fullscreen Mode?
          {
              ChangeDisplaySettings(NULL,0);                  // If So Switch Back To The Desktop
              ShowCursor(TRUE);                               // Show Mouse Pointer
          }
      
          if (hRC)                                            // Do We Have A Rendering Context?
          {
              if (!wglMakeCurrent(NULL,NULL))                 // Are We Able To Release The DC And RC Contexts?
              {
                  MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
              }
      
              if (!wglDeleteContext(hRC))                     // Are We Able To Delete The RC?
              {
                  MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
              }
              hRC=NULL;                                       // Set RC To NULL
          }
      
          if (hDC && !ReleaseDC(hWnd,hDC))                    // Are We Able To Release The DC
          {
              MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
              hDC=NULL;                                       // Set DC To NULL
          }
      
          if (hWnd && !DestroyWindow(hWnd))                   // Are We Able To Destroy The Window?
          {
              MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
              hWnd=NULL;                                      // Set hWnd To NULL
          }
      
          if (!UnregisterClass("OpenGL",hInstance))           // Are We Able To Unregister Class
          {
              MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
              hInstance=NULL;                                 // Set hInstance To NULL
          }
      }
      
      /*  This Code Creates Our OpenGL Window.  Parameters Are:                   *
       *  title           - Title To Appear At The Top Of The Window              *
       *  width           - Width Of The GL Window Or Fullscreen Mode             *
       *  height          - Height Of The GL Window Or Fullscreen Mode            *
       *  bits            - Number Of Bits To Use For Color (8/16/24/32)          *
       *  fullscreenflag  - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE)   */
      
      BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
      {
          GLuint      PixelFormat;            // Holds The Results After Searching For A Match
          WNDCLASS    wc;                     // Windows Class Structure
          DWORD       dwExStyle;              // Window Extended Style
          DWORD       dwStyle;                // Window Style
          RECT        WindowRect;             // Grabs Rectangle Upper Left / Lower Right Values
          WindowRect.left=(long)0;            // Set Left Value To 0
          WindowRect.right=(long)width;       // Set Right Value To Requested Width
          WindowRect.top=(long)0;             // Set Top Value To 0
          WindowRect.bottom=(long)height;     // Set Bottom Value To Requested Height
      
          fullscreen=fullscreenflag;          // Set The Global Fullscreen Flag
      
          hInstance           = GetModuleHandle(NULL);                // Grab An Instance For Our Window
          wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;   // Redraw On Size, And Own DC For Window.
          wc.lpfnWndProc      = (WNDPROC) WndProc;                    // WndProc Handles Messages
          wc.cbClsExtra       = 0;                                    // No Extra Window Data
          wc.cbWndExtra       = 0;                                    // No Extra Window Data
          wc.hInstance        = hInstance;                            // Set The Instance
          wc.hIcon            = LoadIcon(NULL, IDI_WINLOGO);          // Load The Default Icon
          wc.hCursor          = LoadCursor(NULL, IDC_ARROW);          // Load The Arrow Pointer
          wc.hbrBackground    = NULL;                                 // No Background Required For GL
          wc.lpszMenuName     = NULL;                                 // We Don't Want A Menu
          wc.lpszClassName    = "OpenGL";                             // Set The Class Name
      
          if (!RegisterClass(&wc))                                    // Attempt To Register The Window Class
          {
              MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                                           // Return FALSE
          }
      
          if (fullscreen)                                             // Attempt Fullscreen Mode?
          {
              DEVMODE dmScreenSettings;                               // Device Mode
              memset(&dmScreenSettings,0,sizeof(dmScreenSettings));   // Makes Sure Memory's Cleared
              dmScreenSettings.dmSize=sizeof(dmScreenSettings);       // Size Of The Devmode Structure
              dmScreenSettings.dmPelsWidth    = width;                // Selected Screen Width
              dmScreenSettings.dmPelsHeight   = height;               // Selected Screen Height
              dmScreenSettings.dmBitsPerPel   = bits;                 // Selected Bits Per Pixel
              dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
      
              // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
              if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
              {
                  // If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
                  if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
                  {
                      fullscreen=FALSE;       // Windowed Mode Selected.  Fullscreen = FALSE
                  }
                  else
                  {
                      // Pop Up A Message Box Letting User Know The Program Is Closing.
                      MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
                      return FALSE;                                   // Return FALSE
                  }
              }
          }
      
          if (fullscreen)                                             // Are We Still In Fullscreen Mode?
          {
              dwExStyle=WS_EX_APPWINDOW;                              // Window Extended Style
              dwStyle=WS_POPUP;                                       // Windows Style
              ShowCursor(FALSE);                                      // Hide Mouse Pointer
          }
          else
          {
              dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;           // Window Extended Style
              dwStyle=WS_OVERLAPPEDWINDOW;                            // Windows Style
          }
      
          AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);     // Adjust Window To True Requested Size
      
          // Create The Window
          if (!(hWnd=CreateWindowEx(  dwExStyle,                          // Extended Style For The Window
                                      "OpenGL",                           // Class Name
                                      title,                              // Window Title
                                      dwStyle |                           // Defined Window Style
                                      WS_CLIPSIBLINGS |                   // Required Window Style
                                      WS_CLIPCHILDREN,                    // Required Window Style
                                      0, 0,                               // Window Position
                                      WindowRect.right-WindowRect.left,   // Calculate Window Width
                                      WindowRect.bottom-WindowRect.top,   // Calculate Window Height
                                      NULL,                               // No Parent Window
                                      NULL,                               // No Menu
                                      hInstance,                          // Instance
                                      NULL)))                             // Dont Pass Anything To WM_CREATE
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          static  PIXELFORMATDESCRIPTOR pfd=              // pfd Tells Windows How We Want Things To Be
          {
              sizeof(PIXELFORMATDESCRIPTOR),              // Size Of This Pixel Format Descriptor
              1,                                          // Version Number
              PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
              PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
              PFD_DOUBLEBUFFER,                           // Must Support Double Buffering
              PFD_TYPE_RGBA,                              // Request An RGBA Format
              bits,                                       // Select Our Color Depth
              0, 0, 0, 0, 0, 0,                           // Color Bits Ignored
              0,                                          // No Alpha Buffer
              0,                                          // Shift Bit Ignored
              0,                                          // No Accumulation Buffer
              0, 0, 0, 0,                                 // Accumulation Bits Ignored
              16,                                         // 16Bit Z-Buffer (Depth Buffer)  
              0,                                          // No Stencil Buffer
              0,                                          // No Auxiliary Buffer
              PFD_MAIN_PLANE,                             // Main Drawing Layer
              0,                                          // Reserved
              0, 0, 0                                     // Layer Masks Ignored
          };
      
          if (!(hDC=GetDC(hWnd)))                         // Did We Get A Device Context?
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          if(!SetPixelFormat(hDC,PixelFormat,&pfd))       // Are We Able To Set The Pixel Format?
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          if (!(hRC=wglCreateContext(hDC)))               // Are We Able To Get A Rendering Context?
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          if(!wglMakeCurrent(hDC,hRC))                    // Try To Activate The Rendering Context
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          ShowWindow(hWnd,SW_SHOW);                       // Show The Window
          SetForegroundWindow(hWnd);                      // Slightly Higher Priority
          SetFocus(hWnd);                                 // Sets Keyboard Focus To The Window
          ReSizeGLScene(width, height);                   // Set Up Our Perspective GL Screen
      
          if (!InitGL())                                  // Initialize Our Newly Created GL Window
          {
              KillGLWindow();                             // Reset The Display
              MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
              return FALSE;                               // Return FALSE
          }
      
          return TRUE;                                    // Success
      }
      
      LRESULT CALLBACK WndProc(   HWND    hWnd,           // Handle For This Window
                                  UINT    uMsg,           // Message For This Window
                                  WPARAM  wParam,         // Additional Message Information
                                  LPARAM  lParam)         // Additional Message Information
      {
          switch (uMsg)                                   // Check For Windows Messages
          {
              case WM_ACTIVATE:                           // Watch For Window Activate Message
              {
                  if (!HIWORD(wParam))                    // Check Minimization State
                  {
                      active=TRUE;                        // Program Is Active
                  }
                  else
                  {
                      active=FALSE;                       // Program Is No Longer Active
                  }
      
                  return 0;                               // Return To The Message Loop
              }
      
              case WM_SYSCOMMAND:                         // Intercept System Commands
              {
                  switch (wParam)                         // Check System Calls
                  {
                      case SC_SCREENSAVE:                 // Screensaver Trying To Start?
                      case SC_MONITORPOWER:               // Monitor Trying To Enter Powersave?
                      return 0;                           // Prevent From Happening
                  }
                  break;                                  // Exit
              }
      
              case WM_CLOSE:                              // Did We Receive A Close Message?
              {
                  PostQuitMessage(0);                     // Send A Quit Message
                  return 0;                               // Jump Back
              }
      
              case WM_KEYDOWN:                            // Is A Key Being Held Down?
              {
                  keys[wParam] = TRUE;                    // If So, Mark It As TRUE
                  return 0;                               // Jump Back
              }
      
              case WM_KEYUP:                              // Has A Key Been Released?
              {
                  keys[wParam] = FALSE;                   // If So, Mark It As FALSE
                  return 0;                               // Jump Back
              }
      
              case WM_SIZE:                               // Resize The OpenGL Window
              {
                  ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
                  return 0;                               // Jump Back
              }
          }
      
          // Pass All Unhandled Messages To DefWindowProc
          return DefWindowProc(hWnd,uMsg,wParam,lParam);
      }
      
      int WINAPI WinMain( HINSTANCE   hInstance,          // Instance
                          HINSTANCE   hPrevInstance,      // Previous Instance
                          LPSTR       lpCmdLine,          // Command Line Parameters
                          int         nCmdShow)           // Window Show State
      {
          MSG     msg;                                    // Windows Message Structure
          BOOL    done=FALSE;                             // Bool Variable To Exit Loop
      
          // Ask The User Which Screen Mode They Prefer
          if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
          {
              fullscreen=FALSE;                           // Windowed Mode
          }
      
          // Create Our OpenGL Window
          if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
          {
              return 0;                                   // Quit If Window Was Not Created
          }
      
          while(!done)                                    // Loop That Runs While done=FALSE
          {
              if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))   // Is There A Message Waiting?
              {
                  if (msg.message==WM_QUIT)               // Have We Received A Quit Message?
                  {
                      done=TRUE;                          // If So done=TRUE
                  }
                  else                                    // If Not, Deal With Window Messages
                  {
                      TranslateMessage(&msg);             // Translate The Message
                      DispatchMessage(&msg);              // Dispatch The Message
                  }
              }
              else                                        // If There Are No Messages
              {
                  // Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
                  if (active)                             // Program Active?
                  {
                      if (keys[VK_ESCAPE])                // Was ESC Pressed?
                      {
                          done=TRUE;                      // ESC Signalled A Quit
                      }
                      else                                // Not Time To Quit, Update Screen
                      {
                          DrawGLScene();                  // Draw The Scene
                          SwapBuffers(hDC);               // Swap Buffers (Double Buffering)
                      }
                  }
      
                  if (keys[VK_F1])                        // Is F1 Being Pressed?
                  {
                      keys[VK_F1]=FALSE;                  // If So Make Key FALSE
                      KillGLWindow();                     // Kill Our Current Window
                      fullscreen=!fullscreen;             // Toggle Fullscreen / Windowed Mode
                      // Recreate Our OpenGL Window
                      if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
                      {
                          return 0;                       // Quit If Window Was Not Created
                      }
                  }
              }
          }
      
          // Shutdown
          KillGLWindow();                                 // Kill The Window
          return (msg.wParam);                            // Exit The Program
      }
      

      【讨论】:

        【解决方案4】:

        最好的方法是不要自己做。 OpenGL 上下文创建是一个无底洞的复杂性。您有很多工具可以为您完成繁琐的工作,更重要的是,它也可以在 Linux 和 Mac 上运行

        GLFW、FreeGlut、SDL、SFML 可能是最常见的。

        例如,请参阅GLFW's user guide,了解这些库使创建窗口变得多么容易:

        glfwInit();
        glfwOpenWindow( 300,300, 0,0,0,0,0,0, GLFW_WINDOW );
        // bam, you're done
        

        【讨论】:

        • 这个答案离题了...我特意问了如何使用win32 api而不是一些外部库来完成它。我知道外部库的功能,但我希望使用 win32 api。
        • 我正在尝试仅使用 opengl 和 c++ 从头开始​​创建游戏引擎,最好不要使用库...同时使用处理 Windows 创建的库会消除很多控制制作游戏需要。
        • 这或多或少是我的想法。我全心全意地支持您的“从头开始”的方法,我喜欢低级的东西,但老实说,这不值得痛苦。学习 OpenGL 的上下文创建是一个真正的痛苦,正确地做起来很复杂,最重要的是,你不会从中学到任何东西(有用的)。我认为我从头开始编写了一个游戏引擎,但是我使用 GLFW 并且对此没有道德问题。恕我直言,明智地利用你的时间并学习真正的 OpenGL。
        • 我正在使用 opengl superbible 来学习 opengl,在这方面我也在使用免费的 glut。但我也在创建一个游戏引擎,我会将超级圣经中的知识应用到但使用 win32 所以我有完全的控制权,而不是非常严格的过剩
        • 再说一遍:1) 你不会学到任何有趣的东西 2) 过剩限制性的,这就是我提出其他建议的原因。
        猜你喜欢
        • 1970-01-01
        • 2022-11-02
        • 2018-07-08
        • 2011-07-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多