Sign in Join
Wiki copytemporary

OpenGL Tutorial/ko: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11OpenGL은 이기종간 이식가능하고 상호 작용이 가능한 2D 및 3D 그래픽 어플리케이션을 개발할 수 있는 훌륭한 환경이다. 1992년 처음 소개된 이래 OpenGL은 산업계에서 가장 폭넓게 이용되며 2D와 3D 그래픽 어플리케이션 인터페이스(API)를 제공하며 다양한 컴퓨터 플랫폼에서 수 많은 어플리케이션이 있다. OpenGL은 렌더링, 텍스쳐 매핑, 특수효과 및 다른 강력한 시각화 함수등의 다양한 셋을 삽입하여 혁신적이고 빠른 어플리케이션의 개발을 가능하게 하였다. 개발자는 모든 인기있는 데스크톱과 워크스테이션 플랫폼에서 다양한 어플리케이션 개발의 성공을 보장받기 위해 OpenGL의 능력을 저울질하게 된다.
22
33OpenGL에 관한 더 많은 정보는 [이곳](http://www.opengl.org/about/overview/)에서 찾을 수 있다.
44
55# GLUT
66
77GLUT(glutony의 glu와 발음이 비슷)는 OpenGL Utility Toolkit으로,윈도우 시스템과 독립적인 툴킷으로 OpenGL 프로그램 작서에 사용된다. 이것은 OpenGL을 위한 간단한 윈도우 어플리케이션 프로그래밍 인터페이스(API)를 구현한다. GLUT는 이식 가능한 API를 제공하여 모든 PC와 워크스테이션 플랫폼에 동작하는 단일 OpenGL 프로그램을 작성할 수 있게 한다.
88
99GLUT에 관한 더 자세한 정보는 [여기](http://www.opengl.org/resources/libraries/glut/)에 있다.
1010
1111많은 OS는 GLUT를 설치하고 있으나 당신이 [구글](http://www.google.com/)에서 쉽게 찾을 수 없다면 윈도우즈 바이너리를 [www.xmission.com](http://www.xmission.com/~nate/glut.html)에서 다운로드 할 수 있다.
1212
1313# LCL
1414
1515라자루스 컴포넌트 라이브러리는 OpenGL과 함께 하용할 수 있다. 라자루스는 OpenGl 컨텍스트를 가진 LCL 컨트롤을 가진 TOpenGLControl 을 포함하고 있다. 라자루스 패키지 LazOpenGLContext는 lazarus/components/opengl/lazopenglcontext.lpk에서 찾을 수 있다. 예제는 lazarus/examples/openglcontrol/openglcontrol_demo.lpi에서 찾을 수 있다.
1616
1717# LCL / GLUT
1818
1919GLUT와 LCL은 어제 이용하나?
2020
2121- 내 맘대로 무언가를 그리려고 한다면 GLUT가 더 낫다.
2222- 보통의 어플리케이션에서는 LCL이 더 낫다. 예를 들어 3D 에디터는 몇개의 OpenGL 윈도우를 필요로 하며 나머지는 보통의 버튼, 콤보박스, 윈도우 모달 윈도우 등을 사용하는 보통의 어플리케이션이다.
2323
2424OpenGL 파트는 매우 유사하다. GLUT는 윈도우 환경에서 dll을 필요로 하며 LCL은 박스의 바깥에서 실행되지만 LCL 실행 파일은 더 커진다.
2525
2626# 첫번째 GLUT 프로그램 작성
2727
28-GLUT를 이용하기 위해서는 반드시 먼저 초기화가 필요하다.이것은 <b>glutInit</b> 함수를 사용하여 수행한다. 이 함수는 명령어 라인을 파싱하여 메인 윈도우를 위해 파라메터를 설정하지만, C/C++ 스타일로 입력되어야 한다. ParamCount와 ParamStr을 C/C++와 유사한 명령어 파라메터로 변환하는 각자의 함수를 작성할 수가 있다.
28+GLUT를 이용하기 위해서는 반드시 먼저 초기화가 필요하다.이것은 glutInit 함수를 사용하여 수행한다. 이 함수는 명령어 라인을 파싱하여 메인 윈도우를 위해 파라메터를 설정하지만, C/C++ 스타일로 입력되어야 한다. ParamCount와 ParamStr을 C/C++와 유사한 명령어 파라메터로 변환하는 각자의 함수를 작성할 수가 있다.
2929
3030``` pascal
3131 procedure glutInitPascal(ParseCmdLine: Boolean);
3232 var
3333 Cmd: array of PChar;
3434 CmdCount, I: Integer;
3535 begin
3636 if ParseCmdLine then
3737 CmdCount := ParamCount + 1
3838 else
3939 CmdCount := 1;
4040 SetLength(Cmd, CmdCount);
4141 for I := 0 to CmdCount - 1 do
4242 Cmd[I] := PChar(ParamStr(I));
4343 glutInit(@CmdCount, @Cmd);
4444 end;
4545```
4646
4747본질적으로, 프로그래머는 배열을 생성하고 ParamStr에 있는 문자열로 배열을 채워야 한다. 이 함수는 어떤 것이 gluInit에 전달되는지를 컨트롤하는 파라메터(명령어 라인 전체 혹은 실행파일 이름 만)를 취한다.
4848
4949할일: **glutInit(@argc, @argv);**가 충분하다면.
5050
5151glutInit에 더 많은 정보: <http://www.opengl.org/resources/libraries/glut/spec3/node10.html>
5252
53-다음으로는 메인 윈도우를 생성할 필요가 있다. <b>glutInitDisplayMode</b>를 사용하여 메인윈도우의 디스플레이 모드를 설정한다. 이것은 플래그의 조합으로 이루어진 단 한개의 파라메터만을 취한다. 보통 <b>GLUT_DOUBLE 나 GLUT_RGB, GLUT_DEPTH</b>가 필요한 전부이다.
53+다음으로는 메인 윈도우를 생성할 필요가 있다. glutInitDisplayMode를 사용하여 메인윈도우의 디스플레이 모드를 설정한다. 이것은 플래그의 조합으로 이루어진 단 한개의 파라메터만을 취한다. 보통 GLUT_DOUBLE 나 GLUT_RGB, GLUT_DEPTH가 필요한 전부이다.
5454
5555glutInitDisplayMode에 관한 더 많은 정보: <http://www.opengl.org/resources/libraries/glut/spec3/node12.html>
5656
57-윈도우의 위치와 크기는 <b>glutInitWindowPosition</b>와 <b>glutInitWindowSize</b>를 사용하여 조절할 수가 있다. 이것들은 2개의 파라메터를 취한다. 전자는 Y와 Y 좌표를, 후자는 폭(width)과 높이(height)이다. <b>glutGet</b>을 사용하여 스크린의 크기와 윈도우의 중심을 알아낼 수 있다.
57+윈도우의 위치와 크기는 glutInitWindowPosition와 glutInitWindowSize를 사용하여 조절할 수가 있다. 이것들은 2개의 파라메터를 취한다. 전자는 Y와 Y 좌표를, 후자는 폭(width)과 높이(height)이다. glutGet을 사용하여 스크린의 크기와 윈도우의 중심을 알아낼 수 있다.
5858
5959lutInitWindowPosition, glutInitWindowSize 및 glutGet에 관한 더 자세한 것은: <http://www.opengl.org/resources/libraries/glut/spec3/node11.html> <http://www.opengl.org/documentation/specs/glut/spec3/node70.html>
6060
61-마지막으로 윈도우는 <b>glutCreateWindow</b>함수를 사용하여 생성하면 된다. 이것은 윈도우를 생성하고 파라메터를 통해 윈도우의 캡션을 설정한다. 그 결과 윈도우의 핸들을 반환한다. 이 핸들은 이것을 필요로 하는 다른 함수에서 사용할 수 있다.
61+마지막으로 윈도우는 glutCreateWindow함수를 사용하여 생성하면 된다. 이것은 윈도우를 생성하고 파라메터를 통해 윈도우의 캡션을 설정한다. 그 결과 윈도우의 핸들을 반환한다. 이 핸들은 이것을 필요로 하는 다른 함수에서 사용할 수 있다.
6262
6363glutCreateWindow에 관한 더 자세한 정보는: <http://www.opengl.org/resources/libraries/glut/spec3/node16.html>
6464
65-작성한 프로그램이 메인 루프에 들어가기 전에 몇몇 콜백을 설정해야만 한다. 윈도우를 그리고, 크기를 변경하고 키보드 입력을 얻는데 콜백이 필요하다. 이 콜백들은 <b>glutDisplayFunc</b>, <b>glutReshapeFunc</b> 및<b>glutKeyboardFunc</b>을 이용하여 설정한다.
65+작성한 프로그램이 메인 루프에 들어가기 전에 몇몇 콜백을 설정해야만 한다. 윈도우를 그리고, 크기를 변경하고 키보드 입력을 얻는데 콜백이 필요하다. 이 콜백들은 glutDisplayFunc, glutReshapeFunc 및glutKeyboardFunc을 이용하여 설정한다.
6666
6767콜백을 설정하는 더 자세한 정보는: <http://www.opengl.org/resources/libraries/glut/spec3/node45.html#SECTION00080000000000000000>
6868
6969당신의 그리기 함수는 다름과 같은 모습을 띨것이다:
7070
7171`procedure DrawGLScene; cdecl;`\
7272`begin`\
7373`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
7474`  glutSwapBuffers;`\
7575`end;`
7676
7777이것은 윈도우를 배경색상으로 지우고 zbuffer를 리셋한다(zbuffer에 대해 걱정하지 마라... 뒤에 더 자세히 다룰 것이다).
7878
7979당신의 리사이즈 함수는 다음과 같을 것이다:
8080
8181`procedure ReSizeGLScene(Width, Height: Integer); cdecl;`\
8282`begin`\
8383`  if Height = 0 then`\
8484`    Height := 1;`\
85-\
85+
8686`  glViewport(0, 0, Width, Height);`\
8787`  glMatrixMode(GL_PROJECTION);`\
8888`  glLoadIdentity;`\
8989`  gluPerspective(45, Width / Height, 0.1, 1000);`\
90-\
90+
9191`  glMatrixMode(GL_MODELVIEW);`\
9292`  glLoadIdentity;`\
9393`end;`
9494
9595이 코드에서, 윈도우의 어느 곳에 그리며, 원하는 값을 행렬(matrix함수는 뒤에서 설명한다)에 설정할지를 OpenGL에게 알려주어야 한다.
9696
9797키보드 입력은 다음 콜백을 검증한다.
9898
9999`procedure GLKeyboard(Key: Byte; X, Y: Longint); cdecl;`\
100100`begin`\
101101`  if Key = 27 then`\
102102`    Halt(0);`\
103103`end;`
104104
105-이 함수는 프로그램에서 ESC 키가 눌리면 종료하도록 명령한다. GLUT는 이벤트 구동방식이므로 프로그램을 종료하는 유일한 방법은 당신의 콜백함수 중의 하나의 내부에서 <b>Halt</b>를 콜하는 것이다. 만약 다른 방법으로 윈도우를 종료한다면, 윈도우는 사라지지만 프로그램은 메인 루틴에서 무한정 루프를 계속 돌 것이다.
105+이 함수는 프로그램에서 ESC 키가 눌리면 종료하도록 명령한다. GLUT는 이벤트 구동방식이므로 프로그램을 종료하는 유일한 방법은 당신의 콜백함수 중의 하나의 내부에서 Halt를 콜하는 것이다. 만약 다른 방법으로 윈도우를 종료한다면, 윈도우는 사라지지만 프로그램은 메인 루틴에서 무한정 루프를 계속 돌 것이다.
106106
107-메인 루프를 시작하기 위해 <b>glutMainLoop</b>를 콜해야 한다. 이것은 무한 루프에 들어가 프로그램의 모든 콜백함수들을 호출하게 된다
107+메인 루프를 시작하기 위해 glutMainLoop를 콜해야 한다. 이것은 무한 루프에 들어가 프로그램의 모든 콜백함수들을 호출하게 된다
108108
109109프로그램의 메인 파트는 다음과 같은 모습을 띨 것이다:
110110
111111`const `\
112112`  AppWidth = 640; `\
113113`  AppHeight = 480; `\
114-\
114+
115115`procedure InitializeGL; `\
116116`begin `\
117117`  glClearColor(0.18, 0.20, 0.66, 0); `\
118118`end; `\
119-\
119+
120120`var `\
121121`  ScreenWidth, ScreenHeight: Integer; `\
122122`begin `\
123123`  glutInitPascal(True); `\
124124`  glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH); `\
125125`  glutInitWindowSize(AppWidth, AppHeight); `\
126126`  ScreenWidth := glutGet(GLUT_SCREEN_WIDTH); `\
127127`  ScreenHeight := glutGet(GLUT_SCREEN_HEIGHT); `\
128128`  glutInitWindowPosition((ScreenWidth - AppWidth) div 2,`\
129129`    (ScreenHeight - AppHeight) div 2); `\
130130`  glutCreateWindow('OpenGL Tutorial 1'); `\
131-\
131+
132132`  InitializeGL; `\
133-\
133+
134134`  glutDisplayFunc(@DrawGLScene); `\
135135`  glutReshapeFunc(@ReSizeGLScene); `\
136136`  glutKeyboardFunc(@GLKeyboard); `\
137-\
137+
138138`  glutMainLoop; `\
139139`end.`
140140
141141다음 튜토리얼은 간단한 도형을 그리는 몇몇 코드를 더할 것이다.
142142
143143소스코드나 리눅스/윈도우즈 실행 파일은 다음에서 다운로드 할 수가 있다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
144144
145145# 간단한 도형 그리기
146146
147147**Note:**이어지는 부분은 거의 OpenGL에 관한 것이므로 GLUT와 LCL에서 실행하여야 한다. 'glu' 접두어를 통해 GLUT에 관련된 함수라는 것을 알 수가 있다.
148148
149149이 시점에서 단지 몇 라인의 코드만을 추가 할 것이며 몇몇 OpenGL 함수에 관한 설명에 촛점을 맞출 것이다.
150150
151151다음 코드에 대해 설명할 것이다.
152152
153153`  .`\
154154`  .`\
155155`  .`\
156156`  glMatrixMode(GL_PROJECTION);`\
157157`  glLoadIdentity;`\
158158`  gluPerspective(45, Width / Height, 0.1, 1000);`\
159-\
159+
160160`  glMatrixMode(GL_MODELVIEW);`\
161161`  glLoadIdentity;`\
162162`end;`
163163
164-<b>glMatrixMode</b> 함수를 사용하여 변경하고자 하는 매트릭스(행렬)를 선택 할 수가 있다. OpenGL은 3개의 매트릭스를 이용하여 작업을 수행한다:
164+glMatrixMode 함수를 사용하여 변경하고자 하는 매트릭스(행렬)를 선택 할 수가 있다. OpenGL은 3개의 매트릭스를 이용하여 작업을 수행한다:
165165
166-<b>GL_MODELVIEW</b>: 이것은 버텍스를 모델 스페이스로 이동할 때 사용한다.
166+GL_MODELVIEW: 이것은 버텍스를 모델 스페이스로 이동할 때 사용한다.
167167
168-<b>GL_PROJECTION</b>: 이것은 최종 픽셀위치를 위해 3d 좌표를 2d 좌표로 변환하는데 사용한다.
168+GL_PROJECTION: 이것은 최종 픽셀위치를 위해 3d 좌표를 2d 좌표로 변환하는데 사용한다.
169169
170-<b>GL_TEXTURE</b>: 이것은 텍스쳐 좌표를 변경할 떄 사용한다.
170+GL_TEXTURE: 이것은 텍스쳐 좌표를 변경할 떄 사용한다.
171171
172-변화시키고자 하는 매트릭스를 선택했으면, 매트릭스 값을 변화시키는 함수를 호출하여야 한다. <b>glLoadIdentity</b>는 매트릭스를 리셋하므로 버텍스 위치에 영향을 미치지 못한다. 거의 대부분의 매트릭스 함수가 현재 매트릭스를 생성된 매트릭스와 곱하므로, 때때로 이 함수로 매트릭스를 지워주어야 한다.
172+변화시키고자 하는 매트릭스를 선택했으면, 매트릭스 값을 변화시키는 함수를 호출하여야 한다. glLoadIdentity는 매트릭스를 리셋하므로 버텍스 위치에 영향을 미치지 못한다. 거의 대부분의 매트릭스 함수가 현재 매트릭스를 생성된 매트릭스와 곱하므로, 때때로 이 함수로 매트릭스를 지워주어야 한다.
173173
174-perspective 매트릭스를 설정하기 위해 <b>gluPerspective</b> 함수를 사용할 수 있다. 네개의 파라메터는 시야(field of view), 가로세로비율(aspect ratio), 근접(near) 및 far 평면(plane)을 나타낸다. 이렇게 간단하다.
174+perspective 매트릭스를 설정하기 위해 gluPerspective 함수를 사용할 수 있다. 네개의 파라메터는 시야(field of view), 가로세로비율(aspect ratio), 근접(near) 및 far 평면(plane)을 나타낸다. 이렇게 간단하다.
175175
176176이제 모델 매트릭스를 변경할 것이며 identity만 설정하면 된다.
177177
178178좋다... 그리고 이제 첫번째 도형을 그리는 코드이다.:
179179
180180`procedure DrawGLScene; cdecl;`\
181181`begin`\
182182`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
183-\
183+
184184`  glLoadIdentity;`\
185185`  glTranslatef(0, 0, -5);`\
186-\
186+
187187`  glBegin(GL_TRIANGLES);`\
188188`    glColor3f(1, 0, 0);`\
189189`    glVertex3f(-1, -1, 0);`\
190-\
190+
191191`    glColor3f(0, 1, 0);`\
192192`    glVertex3f(1, -1, 0);`\
193-\
193+
194194`    glColor3f(0, 0, 1);`\
195195`    glVertex3f(0, 1, 0);`\
196196`  glEnd;`\
197-\
197+
198198`  glutSwapBuffers;`\
199199`end;`
200200
201201우리는 이미 glClear 함수를 사용하였다. 이것은 버퍼를 리셋하기만 한다. 우리는 다음 두 함수는를 건너뛰고 도형을 그리는 곳으로 향할 것이다.
202202
203-<b>glBegin</b>는 드로잉 블록의 시작을 표시한다. 이 함수 뒤에 버텍스를 입력을 시작할 수 있다. 파라메터는 드로잉 할 때 버텍스가 어떻게 이용되는 지를 설명해 준다:
203+glBegin는 드로잉 블록의 시작을 표시한다. 이 함수 뒤에 버텍스를 입력을 시작할 수 있다. 파라메터는 드로잉 할 때 버텍스가 어떻게 이용되는 지를 설명해 준다:
204204
205205GL_POINTS: 각 버텍스를 단일 포인트로 취급한다. 버텍스 n은 포인트 n으로 정의한다. N개의 포인트가 그려진다.
206206
207207GL_LINES: 각 버텍스 쌍을 독립적인 라인 세그컨트로 취급한다. 버텍스 2n-1과 2n은 라인 n을 정의한다. n/2개의 라인이 그려진다.
208208
209209GL_LINE_STRIP: 첫번째 버텍스에서 마지막까지 라인세그먼트의 연결된 그룹을 그린다. n-1개의 라인이 그려진다.
210210
211211GL_LINE_LOOP: 첫번째 버텍스에서 마지막까지 라인세그먼트의 연결된 그룹을 그린다. 그리고 첫번째 버텍스로 그린다. n과 n+1째 버텍스는 라인 n을 정의한다. 그러나 마지막 라인은 n과 1로 정의된다. n개의 라인이 그려진다.
212212
213213GL_TRIANGLES: 각 세개의 버텍스를 독립된 삼각형으로 취급한다. 버텍스 3n-2, 3n-1 및 3n은 삼각형 n을 정의한다. n/3개의 삼각형이 그려진다.
214214
215215GL_TRIANGLE_STRIP: 삼각형이 연결된 그룹을 그린다. 한개의 삼각형은 각 버텍스가 앞 두 버텍스와 함께 정의된다. 홀수 n에서 버텍스 n, n+1, n+2는 삼각형 n을 정의한다. 짝수 n에서, 버텍스 n+1, n 및 n+2는 삼각형 n을 정의한다. n-2개의 삼각형이 그려진다.
216216
217217GL_TRIANGLE_FAN: 삼각형이 연결된 그룹을 그린다. 한개의 삼각형은 각 버텍스가 앞 두 버텍스와 함께 정의된다. 버텍스 1, n+1 및 n+2는 삼각형 n으로 정의한다. n-2개의 삼각형이 그려진다.
218218
219219GL_QUADS: 각 네개의 버텍스를 독립된 사각형으로 취급한다. 버텍스 4n-3, 4n-2, 4n-1 및 4n은 사각형을 정의한다. n/4개의 사각형이 그려진다.
220220
221221GL_QUAD_STRIP: 사각형이 연결된 그룹을 그린다. 한개의 사각형은 각 쌍의 버텍스가 앞의 한쌍과 함께 정의된다. 버텍스 2n-1, 2n, 2n+2 및 2n+1 는 사각형 n을 정의한다. n/2-1개의 사각형이 그려진다. 스트립 데이타 중의 어떤 버텍스가 사각형을 그리는데 사용되는지의 순서가 독립적인 데이타 함께사용 될 때는 다르다.
222222
223223GL_POLYGON: 한개의 볼록 다각형을 그린다. 버텍스 1에서 n은 이 다각형을 정의한다.
224224
225-![](/wiki-images/f/f3/SimpleShapePic1.jpg) 한개의 삼각형을 그릴 수 있으며, 이를 위해 TRIANGLES 플래그가 트릭으로 사용된다. <b>glVertex3f</b> 함수는 그리고자 하는 버텍스의 위치를 정의한다. 더 많은 glVertex* 함수가 있다. 유일한 차이점은 필요로 하는 파라메터의 수와 타입이다.예를 들면... glVertex2i 는 두개의 파라메터 정수형 (x 및y)를 취한다. glVertex3f 는 거의 항상 당신이 필요로 하는 것일 것이다.
225+![](/wiki-images/f/f3/SimpleShapePic1.jpg) 한개의 삼각형을 그릴 수 있으며, 이를 위해 TRIANGLES 플래그가 트릭으로 사용된다. glVertex3f 함수는 그리고자 하는 버텍스의 위치를 정의한다. 더 많은 glVertex* 함수가 있다. 유일한 차이점은 필요로 하는 파라메터의 수와 타입이다.예를 들면... glVertex2i 는 두개의 파라메터 정수형 (x 및y)를 취한다. glVertex3f 는 거의 항상 당신이 필요로 하는 것일 것이다.
226226
227-glVertex 전에 색상, material, 텍스쳐...를 설정할 수 있다. 간단하게 하기 위해 이 튜토리얼에서는 각 버텍스에 색상을 부여할 것이다. 색상은 <b>glColor3f</b>함수를 사용하여 설정한다. glColor 는 glVertex 같이 다른 셋의 파라메터를 취할 수 있다.
227+glVertex 전에 색상, material, 텍스쳐...를 설정할 수 있다. 간단하게 하기 위해 이 튜토리얼에서는 각 버텍스에 색상을 부여할 것이다. 색상은 glColor3f함수를 사용하여 설정한다. glColor 는 glVertex 같이 다른 셋의 파라메터를 취할 수 있다.
228228
229-코드를 통해 보았듯이 모든 버텍스에서 Z는 0으로 설정되어 있었다. near plane을 0.1로 설정하였으므로 삼각형은 보이지 않을 것이다. 그것은 시작 부분에서 건너뛴 두 함수가 점프한 곳이 그곳이기 때문이다. glLoadIdentity 함수가 매트릭스를 리셋한다는 것을 이미 알고 있다. <b>glTranslatef</b>는 삼각형을 X, Y 및 Z값 만큼 이동시킨다. Z를 -5로 설정하였기 때문에(마이너스 Z는 카메라로 부터 멀리 떨어져 있는 것이다) 모든 버텍스는 우리가 볼 수 있는 뷰에서 5유닛 만큼 후퇴해 있다.
229+코드를 통해 보았듯이 모든 버텍스에서 Z는 0으로 설정되어 있었다. near plane을 0.1로 설정하였으므로 삼각형은 보이지 않을 것이다. 그것은 시작 부분에서 건너뛴 두 함수가 점프한 곳이 그곳이기 때문이다. glLoadIdentity 함수가 매트릭스를 리셋한다는 것을 이미 알고 있다. glTranslatef는 삼각형을 X, Y 및 Z값 만큼 이동시킨다. Z를 -5로 설정하였기 때문에(마이너스 Z는 카메라로 부터 멀리 떨어져 있는 것이다) 모든 버텍스는 우리가 볼 수 있는 뷰에서 5유닛 만큼 후퇴해 있다.
230230
231-마지막에서 <b>glEnd</b>함수를 호출하여 드로잉을 종료한다. 원한다면 이제 새로운 glBegin 함수와 함께 또 다른 블록을 시작할 수가 있다.
231+마지막에서 glEnd함수를 호출하여 드로잉을 종료한다. 원한다면 이제 새로운 glBegin 함수와 함께 또 다른 블록을 시작할 수가 있다.
232232
233233소스코드, 리눅스 실행파일, 또는 윈도우즈 실행파일은 다음에서 다운로드 받을 수 있다: [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
234234
235235# 디스플레이 리스트 사용하기
236236
237-가끔 한 장면(scene)에서 몇몇 오브젝트를 여러 번 그려야 할 때가 있을 것이다. OpenGL은 더 빠르게 그릴 수 있는 <b>display lists</b>를 빌드할 수 있다. 디스플레이 리스트를 생성하는 것은 매우 쉽다.... 이전의 튜토리얼 처럼 버텍스들을 그리기만 하고 <b>glNewList</b> 와 <b>glEndList</b> 호출로 묶어주기만 하면 된다.
237+가끔 한 장면(scene)에서 몇몇 오브젝트를 여러 번 그려야 할 때가 있을 것이다. OpenGL은 더 빠르게 그릴 수 있는 display lists를 빌드할 수 있다. 디스플레이 리스트를 생성하는 것은 매우 쉽다.... 이전의 튜토리얼 처럼 버텍스들을 그리기만 하고 glNewList 와 glEndList 호출로 묶어주기만 하면 된다.
238238
239239`const`\
240240`  LIST_OBJECT = 1;`\
241-\
241+
242242`procedure CreateList;`\
243243`begin`\
244244`  glNewList(LIST_OBJECT, GL_COMPILE);`\
245245`    glBegin(GL_TRIANGLE_FAN);`\
246246`      glColor3f(1, 0, 0);`\
247247`      glVertex3f(0, 0.5, 0);`\
248-\
248+
249249`      glColor3f(1, 1, 0);`\
250250`      glVertex3f(-0.5, -0.5, 0.5);`\
251-\
251+
252252`      glColor3f(1, 1, 1);`\
253253`      glVertex3f(0.5, -0.5, 0.5);`\
254-\
254+
255255`      glColor3f(0, 1, 1);`\
256256`      glVertex3f(0.5, -0.5, -0.5);`\
257-\
257+
258258`      glColor3f(0, 0, 1);`\
259259`      glVertex3f(-0.5, -0.5, -0.5);`\
260-\
260+
261261`      glColor3f(0, 1, 0);`\
262262`      glVertex3f(-0.5, -0.5, 0.5);`\
263263`    glEnd;`\
264-\
264+
265265`    glBegin(GL_QUADS);`\
266266`      glColor3f(1, 1, 0);`\
267267`      glVertex3f(-0.5, -0.5, 0.5);`\
268-\
268+
269269`      glColor3f(1, 1, 1);`\
270270`      glVertex3f(0.5, -0.5, 0.5);`\
271-\
271+
272272`      glColor3f(0, 1, 1);`\
273273`      glVertex3f(0.5, -0.5, -0.5);`\
274-\
274+
275275`      glColor3f(0, 0, 1);`\
276276`      glVertex3f(-0.5, -0.5, -0.5);`\
277-\
277+
278278`      glColor3f(0, 1, 0);`\
279279`      glVertex3f(-0.5, -0.5, 0.5);`\
280280`    glEnd;`\
281281`  glEndList;`\
282282`end;`
283283
284-<b>glNewList</b> 는 새로운 리스트를 생성하고 모든 그리기 함수는 <b>glEndList</b>를 호출하기 전까지는 기록이 된다. glNewList 함수에 대한 첫번째 파라메터는 리스트 ID이다. 각 리스트는 각각의 ID에 의해 정의된다. 만약 리스트가 기존의 ID로 생성되면 이전의 기록은 지워질 것이다. 만약 두번째 파라메터가 GL_COMPILE이면 모든 드로잉 함수는 바로 기록이 될 것이지만, GL_COMPILE_AND_EXECUTE라면 자동적으로 기록되고 실행될 것이다.
284+glNewList 는 새로운 리스트를 생성하고 모든 그리기 함수는 glEndList를 호출하기 전까지는 기록이 된다. glNewList 함수에 대한 첫번째 파라메터는 리스트 ID이다. 각 리스트는 각각의 ID에 의해 정의된다. 만약 리스트가 기존의 ID로 생성되면 이전의 기록은 지워질 것이다. 만약 두번째 파라메터가 GL_COMPILE이면 모든 드로잉 함수는 바로 기록이 될 것이지만, GL_COMPILE_AND_EXECUTE라면 자동적으로 기록되고 실행될 것이다.
285285
286-<b>glIsList</b> 함수는 디스플레이 함수 사용에 도움을 준다. 이것은 어떤 리스트 ID가 이미 데이터로 사용되고 있는 지를 알려준다. 다른 유용한 함수는 <b>glGenLists</b>이다. 이것은 다수의 텅빈 디스플레이 리스트르 생성할 것이다. 원하는 디스플레이 리스트 수를 넘기면 첫번째의 ID를 얻을 수 있을것이다. n 리스트를 원하면 r ID를 받을 것이고 생성된 리스트는: r, r+1, r+2,..., r+n-1 이 된다.
286+glIsList 함수는 디스플레이 함수 사용에 도움을 준다. 이것은 어떤 리스트 ID가 이미 데이터로 사용되고 있는 지를 알려준다. 다른 유용한 함수는 glGenLists이다. 이것은 다수의 텅빈 디스플레이 리스트르 생성할 것이다. 원하는 디스플레이 리스트 수를 넘기면 첫번째의 ID를 얻을 수 있을것이다. n 리스트를 원하면 r ID를 받을 것이고 생성된 리스트는: r, r+1, r+2,..., r+n-1 이 된다.
287287
288288생성된 모든 리스트는 제거해야만 한다. 프로그램을 종료하기 전에 실행하여야 한다:
289289
290290`procedure GLKeyboard(Key: Byte; X, Y: Longint); cdecl;`\
291291`begin`\
292292`  if Key = 27 then`\
293293`  begin`\
294294`    glDeleteLists(LIST_OBJECT, 1);`\
295295`    Halt(0);`\
296296`  end;`\
297297`end;`
298298
299-<b>glDeleteLists</b>는 2개의 파라메터 즉, 삭제하려고하는 디스플레이 리스트의 ID 와 리스트의 수를 필요로 한다. 만약 ID가 r 이고 삭제하려는 리스트의 수가 n이라면 삭제되는 리스트는: r, r+1, r+2,..., r+n-1 이다.
299+glDeleteLists는 2개의 파라메터 즉, 삭제하려고하는 디스플레이 리스트의 ID 와 리스트의 수를 필요로 한다. 만약 ID가 r 이고 삭제하려는 리스트의 수가 n이라면 삭제되는 리스트는: r, r+1, r+2,..., r+n-1 이다.
300300
301301이제 디스플레이 리스트를 생성하고 삭제하는 방법을 알았다... 이것들을 어떻게 그리는 지 알아보자:
302302
303303`procedure DrawGLScene; cdecl;`\
304304`begin`\
305305`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
306-\
306+
307307`  glLoadIdentity;`\
308308`  glTranslatef(-2, 0, -5);`\
309309`  glRotatef(40, 1, 0, 1);`\
310310`  glCallList(LIST_OBJECT);`\
311-\
311+
312312`  glLoadIdentity;`\
313313`  glTranslatef(1, -2, -10);`\
314314`  glRotatef(62, 0, 1, 0);`\
315315`  glCallList(LIST_OBJECT);`\
316-\
316+
317317`  glLoadIdentity;`\
318318`  glTranslatef(-4, 0.5, -15);`\
319319`  glRotatef(200, 1, 0, 0);`\
320320`  glCallList(LIST_OBJECT);`\
321-\
321+
322322`  glutSwapBuffers;`\
323323`end;`
324324
325-![](/wiki-images/a/a5/DisplayListsPic1.jpg) <b>glCallList</b>를 사용하면 당 한개의 디스플레이 리스트를 그릴 수 있다. 이 튜토리얼에서, 디스플레이 리스트를 그리기 전에, 모델 매트릭스를 변경하고 다른 위치에 오브넥트를 그려야 한다.
325+![](/wiki-images/a/a5/DisplayListsPic1.jpg) glCallList를 사용하면 당 한개의 디스플레이 리스트를 그릴 수 있다. 이 튜토리얼에서, 디스플레이 리스트를 그리기 전에, 모델 매트릭스를 변경하고 다른 위치에 오브넥트를 그려야 한다.
326326
327-가끔은 한번에 여러 개의 리스트를 그리고 싶을 것이다. <b>glCallLists</b> 함수를 사용한다면 가능하다. 이것은 그리고자 하는 리스트의 수, 디스플레이 리스트 ID를 가진 배열의 타입 및 디스플레이 리스트 ID를 가진 배열을 받는다. 리스트의 타입은 다음 중의 하나이다:
327+가끔은 한번에 여러 개의 리스트를 그리고 싶을 것이다. glCallLists 함수를 사용한다면 가능하다. 이것은 그리고자 하는 리스트의 수, 디스플레이 리스트 ID를 가진 배열의 타입 및 디스플레이 리스트 ID를 가진 배열을 받는다. 리스트의 타입은 다음 중의 하나이다:
328328
329329GL_BYTE: 리스트는 -128에서 127까지의 부호있는 바이트의 배열로 취급한다.
330330
331331GL_UNSIGNED_BYTE: 리스트는 0에서 255까지의 부호없는 바이트의 배열로 취급한다.
332332
333333GL_SHORT: 리스트는 -32768에서 32767까지의 부호있는 두 바이트 정수의 배열로 취급한다.
334334
335335GL_UNSIGNED_SHORT: 리스트는 0에서 65535까지의 부호없는 두 바이트 정수의 배열로 취급한다.
336336
337337GL_INT: 리스트는 부호있는 네자리 정수의 배열로 취급한다.
338338
339339GL_UNSIGNED_INT: 리스트는 부호없는 네자리 정수의 배열로 취급한다.
340340
341341GL_FLOAT: 리스트는 네자리 부동소수점 배열로 취급한다.
342342
343343GL_2_BYTES: 리스트는 부호없는 바이트의 배열로 취급한다. 각 바이트 쌍은 단일한 디스플레이 리스트 ID를 지정한다. 각 쌍의 값은 부호없는 첫번째 바이트 값과 부호없는 두번째 바이트 값의 합을 256회 계산한다.
344344
345345GL_3_BYTES: 리스트는 부호없는 바이트의 배열로 취급한다. 각 바이트 세 개쌍(triplet)는 단일한 디스플레이 리스트 ID를 지정한다. 세 개쌍의 값은 단일한 디스플레이 리스트 ID를 지정한다. 세 개쌍의 값은 65536회 계산한다. 부호없는 첫번째 바이트 값과 부호없는 두번째 바이트 값의 합을 256회 계산하고 세번째 바이트 값을 더한다.
346346
347347GL_4_BYTES: 리스트는 부호없는 바이트의 배열로 취급한다. 각 바이트 네 개쌍(triplet)는 단일한 디스플레이 리스트 ID를 지정한다. 네 개쌍의 값은 단일한 디스플레이 리스트 ID를 지정한다. 네 개쌍의 값은 16777216회 계산한다. 부호없는 첫번째 바이트 값과 부호없는 두번째 바이트 값의 합을 65535회 계산하고 세번째 바이트 값을 더하고 256회 계산 한 후 네번째 부호없는 바이트를 더한다.
348348
349349다음 튜토리얼은 작은 행성계를 만드는 방법을 보여 줄 것이다. 매트릭스 및 초당 프레임에 얽매이지 않는 움직이는 장면(scene)을 만드는 방법에 대하여 이야기 할 것이다.
350350
351351소스, 리눅스 실행파일과 윈도우즈 실행파일은 다음에서 다운로드 할 수 있다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
352352
353353# 풀스크린 애니메이션
354354
355355GLUT에서 전화면 모드로 진입하는 것은 쉽다. 프로그램의 주요한 부분을 변경해 보자:
356356
357357`const`\
358358`  FSMode = '800x600:32@75';`\
359-\
359+
360360`begin`\
361361`  glutInitPascal(False);`\
362362`  glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);`\
363363`  glutGameModeString(FSMode);`\
364364`  glutEnterGameMode;`\
365365`  glutSetCursor(GLUT_CURSOR_NONE);`\
366-\
366+
367367`  InitializeGL;`\
368-\
368+
369369`  glutDisplayFunc(@DrawGLScene);`\
370370`  glutReshapeFunc(@ReSizeGLScene);`\
371371`  glutKeyboardFunc(@GLKeyboard);`\
372372`  glutIdleFunc(@DrawGLScene);`\
373-\
373+
374374`  glutMainLoop;`\
375375`end.`
376376
377-이 시점에서 GLUT가 명령어 라인을 파싱하기를 원치 않기 때문에 glutInitPascal 에 False파라메터를 주어 호출한다. 아시다시피 윈도우 생성을 위한 코드가 없다. GLUT는 풀스크린 모드의 윈도우 생성을 위한 <b>glutEnterGameMode</b>를 제공한다. 어떤 종류의 풀스크린 모드를 원하는지 알기 위해 모드 정의를 위한 문자열을 가지는 <b>glutGameModeString</b> 함수를 호출할 수 있다.
377+이 시점에서 GLUT가 명령어 라인을 파싱하기를 원치 않기 때문에 glutInitPascal 에 False파라메터를 주어 호출한다. 아시다시피 윈도우 생성을 위한 코드가 없다. GLUT는 풀스크린 모드의 윈도우 생성을 위한 glutEnterGameMode를 제공한다. 어떤 종류의 풀스크린 모드를 원하는지 알기 위해 모드 정의를 위한 문자열을 가지는 glutGameModeString 함수를 호출할 수 있다.
378378
379379문자열을 형식은 다음과 같다:
380380
381381`[width "x" height][":" bpp]["@" hertz]`
382382
383383FSMode에서 풀스크린 모드를 정의하는 문자열은 800x600, 32비트 팔레트 및 75hz 리프레쉬여야 한다. 이들 중 한가지를 건너 뛰어도 좋다. 만약 크리를 빼먹었다면 GLUT는 현재의 크기를 사용하거나 작동할 수 있는 첫번째로 작은 크기를 이용한다. 이런 방식은 다른 파라메터도 마찬가지이다.
384384
385-종종 풀스크린 모드에서 커서는 보이지 않게 된다. 커서를 숨기기 위해 <b>glutSetCursor</b> 함수를 사용하면 된다. 이 함수는 나타내고자 하는 커서중의 하나를 파라메터로 갖게 된다:
385+종종 풀스크린 모드에서 커서는 보이지 않게 된다. 커서를 숨기기 위해 glutSetCursor 함수를 사용하면 된다. 이 함수는 나타내고자 하는 커서중의 하나를 파라메터로 갖게 된다:
386386
387387`GLUT_CURSOR_RIGHT_ARROW`\
388388`GLUT_CURSOR_LEFT_ARROW`\
389389`GLUT_CURSOR_INFO`\
390390`GLUT_CURSOR_DESTROY`\
391391`GLUT_CURSOR_HELP`\
392392`GLUT_CURSOR_CYCLE`\
393393`GLUT_CURSOR_SPRAY`\
394394`GLUT_CURSOR_WAIT`\
395395`GLUT_CURSOR_TEXT`\
396396`GLUT_CURSOR_CROSSHAIR`\
397397`GLUT_CURSOR_UP_DOWN`\
398398`GLUT_CURSOR_LEFT_RIGHT`\
399399`GLUT_CURSOR_TOP_SIDE`\
400400`GLUT_CURSOR_BOTTOM_SIDE`\
401401`GLUT_CURSOR_LEFT_SIDE`\
402402`GLUT_CURSOR_RIGHT_SIDE`\
403403`GLUT_CURSOR_TOP_LEFT_CORNER`\
404404`GLUT_CURSOR_TOP_RIGHT_CORNER`\
405405`GLUT_CURSOR_BOTTOM_RIGHT_CORNER`\
406406`GLUT_CURSOR_BOTTOM_LEFT_CORNER`\
407407`GLUT_CURSOR_FULL_CROSSHAIR`\
408408`GLUT_CURSOR_NONE`\
409409`GLUT_CURSOR_INHERIT`
410410
411-<b>glutIdleFunc</b>는 프로그램이 처리 할 메세지를 갖지 않을 때마다 호출되는 콜백함수이다. 수행해야할 작업이 없으면 새로운 프레인을 런더링하기만 원한다면 아이들(idle) 함수를 DrawGLScene에 설정하기만 하면 된다. 몇몇 다른 튜토리얼은 아이들 함수는 드로잉 대신 리프레쉬 메세지를 보내야한다고 하지만 그 방법은 전술한 방법을 사용한 것 보다 50~100 프레임 작게 된다. 이제 풀스크린 모드를 마치는 프로그램 종료에 대해서 알아보자:
411+glutIdleFunc는 프로그램이 처리 할 메세지를 갖지 않을 때마다 호출되는 콜백함수이다. 수행해야할 작업이 없으면 새로운 프레인을 런더링하기만 원한다면 아이들(idle) 함수를 DrawGLScene에 설정하기만 하면 된다. 몇몇 다른 튜토리얼은 아이들 함수는 드로잉 대신 리프레쉬 메세지를 보내야한다고 하지만 그 방법은 전술한 방법을 사용한 것 보다 50~100 프레임 작게 된다. 이제 풀스크린 모드를 마치는 프로그램 종료에 대해서 알아보자:
412412
413413`procedure GLKeyboard(Key: Byte; X, Y: Longint); cdecl;`\
414414`begin`\
415415`  if Key = 27 then`\
416416`  begin`\
417417`    glutLeaveGameMode;`\
418418`    Halt(0);`\
419419`  end;`\
420420`end;`
421421
422-알다시피 <b>glutLeaveGameMode</b>를 호출하는 것이 전부이다.
422+알다시피 glutLeaveGameMode를 호출하는 것이 전부이다.
423423
424424이제 새로운 매트릭스 함수를 몇개를 소개할 것이다. ReSizeGLScene 함수를 변경해 보자:
425425
426426`procedure ReSizeGLScene(Width, Height: Integer); cdecl;`\
427427`begin`\
428428`  .`\
429429`  .`\
430430`  .`\
431431`  glMatrixMode(GL_MODELVIEW);`\
432432`  glLoadIdentity;`\
433433`  gluLookAt(0, 20, 25, 0, 0, 0, 0, 1, 0);`\
434434`end;`
435435
436-<b>gluLookAt</b> 는 어디에서 오브젝트를 보는지를 정의하는 매트릭스를 생성할 것이다. 첫 세 파라메터는 카메라 위치에 대한 X, Y 및 Z좌표이다. 다음 세 파라메터는 카메라가 보라보는 점의 X, Y 및 Z 좌표이다. 마지막 세 파라메터는 "up" 벡터를 정의한다("up"은 카메라에 대한 것이다). 보통 up은 +y축이다.
436+gluLookAt 는 어디에서 오브젝트를 보는지를 정의하는 매트릭스를 생성할 것이다. 첫 세 파라메터는 카메라 위치에 대한 X, Y 및 Z좌표이다. 다음 세 파라메터는 카메라가 보라보는 점의 X, Y 및 Z 좌표이다. 마지막 세 파라메터는 "up" 벡터를 정의한다("up"은 카메라에 대한 것이다). 보통 up은 +y축이다.
437437
438438좋다. 이제 그려 보자. 모든 오브젝트에대해 사용되어야 하는 gluLookAt 으로 매트릭스를 설정해야 하므로, 다음 오브젝트를 위해 매트릭스를 리셋하기 위해 glLoadIdentity만 사용할 수는 없다. 이전의 매트릭스 상태를 저장하고 오젝트를 그린 후 복원시켜야 한다:
439439
440440`procedure DrawGLScene; cdecl;`\
441441`var`\
442442`  T: Single;`\
443443`begin`\
444444`  T := glutGet(GLUT_ELAPSED_TIME) / 1000;`\
445445`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
446-\
446+
447447`  glPushMatrix;`\
448448`    glRotatef(5 * T, 0, 1, 0);`\
449449`    glColor3f(1, 1, 0);`\
450450`    glutWireSphere(2, 20, 20);`\
451451`  glPopMatrix;`\
452-\
452+
453453`  glPushMatrix;`\
454454`    glRotatef(90 * T, 0, 1, 0);`\
455455`    glTranslatef(5, 0, 0);`\
456456`    glRotatef(40 * T, 0, 1, 0);`\
457457`    glColor3f(1, 0, 0);`\
458458`    glutWireSphere(0.6, 10, 10);`\
459459`  glPopMatrix;`\
460-\
460+
461461`  glPushMatrix;`\
462462`    glRotatef(60 * T, 0, 1, 0);`\
463463`    glTranslatef(-3, 0, 9);`\
464464`    glRotatef(50 * T, 0, 1, 0);`\
465465`    glColor3f(0, 1, 0);`\
466466`    glutWireSphere(1, 16, 16);`\
467-\
467+
468468`    glPushMatrix;`\
469469`      glRotatef(360 * T, 0, 1, 0);`\
470470`      glTranslatef(-1.7, 0, 0);`\
471471`      glRotatef(50 * T, 0, 1, 0);`\
472472`      glColor3f(0, 0, 1);`\
473473`      glutWireSphere(0.4, 10, 10);`\
474474`    glPopMatrix;`\
475-\
475+
476476`  glPopMatrix;`\
477-\
477+
478478`  glutSwapBuffers;`\
479479`end;`
480480
481-![](/wiki-images/5/51/FullScreenAnimationPic1.jpg) <b>glPushMatrix</b> i <b>glPopMatrix</b> 가 매트릭스의 상태를 저장하고 복원하는데 시용된다. 이제 매트릭스 상태를 저장하였고, 오브젝트를 올바른 위치에 그리기 위해 매트릭스를 변경하고 다시, 이전의 매트릭스 상태를 복원한다.
481+![](/wiki-images/5/51/FullScreenAnimationPic1.jpg) glPushMatrix i glPopMatrix 가 매트릭스의 상태를 저장하고 복원하는데 시용된다. 이제 매트릭스 상태를 저장하였고, 오브젝트를 올바른 위치에 그리기 위해 매트릭스를 변경하고 다시, 이전의 매트릭스 상태를 복원한다.
482482
483-<b>T</b>변수가 무엇인지 궁금할 것이다. 이것은 애니메이션 속도를 결정하기 위해 사용된다. 시간에 따른 모든 변화는 T와 곱해진다.그 방법으로 애니메이션 속도는 각 프레임 레이트에서 일정하게 유지된다.
483+T변수가 무엇인지 궁금할 것이다. 이것은 애니메이션 속도를 결정하기 위해 사용된다. 시간에 따른 모든 변화는 T와 곱해진다.그 방법으로 애니메이션 속도는 각 프레임 레이트에서 일정하게 유지된다.
484484
485-<b>glutGet</b> 함수는 <b>GLUT_ELAPSED_TIME</b> 파라메터 일 때 glutInit의 호출로 부터 밀리초 단위의 시간을 되돌려 준다. 이 값을 1000으로 나누어 초단위의 시간을 얻는다.
485+glutGet 함수는 GLUT_ELAPSED_TIME 파라메터 일 때 glutInit의 호출로 부터 밀리초 단위의 시간을 되돌려 준다. 이 값을 1000으로 나누어 초단위의 시간을 얻는다.
486486
487-<b>glRotatef</b> 함수는 회전 매트릭스이다. 첫 파라메터는 각도(도)이고 다음 세 파라메터는 회전을 하는 축이다. 각과 T를 곱했기 때문에 오브젝트는 정확히 1초당의 각도로 회전할 것이다.
487+glRotatef 함수는 회전 매트릭스이다. 첫 파라메터는 각도(도)이고 다음 세 파라메터는 회전을 하는 축이다. 각과 T를 곱했기 때문에 오브젝트는 정확히 1초당의 각도로 회전할 것이다.
488488
489489소스코드, 리눅스 실행파일 및 윈도우즈 실행 파일은 다음에서 다운로드할 수 있다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
490490
491491# 조명(Light)
492492
493493이 튜토리얼은 장면(scene)에 조명하는 것을 소개한다. 회전하는 육면체를 만들고 장면에 사실감을 부여하는 조명 하나를 만들고자 할 것이다 먼저 몇몇 유틸리티 유닛을 만들어 보자.
494494
495495이것은 다음의 작업을 도와줄 기초적인 함수들을 가지고 있어 현재 시간과 한가지 렌더링과 다음번 렌터링 콜 사이의 시간(delta) 및 초당 프레임 수를 계산해 준다.
496496
497497`unit utils;`\
498-\
498+
499499`{$mode objfpc}{$H+}`\
500-\
500+
501501`interface`\
502-\
502+
503503`uses`\
504504`  glut;`\
505-\
505+
506506`function GetTotalTime: Single;`\
507507`function GetDeltaTime: Single;`\
508508`procedure FrameRendered(Count: Integer = 1);`\
509509`function GetFPS: Single;`\
510-\
510+
511511`implementation`\
512-\
512+
513513`var`\
514514`  OldTime: Integer = 0;`\
515515`  FPSTime: Integer = 0;`\
516516`  FPSCount: Integer = 0;`\
517-\
517+
518518`function GetTotalTime: Single;`\
519519`begin`\
520520`  Result := glutGet(GLUT_ELAPSED_TIME) / 1000;`\
521521`end;`\
522-\
522+
523523`function GetDeltaTime: Single;`\
524524`var`\
525525`  NewTime: Integer;`\
526526`begin`\
527527`  NewTime := glutGet(GLUT_ELAPSED_TIME);`\
528528`  Result := (NewTime - OldTime) / 1000;`\
529529`  OldTime := NewTime;`\
530530`end;`\
531-\
531+
532532`procedure FrameRendered(Count: Integer);`\
533533`begin`\
534534`  Inc(FPSCount, Count);`\
535535`end;`\
536-\
536+
537537`function GetFPS: Single;`\
538538`var`\
539539`  NewTime: Integer;`\
540540`begin`\
541541`  NewTime := glutGet(GLUT_ELAPSED_TIME);`\
542-\
542+
543543`  Result := FPSCount / ((NewTime - FPSTime) / 1000);`\
544-\
544+
545545`  FPSTime := NewTime;`\
546546`  FPSCount := 0;`\
547547`end;`\
548-\
548+
549549`end.`
550550
551551이 유닛에 복잡한 것은 전혀 없다. 단순히 호출 간격의 시간을 저장하고차이를 되돌려 준다. FrameRendered 는 장면이 그려지는 매 시간마다 불러야하며 그래야 함수가 FPS를 계산할 수 있다.
552552
553553이제 조명을 가지고 재미있게 지내보자.
554554
555555OpenGL은 몇가지 종류의 라이트가 있다... ambient, diffuse, point, spot, specular 및 emissive 등 이다.
556556
557557Ambient 라이트는 태양과 유사한 것이다. 햇빛이 방에 있는 창을 통과해 비추면 빛은 벽에 부딪치고 반사되고 모든 다른 방향으로 산란되어 평균적으로 방 전체를 밝게 해준다. 모든 버텍스는 ambient 조명으로 밝게 된다.
558558
559559Diffuse 라이트는 아주 멀리서 오는 평행광으로 간주 된다. 이것은 조명원 방향의 버텍스만 밝게 된다.
560560
561561Point 라이트는 모든 방향으로 빛을 비춘다. 이것은 불덩이 같아서 모든 방향으로 빛을 발산하고 조명원 방향으로 있으며 가까이 있는 버텍스들을 비춘다.
562562
563563Spot 라이트는 플레쉬 라이트에서 오는 조명으로 좁은 반경의 점 광원이다. 콘의 내부에 있는 모든 버텍스는 충분히 가까워 밝게 비춰 진다.
564564
565565Diffuse 라이트와 같이 Specular 라이트는 방향이 있는 라이트이다. 이것은 하나의 특별한 방향에서 온다. 두개의 차이라면 specular 라이트는 표면에서 단일한 방법과 날카롭게 반사한다. specular 라이트를 렌더링하는 것은 관찰자와 광원의 각에 따라 달라진다.관찰자의 관점에서 specular 라이트는 보이는 오브젝트의 표면영역에 specular 하이라이트 또는 specular 반사라는 밝게 빛나는 구역을 만들어 낸다.
566566
567567Emissive 라이트는 이전에 절명한 라이트 와는 약간 차이가 있다. 이 라이트는 그린 오브젝트에서 나오며가까이 있는 다른 오브젝트를 비추지 않는다.
568568
569569간단하게 이 튜토리얼에서는 diffuse 라이트만을 사용할 것이다. 추후에는 몇몇 다른 라이트도 튜토리얼에 나올 수 있다 :)
570570
571571장면에서 라이트를 사용가능하게하는 방법을 알아보자:
572572
573573`const`\
574574`  DiffuseLight: array[0..3] of GLfloat = (0.8, 0.8, 0.8, 1);`\
575-\
575+
576576`  glEnable(GL_LIGHTING);`\
577577`  glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);`\
578578`  glEnable(GL_LIGHT0);`
579579
580-보듯이 OpenGL에서 라이트를 사용가능하게 했으므로 라이트는 렌더링한 장면에 영향을 준다. 라이트 파라메터를 <b>glLightfv</b> 함수에서 설정한다. 3개의 파라메터를 가지며 하나는변화를 주고자 하는 라이트의 수(OpenGL은 8개의 라이트를 지원한다.), 다음은 변화를 주고자 하는 라이트 파라메터를 OpenGL에 알려 주는 것이고 마지막은라이트를 위한 새로운 파라메터이다. 이 튜토리얼에서는 diffuse 컬러만을 설정할 것이다. 그 후, 라이트를 사용가능하게 하면 장면에 라이트가 보일 것이다.. 그러나 이것이 다는 아니다.
580+보듯이 OpenGL에서 라이트를 사용가능하게 했으므로 라이트는 렌더링한 장면에 영향을 준다. 라이트 파라메터를 glLightfv 함수에서 설정한다. 3개의 파라메터를 가지며 하나는변화를 주고자 하는 라이트의 수(OpenGL은 8개의 라이트를 지원한다.), 다음은 변화를 주고자 하는 라이트 파라메터를 OpenGL에 알려 주는 것이고 마지막은라이트를 위한 새로운 파라메터이다. 이 튜토리얼에서는 diffuse 컬러만을 설정할 것이다. 그 후, 라이트를 사용가능하게 하면 장면에 라이트가 보일 것이다.. 그러나 이것이 다는 아니다.
581581
582582glLightfv에 관한 더많은 정보는 다음에 있다: <http://www.opengl.org//documentation/specs/man_pages/hardcopy/GL/html/gl/light.html>
583583
584584만약 라이트를 사용하길 원한다면 버텍스에 대해서만 컬러를 설정할 수는 없다... 반드시 버텍스에 재질(material)을 설정해야 한다. 드로잉을 위해 재질을 설정해 보자:
585585
586586`glEnable(GL_COLOR_MATERIAL);`\
587587`glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);`
588588
589-![](/wiki-images/e/ed/LightPic1.jpg) 괭장히 복잡한 것을 기대했을 지도 모른다.. 그렇죠 :) 좋다. 이 코드가 버텍스에 재질을 설정하기 위해 사용하는 glColor 를 사용할 수 있게 해준다. glEnable 함수와 GL_COLOR_MATERIAL 플래그를 사용하여, 무슨 재질 특성이 glColor 를 변화하게 하는지를 정의 할 수 있다. <b>glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)</b> 은 OpenGL 에게 glColor 가 ambient 하고 diffuse한 재질을 변경하도록 알려준다. 다음의 튜토리얼에서 재질에 관해서 더 이야기할 것이다.
589+![](/wiki-images/e/ed/LightPic1.jpg) 괭장히 복잡한 것을 기대했을 지도 모른다.. 그렇죠 :) 좋다. 이 코드가 버텍스에 재질을 설정하기 위해 사용하는 glColor 를 사용할 수 있게 해준다. glEnable 함수와 GL_COLOR_MATERIAL 플래그를 사용하여, 무슨 재질 특성이 glColor 를 변화하게 하는지를 정의 할 수 있다. glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) 은 OpenGL 에게 glColor 가 ambient 하고 diffuse한 재질을 변경하도록 알려준다. 다음의 튜토리얼에서 재질에 관해서 더 이야기할 것이다.
590590
591591라이트를 사용할 때 중요한 것이 하나 더 있다. 모든 버텍스는 라이트와 normal하게 연관이 있어야만 하는 것이다. Normal은 버텍스의 방향을 알아내는데 사용되므로 적절하게 게산될 수 있다. 육면체를 그리기 위해 GLUT함수를 이용할 수 있으며 이것에서 normal을 알수 있으므로 지금 부터 normal을 가지고 작없을 시작할 것이다.
592592
593593모든것이 설정 된 후 라이트는 육면체를 및나게 할 것이다:)
594594
595595텍스트의 일부분은 다음에서 복사해왔다 [The OpenGL Light Bible](http://www.falloutsoftware.com/tutorials/gl/gl8.htm)
596596
597597소스코드와 리눅스 실행파일 및 윈도우즈 실행파일은 다음에서 다운로드할 수 있다[Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
598598
599599# 비트맵 폰트
600600
601601게임과 프로그램음 종종 스크린에 어떤 텍스트를 써야할 때가 있다. GLUT는 플랫폼에 독립적으로 문자를 그릴 수 있는 몇몇 함수를 제공한다.
602602
603603먼저 디폴트 비트맵 폰트를 사용하는 법을 보여줄 것이다. 대부분의 추가적인 코드는 utils.pas 유닛에 만들어질 것이다.
604604
605605텍스트는 2D에서 그려진 것이기 때문에 viewpoint...의 폭과 높이를 알아야 한다. 그러므로 이를 위해 2개의 함수를 작성할 것이다:
606606
607607`function glGetViewportWidth: Integer;`\
608608`var`\
609609`  Rect: array[0..3] of Integer;`\
610610`begin`\
611611`  glGetIntegerv(GL_VIEWPORT, @Rect);`\
612612`  Result := Rect[2] - Rect[0];`\
613613`end;`\
614-\
614+
615615`function glGetViewportHeight: Integer;`\
616616`var`\
617617`  Rect: array[0..3] of Integer;`\
618618`begin`\
619619`  glGetIntegerv(GL_VIEWPORT, @Rect);`\
620620`  Result := Rect[3] - Rect[1];`\
621621`end;`
622622
623623방금 왼쪽/오른쪽, 윗쪽/아래쪽을 얻었으므로 각각을 빼서 폭/높이를 계산한다.
624624
6256252D 모드에 진입하고 나오는 함수가 필요하다:
626626
627627`procedure glEnter2D;`\
628628`begin`\
629629`  glMatrixMode(GL_PROJECTION);`\
630630`  glPushMatrix;`\
631631`  glLoadIdentity;`\
632632`  gluOrtho2D(0, glGetViewportWidth, 0, glGetViewportHeight);`\
633-\
633+
634634`  glMatrixMode(GL_MODELVIEW);`\
635635`  glPushMatrix;`\
636636`  glLoadIdentity;`\
637-\
637+
638638`  glDisable(GL_DEPTH_TEST);`\
639639`end;`\
640-\
640+
641641`procedure glLeave2D;`\
642642`begin`\
643643`  glMatrixMode(GL_PROJECTION);`\
644644`  glPopMatrix;`\
645645`  glMatrixMode(GL_MODELVIEW);`\
646646`  glPopMatrix;`\
647-\
647+
648648`  glEnable(GL_DEPTH_TEST);`\
649649`end;`
650650
651-2D 모드로 들어갈 때 현재 매트릭스를 저장하고 <b>gluOrtho2D</b> 함수를 사용하여 2D 매트릭스를 설정한다.100,100 위치에 어떤것을 이런 방법으로 그린다면 윈도우의 왼쪽 모서리에서 정확히 100 픽셀, 아래에서 100 픽셀(Y는 윗쪽으로 증가한다) 의 위치에 그릴 것이다. 또한 ZBuffer를 사용불능으로 할 것이다. 2D모드로 진입할 떄 현재 매트릭스는 저장하고 <b>gluOrtho2D</b> 함수로 2D 매트릭스를 절정한다. 이방법으로 100, 100 위치에 어떤 것을 그리면 윈도우의 왼쪽에서 100 픽셀, 아래에서 100 픽셀(Y축은 위로 증가한다) 위치에 장확히 그려질 것이다. 또한 ZBuffer를 사용불능으로 만든다. 이 방법으로 ZBuffer를 변경할 수는 없다.
651+2D 모드로 들어갈 때 현재 매트릭스를 저장하고 gluOrtho2D 함수를 사용하여 2D 매트릭스를 설정한다.100,100 위치에 어떤것을 이런 방법으로 그린다면 윈도우의 왼쪽 모서리에서 정확히 100 픽셀, 아래에서 100 픽셀(Y는 윗쪽으로 증가한다) 의 위치에 그릴 것이다. 또한 ZBuffer를 사용불능으로 할 것이다. 2D모드로 진입할 떄 현재 매트릭스는 저장하고 gluOrtho2D 함수로 2D 매트릭스를 절정한다. 이방법으로 100, 100 위치에 어떤 것을 그리면 윈도우의 왼쪽에서 100 픽셀, 아래에서 100 픽셀(Y축은 위로 증가한다) 위치에 장확히 그려질 것이다. 또한 ZBuffer를 사용불능으로 만든다. 이 방법으로 ZBuffer를 변경할 수는 없다.
652652
6536532D모드를 벗어나면 이전의 매트릭스를 반환하고 ZBuffer를 가능토록 한다.
654654
655655이제 텍스트를그리는 함수를 만들어 보자:
656656
657657`procedure glWrite(X, Y: GLfloat; Font: Pointer; Text: String);`\
658658`var`\
659659`  I: Integer;`\
660660`begin`\
661661`  glRasterPos2f(X, Y);`\
662662`  for I := 1 to Length(Text) do`\
663663`    glutBitmapCharacter(Font, Integer(Text[I]));`\
664664`end;`
665665
666-<b>glutBitmapCharacter</b> 는 선택된 폰트로 한개의 문자를 만들어 낼 뿐이다. 첫번째 파라메터는 원하는 폰트로 다름과 같은 것이 있으며, (GLUT_BITMAP_9_BY_15, GLUT_BITMAP_8_BY_13, GLUT_BITMAP_TIMES_ROMAN_10, GLUT_BITMAP_TIMES_ROMAN_24, GLUT_BITMAP_HELVETICA_10, GLUT_BITMAP_HELVETICA_12 or GLUT_BITMAP_HELVETICA_18), 다른 하나는 문자이다.
666+glutBitmapCharacter 는 선택된 폰트로 한개의 문자를 만들어 낼 뿐이다. 첫번째 파라메터는 원하는 폰트로 다름과 같은 것이 있으며, (GLUT_BITMAP_9_BY_15, GLUT_BITMAP_8_BY_13, GLUT_BITMAP_TIMES_ROMAN_10, GLUT_BITMAP_TIMES_ROMAN_24, GLUT_BITMAP_HELVETICA_10, GLUT_BITMAP_HELVETICA_12 or GLUT_BITMAP_HELVETICA_18), 다른 하나는 문자이다.
667667
668-문자는 현재 래스터 위치에서 그려진다. 원하는 래스터 위치를 설정하기 위해 <b>glRasterPos</b> 함수를 콜한다. glRasterPos는 glVertex 함수와 같이 각기 다른 수와 타입의 파라메터를 인수를 갖는다. 지정한 좌표는 모델과 프로젝션 매트리스에 의해 변환되어 새로운 래스터 위치가 될 2D위치를 얻는다. 2D모드에 있기 때문에 X, Y 좌표는 그림이 그려지는 실제 2D 좌표이다.
668+문자는 현재 래스터 위치에서 그려진다. 원하는 래스터 위치를 설정하기 위해 glRasterPos 함수를 콜한다. glRasterPos는 glVertex 함수와 같이 각기 다른 수와 타입의 파라메터를 인수를 갖는다. 지정한 좌표는 모델과 프로젝션 매트리스에 의해 변환되어 새로운 래스터 위치가 될 2D위치를 얻는다. 2D모드에 있기 때문에 X, Y 좌표는 그림이 그려지는 실제 2D 좌표이다.
669669
670670이 새로운 함수는 텍스트 그리기를 쉽게 해 줄것이다:
671671
672672`procedure DrawGLScene; cdecl;`\
673673`begin`\
674674`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
675-\
675+
676676`  glLoadIdentity;`\
677677`  glTranslatef(0, 0, -5);`\
678678`  glRotatef(GetTotalTime * 10, 0, 0.5, 0.5);`\
679-\
679+
680680`  glColor3f(1, 0, 0);`\
681681`  glutSolidCube(2);`\
682-\
682+
683683`  glEnter2D;`\
684-\
684+
685685`  glColor3f(0.2, 0.8 + 0.2 * Sin(GetTotalTime * 5), 0);`\
686686`  glWrite(20, glGetViewportHeight - 20, GLUT_BITMAP_8_BY_13,`\
687687`    Format('OpenGL Tutorial :: Bitmap Fonts :: FPS - %.2f FPS', [FPS]));`\
688-\
688+
689689`  glColor3f(1, 1, 1);`\
690690`  glWrite(50, glGetViewportHeight - 60, GLUT_BITMAP_9_BY_15, 'GLUT_BITMAP_9_BY_15');`\
691691`  glWrite(50, glGetViewportHeight - 90, GLUT_BITMAP_8_BY_13, 'GLUT_BITMAP_8_BY_13');`\
692692`  glWrite(50, glGetViewportHeight - 120, GLUT_BITMAP_TIMES_ROMAN_10, 'GLUT_BITMAP_TIMES_ROMAN_10');`\
693693`  glWrite(50, glGetViewportHeight - 150, GLUT_BITMAP_TIMES_ROMAN_24, 'GLUT_BITMAP_TIMES_ROMAN_24');`\
694694`  glWrite(50, glGetViewportHeight - 180, GLUT_BITMAP_HELVETICA_10, 'GLUT_BITMAP_HELVETICA_10');`\
695695`  glWrite(50, glGetViewportHeight - 210, GLUT_BITMAP_HELVETICA_12, 'GLUT_BITMAP_HELVETICA_12');`\
696696`  glWrite(50, glGetViewportHeight - 240, GLUT_BITMAP_HELVETICA_18, 'GLUT_BITMAP_HELVETICA_18');`\
697-\
697+
698698`  glColor3f(0.5, 0.5, 1);`\
699699`  glWrite(`\
700700`    glGetViewportWidth - glutBitmapLength(GLUT_BITMAP_9_BY_15, LazText) - 5,`\
701701`    10, GLUT_BITMAP_9_BY_15, LazText);`\
702-\
702+
703703`  glLeave2D;`\
704-\
704+
705705`  glutSwapBuffers;`\
706-\
706+
707707`  FrameRendered;`\
708708`end;`
709709
710-![](/wiki-images/b/ba/BitmapFontsPic1.jpg) 빨간 정육면체를 그리고 회전시키며 텍스트를 여러가지 폰트로그리는 방법을 보여줄 것이다. <b>glutBitmapLength</b> 함수가 문자열의 폭을 알아내는데 사용되어 우측 정렬을 할 수 있게 한다. 중심에 텍스트가 오도록 코드를 쉽게 바꿀 수 있다.
710+![](/wiki-images/b/ba/BitmapFontsPic1.jpg) 빨간 정육면체를 그리고 회전시키며 텍스트를 여러가지 폰트로그리는 방법을 보여줄 것이다. glutBitmapLength 함수가 문자열의 폭을 알아내는데 사용되어 우측 정렬을 할 수 있게 한다. 중심에 텍스트가 오도록 코드를 쉽게 바꿀 수 있다.
711711
712712Note: 라이트가 없을 때 정육면체가 어떻게 보이나 알아보라.
713713
714714소스코드와 리눅스 실행파일 윈도우 실행파일은 다음에서 다운로드 할 수 있다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
715715
716716# 텍스쳐
717717
718718이제 텍스쳐를 사용할 시간이군 :)
719719
720720이 튜토리얼은 텍스쳐된 다각형을 그리는 방법과 멀티패스 기법을 사용하여 텍스쳐를 섞는 방법을 보여 줄 것이다. OPenGL은 텍스쳐를 로딩하는 내장 메카니즘이 없기 때문데 외부 라이브러리를 이용할 것이다: [Vampyre Imaging Library](http://imaginglib.sourceforge.net/). OpenGL 도움 함수를 사용할 것이며 이것은 다른 일을 하기에도 간편한 라이브러리라는 것을 알 수 있을 것이다.
721721
722722시작해 볼까요.... 텍스쳐된 사작형을 그리기 위해 디스플레이 리스트를 만들 것이다:
723723
724724`procedure CreateList;`\
725725`begin`\
726726`  glNewList(LIST_OBJECT, GL_COMPILE);`\
727727`    glBegin(GL_QUADS);`\
728728`      glTexCoord2f(1, 0);`\
729729`      glVertex3f( 2, 2, 0);`\
730730`      glTexCoord2f(0, 0);`\
731731`      glVertex3f(-2, 2, 0);`\
732732`      glTexCoord2f(0, 1);`\
733733`      glVertex3f(-2,-2, 0);`\
734734`      glTexCoord2f(1, 1);`\
735735`      glVertex3f( 2,-2, 0);`\
736736`    glEnd;`\
737737`  glEndList;`\
738738`end;`
739739
740-<b>glTexCoord</b> 함수를 주목해 보다. 이 함수는 텍스쳐의 어느 부분이 버텍스에 할당되었는지 지정하는 데 사용한다. 이 함수에서 정의된 좌표는 0에서 1까지 이다( 1보다 큰 값도 가능하지만 결과는 많은 차이를 가져온다). 0 은 첫 픽셀이고 1 은 마지막 픽셀이다. 그러므로 0.5 는 텍스쳐의 중간이 맞을 것이다.
740+glTexCoord 함수를 주목해 보다. 이 함수는 텍스쳐의 어느 부분이 버텍스에 할당되었는지 지정하는 데 사용한다. 이 함수에서 정의된 좌표는 0에서 1까지 이다( 1보다 큰 값도 가능하지만 결과는 많은 차이를 가져온다). 0 은 첫 픽셀이고 1 은 마지막 픽셀이다. 그러므로 0.5 는 텍스쳐의 중간이 맞을 것이다.
741741
742742텍스쳐 로딩은 뱀파이어(Vampyre) 이미징 라이브러리를 사용한다면 매우 쉽다:
743743
744744`var`\
745745`  Tex1, Tex2: GLuint;`\
746-\
746+
747747`procedure InitializeGL;`\
748748`begin`\
749749`  glClearColor(0, 0, 0, 0);`\
750750`  Tex1 := LoadGLTextureFromFile('ashwood.bmp');`\
751751`  Tex2 := LoadGLTextureFromFile('Flare.bmp');`\
752752`  glEnable(GL_TEXTURE_2D);`\
753753`end;`
754754
755-<b>LoadGLTextureFromFile</b> 은 텍스쳐를 파일에서 읽어들이고 그 ID를 반환한다. 텍스쳐가 로드되면 이는 렌더링을 위한것은 거의 설정 된 것이다. 마지막 라인은 2D 텍스쳐를 가능하게 하는 것이다.
755+LoadGLTextureFromFile 은 텍스쳐를 파일에서 읽어들이고 그 ID를 반환한다. 텍스쳐가 로드되면 이는 렌더링을 위한것은 거의 설정 된 것이다. 마지막 라인은 2D 텍스쳐를 가능하게 하는 것이다.
756756
757757텍스쳐된 다각형을 그리기 위해 텍스쳐를 연결하고 텍스쳐 좌표를 설정하여야 한다(텍스쳐 좌표는 이 튜토리얼에서는 디스플레이 리스트 내에서 설정 되었다):
758758
759759`  ...`\
760760`  glLoadIdentity;`\
761761`  glTranslatef(-5, 0, -15);`\
762762`  glBindTexture(GL_TEXTURE_2D, Tex1);`\
763763`  glCallList(LIST_OBJECT);`\
764764`  ...`
765765
766-<b>glBindTexture</b> 함수는 텍스쳐를 선택하는데 사용된다. 다각형을 그릴 때 그 위에 입힐 텍스쳐를 선택할 수 있다. 아주 쉽다 :)
766+glBindTexture 함수는 텍스쳐를 선택하는데 사용된다. 다각형을 그릴 때 그 위에 입힐 텍스쳐를 선택할 수 있다. 아주 쉽다 :)
767767
768768그러므로 하나의 텍스쳐를 사용하는 것은 쉽다... 그런 두 텍스쳐는 어떻게 섞을까. 기본적으로 하나의 텍스쳐에 다각형을 한번 그릴 수 있고, 블렌딩 파라메터를 설정하고 다른 텍스쳐를 가지고 다각형을 한번도 그린다. 이런 방법으로 수만흥 텍스쳐를 블렌드 할 수 있다. 그럼 이를 위한 코드는 어떤가 보자:
769769
770770`  ...`\
771771`  glLoadIdentity;`\
772772`  glTranslatef(5, 0, -15);`\
773773`  glBindTexture(GL_TEXTURE_2D, Tex1);`\
774774`  glCallList(LIST_OBJECT);`\
775-\
775+
776776`  glEnable(GL_BLEND);`\
777777`  glBlendFunc(GL_ZERO, GL_SRC_COLOR);`\
778778`  glLoadIdentity;`\
779779`  glTranslatef(5, 0, -15);`\
780780`  glBindTexture(GL_TEXTURE_2D, Tex2);`\
781781`  glCallList(LIST_OBJECT);`\
782782`  glDisable(GL_BLEND);`\
783783`...`
784784
785-다각형은 이미 알고 있는 방법으로 첫번째에 그려진다. 두번째 그려지기 전 <b>glEnable(GL_BLEND)</b>를 콜하여 블렌딩이 가능하게 한다. 블렌딩은 마지막 픽셀 컬러를 이렇게 계산한다:
785+다각형은 이미 알고 있는 방법으로 첫번째에 그려진다. 두번째 그려지기 전 glEnable(GL_BLEND)를 콜하여 블렌딩이 가능하게 한다. 블렌딩은 마지막 픽셀 컬러를 이렇게 계산한다:
786786
787787`DrawingColor * SRCBLEND + BackgroundColor * DESTBLEND`
788788
789-SRCBLEND 와 DESTBLEND 은 <b>glBlendFunc</b> 함수를 사용하여 정의한다. 이 튜토리얼에서 SRCBLEND 을 GL_ZERO (zero)로, DESTBLENT 는 GL_SRC_COLOR (DrawingColor)로 설정하면 마지막 색상은 다음과 같다:
789+SRCBLEND 와 DESTBLEND 은 glBlendFunc 함수를 사용하여 정의한다. 이 튜토리얼에서 SRCBLEND 을 GL_ZERO (zero)로, DESTBLENT 는 GL_SRC_COLOR (DrawingColor)로 설정하면 마지막 색상은 다음과 같다:
790790
791791`DrawingColor * 0 + BackgroundColor * DrawingColor`
792792
793-<figure>
794-<img src="TexturesPic1.jpg" title="TexturesPic1.jpg" />
795-<figcaption>TexturesPic1.jpg</figcaption>
796-</figure>
793+![](/wiki-images/d/d4/TexturesPic1.jpg)
797794
798795이것은어두운 색상으로 그릴 떄 배경은 더 어두워지고 백색으로 배경을 그리면 배경은 변경되지 않는다는 것을 의미한다. 결과는 이와 같다.
799796
800797다음에는 싱글패스로 멀티 텍스쳐를 하는 방법을 익스텬션을 사용하여 보여 줄것이다.
801798
802799소스코드 리눅스 실행파일 및 윈도우 실행파일은 다음에서 다운로드 할 수 있다.[Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
803800
804801# 멀티 텍스쳐(확장)
805802
806803복수 처리(multipass)에 의한 멀티 텍스쳐를 알고 있다면 단일 처리(singlepass)는 매우 쉬울 것이다. 텍스쳐를 입히는 것은 각 단계별로 분리되어 있다. 첫 단계는 설정하고 첫번째 텍스쳐를 그리고, 두번 째 단계는 다른 것을 그리고...등등. 해야할 것들은 텍스쳐 단계를 설정하고 오브젝트를 그리는 것이 전부이다.
807804
808805코드가 어떻게 되는지 보자:
809806
810807`procedure InitializeGL;`\
811808`begin`\
812809`  Load_GL_ARB_multitexture;`\
813810`  glClearColor(0, 0, 0, 0);`\
814811`  Tex1 := LoadGLTextureFromFile('Lazarus.bmp');`\
815812`  Tex2 := LoadGLTextureFromFile('Mask.bmp');`\
816813`  glActiveTextureARB(GL_TEXTURE0_ARB);`\
817814`  glEnable(GL_TEXTURE_2D);`\
818815`  glBindTexture(GL_TEXTURE_2D, Tex1);`\
819816`  glActiveTextureARB(GL_TEXTURE1_ARB);`\
820817`  glEnable(GL_TEXTURE_2D);`\
821818`  glBindTexture(GL_TEXTURE_2D, Tex2);`\
822819`end;`
823820
824-먼저 복수 처리를 가능케 하는 함수를 사용하기 위한 OpenGL 확장을 로드하는 것이 필요하다. <b>Load_GL_ARB_multitexture</b> 는 이 확정판을 로드할 것이고 만약 작동이 성공적이라면 TRUE를 되돌려 줄 것이다.
821+먼저 복수 처리를 가능케 하는 함수를 사용하기 위한 OpenGL 확장을 로드하는 것이 필요하다. Load_GL_ARB_multitexture 는 이 확정판을 로드할 것이고 만약 작동이 성공적이라면 TRUE를 되돌려 줄 것이다.
825822
826-원하는 작업을 수행 할 텍스쳐 단계를 선택하기 위해서는 <b>glActiveTextureARB</b> 함수를 사용해라. 이 함수는 원하는 단계를 정의하는 한개의 파라메터만을 필요로 한다. 이후 모든 텍스쳐 함수(enabling, disabling, binding, creating...)가 그 단계에 영향을 끼친다.
823+원하는 작업을 수행 할 텍스쳐 단계를 선택하기 위해서는 glActiveTextureARB 함수를 사용해라. 이 함수는 원하는 단계를 정의하는 한개의 파라메터만을 필요로 한다. 이후 모든 텍스쳐 함수(enabling, disabling, binding, creating...)가 그 단계에 영향을 끼친다.
827824
828825초기화 함수에서 모든 것을 설정하므로 우리가 해야 할 것은 오브젝트를 그리기만 하는 것이다:
829826
830827`procedure DrawGLScene; cdecl;`\
831828`begin`\
832829`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
833-\
830+
834831`  glLoadIdentity;`\
835832`  glTranslatef(0, 0, -5);`\
836-\
833+
837834`  glBegin(GL_QUADS);`\
838835`    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 0);`\
839836`    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);`\
840837`    glVertex3f(2.516, 2, 0);`\
841838`    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);`\
842839`    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);`\
843840`    glVertex3f(-2.516, 2, 0);`\
844841`    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 1);`\
845842`    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);`\
846843`    glVertex3f(-2.516,-2, 0);`\
847844`    glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 1);`\
848845`    glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);`\
849846`    glVertex3f(2.516,-2, 0);`\
850847`  glEnd;`\
851-\
848+
852849`  glutSwapBuffers;`\
853850`end;`
854851
855-![](/wiki-images/5/52/MultitexturePic1.jpg) 차이는 텍스쳐 좌표를 정희하는 것 뿐이다. 이제 사용할 함수는 <b>glMultiTexCoord2fARB</b>로서 텍스쳐 단계와 텍스쳐 좌표를 취한다. 다른 모든 것은 변화가 없다.
852+![](/wiki-images/5/52/MultitexturePic1.jpg) 차이는 텍스쳐 좌표를 정희하는 것 뿐이다. 이제 사용할 함수는 glMultiTexCoord2fARB로서 텍스쳐 단계와 텍스쳐 좌표를 취한다. 다른 모든 것은 변화가 없다.
856853
857854오늘날의 거의 모든 그래픽 카드는 최소한 2 단계를 지원한다. 단일처리에 의한 복수텍스쳐는 복수처리 할 때보다 더 빠른데 이는 오브젝트를 한번만 그리기 때문이다. 하드웨어가 단일처리 복수 텍스쳐를 지원한다면(Load_GL_ARB_multitexture는 TRUE를 되돌린다) 그것을 상용해라.
858855
859856소스코드와 리눅스 실행파일 및 윈도우 실행파일은 다음에서 다운로드할 수 있다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
860857
861858# 텍스쳐에 렌더링하기
862859
863860이부분은 간단하다. OpenGL은현재 장면을 텍스쳐에 캡춰해서 다른 오브젝트(TV스크린, 거울 또는 다른 것들)를 텍스쳐하기 위해 사용할 수 있다. 장면을 텍스쳐에 런더링하고 회전면에 적용할 수 있다.
864861
865862먼저, 캡쳐한 장면에 사용할 빈 텍스쳐를 하나 생성해야만 한다:
866863
867864`procedure SetupRenderTexture;`\
868865`var`\
869866`  Data: Pointer;`\
870867`begin`\
871868`  GetMem(Data, 256*256*3);`\
872869`  glGenTextures(1, @RenderTexture);`\
873870`  glBindTexture(GL_TEXTURE_2D, RenderTexture);`\
874871`  glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);`\
875872`  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);`\
876873`  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);`\
877874`  FreeMem(Data);`\
878875`end;`
879876
880877256*256 RGB 이미지를 위한 버퍼가 만들어지고 2D 텍스쳐를 설정한다.
881878
882879주요한 부분은 그리기 함수내에 있다:
883880
884881`procedure DrawGLScene; cdecl;`\
885882`var`\
886883`  TotalTime: Single;`\
887884`begin`\
888885`  glClearColor(0, 0, 0, 0);`\
889886`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
890887`  glEnable(GL_LIGHTING);`\
891888`  glDisable(GL_TEXTURE_2D);`\
892889`  glViewport(0, 0, 256, 256);`\
893-\
890+
894891`  TotalTime := GetTotalTime;`\
895-\
892+
896893`  glLoadIdentity;`\
897894`  glTranslatef(0, 0, -5);`\
898895`  glRotatef(50 * TotalTime, 1, 0, 0);`\
899896`  glRotatef(100 * TotalTime, 0, 1, 0);`\
900897`  glRotatef(50 * TotalTime, 0, 0, 1);`\
901-\
898+
902899`  glColor3f(1, 1, 1);`\
903900`  glutSolidCube(2);`\
904-\
901+
905902`  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 256, 256, 0);`\
906-\
903+
907904`  glClearColor(0.18, 0.20, 0.66, 0);`\
908905`  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);`\
909906`  glDisable(GL_LIGHTING);`\
910907`  glEnable(GL_TEXTURE_2D);`\
911908`  glViewport(0, 0, AppWidth, AppHeight);`\
912-\
909+
913910`  glLoadIdentity;`\
914911`  glTranslatef(0, 0, -7);`\
915912`  glRotatef(20 * TotalTime, 1, 0, 0);`\
916913`  glRotatef(50 * TotalTime, 0, 1, 0);`\
917-\
914+
918915`  glBegin(GL_QUADS);`\
919916`    glTexCoord2f(1, 0);`\
920917`    glVertex3f(2, 2, 0);`\
921918`    glTexCoord2f(0, 0);`\
922919`    glVertex3f(-2, 2, 0);`\
923920`    glTexCoord2f(0, 1);`\
924921`    glVertex3f(-2,-2, 0);`\
925922`    glTexCoord2f(1, 1);`\
926923`    glVertex3f(2,-2, 0);`\
927924`  glEnd;`\
928-\
925+
929926`  glutSwapBuffers;`\
930927`end;`
931928
932-![](/wiki-images/6/6e/RenderToTexturePic1.jpg) 먼저, 캡쳐되는 장면을 위해 모든것이 설정 되었다. 뷰포트는 256*256 크기로 줄어들어 텍스쳐에 맞출 수 있으며 장면이 그려질 수 있게 된다. <b>glCopyTexImage2D</b> 가 현재 선택된 텍스쳐에 장면을 캡쳐하는데 사용된다.
929+![](/wiki-images/6/6e/RenderToTexturePic1.jpg) 먼저, 캡쳐되는 장면을 위해 모든것이 설정 되었다. 뷰포트는 256*256 크기로 줄어들어 텍스쳐에 맞출 수 있으며 장면이 그려질 수 있게 된다. glCopyTexImage2D 가 현재 선택된 텍스쳐에 장면을 캡쳐하는데 사용된다.
933930
934931텍스쳐에 캡쳐된 장면이 있을 때, 모든 것이 다시 지워지고, 뷰포트는 원래의 크기로 줄어들며, 마지막 장면은 텍스쳐로된 이전 장면을 사용해 그려진다.
935932
936-P.S. 캡쳐된 텍스쳐는 <b>SaveGLTextureToFile</b> 함수를 사용해서 저장된다[Vampyre Imaging Library](http://imaginglib.sourceforge.net/).
933+P.S. 캡쳐된 텍스쳐는 SaveGLTextureToFile 함수를 사용해서 저장된다[Vampyre Imaging Library](http://imaginglib.sourceforge.net/).
937934
938935소스코드와 리눅스 실행파일, 윈도우 실행파일을 다음에서 다운로드한다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
939936
940937# 버텍스 배열
941938
942939OpenGL 은 glVertex 를 부르지 않고 버퍼 내부에 저장된 데이터를 사용해서 기본적인 것을 렌더링 할 수 있다. 버퍼는 버텍스, 텍스쳐 죄표, 색상(인덱스와 RGBA), 노멀과 에지 플래그를 정의한다.
943940
944941이 튜토리얼에서 버텍스와 컬러 버퍼만을 사용할 것이다. 그리고 비-인텍스된 것과 인데스된 드로잉을 보여 줄 것이다. 비-인덱스 모드는 버퍼를 스트림으로 그린다. 인덱스 코드는 인덱스 버퍼에 정의된 순서대로 버퍼 요소를 그린다. 코딩을 시작해 보자.
945942
946943먼저, 몇몇 타입과 상수를 정의하자:
947944
948945`type`\
949946`  TVertex3f = record`\
950947`    X, Y, Z: Single;`\
951948`  end;`\
952-\
949+
953950`  TColor3f = record`\
954951`   R, G, B: Single;`\
955952`  end;`\
956-\
953+
957954`  VertexBuffer: array [0..5] of TVertex3f = (`\
958955`    (X : 1; Y : 1; Z : 0),`\
959956`    (X : -1; Y : 1; Z : 0),`\
960957`    (X : -1; Y : -1; Z : 0),`\
961958`    (X : 1; Y : 1; Z : 0),`\
962959`    (X : -1; Y : -1; Z : 0),`\
963960`    (X : 1; Y : -1; Z : 0)`\
964961`  );`\
965962`  ColorBuffer: array [0..5] of TColor3f = (`\
966963`    (R : 1; G : 0; B : 1),`\
967964`    (R : 0; G : 0; B : 1),`\
968965`    (R : 0; G : 1; B : 0),`\
969966`    (R : 1; G : 0; B : 1),`\
970967`    (R : 0; G : 1; B : 0),`\
971968`    (R : 1; G : 1; B : 0)`\
972969`  );`
973970
974971두개의 버퍼가 있다. 하나는 버텍스 좌표를 위한 것이고 하나는 버텍스 컬러를 위한 것이다. 이 6개의 버텍스는 2개의 삼각형을 정의하여 사각형을 만든다.
975972
976973버퍼를 이용하여 기초적인 모양을 그리는 것은 쉽다:
977974
978975`  glEnableClientState(GL_VERTEX_ARRAY);`\
979976`  glEnableClientState(GL_COLOR_ARRAY);`\
980977`  glVertexPointer(3, GL_FLOAT, 0, @VertexBuffer[0]);`\
981978`  glColorPointer(3, GL_FLOAT, 0, @ColorBuffer[0]);`\
982-\
979+
983980`  glDrawArrays(GL_TRIANGLES, 0, Length(VertexBuffer));`\
984-\
981+
985982`  glDisableClientState(GL_VERTEX_ARRAY);`\
986983`  glDisableClientState(GL_COLOR_ARRAY);`
987984
988-먼저 <b>glEnableClientState</b> 함수를 사용하여 사용하기를 원하는 버퍼를 사용가능하게 한다. 그리고 사용하기 원하는 버퍼를 선택할 수 있다. 각 버퍼 타입 (<b>glColorPointer</b>, <b>glEdgeFlagPointer</b>, <b>glIndexPointer</b>, <b>glNormalPointer</b>, <b>glTexCoordPointer</b>, <b>glVertexPointer</b>) 등을 선택하기 위한 각각의 함수를 가지고 있다. 이 함수의 첫번째 파라메터는 얼마나 많은 요소를 가지고 있는가를 정의한다. 예를 들어, 버텍스 버퍼를 가정해 보자. 만약 이 파라메터가 2라면 버퍼의 각 요소는 x와 y 좌표를 갖는다.예를 들어 이 파라메터가 4라면, 각 요소는 x, y, x 및 w 좌표를 갖는다. 다음 파라메터는 어떤 형태의 요소가 포함되어 있는지(GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT or GL_DOUBLE) 정의한다. 다음 하나는 각 요소 사이에 얼마나 많은 요소가 있는 지를 정의한다. 이런 방법으로 버텍스 좌표와 데이터를 가진 버퍼를 갖게 된다. 임의의 데이터 타입을 위해서 이 파라메터는 다음과 같이 계산할 수 있다:
985+먼저 glEnableClientState 함수를 사용하여 사용하기를 원하는 버퍼를 사용가능하게 한다. 그리고 사용하기 원하는 버퍼를 선택할 수 있다. 각 버퍼 타입 (glColorPointer, glEdgeFlagPointer, glIndexPointer, glNormalPointer, glTexCoordPointer, glVertexPointer) 등을 선택하기 위한 각각의 함수를 가지고 있다. 이 함수의 첫번째 파라메터는 얼마나 많은 요소를 가지고 있는가를 정의한다. 예를 들어, 버텍스 버퍼를 가정해 보자. 만약 이 파라메터가 2라면 버퍼의 각 요소는 x와 y 좌표를 갖는다.예를 들어 이 파라메터가 4라면, 각 요소는 x, y, x 및 w 좌표를 갖는다. 다음 파라메터는 어떤 형태의 요소가 포함되어 있는지(GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT or GL_DOUBLE) 정의한다. 다음 하나는 각 요소 사이에 얼마나 많은 요소가 있는 지를 정의한다. 이런 방법으로 버텍스 좌표와 데이터를 가진 버퍼를 갖게 된다. 임의의 데이터 타입을 위해서 이 파라메터는 다음과 같이 계산할 수 있다:
989986
990987`type`\
991988`  TBufferData = record`\
992989`    DataBefore: TDataBefore;`\
993990`    Vertex: TVertex;`\
994991`    DataAfter: TDataAfter;`\
995992`  end;`\
996-\
993+
997994`요소 사이의 바이트 = SizeOf(TDataBefore) + SizeOf(TDataAfter)`\
998995
999996마지막 파라메터는 포인터라면 버퍼를 가르킨다.
1000997
1001-버퍼가 선택되면, <b>glDrawArrays</b> 를 사용하여 드로잉 할 수가 있다. 모든 사용가능한 버퍼는 기본적인 모양을 그리기 위해 사용된다. 어떤 종류의 다각형이 생성되는지는 첫번째 파라메터에 정의되어 있다(glBegin 함수 처럼). 다음 두 개는 드로잉(시작과 카운트)을 위해 사용되는 버퍼의 서브셋이다
998+버퍼가 선택되면, glDrawArrays 를 사용하여 드로잉 할 수가 있다. 모든 사용가능한 버퍼는 기본적인 모양을 그리기 위해 사용된다. 어떤 종류의 다각형이 생성되는지는 첫번째 파라메터에 정의되어 있다(glBegin 함수 처럼). 다음 두 개는 드로잉(시작과 카운트)을 위해 사용되는 버퍼의 서브셋이다
1002999
10031000버퍼가 불필요할 때는 사용 불능으로 할 수 있다.
10041001
10051002인덱스 모드를 설명하기 위해 외부 파일에서 버텍스와 컬러, 인스 데이터를 로드할 수 있는 간단한 메쉬 클래스를 만들었다:
10061003
10071004`type`\
10081005`  TMesh = class`\
10091006`  private`\
10101007`    FVertices: array of TVertex3f;`\
10111008`    FColors: array of TColor3f;`\
10121009`    FIndices: array of Integer;`\
10131010`    procedure FreeBuffers;`\
10141011`  public`\
10151012`    constructor Create;`\
10161013`    destructor Destroy; override;`\
10171014`    procedure LoadMesh(FileName: String);`\
10181015`    procedure DrawMesh;`\
10191016`  end;`
10201017
10211018FVertices 는 버텍스에 관한 데이터를 가지고, FColors 데이터는 색상에 관한 것을, FIndices 는 외부 파일이 로드 될 때의 인덱스를 가지고 있다.
10221019
10231020번저 클래스를 생성하고 소멸하기위한 코드를 작성해 보자:
10241021
10251022`procedure TMesh.FreeBuffers;`\
10261023`begin`\
10271024`  FVertices := nil;`\
10281025`  FColors := nil;`\
10291026`  FIndices := nil;`\
10301027`end;`\
1031-\
1028+
10321029`constructor TMesh.Create;`\
10331030`begin`\
10341031`  FreeBuffers;`\
10351032`end;`\
1036-\
1033+
10371034`destructor TMesh.Destroy;`\
10381035`begin`\
10391036`  FreeBuffers;`\
10401037`  inherited Destroy;`\
10411038`end;`
10421039
10431040메쉬 데이터를 가진 파일은 간단한 텍스트 파일이다. 먼저 행은 버텍스의 수를 포함하며, 공백 문자로 나뉘어진 인덱스를 가진다. 행 다음에는 각 버텍스와 색상을 가진 행이 온다. X, Y, Z, R, G 및 B 모두는 공백문자에 의해 나뉘어진다. 마지막은 인덱스를 위한 행이며... 각 인덱스 숫자는 각자의 행안에 씌여있다. 그러므로 하나의 삼각형을 위해서, 데이터 파일은 다음고 같을 것이다:
10441041
10451042`3 3`\
10461043`-1 -1 0 1 1 1`\
10471044`1 -1 0 1 1 1`\
10481045`0 1 0 1 1 1`\
10491046`0`\
10501047`1`\
10511048`2`
10521049
10531050이것은 3개의 버텍스와 3개의 인덱스가 파일에 정의 되어있음을 의미한다. 첫번째 버텍스는 -1, -1, 0 이고 색상은 1, 1, 1 이런식이다. 인덱스는 버텍스가 그려지는 순서를 정의한다(이 경우에서는, 버넥스는 정의된 것과 같은 순서로 그려진다).
10541051
10551052이 데이터를 로딩하기 위한 코드는 다음과 같을 것이다:
10561053
10571054`procedure TMesh.LoadMesh(FileName: String);`\
10581055`var`\
10591056`  MeshFile: TextFile;`\
10601057`  VertexCount, IndexCount: Integer;`\
10611058`  iV, iI: Integer;`\
10621059`begin`\
10631060`  FreeBuffers;`\
1064-\
1061+
10651062`  AssignFile(MeshFile, FileName);`\
10661063`  Reset(MeshFile);`\
1067-\
1064+
10681065`  ReadLn(MeshFile, VertexCount, IndexCount);`\
1069-\
1066+
10701067`  SetLength(FVertices, VertexCount);`\
10711068`  SetLength(FColors, VertexCount);`\
10721069`  SetLength(FIndices, IndexCount);`\
1073-\
1070+
10741071`  for iV := 0 to VertexCount - 1 do`\
10751072`    ReadLn(MeshFile,`\
10761073`      FVertices[iV].X, FVertices[iV].Y, FVertices[iV].Z,`\
10771074`      FColors[iV].R, FColors[iV].G, FColors[iV].B);`\
1078-\
1075+
10791076`  for iI := 0 to IndexCount - 1 do`\
10801077`    ReadLn(MeshFile, FIndices[iI]);`\
1081-\
1078+
10821079`  CloseFile(MeshFile);`\
10831080`end;`
10841081
10851082데이터를 로딩한 후 그리기 위한 여러가지를 할 수 있다:
10861083
10871084`procedure TMesh.DrawMesh;`\
10881085`begin`\
10891086`  glEnableClientState(GL_VERTEX_ARRAY);`\
10901087`  glEnableClientState(GL_COLOR_ARRAY);`\
10911088`  glVertexPointer(3, GL_FLOAT, 0, @FVertices[0]);`\
10921089`  glColorPointer(3, GL_FLOAT, 0, @FColors[0]);`\
1093-\
1090+
10941091`  glDrawElements(GL_TRIANGLES, Length(FIndices), GL_UNSIGNED_INT, @FIndices[0]);`\
1095-\
1092+
10961093`  glDisableClientState(GL_VERTEX_ARRAY);`\
10971094`  glDisableClientState(GL_COLOR_ARRAY);`\
10981095`end;`
10991096
1100-거의 모든 것이 비-인덱스된 드로잉과 같다. 다만 실제 그리는 함수만 제외하고 말이다. 이 경우에는 <b>glDrawElements</b> 함수를 사용하였다. 이것 하나를 위해 어떤 다각형을 원하는지 지정하였고, 인덱스 버퍼에 얼마나 많은 인덱스가 있는지, 인텍스 버퍼에는 데이터 타입이 얼마나 있는지 그리고 인덱스 버퍼의 시작에 대한 포인터를 지정하였다. ![](/wiki-images/7/77/VertexArrayPic1.jpg) 풀 소스코드는 메쉬데이터 파일과 같이 있으며 비-인덱스 모드를 사용하여 그려진 것과 동일한 사각형을 만들어 낼 수있다. 메쉬 데이터 파일은 다음과 같을 것이다:
1097+거의 모든 것이 비-인덱스된 드로잉과 같다. 다만 실제 그리는 함수만 제외하고 말이다. 이 경우에는 glDrawElements 함수를 사용하였다. 이것 하나를 위해 어떤 다각형을 원하는지 지정하였고, 인덱스 버퍼에 얼마나 많은 인덱스가 있는지, 인텍스 버퍼에는 데이터 타입이 얼마나 있는지 그리고 인덱스 버퍼의 시작에 대한 포인터를 지정하였다. ![](/wiki-images/7/77/VertexArrayPic1.jpg) 풀 소스코드는 메쉬데이터 파일과 같이 있으며 비-인덱스 모드를 사용하여 그려진 것과 동일한 사각형을 만들어 낼 수있다. 메쉬 데이터 파일은 다음과 같을 것이다:
11011098
11021099`4 6`\
11031100`1 1 0 1 0 1`\
11041101`-1 1 0 0 0 1`\
11051102`-1 -1 0 0 1 0`\
11061103`1 -1 0 1 1 0`\
11071104`0`\
11081105`1`\
11091106`2`\
11101107`0`\
11111108`2`\
11121109`3`
11131110
111411114개의 버텍스와 6개의 인텍스를 위한 데이터가 있다. 그러므로 첫 삼각형은 버텍스 0, 1, 2로 정의되고, 두번째 버텍스는 0, 2, 3으로 정의된다. 인덱스 모드를 사용하여 버텍스를 복제할 수는 없다.
11151112
11161113소스코드, 리눅스 실행파일, 윈도우즈 실행파일은 다음에서 다운로드 할 수 있다 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
11171114
11181115------------------------------------------------------------------------
11191116
11201117[[Creating bindings for C libraries]]
11211118
11221119---
11231120*From the Free Pascal wiki, page "OpenGL Tutorial/ko", as it stood on 2020-02-23 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history