glskeleton.h
//---------------------------------------------------------------------------
#include <vclvcl.h>
//---------------------------------------------------------------------------
#ifndef GLSkeletonH
#define GLSkeletonH
//---------------------------------------------------------------------------
#include <vclClasses.hpp>
#include <vclControls.hpp>
#include <vclStdCtrls.hpp>
#include <vclForms.hpp>
#include <gl/gl.h>
#include <gl/glu.h>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
published: // IDE-managed Components
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall FormResize(TObject *Sender);
void __fastcall FormPaint(TObject *Sender);
private: // User declarations
HDC hdc;
HGLRC hrc;
int PixelFormat;
public: // User declarations
fastcall TForm1(TComponent* Owner);
void __fastcall IdleLoop(TObject*, bool&);
void __fastcall RenderGLScene();
void __fastcall SetPixelFormatDescriptor();
};
glskeleton.cpp
//---------------------------------------------------------------------------
extern TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vclvcl.h>
#pragma hdrstop
#include "GLSkeleton.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Application->OnIdle = IdleLoop;
_control87(MCW_EM, MCW_EM);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdleLoop(TObject*, bool& done)
{
done = false;
RenderGLScene();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RenderGLScene()
{
//Place your OpenGL drawing code here
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
hdc = GetDC(Handle);
SetPixelFormatDescriptor();
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
SetupRC();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SetupRC()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
ReleaseDC(hdc);
wglMakeCurrent(hdc, NULL);
wglDeleteContext(hrc);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SetPixelFormatDescriptor()
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
24,
0,0,0,0,0,0,
0,0,
0,0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};
PixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, PixelFormat, &pfd);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
GLfloat nRange = 200.0f;
glViewport(0, 0, ClientWidth, ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (ClientWidth <= ClientHeight)
glOrtho(-nRange, nRange, -nRange*ClientHeight/ClientWidth,
nRange*ClientHeight/ClientWidth, -nRange, nRange);
else
glOrtho(-nRange*ClientWidth/ClientHeight, nRange*ClientWidth/ClientHeight,
-nRange, nRange, -nRange, nRange);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//---------------------------------------------------------------------------
위 코드는 C++ 빌더의 VCL 을 사용하는 환경에서 OPENGL 을 사용할 경우 기본적인 뼈대가 되는 코드이다
- 몇몇 환경에서는 부동소수점 예외가 발생하는데 이때는 _control87(MCW_EM, MCW_EM); 을 사용하여 연산과정중 opengl 내부에서 발생한 예외를 지긋이 disable 시키자.
- 뷰가 여러개 있을 경우에는 렌더링 타켓이 바뀌는 경우가 있기 때문에 항상 새로그리기 전에는 wglMakeCurrent(hdc, hrc); 을 사용하여 타켓을 변경하도록 하자.
- 위 예에서는 IdleLoop 즉 윈도우 메시지 처리할것이 없을때 화면을 주기적으로 갱신하고 있는데, 지속적인 렌더링이 필요없는 경우에는 OnPaint 즉 영역을 다시 그리는것이 필요할때만 그려도 무방하다.
댓글 없음:
댓글 쓰기