OpenGL

Windows OpenGL: Making Window Application with OpenGL

FunnyPR 2014. 4. 19. 15:46

◆ 윈도우즈 OPENGL - 창 만들기 


장치 컨텍스트 얻기 및 해제

- 장치 컨텍스를 얻고 드로잉 후 가능한 빨리 해제 하는 것이 좋음 (시스템 자원 관리)

HDC hDC = GetDC(hWnd);

ReleaseDC(hWnd, hDC);


윈도우즈 OPenGL 프로그램을 만들기 위한 단계를 다음과 같다.

[step 1] 랜더링 컨텍스트 초기화 

[step 2] 픽셀 포맷 지정

[step 3] 랜더링 컨텍스트 활성화 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int COpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1) return -1;
    
    int nPixelFormat;                    // Pixel format index
    m_hDC = ::GetDC(m_hWnd);            // Get the Device context
    static PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),    // Size of this structure
        1,                                // Version of this structure    
        PFD_DRAW_TO_WINDOW |            // Draw to Window (not to bitmap)
        PFD_SUPPORT_OPENGL |            // Support OpenGL calls in window
        PFD_DOUBLEBUFFER,                // Double buffered mode
        PFD_TYPE_RGBA,                    // RGBA Color mode
        24,                                // Want 24bit color 
        0,0,0,0, 0,0,0,0, 0,0,0,0,0,    // Not used to select mode
        32,                                // Size of depth buffer
        0,0,
        PFD_MAIN_PLANE,                    // Draw in main plane
        0,0,0,0};                        // Not used to select mode
    
    // Choose a pixel format that best matches that described in pfd
        nPixelFormat = ChoosePixelFormat(m_hDC, &pfd);
    // Set the pixel format for the device context
        VERIFY(SetPixelFormat(m_hDC, nPixelFormat, &pfd));
    // Create the rendering context
        m_hRC = wglCreateContext(m_hDC);
    // Make the rendering context current, perform initialization, then
    // deselect it
        VERIFY(wglMakeCurrent(m_hDC,m_hRC));
        GLSetupRC(m_hDC);
        wglMakeCurrent(NULL,NULL);
    // Create the palette if needed
        InitializePalette();
    return 0;
}


[step 4] 드로잉 코드 호출 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void COpenGLView::OnDraw(CDC* /*pDC*/)
{
    CProjectOpenGLDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;
    
    // TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.
 
    // Make the rendering context current
    wglMakeCurrent(m_hDC,m_hRC);
    
    // Call our external OpenGL code
    GLRenderScene();
    
    // Swap our scene to the front
    SwapBuffers(m_hDC);
    
    // Allow other rendering contexts to co-exist
    wglMakeCurrent(m_hDC,NULL);
}

SwapBuffers함수: 장치 컨텍스를 인자를 받고 이중 버퍼 렌더링을 위한 버퍼 교환을 수행하는 것. 이것이 렌더링 작업에 작업 컨텍스트를 빠르게 이용할 수 있어야 하는 이유 중 하나


1
2
3
4
5
// OpenGL의 영역을 그립니다.
void GLRenderScene()
{
    //OpenGL 드로잉 코드 
}


[step 5] 종료시 현재 렌더링 컨텍스트 해제 및 제거 

Colored By Color Scripter

1
2
3
4
5
6
7
8
9
void OnDestroy()
{
    // Clean up rendering context stuff
    wglDeleteContext(m_hRC);
    ::ReleaseDC(m_hWnd,m_hDC);
    
    CView::OnDestroy();
    // TODO: 여기에 메시지 처리기 코드를 추가합니다.
}


주의사항 

윈도우즈 프로그래밍에서 창을 만들때 반드시 아래 스타일을 선언해야 함

 - WS_CLIPCHILDREN | WS_CLIPSIBLINGS

 - OpenGL 랜더링 컨텍스트가 다른 창에 렌더링 하는 것을 막기 위함


GDI 렌더링과 OpenGL 이중 버퍼 페이지 전환 시 모든 장치 컨텍스트가 필요하기 때문에 창스타일에 CS_OWNDC 설정 필요


1
2
3
4
5
6
7
BOOL PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: CREATESTRUCT cs를 수정하여 여기에서
    //  Window 클래스 또는 스타일을 수정합니다.
    cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);
    return CView::PreCreateWindow(cs);
}

MFC에서 호출해야 하는 함수 
OnDestroy, : 종료시 OpenGL 랜더링 컨텍스트 해제
PreCreateWindow,  :: 윈도우 창 속성 설정
OnCreate, : 랜더링 컨텍스트 및 픽셀 포맷 설정
OnSize, : 사이즈 조절
OnPaint, : 드로잉 
OnEraseBkgnd : 사이즈 조절시 깜빡임 방지 

1
2
3
4
5
6
7
BOOL COpenGLView::OnEraseBkgnd(CDC* pDC)
{
    // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
 
    // return CView::OnEraseBkgnd(pDC);
    return true;
}