상세 컨텐츠

본문 제목

OpenGL 을 window DC 에 따로 렌더링 하기 다른부분에 랜더링 관련

프로그래밍 관련/3D,2D DRAW 관련

by AlrepondTech 2017. 6. 20. 03:59

본문

반응형

 

 

 

=================================

=================================

=================================

 

 

 

 

OpenGL을 쓰고 항시 API를 쓰고 다시 해제해주어야 하는 API들은 해제 해주는것을 잊지 마세요 

예로들어 wglMakeCurrent(...)로 들자면 

 

HDC   hdc    = getHDC();

HGLRC hglrc = getHGLRCRES_GL();

 

::wglMakeCurrent(hdc, hglrc); //사용

 
//-----------------------------------------------
//{랜더링 코드들
 
..................................................................
 
//}
//----------------------------------------------
 
::wglMakeCurrent(NULL, NULL);  //::wglMakeCurrent(hdc, NULL);  //해제

 

 

위와같이 wglMakeCurrent(...) 랜더링 부분에 Api 사용과 해제 부분을 제대로 하지 않으면 다른 

위치의 wglMakeCurrent(...) 를 사용시 문제가 생길수 있습니다.

 

 

 

 

=================================

=================================

=================================

 

 

 

OpenGL화면을 windows에서 메모리 DC에 그릴수는 없는건가요??

 
ko1205의 이미지

OpenGL화면을 windows에서 메모리 DC에 그릴수는 없는건가요??

OpenGL로 간단한 화면을 뿌리는데.. 회면위에 text를 올려야 해서 그냥 TextOut으로 올려보니 Text가 심하게 껌벅거려서 단순한 생각으로 OpenGL을 메모리DC에 그리고
테스트를 출력후에 화면 복사를 할려고 해봤더니...

메모리 DC에는 OpenGL 출력이 되질 않습니다...

여기저기 검색해보니 옛날 글중에 원래 않된다는 말이있는것 같은데...

원래 않되는것이 맞는건가요??? 아니면 OpenGL 화면을 메모리DC에 출력하기 위해서는 다른 처리 방식이 있는건가요???

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 


프로젝트 생성 - MultiMedia - OpenGL 생성하면. 바로 만들어 줍니다. ㅇ_ㅇ;;

 

/**************************  * Includes  *  **************************/   #include <windows.h> #include <gl/gl.h>     /**************************  * Function Declarations  *  **************************/   LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC); void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC);     /**************************  * WinMain  *  **************************/   int WINAPI WinMain (HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR lpCmdLine,                     int iCmdShow) {     WNDCLASS wc;     HWND hWnd;     HDC hDC;     HGLRC hRC;             MSG msg;     BOOL bQuit = FALSE;     float theta = 0.0f;       /* register window class */     wc.style = CS_OWNDC;     wc.lpfnWndProc = WndProc;     wc.cbClsExtra = 0;     wc.cbWndExtra = 0;     wc.hInstance = hInstance;     wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);     wc.hCursor = LoadCursor (NULL, IDC_ARROW);     wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);     wc.lpszMenuName = NULL;     wc.lpszClassName = "GLSample";     RegisterClass (&wc);       /* create main window */     hWnd = CreateWindow (       "GLSample", "OpenGL Sample",        WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,       0, 0, 256, 256,       NULL, NULL, hInstance, NULL);       /* enable OpenGL for the window */     EnableOpenGL (hWnd, &hDC, &hRC);       /* program main loop */     while (!bQuit)     {         /* check for messages */         if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))         {             /* handle or dispatch messages */             if (msg.message == WM_QUIT)             {                 bQuit = TRUE;             }             else             {                 TranslateMessage (&msg);                 DispatchMessage (&msg);             }         }         else         {             /* OpenGL animation code goes here */               glClearColor (0.0f, 0.0f, 0.0f, 0.0f);             glClear (GL_COLOR_BUFFER_BIT);               glPushMatrix ();             glRotatef (theta, 0.0f, 0.0f, 1.0f);             glBegin (GL_TRIANGLES);             glColor3f (1.0f, 0.0f, 0.0f);   glVertex2f (0.0f, 1.0f);             glColor3f (0.0f, 1.0f, 0.0f);   glVertex2f (0.87f, -0.5f);             glColor3f (0.0f, 0.0f, 1.0f);   glVertex2f (-0.87f, -0.5f);             glEnd ();             glPopMatrix ();               SwapBuffers (hDC);               theta += 1.0f;             Sleep (1);         }     }       /* shutdown OpenGL */     DisableOpenGL (hWnd, hDC, hRC);       /* destroy the window explicitly */     DestroyWindow (hWnd);       return msg.wParam; }     /********************  * Window Procedure  *  ********************/   LRESULT CALLBACK WndProc (HWND hWnd, UINT message,                           WPARAM wParam, LPARAM lParam) {       switch (message)     {     case WM_CREATE:         return 0;     case WM_CLOSE:         PostQuitMessage (0);         return 0;       case WM_DESTROY:         return 0;       case WM_KEYDOWN:         switch (wParam)         {         case VK_ESCAPE:             PostQuitMessage(0);             return 0;         }         return 0;       default:         return DefWindowProc (hWnd, message, wParam, lParam);     } }     /*******************  * Enable OpenGL  *  *******************/   void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC) {     PIXELFORMATDESCRIPTOR pfd;     int iFormat;       /* get the device context (DC) */     *hDC = GetDC (hWnd);       /* set the pixel format for the DC */     ZeroMemory (&pfd, sizeof (pfd));     pfd.nSize = sizeof (pfd);     pfd.nVersion = 1;     pfd.dwFlags = PFD_DRAW_TO_WINDOW |        PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;     pfd.iPixelType = PFD_TYPE_RGBA;     pfd.cColorBits = 24;     pfd.cDepthBits = 16;     pfd.iLayerType = PFD_MAIN_PLANE;     iFormat = ChoosePixelFormat (*hDC, &pfd);     SetPixelFormat (*hDC, iFormat, &pfd);       /* create and enable the render context (RC) */     *hRC = wglCreateContext( *hDC );     wglMakeCurrent( *hDC, *hRC );   }     /******************  * Disable OpenGL  *  ******************/   void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC) {     wglMakeCurrent (NULL, NULL);     wglDeleteContext (hRC);     ReleaseDC (hWnd, hDC); }

젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

답변 감사합니다.. 근댕 위 코드는.....
메모리 DC에 OpenGL을 출력 하는코드가 아니라 .. 그냥 윈도우 DC에 출력 하는 코드 아닌가요???

지금도 그냥 윈도우 DC에 출력 하는 방법으로는 OpenGL 자체를 그려서 출력하는것에는 문제가 없는데... 혹시 메모리DC에 출력을 할 수 있을까 하는겁니다.. ㅜ.ㅜ

메모리 DC에 출력을 해보면 그냥 에러는 나지 않는대 그림이 없습니다.... ㅠ.ㅠ 누구 아시는분 않계신가요...

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

이유를 찾았습니다.... ㅠ.ㅠ

질문에 스스로 답하네요..

pfd.dwFlags 지정할때 = PFD_DRAW_TO_BITMAP 을 줘야하는군요..

그런대 여기서 다시 질문드리면 누가 답해주실 까요... ㅠ.ㅠ

찾다 보니.. 윈도우에 바로 그리지 않을 경우에는 하드웨어가속으로 그려지지 않고 CPU에 의해서 그려진다고 하는 말이 있던대...

확실한건가요????

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

pfd.dwFlags 지정할때 = PFD_DRAW_TO_BITMAP 을 추가해주셨다고 하셨자나요..

혹시 pfd 설정한 내용좀 알 수 있을까요....

 

 

 

 

반응형

 

728x90

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://rageworx.tistory.com/400

 

 

뮬레이터 라던가 , 이런 저런 이유로 OpenGL 을 활성화 된 window DC 에 그리지 않고 , 별도의 다른 컴퍼넌트와 함께 사용하거나 , OpenGL 로 렌더링 된 결과물을 가져와서 다른 가공 처리를 하고 싶을때가 간혹 많습니다.
 
그럴려면 OpenGL 렌더링을 Window DC 에 바로 하지 않고 처리를 해야 하는데 .. 이런 처리는 정말 찾기가 어렵죠.
 
그래서 온갖 방법을 다 동원 하다가 다음과 같이 방법을 찾았습니다.
 
이 방법은 현재 DEV-C++ 에서만 사용해 보았습니다만 , 응용 한다면 Delphi 에서도 사용이 가능해 보입니다.
실제 바로 사용으로는 delphi 에서 DC 에 바로 그리질 못하더군요 (아마 VCL 때문에 다른 차이점이 있어 보입니다.)
 
다음은 코드 입니다.
간단히 windows 를 생성 한 다음 바로 이 함수를 window Handle 로 넘겨 주게 되면 전역변수로 선언 해 둔 hdcOpenGL 에 OpenGL 렌더링 물이 그려지게 됩니다.
 
 
HDC     hdcOpenGL;
HGLRC   hrcOpenGL;
HBITMAP hbmOpenGL;
 
void InitOpenGLContext(HWND hWnd, int nWidth, int nHeight)
{
    HDC hdcWin = GetDC(hWnd);
    hdcOpenGL  = CreateCompatibleDC(hdcWin);
    hbmOpenGL  = CreateCompatibleBitmap(hdcWin, nWidth, nHeight);
    SelectObject(hdcOpenGL, hbmOpenGL);
    ReleaseDC(hWnd, hdcWin);
    
    BITMAP bmInfo;
    GetObject(hbmOpenGL, sizeof(BITMAP), &bmInfo);
 
    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize      = sizeof(pfd);
    pfd.nVersion   = 1;
    pfd.dwFlags    = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = (BYTE)bmInfo.bmBitsPixel;
    pfd.cDepthBits = 8;
    pfd.iLayerType = PFD_MAIN_PLANE;
    int nFormat    = ChoosePixelFormat(hdcOpenGL, &pfd);
    SetPixelFormat(hdcOpenGL, nFormat, &pfd);
    
    hrcOpenGL = wglCreateContext(hdcOpenGL);
    wglMakeCurrent(hdcOpenGL, hrcOpenGL);
}
 
 
여기서 중요한 것은 PIXELFORMATDESCTIPTOR 에 적용되는 cColorBits 입니다.
이 cColorBits 가 BITMAP 으로 가져온 정보의 bmBitsPixel 로 사용하지 않으면 wglMakeCurrent() 에서 그리기 버퍼용 DC 를 openGL 용으로 만들수 없게 된다는 점 입니다. (FALSE 가 return 됩니다)
 
또한 DC 에 그리므로 dwFlags 에 PFD_DOUBLEBUFFER 를 선언 할 필요는 없습니다.
 
이렇게 한 다음 OpenGL API 를 이용하여 렌더링을 한다음 반드시 glFlush(); 를 호출해 주시기 바랍니다.
하드웨어 가속으로 그릴때와 달리 버퍼에 그리는 작업은 CPU 가 하기 때문에 glFlush() 를 하지 않고 DC 를 swap 하게 되면 다 그려지지 않은 상태로 렌더링 되는 경우가 많기 때문 입니다.
 
렌더링을 마치고 glFlush() 로 현재 매트릭스 내의 모든 연산과 렌더링을 마치면 이제 그려진 DC 를 필요로 하는 곳으로 복사 하는 일이 남았습니다.
 
예제로 저는 windowDC 에다가 BitBlt() 함수로 복사 하는 것을 만들어 보았습니다.

 

 
 
        HDC hdcWin = GetDC(hWnd);
        BitBlt(hdcWin, 
       5, 
   5, 
   OPENGL_SURFACE_WIDTH + 5, 
   OPENGL_SURFACE_HEIGHT + 5, 
   hdcOpenGL, 
   0, 
   0, 
   SRCCOPY);
        ReleaseDC(hWnd, hdcWin);
 
 
예제 프로그램은 windows API 로만 만들었기 때문에 WinMain callback 내부에서 while(1){ ... } 루프내에 메시지를 grab 하면서 계속 그리도록 만들었습니다.
WinMain 에서 그리게 되면 ON_PAINT 이벤트를 받지 않고 지속적으로 그릴수 있기 때문에 이상하게 렌더링 되는 문제를 해결 할 수 있습니다.
 
CPU 로 렌더링 하는 것인지 .. 아니면 비디오 하드웨어가 버퍼에 그리면 느린것인지는 확실 하지 않습니다만 렌더링이 매우 느립니다.
예제로 만들어 본 것으로는 240x320 해상도로 그리는 것과 640x480 으로 그리는 것 모두 Core2Duo E6550 기준으로 한쪽 코어가 50~60% 정도 사용율이 올라가게 됩니다.
해상도엔 크게 차이가 없어 보이구요 ... 같은 렌더링을 그릴 경우 화면에 따라 다르지만 대충 10~20fps 로 그리게 됩니다.
 
Off-screen 으로 그리는 것은 별도로 OpenGL 로 렌더링 된 결과물을 가져다 다른 이미지와 함께 쓰고 싶을때 사용하는 것이 더 나을지도 모른다는 생각이 드는 결과 였습니다.
 
이번 테스트에 대해서는 예제 샘플을 제공할 수가 없어서 소스를 공유 하지 못하는 것에 혹시나 소스가 필요하신 분들에게 죄송합니다. (하지만 중요한건 위에 다 설명 되어 있습니다 ^^)
 



출처: http://rageworx.tistory.com/400 [자유로운 그날을 위해]

 

 

=================================

=================================

=================================

 

 

 

반응형


관련글 더보기

댓글 영역