簡體   English   中英

OpenGL 在 Windows 中創建上下文

[英]OpenGL context creation in Windows

這是我的代碼。 我不想要一個用於設備上下文/rc 創建的庫。

什么都不會畫。 也許我設置了 DC 或 RC 錯誤?

我正在嘗試從頭開始制作游戲引擎。

#pragma once
#include <cstdlib>
#include <windows.h>
#include <GL/GL.h>

#pragma comment (lib, "opengl32.lib")

#include <iostream>

using namespace std;



class shadoeGE
{
public:

    HWND s_Window = NULL;


    int __cdecl Init(const char*, int, int);

private:

};




LRESULT __stdcall s_WindowEvent(HWND hWnd, unsigned int message, unsigned int wParam, long lParam)
{
    switch (message)
    {
    default:

        return DefWindowProc(hWnd, message, wParam, lParam);
    };
};


int shadoeGE::Init(const char* title, int x, int y)
{
    MSG msg = { 0 };
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = s_WindowEvent;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = "sWindowClass";
    wc.style = CS_OWNDC;

    if (!RegisterClass(&wc))
    {
        return 0;
    };

    this->s_Window = CreateWindowA(wc.lpszClassName, title, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, x, y, 0, 0, GetModuleHandle(NULL), 0);

    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        DispatchMessage(&msg);
    }; 

    PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,  
        PFD_TYPE_RGBA,       
        32,                   
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        24,                   
        8,                   
        0,                   
        PFD_MAIN_PLANE,
        0,
        0, 0, 0
    };

    HDC deviceContextHandle = GetDC(this->s_Window);

    int windowsChosen = ChoosePixelFormat(deviceContextHandle, &pfd);
    SetPixelFormat(deviceContextHandle, windowsChosen, &pfd);

    HGLRC ourOpenGLRenderingContext = wglCreateContext(deviceContextHandle);
    wglMakeCurrent(deviceContextHandle, ourOpenGLRenderingContext);

    glViewport(0, 0, 640, 480);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBegin(GL_TRIANGLES);

    glColor3f(0.1, 0.2, 0.3);
    glVertex3f(0, 0, 0);
    glVertex3f(1, 0, 0);
    glVertex3f(0, 1, 0);

    glEnd();

    SwapBuffers(deviceContextHandle);


    return 1;
};

你必須實現一個消息循環:

MSG msg;
while( ::GetMessage( &msg, 0, 0, 0 ) )
  ::DispatchMessage( &msg );

當發送WM_PAINT消息時,您必須在消息循環中繪制場景:

LRESULT CALLBACK shadoeGE::s_WindowEvent( HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam )
{
  switch(msg)
  {
    // [...]

    case WM_PAINT: 
      wnd.Display();
      break;
  }
  return DefWindowProc( hWnd, msg, wparam, lparam );
}
void shadoeGE::Display( void )
{
  RECT clientRect;
  ::GetClientRect( hOGLWnd, &clientRect );

  glViewport( 0, 0, clientRect.right-clientRect.left, clientRect.bottom-clientRect.top );
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    

  // [...]

  HDC hDC = ::GetDC( hOGLWnd );
  ::SwapBuffers( hDC );
  ::ReleaseDC( hOGLWnd, hDC );
}

請參閱示例:

#include <windows.h>
#include <GL/gl.h>
#include <vector>
#include <stdexcept>

class shadoeGE
{
public:

  static LRESULT CALLBACK s_WindowEvent( HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam );
  HWND Init( int width, int height );
  void DestroyWindow( void );
  void MessageLoop( void );
  void Display( void );

private:

  HWND hOGLWnd = NULL;
  HGLRC hOGLRenderContext = NULL;
};

std::wstring wnd_class( L"my_wnd_class" );
shadoeGE wnd;

int main()
{
    int w = 800;
    int h = 600;

    HWND hWnd = wnd.Init( w, h );
    if ( hWnd == 0 )
        throw std::runtime_error( "error initializing window" ); 

    wnd.MessageLoop();    
    wnd.DestroyWindow();
    return 0;
}

HWND shadoeGE::Init( int width, int height )
{
  // Get module handle
  HMODULE hModule = ::GetModuleHandle( 0 );
  if (!hModule)
      return NULL;

  // Create window class
  WNDCLASSEX wndClassData;
  memset( &wndClassData, 0, sizeof( WNDCLASSEX ) );
  wndClassData.cbSize         = sizeof( WNDCLASSEX );
  wndClassData.style          = CS_DBLCLKS;
  wndClassData.lpfnWndProc    = s_WindowEvent;
  wndClassData.cbClsExtra     = 0;
  wndClassData.cbWndExtra     = 0;
  wndClassData.hInstance      = hModule;
  wndClassData.hIcon          = ::LoadIcon(0,IDI_APPLICATION);
  wndClassData.hCursor        = ::LoadCursor(0,IDC_ARROW);
  wndClassData.hbrBackground  = ::CreateSolidBrush(COLOR_WINDOW+1);
  wndClassData.lpszMenuName   = 0;
  wndClassData.lpszClassName  = wnd_class.c_str();
  wndClassData.hIconSm        = 0;
  if ( !::RegisterClassEx( &wndClassData ) )
      return false;

  // Creaate Window
  hOGLWnd = ::CreateWindow( wnd_class.c_str(), NULL, WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, hModule, NULL);
  if ( hOGLWnd == NULL )
      return NULL;

  // Get device context
  HDC hDC = ::GetDC( hOGLWnd );

  // Create OpenGL context
  DWORD pixelFormatFlags = PFD_SUPPORT_OPENGL | PFD_SUPPORT_COMPOSITION | PFD_GENERIC_ACCELERATED | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
  PIXELFORMATDESCRIPTOR pfd =
  {
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    pixelFormatFlags,         //Flags
    PFD_TYPE_RGBA,            //The kind of framebuffer. RGBA or palette.
    32,                       //Colordepth of the framebuffer.
    0, 0, 0, 0, 0, 0,
    0,
    0,
    0,
    0, 0, 0, 0,
    24,                        //Number of bits for the depthbuffer
    8,                        //Number of bits for the stencilbuffer
    0,                        //Number of Aux buffers in the framebuffer.
    PFD_MAIN_PLANE,
    0,
    0, 0, 0
  };
  int pixelFormat = ::ChoosePixelFormat( hDC, &pfd ); 
  ::SetPixelFormat( hDC, pixelFormat, &pfd );
  hOGLRenderContext = ::wglCreateContext( hDC );

  // make OpenGL context the current context
  ::wglMakeCurrent( hDC, hOGLRenderContext );

  // release device context
  ::ReleaseDC( hOGLWnd, hDC );

  // show the window
  ::ShowWindow( hOGLWnd, SW_SHOWDEFAULT );
  return hOGLWnd;
}

void shadoeGE::MessageLoop( void )
{
  MSG msg;
  while( ::GetMessage( &msg, 0, 0, 0 ) )
    ::DispatchMessage( &msg );
}

void shadoeGE::DestroyWindow(void)
{
  ::DestroyWindow( hOGLWnd );
  ::wglMakeCurrent( NULL, NULL );
  ::wglDeleteContext( hOGLRenderContext );

  HMODULE hModule = ::GetModuleHandle( 0 );
  if (!hModule)
    return;
  ::UnregisterClass( wnd_class.c_str(), hModule );
}

LRESULT CALLBACK shadoeGE::s_WindowEvent( HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam )
{
  switch(msg)
  {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;

    case WM_PAINT: 
      wnd.Display();
      break;
  }
  return DefWindowProc( hWnd, msg, wparam, lparam );
}

void shadoeGE::Display( void )
{
  RECT clientRect;
  ::GetClientRect( hOGLWnd, &clientRect );

  glViewport( 0, 0, clientRect.right-clientRect.left, clientRect.bottom-clientRect.top );
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    

  glBegin(GL_TRIANGLES);

  glColor3f(0.1, 0.2, 0.3);
  glVertex3f(0, 0, 0);
  glVertex3f(1, 0, 0);
  glVertex3f(0, 1, 0);

  glEnd();

  HDC hDC = ::GetDC( hOGLWnd );
  ::SwapBuffers( hDC );
  ::ReleaseDC( hOGLWnd, hDC );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM