델파이 자체 OpenGL.pas는 버전 1.0이고, 현재 실제로 사용되는 것도 버전 1.1 이상이며, 윈도우 순수 소프트웨어 시뮬레이션 방법도 버전 1.1이기 때문에 필요한 일부 기능을 직접 import 해야 합니다. Mike Lischke의 OpenGL12.pas와 같은 일부 오픈 소스 무료 단위도 사용할 수 있습니다. 물론, 직접 작성하면 디자인이 더욱 간결해질 수 있고, 너무 고급스럽고 완성도 높은 거대한 코드에서 오류를 찾을 필요도 없습니다.
먼저 필요한 단위 Windows, 메시지, OpenGL을 소개합니다.
필요한 확장을 추가합니다.
const
//GL_EXT_bgra
GL_BGR_EXT = $80E0;
GL_BGRA_EXT = $80E1;
// 다각형 오프셋
GL_POLYGON_OFFSET_UNITS = $2A00;
GL_POLYGON_OFFSET_POINT = $2A01;
GL_POLYGON_OFFSET_LINE = $2A02;
GL_POLYGON_OFFSET_FILL = $8037;
GL_POLYGON_OFFSET_FACTOR = $8038;
PRocedure glBindTexture(대상: GLEnum; 텍스처: GLuint); 외부 opengl32;
절차 glDeleteTextures(n: GLsizei; 텍스처: PGLuint); 외부 opengl32;
절차 glGenTextures(n: GLsizei; 텍스처: PGLuint); 외부 opengl32;
function glIsTexture(texture: GLuint): GLboolean 외부 opengl32;
절차 glPolygonOffset(인자, 단위: GLfloat) 외부 opengl32;
// 이 구문은 OpenGL.pas의 버그를 수정하는 데 사용됩니다.
function gluBuild2DMipmaps(대상: GLEnum; 구성 요소, 너비, 높이: GLint; 형식, atype: GLEnum; 데이터: 포인터): GLintcall;
이제 인터페이스가 기본적으로 버전 1.1로 업그레이드되었습니다. 다른 확장이 필요한 경우 유사하게 추가할 수 있습니다.
다음으로 GDI 창의 장치 컨텍스트 DC가 필요한 OpenGL 드로잉 컨텍스트 RC를 만들어야 합니다. TForm.Handle 속성 또는 TWinControl의 기타 Handle 속성은 DC입니다. 다음 함수를 사용하여 DC에서 RC를 만들 수 있으며 반환 값은 RC의 핸들입니다. 그런 다음 OpenGL을 사용하여 그릴 수 있습니다. 일반적으로 양식의 OnCreate 이벤트 내에서 사용할 수 있습니다. 이 기능의 옵션은 깊이 버퍼, 템플릿 버퍼, 누적 버퍼 및 알파 채널 값 생성을 의미합니다.
유형
TRCOptions = (roDepth, roStencil, roAccum, roAlpha) 집합;
함수 CreateRC(dc: HDC; 선택: TRCOptions): HGLRC;
var
PFDescriptor: TPixelFormatDescriptor;
PixelFormat: 정수;
시작하다
FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
PFDescriptor를 사용하면
시작하다
nSize := SizeOf(PFDescriptor);
n버전 := 1;
dwFlags := PFD_SUPPORT_OPENGL 또는 PFD_DRAW_TO_WINDOW 또는 PFD_DOUBLEBUFFER;
iPixelType := PFD_TYPE_RGBA;
cColorBits := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
roDepth가 opt이면 cDepthBits := 24;
roStencil이 opt인 경우 cStencilBits := 8;
roAccum이 선택되어 있으면 cAccumBits := 64;
iLayerType := PFD_MAIN_PLANE;
끝;
PixelFormat := ChoosePixelFormat(DC, @PFDescriptor);
Assert(PixelFormat <> 0);
Assert(SetPixelFormat(DC, PixelFormat, @PFDescriptor));
결과 := wglCreateContext(DC);
Assert(결과 <> 0);
wglMakeCurrent(dc, 결과);
끝;
양식의 OnPaint 이벤트를 그립니다. 드로잉이 완료된 후 이미지가 표시되도록 SwapBuffers(dc: HDC)를 사용하여 드로잉 버퍼와 디스플레이 버퍼를 교환해야 한다는 점을 기억하세요. 또한 RC와 DC가 동기화될 수 있도록 양식의 OnResize 이벤트에서 glViewport(0, 0, ClientWidth, ClientHeight)를 호출하는 것을 기억하세요.
양식의 OnDestroy 이벤트에서 RC를 파괴합니다.
절차 DestroyRC(rc: HGLRC);
시작하다
rc = 0이면 종료합니다.
wglMakeCurrent(0, 0);
wglDeleteContext(rc);
끝;
이 시점에서 OpenGL 프로그램의 프레임워크는 대략적으로 형성되었습니다. 하지만 아직 해결해야 할 문제가 있습니다.
첫째, Windows가 배경을 지우고 속도에 영향을 미치는 것을 방지합니다. 양식에 멤버 함수 추가
사적인
절차 WMEraseBkgnd(var 메시지: TWmEraseBkgnd); 메시지 WM_ERASEBKGND;
절차 TGLWindow.WMEraseBkgnd(var 메시지: TWmEraseBkgnd);
시작하다
메시지.결과 := 1;
끝;
둘째, 좀 더 안전하게. 다음 멤버 함수를 추가합니다.
보호됨
절차 CreateParams(var Params: TCreateParams);
절차 TGLWindow.CreateParams(var Params: TCreateParams);
시작하다
상속됨;
Params와 함께
시작하다
스타일 := 스타일 또는 WS_CLIPCHILDREN 또는 WS_CLIPSIBLINGS;
WindowClass.Style := CS_VREDRAW 또는 CS_HREDRAW 또는 CS_OWNDC;
끝;
끝;
자, 이제 이런 귀찮은 일을 잊고 멋진 3D 디스플레이를 작성할 수 있습니다 :)
몇 마디 말씀드리지만, 하나의 스레드에 여러 개의 RC를 생성하지 마십시오. 이는 성능에 심각한 영향을 미칠 수 있습니다. 일부 개인 OpenGL 창 컨트롤 데모에서는 양식에 여러 컨트롤을 배치하는데 이는 실제로 좋은 생각이 아닙니다. 하나의 OpenGL 창으로 여러 뷰를 표시해야 합니다. 또한 스레드 간에 OpenGL 기능에 액세스하지 마십시오.
또한 Windows에서 그래픽 카드 드라이버를 자동으로 설치하는 경우 OpenGL 하드웨어 가속기는 설치되지 않습니다. 그래픽 카드 제조업체의 드라이버를 직접 설치해야 합니다.
게다가 무료 전체화면 표시 기능도 제공됩니다 :)
function FullScreen(win: TWinControl; 너비, 높이, 비트 심도: 정수): 부울;
var 디스플레이 모드: DEVMODE;
시작하다
FillChar(displaymode, sizeof(displaymode), 0);
디스플레이 모드를 사용하면
시작하다
dmSize := sizeof(디스플레이 모드);
dmPelsWidth:= 너비;
dmPelsHeight := 높이;
dmBitsPerPel := 비트 심도;
dmFields := DM_BITSPERPEL 또는 DM_PELSWIDTH 또는 DM_PELSHEIGHT;
끝;
ChangeDisplaySettings(displaymode, CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL인 경우
그럼 시작해
ShowWindow(win.Handle, WS_MAXIMIZE);
결과 := 참;
끝
그렇지 않으면 결과 := false;
끝;
프로시저 RestoreDisplay(win: TwinControl);
시작하다
ChangeDisplaySettings(PDEVMODE(0)^, 0);
ShowWindow(win.Handle, SW_RESTORE);
끝;