CKER에서 번역한 NeHe의 VC OPENGL 프레임워크를 Delphi 버전으로 변환합니다.
델파이를 사용하여 OPENGL을 배우는 형제들에게 도움이 되었으면 좋겠습니다.
왜인지는 모르겠지만 제 델파이 환경에서는 바로 실행이 안되는데, 다른 머신에서는 괜찮은 것 같습니다.
내 컴퓨터에서는 EXE 파일만 컴파일하고 실행할 수 있습니다.
이렇게 좋은 프레임워크를 제공해 주신 NeHe에게 감사드리며, VC 정보를 번역해 주신 CKER에게도 감사드립니다.
프로그램 프로젝트1;
용도
오픈글,
창문,
메시지;
상수
WND_TITLE = 'OPenGl 기본 프레임워크'; //제목
바르
//================================================ ===========================
// 각 OpenGL은 셰이딩 컨텍스트에 연결됩니다. 셰이딩 컨텍스트 테이블은 모든 OpenGL 호출을 연결합니다.
// Device Context(장치 설명 테이블)를 수신하고 OpenGL 셰이딩 설명 테이블을 hRC로 정의하여 프로그램이
// 창을 그리는 데 충분하다면 장치 설명 테이블도 생성해야 합니다. Windows 장치 설명 테이블은 hDC로 정의되어 있으며,
// DC는 창을 GDI(그래픽 장치 인터페이스)에 연결합니다. 그리고 RC는 OpenGL을 연결합니다
// DC로.
//================================================ ===========================
h_RC: HGLRC; // 렌더링 컨텍스트(쉐이딩 설명 테이블).
h_DC: HDC; // 장치 컨텍스트(장치 설명 테이블)
h_Wnd: HWND; // 창 핸들
h_Instance: HINST; // 프로그램 인스턴스(인스턴스).
키 : Array[0..255] Of Boolean // 키보드 루틴용 배열;
{$R *.res}
//================================================ ==============================
//창 크기 변경 여부에 관계없이 OpenGL 장면의 크기를 재설정합니다(전체 화면 모드를 사용하지 않는다고 가정).
//창 크기를 조정할 수 없는 경우에도(예: 전체 화면 모드) 적어도 한 번은 실행됩니다.————————
//프로그램 시작 부분에서 관점을 설정합니다. OpenGL 장면의 크기는 해당 장면이 표시되는 창의 크기에 따라 설정됩니다.
//================================================ ==============================
Procedure glResizeWnd(Width, Height: Integer); //GL 창 크기 재설정 및 초기화
시작하다
If (Height = 0) Then // 높이가 0이 되어 0으로 나누기 예외가 발생하는 것을 방지합니다.
높이 := 1;
glViewport(0, 0, Width, Height); //현재 뷰포트(Viewport) 재설정
//다음 줄은 원근감 있는 화면을 설정합니다. 즉, 멀리 있는 것이 더 작게 보인다는 뜻이다. 그렇게 하면 현실이 된다.
//출연 장면. 여기서 원근감은 창의 너비와 높이를 기준으로 45도 시야각으로 계산됩니다. 0.1f, 100.0f는
//장면에 그릴 수 있는 깊이의 시작점과 끝점입니다.
//glMatrixMode(GL_PROJECTION)는 다음 두 줄의 코드가 투영 행렬에 영향을 미치도록 지정합니다.
//투영 행렬은 장면에 원근감을 추가하는 역할을 합니다.
//glLoadIdentity()는 재설정과 유사합니다. 선택한 매트릭스 상태를 원래 상태로 복원합니다.
//glLoadIdentity()를 호출한 후 장면에 대한 관점을 설정합니다.
glMatrixMode(GL_PROJECTION); //투영 행렬을 선택합니다.
glLoadIdentity(); // 투영 행렬 재설정
gluPerspective(45.0, Width / Height, 0.1, 100.0) // 창이 나타나는 비율을 계산합니다.
//glMatrixMode(GL_MODELVIEW)는 모든 새로운 변환이 모델 뷰 행렬(모델 관측 행렬)에 영향을 미치도록 지정합니다.
//객체 정보는 모델 관찰 행렬에 저장됩니다.
glMatrixMode(GL_MODELVIEW); //모델 관측 행렬 선택
glLoadIdentity(); //모델 관찰 행렬 재설정
//이 용어의 의미를 아직 이해하지 못하더라도 걱정하지 마세요.
//훌륭한 원근감 있는 장면을 얻으려면 이 작업을 수행해야 한다는 점만 알아두세요.
끝;
//================================================ ==============================
// OpenGL에 대한 모든 설정을 수행합니다. 화면을 지우는 색상을 설정하고, 깊이 캐시를 켜고,
// 부드러운 음영처리(그림자 스무딩) 등을 활성화합니다. 이 루틴은 OpenGL 창이 생성될 때까지 호출되지 않습니다.
// 이 프로세스는 반환 값을 갖습니다. 하지만 여기서 초기화는 그다지 복잡하지 않으며 아직 반환 값에 대해 걱정할 필요가 없습니다.
//================================================ ==============================
절차 glInit();
시작하다
//화면을 지울 때 사용되는 색상을 설정합니다. 색상이 어떻게 작동하는지 확실하지 않은 경우 여기에 간단한 설명이 있습니다.
//색상 값의 범위는 0.0f에서 1.0f까지입니다. 0.0f는 가장 어두운 상황을 나타내고, 1.0f는 가장 밝은 상황을 나타냅니다.
//glClearColor 다음의 첫 번째 매개변수는 Red Intensity(빨간색 구성 요소)이고, 두 번째는 녹색, 세 번째는 파란색입니다.
//최대값도 1.0f이며, 이는 특정 색상 구성요소의 가장 밝은 경우를 나타냅니다. 마지막 매개변수는 Alpha 값입니다.
//화면을 지우는 데 사용할 경우 네 번째 숫자는 신경쓰지 마세요. 이제 0.0f로 놔두세요.
//세 가지 기본 색상(빨간색, 녹색, 파란색)을 혼합하면 다양한 색상을 얻을 수 있습니다.
//따라서 파란색인 glClearColor(0.0f,0.0f,1.0f,0.0f)를 사용하여 화면을 지웁니다.
//glClearColor(0.5f,0.0f,0.0f,0.0f)를 사용하면 중간 빨간색이 화면을 지우는 데 사용됩니다.
//가장 밝은 것(1.0f)도 아니고 가장 어두운 것(0.0f)도 아닙니다. 흰색 배경을 얻으려면 모든 색상을 가장 밝게(1.0f) 설정해야 합니다.
//검은색 배경을 원할 경우 모든 색상을 가장 어두운 색(0.0f)으로 설정합니다.
glClearColor(0.0, 0.0, 0.0, 0.0) // 검정색 배경
//섀도우 스무딩(Shadow Smoothing)은 폴리곤을 통해 색상을 미세하게 혼합하고 외부 조명을 부드럽게 합니다.
glShadeModel(GL_SMOOTH); // 그림자 다듬기 활성화
//다음으로 해야 할 일은 깊이 버퍼에 관한 것입니다. 깊이 버퍼를 화면 뒤의 레이어로 생각하세요.
//깊이 버퍼는 객체가 화면에 얼마나 깊이 들어가는지 지속적으로 추적합니다. 이 프로그램은 실제로 깊이 캐시를 사용하지 않습니다.
//그러나 화면에 3D 장면을 표시하는 거의 모든 OpenGL 프로그램은 깊이 버퍼를 사용합니다. 순서에 따라 어떤 객체가 먼저 그려질지 결정됩니다.
//이 방법을 사용하면 원 뒤에 사각형을 원 위에 그리지 않습니다. 깊이 버퍼는 OpenGL에서 매우 중요한 부분입니다.
glClearDepth(1.0); //깊이 버퍼 설정
glEnable(GL_DEPTH_TEST); // 깊이 테스트 활성화
glDepthFunc(GL_LESS); // 완료된 깊이 테스트 유형
//그런 다음 가능한 최상의 원근 교정을 원한다고 OpenGL에 알립니다.
//이것은 성능에 아주 약간 영향을 미칩니다. 그러나 관점이 조금 더 좋아 보이게 만듭니다.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 정말 정밀한 원근 교정
끝;
//================================================ ==============================
//모든 그리기 코드. 화면에 표시하려는 모든 내용이 이 코드에 나타납니다.
//향후 모든 프로그램에는 여기에 새로운 코드가 추가될 것입니다.
//================================================ ==============================
절차 glDraw();
시작하다
glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT) // 화면 및 깊이 버퍼 지우기
glLoadIdentity(); //현재 모델 관찰 행렬을 재설정합니다.
끝;
함수 WndProc(hWnd: HWND; // 윈도우 핸들
Msg: UINT; // 창 메시지
wParam: WPARAM; // 추가 메시지 내용
lParam: LPARAM // 추가 메시지 내용
): LRESULT;
시작하다
결과 := 0;
Case (Msg) Of // Windows 메시지 확인
WM_ACTIVATE: // 모니터 창 활성화 메시지
시작하다
끝;
WM_CREATE: // 생성
시작하다
끝;
WM_CLOSE: // 닫기
시작하다
PostQuitMessage(0); //종료 메시지 보내기
결과 := 0
끝;
WM_KEYDOWN: // 키를 눌렀습니다.
시작하다
keys[wParam] := True; // 그렇다면 TRUE로 설정하세요.
결과 := 0;
끝;
WM_KEYUP: // 키를 놓습니다.
시작하다
keys[wParam] := False; // 그렇다면 FALSE로 설정하세요.
결과 := 0;
끝;
WM_SIZE: //OpenGL 창 크기 조정
시작하다
glResizeWnd(LOWord(lParam), HIWORD(lParam)); //LoWord=너비, HiWord=높이
결과 := 0;
끝;
WM_TIMER: //타이머
시작하다
끝;
Else //나머지는 Windows에서 처리하도록 합니다.
Result := DefWindowProc(hWnd, Msg, wParam, lParam); // 처리되지 않은 모든 메시지를 DefWindowProc에 전달합니다.
끝;
끝;
//================================================ ==============================
// 프로그램이 종료되기 전에만 호출됩니다. 컬러링 컨텍스트 테이블, 디바이스 컨텍스트 테이블, 윈도우 핸들을 차례로 해제하는 기능입니다.
// 오류 검사를 많이 추가했습니다. 프로그램이 창의 일부를 삭제할 수 없으면 해당 오류 메시지가 나타납니다.
// 메시지 창,
//================================================ ==============================
절차 glKillWnd(전체 화면: 부울);
시작하다
//KillGLWindow()에서 가장 먼저 수행되는 작업은 전체 화면 모드인지 확인하는 것입니다.
//그렇다면 데스크탑으로 다시 전환하세요. 전체 화면 모드를 비활성화하기 전에 창이 파괴되어야 합니다.
//그러나 일부 그래픽 카드에서 이 작업을 수행하면 데스크탑이 충돌할 수 있습니다. 따라서 먼저 전체 화면 모드를 비활성화하는 것이 좋습니다.
//이것은 데스크탑 충돌을 방지하고 Nvidia 및 3dfx 그래픽 카드 모두에서 훌륭하게 작동합니다!
전체화면인 경우 // 전체화면 모드인가요?
시작하다
// 원래 데스크탑으로 돌아가려면 ChangeDisplaySettings(NULL,0)을 사용하십시오.
// 첫 번째 매개변수로 NULL을 취하고,
// 두 번째 매개변수로 0을 전달하면 Windows는 현재 레지스트리에 저장된 값을 사용하게 됩니다.
// (기본 해상도, 색 농도, 새로 고침 빈도 등)을 사용하여 원래 데스크탑을 효과적으로 복원합니다.
// 데스크탑으로 다시 전환한 후 마우스 포인터가 다시 표시되어야 합니다.
ChangeDisplaySettings(devmode(Nil^), 0); // 그렇다면 데스크탑으로 다시 전환합니다.
ShowCursor(True); //마우스 표시
끝;
//채색 설명표(hRC)가 있는지 여부.
h_RC > 0이면
//해제할 수 있는지 확인합니다(hDC와 hRC를 분리).
If (wglMakeCurrent(h_DC, 0) 아님) Then
MessageBox(0, 'DC와 RC를 해제할 수 없습니다!', 'Error', MB_OK Or
MB_ICONERROR);
// 음영 설명 테이블을 삭제할 수 있나요?
If (wglDeleteContext(h_RC) 아님) Then
시작하다
MessageBox(0, '쉐이딩 컨텍스트 테이블을 삭제하지 못했습니다!', 'Error', MB_OK Or
MB_ICONERROR);
h_RC := 0;
끝;
//디바이스 컨텍스트 테이블이 존재하는지 여부, 존재한다면 해제를 시도합니다.
If ((h_DC > 0) And (ReleaseDC(h_Wnd, h_DC) = 0)) 그러면
시작하다
MessageBox(0, '장치 컨텍스트를 해제하지 못했습니다!', '오류', MB_OK Or
MB_ICONERROR);
h_DC := 0;
끝;
//창 핸들이 있는지 여부에 관계없이 DestroyWindow(hWnd)를 호출하여 창 파괴를 시도합니다.
If ((h_Wnd <> 0) And (DestroyWindow(h_Wnd)가 아님)) 그러면
시작하다
MessageBox(0, '양식을 삭제할 수 없습니다!', '오류', MB_OK Or
MB_ICONERROR);
h_Wnd := 0;
끝;
//창 클래스 로그아웃
//이렇게 하면 창을 정상적으로 삭제한 다음 다른 창을 열 수 있습니다.
//"Windows 클래스가 이미 등록되었습니다"(창 클래스가 이미 등록되어 있음)와 같은 오류 메시지는 수신되지 않습니다.
If (UnRegisterClass('OpenGL', hInstance) 아님) Then
시작하다
MessageBox(0, '윈도우 클래스를 로그아웃할 수 없습니다!', 'Error', MB_OK Or
MB_ICONERROR);
h인스턴스 := 0;
끝;
끝;