2011-07-06 6 views
2

OpenGL 컨텍스트가 포함 된 MFC 응용 프로그램에서 작업합니다. MFC를 처음 사용하는 이유는 무엇입니까? OpenGL이 제대로 작동하지만 3D 창 위에 텍스트를 그리려 할 때 WindowProc 내부 코드 : OpenGL을보다 일시 렌더링 같이 창의 크기 만 때 OpenGL의 context.I 아래 도시MFC에서 OpenGL 컨텍스트 위에 텍스트 페인팅

 case WM_PAINT: 

     hDC=BeginPaint(window,&paintStr); 
     GetClientRect(window,&aRect); 
     SetBkMode(hDC,TRANSPARENT); 
     DrawText(hDC,L"He He I am a text on top of OpenGL",-1,&aRect,DT_SINGLELINE|DT_CENTER|DT_VCENTER); 
     EndPaint(window,&paintStr); 

     return 0; 

그것을 볼 수있다.

+0

어디에서 OpenGL 렌더링 코드입니까? WM_PAINT에 있어야하지만 코드 발췌 부분에서 볼 수는 없습니다 ... –

+0

@Felice Pollano : 유휴 루프에서 호출 된 것 같습니다. – datenwolf

답변

4

당신이하고있는 일은 OpenGL에서 모든 일을하는 것보다 틀리거나 어렵습니다. OpenGL에서 그려진 창에 텍스트를 추가하는 문제를 해결하려면, OpenGL에서 텍스트를 그려야합니다. WM_CREATE를 처리 할 때 CFont 인스턴스를 만들고 DC로 글꼴을 선택하고 glCallLists와 함께 사용할 수있는 일련의 래스터 화 된 비트 맵을 만드는 wglUseFontBitmaps를 호출하여 MFC에서 사용했던 글꼴과 똑같은 글꼴을 사용할 수도 있습니다. , 그럼 당신은 WM_PAINT를 처리 할 때

ABC glyphInfo[256]; // for font widths 
TEXTMETRIC tm; // for font heights 

// create a bitmap font 
CFont myFont; 
myFont.CreateFont(
    16,      // nHeight 
    0,       // nWidth 
    0,       // nEscapement 
    0,       // nOrientation 
    FW_NORMAL,     // nWeight 
    FALSE,      // bItalic 
    FALSE,      // bUnderline 
    0,       // cStrikeOut 
    ANSI_CHARSET,    // nCharSet 
    OUT_DEFAULT_PRECIS,  // nOutPrecision 
    CLIP_DEFAULT_PRECIS,  // nClipPrecision 
    DEFAULT_QUALITY,   // nQuality 
    DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily 
    _T("Arial")    // lpszFacename 
); 

// change the current font in the DC 
CDC* pDC = CDC::FromHandle(hdc); 

// make the system font the device context's selected font 
CFont *pOldFont = (CFont *)pDC->SelectObject (&myFont); 

// the display list numbering starts at 1000, an arbitrary choice 
wglUseFontBitmaps (hdc, 0, 255, 1000); 
VERIFY(GetCharABCWidths (hdc, 0, 255, &glyphInfo[0])); 
pDC->GetTextMetrics(&tm); 

if(pOldFont) 
    pDC->SelectObject(pOldFont); 

myFont.DeleteObject(); 

을 (당신이 그것에 인 동안,. 각각, 각 그래프의 폭과 높이를 결정하기 위해 GetCharABCWidths 및 GetTextMetrics 전화) 당신의 행렬을 재설정하고 텍스트를 넣어 glRasterPos2d를 사용 어디로 가야할까요? 가로로 가운데에 배치하려면 아래 코드와 비슷한 코드를 사용하여 문자열의 정확한 너비를 계산하는 것이 좋습니다.

// indicate start of glyph display lists 
glListBase (1000); 

CRect r; 
GetWindowRect(r); 

glMatrixMode(GL_PROJECTION); 
glPushMatrix(); 
glLoadIdentity(); 
gluOrtho2D(0, r.Width(), 0, r.Height()); 

glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadIdentity(); 

CString formattedString; 
formattedString.Format("Pi is about %1.2f", 3.1415); 

int stringWidth=0; // pixels 
for(int j=0; j < formattedString.GetLength(); ++j) 
    stringWidth += glyphInfo[ formattedString.GetAt(j) ].abcA + glyphInfo[ formattedString.GetAt(j) ].abcB + glyphInfo[ formattedString.GetAt(j) ].abcC; 

double textXPosition, textYPosition; 
textXPosition = r.Width()/2-stringWidth/2; // horizontally centered 
textYPosition = r.Height()/2-tm.tmHeight/2; // vertically centered 

glRasterPos2d(textXPosition,textYPosition); 

// this is what actually draws the text (as a series of rasterized bitmaps) 
glCallLists (formattedString.GetLength(), GL_UNSIGNED_BYTE, (LPCSTR)formattedString); 

glMatrixMode(GL_MODELVIEW); 
glPopMatrix(); 
glMatrixMode(GL_PROJECTION); 
glPopMatrix(); 

설치가 성가신 동안, 당신은 한 번만해야하고, 나는 GDI를 다루는 것보다 덜 불편하다고 생각합니다. GDI와 OpenGL을 함께 쓰면 정말 문제가 생길 것입니다. OpenGL은 텍스트를 표시하는 데 아주 능숙합니다. 서브 픽셀의 정확도를 무료로 얻을 수 있습니다.

편집 : GUI 요소를 포함한 귀하의 요청에 대한 응답으로, 나는 당신이, OpenGL을 그린 창 또한 표준 Windows 컨트롤 (편집 상자 모두가 상자, 단추, 목록 컨트롤을 확인하고 싶은 것을 의미한다고 가정합니다 , 등). 또한 윈도우의 배경이 아닌 윈도우의 일부분 만 그리는 OpenGL을 사용한다고 가정합니다.

MFC를 사용한다고 했으므로 대화 상자 창을 만들고 모든 표준 Windows 컨트롤을 추가 한 다음 WM_PAINT를 처리하는 CWnd 파생 클래스를 추가하는 것이 좋습니다. 리소스 편집기를 사용하여 원하는 위치로 컨트롤을 이동하십시오. 실제로 OpenGL이 드로잉을하고있는 곳에서는 소유자가 그리는 사용자 정의 컨트롤을 만들고 있습니다. 따라서 OpenGL은 그 윈도우를 그리고 표준 MFC 클래스 (CEdit, CButton 등)를 그릴 것입니다. 이것은 내 경험에 잘 작동하며 GDI가 소유자 제어 제어에서 수행하는 것과별로 다르지 않습니다.

대신 OpenGL에서 창 배경을 그려보고 표준 Windows 컨트롤을 그 위에 표시하려면 어떻게해야합니까? 나는 이것이 훌륭한 생각이라고 생각하지 않지만 CDialog 파생 클래스에 WM_PAINT와 WM_ERASE를 처리 할 수 ​​있습니다. WM_ERASE에서 OpenGL을 호출하여 3D 콘텐츠를 그리면 WM_PAINT가 호출 될 때 표준 Windows 컨트롤에서 덮어 씁니다. 또는 WM_PAINT에서 유사한 CDialog :: OnDraw를 호출하기 전에 OpenGL을 호출 할 수 있습니다.

더 많은 것을 쓰려면 "2s 그래픽 오버레이 (라벨, GUI 요소와 같은)를 추가하고 싶습니다"라는 문장을 분명히하십시오.

+0

안녕하세요 @ user244795 당신이 대답을 동의하는 동안 나는 이미 내 원래 목표는 OpenGL을 위의 Windows 콘텐트를 그릴 수 있습니다. 그래서 내가 텍스트 예제를 시도했습니다.하지만 내가 추가하려는 경우 일부 2s 그래픽 오버레이 (레이블, GUI 요소와 같은), 나는 또한 OpenGL 내부에서이 모든 작업을 수행해야합니까? 그런 기본적인 질문에 대해 미안하지만이 모든 것을 통해 나의 NOOB의 길을 만들려고 노력하고 있습니다. –

2

코드에서 OpenGL 렌더링이 타이머 또는 idel 루프 동작으로 호출된다고 가정합니다. 자연적으로 OpenGL 실행은 아마도 약간의 클리어링을 포함 할 것이고, 그리하여 그 밖의 무엇인가를 그릴 것이다.

GDI 텍스트 그리기와 OpenGL의 혼합은 권장되지 않지만 수행 할 수 있습니다. 그러나 물론 OpenGL 그리기 함수에 코드를 포함시켜 버퍼 스왑 후에 모든 GDI 연산을 배치해야합니다.

+0

버퍼 스왑뿐만 아니라'glFlush' 또는'glFinish'가 동기화에 필요합니다. 그렇지 않으면 GPU가 여전히 명령을 처리하고 GUI 출력을 덮어 쓰는 미래의 시점에서 스왑을 수행 할 수 있습니다. –

+0

wglSwapBuffers는 glFinish()를 의미합니다. OpenGL이 렌더링을 끝내면 버퍼 스왑 만 이해할 수 있습니다. – datenwolf

+0

그러면 혼합 된 OpenGL/GDI 시나리오에는'glFlush'가 필요합니다. 'wglSwapBuffers'는 다른 모든 OpenGL 커맨드와 같은 파이프 라인에 들어가고, 버퍼 스왑이 일어나기 전에 리턴되며,'wglSwapBuffers' 이후에 발행 된 GDI 커맨드는 여전히 버퍼 스왑 전에 실행될 수 있습니다. –