Sign in Join
Wiki copytemporary

OpenGL Tutorial/ja: what changed

Revision 3 to 4. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-# 概要
2-
3-OpenGLは2Dや3DのインタラクティブなグラフィックスアプリケーションをOSなどに依存せず作成できる、優れた開発環境です。OpenGLは1992年から開発がすすめられ、いまや2D、3DグラフィックスアプリケーションのAPIとしては、数多くのアプリケーションで使われ、いろんなコンピュータプラットホームで利用でき、業界標準になっています。
4-
5-OpenGLは、様々な種類のレンダリング、テクスチャマッピング、特殊効果、および他の強力なビジュアライゼーション機能を取り入れており、革新的な、アプリケーション開発を加速できます。
6-
7-開発者はすべてのポピュラーなデスクトップとワークステーションプラットホームに、OpenGLのパワーを利用することができますので、広いアプリケーション展開が可能になります。もっと詳しい情報は、 [OpenGLのサイト](http://www.opengl.org/about/overview/)で得ることができます。
1+**日本語版メニュー**
2+---
3+[[Main Page/ja|メインページ]] \- [[Lazarus Documentation/ja|Lazarus Documentation日本語版]] \- [[Japanese Localization Notes|翻訳ノート]] \- [[Bug Tracking/ja|日本語障害情報]]
4+
5+You'll draw single triangle and for that GL_TRIANGLES flag will do the trick. **glVertex3f** function defines the position of a vertex you want to draw. There are more glVertex* functions. Only difference is number and type of parameters they take. For instance... glVertex2i takes two parameters (x and y) of integer type. glVertex3f will almost always be just what you need.
86
9-GLUTはOpenGL Utility Toolkitですの略です。OpenGLを使ったプログラムを書くために、どのようなウィンドウシステムで利用できるツールキットです。 これは、簡単なウインドウをもつOpenGLを使うプログラムで使える、アプリケーションプログラミングインターフェース(API)を実装します。(訳注:GLUTを使えば、ウインドウシステム、プラットフォームの違いを吸収してくれます。) GLUTを使えば、OpenGLプログラミングを学んだり、調査すしたりすることが簡単になります。 また、いろいろなPCとワークステーション、OSにわたって動作するひとつのOpenGLプログラムに書けるのと同様に、GLUTは携帯用のAPIも提供しています。もっと詳しい情報は、 [OpenGLのGLUTのサイト](http://www.opengl.org/resources/libraries/glut/)で得ることができます。
7+Before glVertex you can set color, material, texture... For simplicity you'll just specify color for each vertex in this tutorial. Color is set using **glColor3f** function. glColor can also take different set of parameters like glVertex.
108
11-多くのOSにGLUTがプレインストールされています。もし、自分の環境にあったものが分からない場合は、 [Google](http://www.google.com/)で調べてみてください。
9+As we look through code we can see that Z is set to 0 for all vertices. Since you set near plane to 0.1, triangle will not be visible. That is where those two functions we skipped in the beginning jump in. We already know that glLoadIdentity reset matrix. **glTranslatef** moves triangles by X, Y and Z values you provide. Since you set Z to -5 (negative Z is farther from camera) all vertices will be drawn 5 units far from point of view and will be visible.
1210
13-Windowsのバイナリは、[www.xmission.com](http://www.xmission.com/~nate/glut.html)でダウンロードできます。
11+In the end you call **glEnd** functions that finishes drawing. You could now start another drawing block with new glBegin function if you wish.
1412
15-# 最初のGLUTプログラムを作ろう
13+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
1614
17-GLUTを使うために、初期化処理をおこなう必要があります。これは、glutInit関数を使って行えます。 この関数はコマンドラインを解析し、メインウインドウのパラメータをセットします。しかし、それは、C/C++形式の入力を前提としています。 あなたは、自分の関数内で、ParamCountとParamStrから、C/C++風のコマンドラインパラメータに変換する必要があります。
15+# Using display lists
1816
19-``` pascal
20-procedure glutInitPascal(ParseCmdLine: Boolean);
21-var
22- Cmd: array of PChar;
23- CmdCount, I: Integer;
24-begin
25- if ParseCmdLine then
26- CmdCount := ParamCount + 1
27- else
28- CmdCount := 1;
29- SetLength(Cmd, CmdCount);
30- for I := 0 to CmdCount - 1 do
31- Cmd[I] := PChar(ParamStr(I));
32- glutInit(@CmdCount, @Cmd);
33-end;
17+Sometimes you'll need to draw some object multiple times on scene. OpenGL has ability to build **display lists** which make drawing a bit faster. Creating display list is very easy... just draw vertices as you did in previous tutorial and enclose them with **glNewList** and **glEndList** calls.
3418```
35-
36-要するに、配列を作って、ParamStrからの文字列をセットしています。この関数は、glutInitに渡して、制御するためのパラメータを取ることができます。コマンドライン、もしくは、実行ファイルそのものの名です。
37-
38-glutInitについての情報は: <http://www.opengl.org/resources/libraries/glut/spec3/node10.html>
39-
40-次に、メインウインドウを生成する必要があります。 メインウインドウに、glutInitDisplayModeを使って、ディスプレイモードを設定します。 これは、フラグの組み合わせで表現されるただ1つのパラメータを取ります。 通常は、GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH で充分でしょう。
41-
42-glutInitDisplayModeについての情報は: <http://www.opengl.org/resources/libraries/glut/spec3/node12.html>
43-
44-The position and size of the window is controlled using ウインドウの位置とサイズは、 glutInitWindowPosition と、 glutInitWindowSize.によって制御されます。 これらは、2個のパラメータをとります。 最初のものはX and Y の組、後のものは、幅と高さです。ウインドウのサイズと中心を得るために、glutGetを使うこともできます。
45-
46-glutInitWindowPosition, glutInitWindowSize と glutGetについての情報は: <http://www.opengl.org/resources/libraries/glut/spec3/node11.html> <http://www.opengl.org/documentation/specs/glut/spec3/node70.html>
47-
48-最後に、glutCreateWindow 関数を使って、ウインドウを生成します。 これは、ウインドウを生成し、パラメータを通してキャプションを設定します。
49-
50-結果として、この関数はウインドウのハンドルを返します。これは、他の関数で必要とされて使われる事があります。
51-
52-glutCreateWindowについての情報は: <http://www.opengl.org/resources/libraries/glut/spec3/node16.html>
53-
54-プログラムがメインループにはいる前に、いくつかコールバックを設定しておきます。ウインドウを描画するとき、リサイズするとき、キーボード入力があったとき、などに、コールバックを必要とします。これらのコールバックは、glutDisplayFunc、 glutReshapeFunc 、 glutKeyboardFuncを使って設定します。
55-
56-コールバックについての情報は: <http://www.opengl.org/resources/libraries/glut/spec3/node45.html#SECTION00080000000000000000>
57-
58-描画関数は、このようになるでしょう。
59-
60-``` pascal
61-procedure DrawGLScene; cdecl;
62-begin
63- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
64- glutSwapBuffers;
65-end;
19+const
20+ LIST_OBJECT = 1;
21+
22+ procedure CreateList;
23+ begin
24+ glNewList(LIST_OBJECT, GL_COMPILE);
25+ glBegin(GL_TRIANGLE_FAN);
26+ glColor3f(1, 0, 0);
27+ glVertex3f(0, 0.5, 0);
28+
29+ glColor3f(1, 1, 0);
30+ glVertex3f(-0.5, -0.5, 0.5);
31+
32+ glColor3f(1, 1, 1);
33+ glVertex3f(0.5, -0.5, 0.5);
34+
35+ glColor3f(0, 1, 1);
36+ glVertex3f(0.5, -0.5, -0.5);
37+
38+ glColor3f(0, 0, 1);
39+ glVertex3f(-0.5, -0.5, -0.5);
40+
41+ glColor3f(0, 1, 0);
42+ glVertex3f(-0.5, -0.5, 0.5);
43+ glEnd;
44+
45+ glBegin(GL_QUADS);
46+ glColor3f(1, 1, 0);
47+ glVertex3f(-0.5, -0.5, 0.5);
48+
49+ glColor3f(1, 1, 1);
50+ glVertex3f(0.5, -0.5, 0.5);
51+
52+ glColor3f(0, 1, 1);
53+ glVertex3f(0.5, -0.5, -0.5);
54+
55+ glColor3f(0, 0, 1);
56+ glVertex3f(-0.5, -0.5, -0.5);
57+
58+ glColor3f(0, 1, 0);
59+ glVertex3f(-0.5, -0.5, 0.5);
60+ glEnd;
61+ glEndList;
62+ end;
6663```
6764
68-これは、単にウインドウをバックグラウンド色でクリアして、Zバッファをリセットします。(Zバッファについては、後で説明するので分からなくても気にしないでください。)
69-
70-リサイズ関数は、次のようになるでしょう。
71-
72-``` pascal
73-procedure ReSizeGLScene(Width, Height: Integer); cdecl;
74-begin
75- if Height = 0 then
76- Height := 1;
65+**glNewList** creates new display list and all drawing functions will be recorded until **glEndList** is called. The first parameter for glNewList function is list ID. Every list is defined by it's ID. If list with given ID is already created it fill be cleared before recording. If the second parameter is GL_COMPILE then all drawing functions are just recorded, but if it is GL_COMPILE_AND_EXECUTE then they are recorded and executed automaticly.
7766
78- glViewport(0, 0, Width, Height);
79- glMatrixMode(GL_PROJECTION);
80- glLoadIdentity;
81- gluPerspective(45, Width / Height, 0.1, 1000);
67+**glIsList** function can help you with display lists. It can tell if some list ID is already filled with data. Another useful function is **glGenLists**. It will create multiple empty display lists. You pass number of display lists you need and you get ID of the first one. If you require n lists, and get r ID, generated display lists are: r, r+1, r+2,..., r+n-1
8268
83- glMatrixMode(GL_MODELVIEW);
84- glLoadIdentity;
85-end;
69+All created lists should be deleted. You will do that before program exits:
8670```
87-
88-このコードで、OpenGLにウインドウのどの部分に描画し、必要な値を適切な行列に設定することができます。 (行列関数は、後で説明します。)
89-
90-キーボード入力は、次の関数で評価されます。
91-
92-``` pascal
9371procedure GLKeyboard(Key: Byte; X, Y: Longint); cdecl;
94-begin
95- if Key = 27 then
96- Halt(0);
97-end;
98-```
99-
100-この関数はESCキーを押すとプログラムを終了するようにします。GLUTはイベントドリブンであり、プログラムを終了するためには、コールバック関数の中でHalt関数をコールします。
101-
102-もし、別の方法でウインドウをクローズすると、ウインドウは消えても、プログラムは見えないところでループを続けているでしょう。
103-
104-メインループを開始するには、glutMainLoopをコールします。 これは、終了しないループに突入し、コールバック関数をコールしていきます。 プログラムの主要部分は次のようになるでしょう。
105-
106-``` pascal
107-const
108- AppWidth = 640;
109- AppHeight = 480;
110-
111-procedure InitializeGL;
112-begin
113- glClearColor(0.18, 0.20, 0.66, 0);
114-end;
115-
116-var
117- ScreenWidth, ScreenHeight: Integer;
118-begin
119- glutInitPascal(True);
120- glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
121- glutInitWindowSize(AppWidth, AppHeight);
122- ScreenWidth := glutGet(GLUT_SCREEN_WIDTH);
123- ScreenHeight := glutGet(GLUT_SCREEN_HEIGHT);
124- glutInitWindowPosition((ScreenWidth - AppWidth) div 2,
125- (ScreenHeight - AppHeight) div 2);
126- glutCreateWindow('OpenGL Tutorial 1');
127-
128- InitializeGL;
129-
130- glutDisplayFunc(@DrawGLScene);
131- glutReshapeFunc(@ReSizeGLScene);
132- glutKeyboardFunc(@GLKeyboard);
133-
134- glutMainLoop;
135-end.
72+ begin
73+ if Key = 27 then
74+ begin
75+ glDeleteLists(LIST_OBJECT, 1);
76+ Halt(0);
77+ end;
78+ end;
13679```
13780
138-次のチュートリアルでは、少しコードを追加して、簡単な図形を書いてみます。
139-
140-下記でソースコードやlinux/Windowsの実行ファイルをダウンロードできます。 [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
141-
142-# 単純な形状を描画する
143-
144-今回は、少しだけコードを追加して、OpenGLの関数の説明にフォーカスします。
145-
146-これまでのコードで説明します。
147-
148-``` pascal
149- .
150- .
151- .
152- glMatrixMode(GL_PROJECTION);
153- glLoadIdentity;
154- gluPerspective(45, Width / Height, 0.1, 1000);
81+**glDeleteLists** takes 2 parameters, ID of display list and number of lists to delete. If ID is r, and number of lists to delete is n, deleted lists are: r, r+1, r+2,..., r+n-1
15582
156- glMatrixMode(GL_MODELVIEW);
157- glLoadIdentity;
158-end;
83+Now you know how to create and delete display lists... let's see how to draw them:
15984```
160-
161-glMatrixMode関数で、変更したい行列を選択します。 OpenGL には、3つの行列があります。
162-
163-GL_MODELVIEW: この行列は、頂点をモデル空間へ移動するためのものです。
164-
165-GL_PROJECTION: この行列は、3次元の位置を2次元の最終的に表示するピクセル位置に変換するためのものです。
166-
167-GL_TEXTURE: この行列はテクスチャ座標を変換するためのものです。
168-
169-いったん、変更したい行列を選択したら、行列値に影響を与える関数をコールします。
170-
171-glLoadIdentity は、行列をリセットするので、頂点位置に影響をあたえなくなります。 ほとんどすべての行列関数は、現在の行列に、生成した一つの行列を掛けるので、時々この関数で行列をクリアする必要があるでしょう。 (訳注:glLoadIdentityは、変換行列を単位行列にする。reset(リセット)や、clear(クリアする)、というと、プログラミング的な表現では、ゼロ行列をおもいうかべそうだが、原文作者の数学的な観念の表現であると考えて、そのまま和訳した)
172-
173-視野行列を設定したいなら、 gluPerspective を使うことができます。4つのパラメータ(アスペクト比、視野の近い側の面、遠い側の面)、が視野をあらわします。これは、シンプルです。
174-
175-(訳注:OpenGLの観念としては、視野は、体積としてとらえるので、視野体積として空間を捉えるとよいだろう。) それで、モデル行列を変更できます。この時点で、固有のものをセットすればよいでしょう。 よろしいでしょうか。それでは、最初の形状を書いてみましょう。
176-
177-``` pascal
17885procedure DrawGLScene; cdecl;
179-begin
180- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
181-
182- glLoadIdentity;
183- glTranslatef(0, 0, -5);
184-
185- glBegin(GL_TRIANGLES);
186- glColor3f(1, 0, 0);
187- glVertex3f(-1, -1, 0);
188-
189- glColor3f(0, 1, 0);
190- glVertex3f(1, -1, 0);
191-
192- glColor3f(0, 0, 1);
193- glVertex3f(0, 1, 0);
194- glEnd;
195-
196- glutSwapBuffers;
197-end;
198-```
199-
200-すでに、glClear関数は使いましたが、これは、バッファをリセットします。 次の2個の関数はスキップして、描画関数に注目します。
201-
202-glBegin marks beginning of drawing block. After this function you can start entering vertices. Parameter describes how are vertices used when drawing: GL_POINTS: Treats each vertex as a single point. Vertex n defines point n. N points are drawn.
203-
204-GL_LINES: Treats each pair of vertices as an independent line segment. Vertices 2n-1 and 2n define line n. n/2 lines are drawn.
205-
206-GL_LINE_STRIP: Draws a connected group of line segments from the first vertex to the last. n-1 lines are drawn.
207-
208-GL_LINE_LOOP: Draws a connected group of line segments from the first vertex to the last, then back to the first. Vertices n and n+1 define line n. The last line, however, is defined by vertices n and 1. n lines are drawn.
209-
210-GL_TRIANGLES: Treats each triplet of vertices as an independent triangle. Vertices 3n-2, 3n-1 and 3n define triangle n. n/3 triangles are drawn.
211-
212-GL_TRIANGLE_STRIP: Draws a connected group of triangles. One triangle is defined for each vertex presented after the first two vertices. For odd n, vertices n, n+1 and n+2 define triangle n. For even n, vertices n+1, n and n+2 define triangle n. n-2 triangles are drawn.
213-
214-GL_TRIANGLE_FAN: Draws a connected group of triangles. One triangle is defined for each vertex presented after the first two vertices. Vertices 1. n+1 and n+2 define triangle n. n-2 triangles are drawn.
215-
216-GL_QUADS: Treats each group of four vertices as an independent quadrilateral. Vertices 4n-3, 4n-2, 4n-1 and 4n define quadrilateral n. n/4 quadrilaterals are drawn.
217-
218-GL_QUAD_STRIP: Draws a connected group of quadrilaterals. One quadrilateral is defined for each pair of vertices presented after the first pair. Vertices 2n-1, 2n, 2n+2 and 2n+1 define quadrilateral n. n/2-1 quadrilaterals are drawn. Note that the order in which vertices are used to construct a quadrilateral from strip data is different from that used with independent data.
219-
220-GL_POLYGON: Draws a single, convex polygon. Vertices 1 through n define this polygon.
221-
222-![](/wiki-images/f/f3/SimpleShapePic1.jpg) You'll draw single triangle and for that GL_TRIANGLES flag will do the trick. glVertex3f function defines the position of a vertex you want to draw. There are more glVertex* functions. Only difference is number and type of parameters they take. For instance... glVertex2i takes two parameters (x and y) of integer type. glVertex3f will almost always be just what you need.
223-
224-Before glVertex you can set color, material, texture... For simplicity you'll just specify color for each vertex in this tutorial. Color is set using glColor3f function. glColor can also take different set of parameters like glVertex.
225-
226-As we look through code we can see that Z is set to 0 for all vertices. Since you set near plane to 0.1, triangle will not be visible. That is where those two functions we skipped in the beginning jump in. We already know that glLoadIdentity reset matrix. glTranslatef moves triangles by X, Y and Z values you provide. Since you set Z to -5 (negative Z is farther from camera) all vertices will be drawn 5 units far from point of view and will be visible.
227-
228-In the end you call glEnd functions that finishes drawing. You could now start another drawing block with new glBegin function if you wish.
229-
230-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
231-
232-# Using display lists
233-
234-Sometimes you'll need to draw some object multiple times on scene. OpenGL has ability to build display lists which make drawing a bit faster. Creating display list is very easy... just draw vertices as you did in previous tutorial and enclose them with glNewList and glEndList calls.
235-
236-``` pascal
237-const
238- LIST_OBJECT = 1;
239-
240-procedure CreateList;
241-begin
242- glNewList(LIST_OBJECT, GL_COMPILE);
243- glBegin(GL_TRIANGLE_FAN);
244- glColor3f(1, 0, 0);
245- glVertex3f(0, 0.5, 0);
246-
247- glColor3f(1, 1, 0);
248- glVertex3f(-0.5, -0.5, 0.5);
249-
250- glColor3f(1, 1, 1);
251- glVertex3f(0.5, -0.5, 0.5);
252-
253- glColor3f(0, 1, 1);
254- glVertex3f(0.5, -0.5, -0.5);
255-
256- glColor3f(0, 0, 1);
257- glVertex3f(-0.5, -0.5, -0.5);
258-
259- glColor3f(0, 1, 0);
260- glVertex3f(-0.5, -0.5, 0.5);
261- glEnd;
262-
263- glBegin(GL_QUADS);
264- glColor3f(1, 1, 0);
265- glVertex3f(-0.5, -0.5, 0.5);
266-
267- glColor3f(1, 1, 1);
268- glVertex3f(0.5, -0.5, 0.5);
269-
270- glColor3f(0, 1, 1);
271- glVertex3f(0.5, -0.5, -0.5);
272-
273- glColor3f(0, 0, 1);
274- glVertex3f(-0.5, -0.5, -0.5);
275-
276- glColor3f(0, 1, 0);
277- glVertex3f(-0.5, -0.5, 0.5);
278- glEnd;
279- glEndList;
280-end;
281-```
282-
283-glNewList creates new display list and all drawing functions will be recorded until glEndList is called. The first parameter for glNewList function is list ID. Every list is defined by it's ID. If list with given ID is already created it fill be cleared before recording. If the second parameter is GL_COMPILE then all drawing functions are just recorded, but if it is GL_COMPILE_AND_EXECUTE then they are recorded and executed automaticly.
284-
285-glIsList function can help you with display lists. It can tell if some list ID is already filled with data. Another useful function is glGenLists. It will create multiple empty display lists. You pass number of display lists you need and you get ID of the first one. If you require n lists, and get r ID, generated display lists are: r, r+1, r+2,..., r+n-1
286-
287-All created lists should be deleted. You will do that before program exits:
288-
289-``` pascal
290-procedure GLKeyboard(Key: Byte; X, Y: Longint); cdecl;
291-begin
292- if Key = 27 then
293- begin
294- glDeleteLists(LIST_OBJECT, 1);
295- Halt(0);
296- end;
297-end;
86+ begin
87+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
88+
89+ glLoadIdentity;
90+ glTranslatef(-2, 0, -5);
91+ glRotatef(40, 1, 0, 1);
92+ glCallList(LIST_OBJECT);
93+
94+ glLoadIdentity;
95+ glTranslatef(1, -2, -10);
96+ glRotatef(62, 0, 1, 0);
97+ glCallList(LIST_OBJECT);
98+
99+ glLoadIdentity;
100+ glTranslatef(-4, 0.5, -15);
101+ glRotatef(200, 1, 0, 0);
102+ glCallList(LIST_OBJECT);
103+
104+ glutSwapBuffers;
105+ end;
298106```
299107
300-glDeleteLists takes 2 parameters, ID of display list and number of lists to delete. If ID is r, and number of lists to delete is n, deleted lists are: r, r+1, r+2,..., r+n-1
301-
302-Now you know how to create and delete display lists... let's see how to draw them:
303-
304-``` pascal
305-procedure DrawGLScene; cdecl;
306-begin
307- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
308-
309- glLoadIdentity;
310- glTranslatef(-2, 0, -5);
311- glRotatef(40, 1, 0, 1);
312- glCallList(LIST_OBJECT);
313-
314- glLoadIdentity;
315- glTranslatef(1, -2, -10);
316- glRotatef(62, 0, 1, 0);
317- glCallList(LIST_OBJECT);
108+[![DisplayListsPic1.jpg](/wiki-images/a/a5/DisplayListsPic1.jpg)](</File:DisplayListsPic1.jpg>)
318109
319- glLoadIdentity;
320- glTranslatef(-4, 0.5, -15);
321- glRotatef(200, 1, 0, 0);
322- glCallList(LIST_OBJECT);
110+[](</File:DisplayListsPic1.jpg> "Enlarge")
323111
324- glutSwapBuffers;
325-end;
326-```
112+Using **glCallList** you can draw only one display list. In this tutorial, before drawing display list, you change model matrix and draw object in different places.
327113
328-![](/wiki-images/a/a5/DisplayListsPic1.jpg) Using glCallList you can draw only one display list. In this tutorial, before drawing display list, you change model matrix and draw object in different places. Some times you would like to draw multiple lists at once. That is possible using glCallLists function. It takes number of lists you want to draw, type of array that contains display list IDs and array with display list IDs. Type of list can be one of the following:
114+Some times you would like to draw multiple lists at once. That is possible using **glCallLists** function. It takes number of lists you want to draw, type of array that contains display list IDs and array with display list IDs. Type of list can be one of the following:
329115
330-GL_BYTE: list is treated as an array of signed bytes, each in the range -128 through 127.
116+GL_BYTE: list is treated as an array of signed bytes, each in the range -128 through 127.
331117
332-GL_UNSIGNED_BYTE: list is treated as an array of unsigned bytes, each in the range 0 through 255.
118+GL_UNSIGNED_BYTE: list is treated as an array of unsigned bytes, each in the range 0 through 255.
333119
334-GL_SHORT: list is treated as an array of signed two-byte integers, each in the range -32768 through 32767.
120+GL_SHORT: list is treated as an array of signed two-byte integers, each in the range -32768 through 32767.
335121
336-GL_UNSIGNED_SHORT: list is treated as an array of unsigned two-byte integers, each in the range 0 through 65535.
122+GL_UNSIGNED_SHORT: list is treated as an array of unsigned two-byte integers, each in the range 0 through 65535.
337123
338-GL_INT: lists is treated as an array of signed four-byte integers.
124+GL_INT: lists is treated as an array of signed four-byte integers.
339125
340-GL_UNSIGNED_INT: list is treated as an array of unsigned four-byte integers.
126+GL_UNSIGNED_INT: list is treated as an array of unsigned four-byte integers.
341127
342-GL_FLOAT: list is treated as an array of four-byte floating-point values.
128+GL_FLOAT: list is treated as an array of four-byte floating-point values.
343129
344-GL_2_BYTES: list is treated as an array of unsigned bytes. Each pair of bytes specifies a single display list ID. The value of the pair is computed as 256 times the unsigned value of the first byte plus the unsigned value of the second byte.
130+GL_2_BYTES: list is treated as an array of unsigned bytes. Each pair of bytes specifies a single display list ID. The value of the pair is computed as 256 times the unsigned value of the first byte plus the unsigned value of the second byte.
345131
346-GL_3_BYTES: list is treated as an array of unsigned bytes. Each triplet of bytes specifies a single display list ID. The value of the triplet is computed as 65536 times the unsigned value of the first byte, plus 256 times the unsigned value of the second byte, plus the unsigned value of the third byte.
132+GL_3_BYTES: list is treated as an array of unsigned bytes. Each triplet of bytes specifies a single display list ID. The value of the triplet is computed as 65536 times the unsigned value of the first byte, plus 256 times the unsigned value of the second byte, plus the unsigned value of the third byte.
347133
348-GL_4_BYTES: list is treated as an array of unsigned bytes. Each quadruplet of bytes specifies a single display list ID. The value of the quadruplet is computed as 16777216 times the unsigned value of the first byte, plus 65536 times the unsigned value of the second byte, plus 256 times the unsigned value of the third byte, plus the unsigned value of the fourth byte.
134+GL_4_BYTES: list is treated as an array of unsigned bytes. Each quadruplet of bytes specifies a single display list ID. The value of the quadruplet is computed as 16777216 times the unsigned value of the first byte, plus 65536 times the unsigned value of the second byte, plus 256 times the unsigned value of the third byte, plus the unsigned value of the fourth byte.
349135
350-That is for now. Next tutorial will show how to create little planetary system. We'll talk about matrices and how to make animated scene that doesn't depend of number of frames per second.
136+That is for now. Next tutorial will show how to create little planetary system. We'll talk about matrices and how to make animated scene that doesn't depend of number of frames per second.
351137
352-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
138+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
353139
354140# Full screen animation
355141
356-Entering full screen mode is easy with GLUT. Let's change main part of the program:
357-
358-``` pascal
142+Entering full screen mode is easy with GLUT. Let's change main part of the program:
143+```
359144const
360- FSMode = '800x600:32@75';
361-
362-begin
363- glutInitPascal(False);
364- glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
365- glutGameModeString(FSMode);
366- glutEnterGameMode;
367- glutSetCursor(GLUT_CURSOR_NONE);
368-
369- InitializeGL;
370-
371- glutDisplayFunc(@DrawGLScene);
372- glutReshapeFunc(@ReSizeGLScene);
373- glutKeyboardFunc(@GLKeyboard);
374- glutIdleFunc(@DrawGLScene);
375-
376- glutMainLoop;
377-end.
145+ FSMode = '800x600:32@75';
146+
147+ begin
148+ glutInitPascal(False);
149+ glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
150+ glutGameModeString(FSMode);
151+ glutEnterGameMode;
152+ glutSetCursor(GLUT_CURSOR_NONE);
153+
154+ InitializeGL;
155+
156+ glutDisplayFunc(@DrawGLScene);
157+ glutReshapeFunc(@ReSizeGLScene);
158+ glutKeyboardFunc(@GLKeyboard);
159+ glutIdleFunc(@DrawGLScene);
160+
161+ glutMainLoop;
162+ end.
378163```
379164
380-Since we don't want GLUT to parse command line this time we call glutInitPascal with False parameter. As you can see, there is no code for window creation. GLUT have glutEnterGameMode that create full screen window. To specify what kind of full screen mode you want, you call glutGameModeString function which takes string that defines mode you like. Format of that string is:
381-
382-```text
165+Since we don't want GLUT to parse command line this time we call glutInitPascal with False parameter. As you can see, there is no code for window creation. GLUT have **glutEnterGameMode** that create full screen window. To specify what kind of full screen mode you want, you call **glutGameModeString** function which takes string that defines mode you like. Format of that string is:
166+```
383167[width "x" height][":" bpp]["@" hertz]
384168```
385169
386-In FSMode string we declared that full screen mode should be 800x600, with 32bit pallete and 75Hz refresh. It is possible to skip one of the group. If you omit size, GLUT will try to use current one or first smaller that can work. That policy is used and for other parameters.
387-
388-Usually in full screen mode cursor is not visible. To hide cursor you use glutSetCursor function. It takes only one parameter which describes cursor you would like to see:
170+In FSMode string we declared that full screen mode should be 800x600, with 32bit pallete and 75Hz refresh. It is possible to skip one of the group. If you omit size, GLUT will try to use current one or first smaller that can work. That policy is used and for other parameters.
389171
390-```text
172+Usually in full screen mode cursor is not visible. To hide cursor you use **glutSetCursor** function. It takes only one parameter which describes cursor you would like to see:
173+```
391174GLUT_CURSOR_RIGHT_ARROW
392-GLUT_CURSOR_LEFT_ARROW
393-GLUT_CURSOR_INFO
394-GLUT_CURSOR_DESTROY
395-GLUT_CURSOR_HELP
396-GLUT_CURSOR_CYCLE
397-GLUT_CURSOR_SPRAY
398-GLUT_CURSOR_WAIT
399-GLUT_CURSOR_TEXT
400-GLUT_CURSOR_CROSSHAIR
401-GLUT_CURSOR_UP_DOWN
402-GLUT_CURSOR_LEFT_RIGHT
403-GLUT_CURSOR_TOP_SIDE
404-GLUT_CURSOR_BOTTOM_SIDE
405-GLUT_CURSOR_LEFT_SIDE
406-GLUT_CURSOR_RIGHT_SIDE
407-GLUT_CURSOR_TOP_LEFT_CORNER
408-GLUT_CURSOR_TOP_RIGHT_CORNER
409-GLUT_CURSOR_BOTTOM_RIGHT_CORNER
410-GLUT_CURSOR_BOTTOM_LEFT_CORNER
411-GLUT_CURSOR_FULL_CROSSHAIR
412-GLUT_CURSOR_NONE
413-GLUT_CURSOR_INHERIT
175+ GLUT_CURSOR_LEFT_ARROW
176+ GLUT_CURSOR_INFO
177+ GLUT_CURSOR_DESTROY
178+ GLUT_CURSOR_HELP
179+ GLUT_CURSOR_CYCLE
180+ GLUT_CURSOR_SPRAY
181+ GLUT_CURSOR_WAIT
182+ GLUT_CURSOR_TEXT
183+ GLUT_CURSOR_CROSSHAIR
184+ GLUT_CURSOR_UP_DOWN
185+ GLUT_CURSOR_LEFT_RIGHT
186+ GLUT_CURSOR_TOP_SIDE
187+ GLUT_CURSOR_BOTTOM_SIDE
188+ GLUT_CURSOR_LEFT_SIDE
189+ GLUT_CURSOR_RIGHT_SIDE
190+ GLUT_CURSOR_TOP_LEFT_CORNER
191+ GLUT_CURSOR_TOP_RIGHT_CORNER
192+ GLUT_CURSOR_BOTTOM_RIGHT_CORNER
193+ GLUT_CURSOR_BOTTOM_LEFT_CORNER
194+ GLUT_CURSOR_FULL_CROSSHAIR
195+ GLUT_CURSOR_NONE
196+ GLUT_CURSOR_INHERIT
414197```
415198
416-glutIdleFunc defines callback function that you want to be called every time you program has no messages to process. Since we just want to render new frame if there is nothing to do, just set idle function to DrawGLScene. Some other tutorials show that idle function should send refresh message insted of drawing, but that way I have 50-100 frames less than using method I described.
417-
418-Now, let's look at the program termination where you need to exit full screen mode:
199+**glutIdleFunc** defines callback function that you want to be called every time you program has no messages to process. Since we just want to render new frame if there is nothing to do, just set idle function to DrawGLScene. Some other tutorials show that idle function should send refresh message insted of drawing, but that way I have 50-100 frames less than using method I described.
419200
420-``` pascal
201+Now, let's look at the program termination where you need to exit full screen mode:
202+```
421203procedure GLKeyboard(Key: Byte; X, Y: Longint); cdecl;
422-begin
423- if Key = 27 then
424- begin
425- glutLeaveGameMode;
426- Halt(0);
427- end;
428-end;
204+ begin
205+ if Key = 27 then
206+ begin
207+ glutLeaveGameMode;
208+ Halt(0);
209+ end;
210+ end;
429211```
430212
431-As you can see, all you need to do is to call glutLeaveGameMode.
432-
433-Now, we'll introduce some new matrix functions. First, let's change ReSizeGLScene function:
213+As you can see, all you need to do is to call **glutLeaveGameMode**.
434214
435-``` pascal
215+Now, we'll introduce some new matrix functions. First, let's change ReSizeGLScene function:
216+```
436217procedure ReSizeGLScene(Width, Height: Integer); cdecl;
437-begin
438- .
439- .
440- .
218+ begin
219+ .
220+ .
221+ .
441222```
442-
443-``` pascal
444- glMatrixMode(GL_MODELVIEW);
445- glLoadIdentity;
446- gluLookAt(0, 20, 25, 0, 0, 0, 0, 1, 0);
447-end;
448223```
449-
450-gluLookAt create matrix that will define from where are you look to objects. First 3 parameters are X, Y and Z coordinate of position of camera. Next 3 parameters are X, Y and Z coordinate of point where camera look at, and last 3 parameters defines "up" vector (where is "up" for the camera). Usually, up is positive y axis.
224+glMatrixMode(GL_MODELVIEW);
225+ glLoadIdentity;
226+ gluLookAt(0, 20, 25, 0, 0, 0, 0, 1, 0);
227+ end;
228+```
451229
452-OK, let's draw now. Since you set matrix with gluLookAt that should be used with all objects, you can't just use glLoadIdentity to reset matrix for next object... you'll save previous matrix state and restore it after object is drawn:
230+**gluLookAt** create matrix that will define from where are you look to objects. First 3 parameters are X, Y and Z coordinate of position of camera. Next 3 parameters are X, Y and Z coordinate of point where camera look at, and last 3 parameters defines "up" vector (where is "up" for the camera). Usually, up is positive y axis.
453231
454-``` pascal
232+OK, let's draw now. Since you set matrix with gluLookAt that should be used with all objects, you can't just use glLoadIdentity to reset matrix for next object... you'll save previous matrix state and restore it after object is drawn:
233+```
455234procedure DrawGLScene; cdecl;
456-var
457- T: Single;
458-begin
459- T := glutGet(GLUT_ELAPSED_TIME) / 1000;
460- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
461-
462- glPushMatrix;
463- glRotatef(5 * T, 0, 1, 0);
464- glColor3f(1, 1, 0);
465- glutWireSphere(2, 20, 20);
466- glPopMatrix;
467-
468- glPushMatrix;
469- glRotatef(90 * T, 0, 1, 0);
470- glTranslatef(5, 0, 0);
471- glRotatef(40 * T, 0, 1, 0);
472- glColor3f(1, 0, 0);
473- glutWireSphere(0.6, 10, 10);
474- glPopMatrix;
475-
476- glPushMatrix;
477- glRotatef(60 * T, 0, 1, 0);
478- glTranslatef(-3, 0, 9);
479- glRotatef(50 * T, 0, 1, 0);
480- glColor3f(0, 1, 0);
481- glutWireSphere(1, 16, 16);
482-
483- glPushMatrix;
484- glRotatef(360 * T, 0, 1, 0);
485- glTranslatef(-1.7, 0, 0);
486- glRotatef(50 * T, 0, 1, 0);
487- glColor3f(0, 0, 1);
488- glutWireSphere(0.4, 10, 10);
489- glPopMatrix;
235+ var
236+ T: Single;
237+ begin
238+ T := glutGet(GLUT_ELAPSED_TIME) / 1000;
239+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
240+
241+ glPushMatrix;
242+ glRotatef(5 * T, 0, 1, 0);
243+ glColor3f(1, 1, 0);
244+ glutWireSphere(2, 20, 20);
245+ glPopMatrix;
246+
247+ glPushMatrix;
248+ glRotatef(90 * T, 0, 1, 0);
249+ glTranslatef(5, 0, 0);
250+ glRotatef(40 * T, 0, 1, 0);
251+ glColor3f(1, 0, 0);
252+ glutWireSphere(0.6, 10, 10);
253+ glPopMatrix;
254+
255+ glPushMatrix;
256+ glRotatef(60 * T, 0, 1, 0);
257+ glTranslatef(-3, 0, 9);
258+ glRotatef(50 * T, 0, 1, 0);
259+ glColor3f(0, 1, 0);
260+ glutWireSphere(1, 16, 16);
261+
262+ glPushMatrix;
263+ glRotatef(360 * T, 0, 1, 0);
264+ glTranslatef(-1.7, 0, 0);
265+ glRotatef(50 * T, 0, 1, 0);
266+ glColor3f(0, 0, 1);
267+ glutWireSphere(0.4, 10, 10);
268+ glPopMatrix;
269+
270+ glPopMatrix;
271+
272+ glutSwapBuffers;
273+ end;
274+```
490275
491- glPopMatrix;
276+[![FullScreenAnimationPic1.jpg](/wiki-images/5/51/FullScreenAnimationPic1.jpg)](</File:FullScreenAnimationPic1.jpg>)
492277
493- glutSwapBuffers;
494-end;
495-```
278+[](</File:FullScreenAnimationPic1.jpg> "Enlarge")
496279
497-![](/wiki-images/5/51/FullScreenAnimationPic1.jpg) glPushMatrix i glPopMatrix are used to save and restore matrix state. As you can see, we save matrix state, then change matrix in order to draw object in right place, and then restore old matrix state.
280+**glPushMatrix** i **glPopMatrix** are used to save and restore matrix state. As you can see, we save matrix state, then change matrix in order to draw object in right place, and then restore old matrix state.
498281
499-You may wonder what is T variable for. Well, it is used to determen animation speed. Every change that depends on time is multiplied with T. That way animation speed is constant on every frame rate. glutGet function with GLUT_ELAPSED_TIME parameter returns time in milliseconds from glutInit is called. By dividing that value with 1000, we get time in seconds.
282+You may wonder what is **T** variable for. Well, it is used to determen animation speed. Every change that depends on time is multiplied with T. That way animation speed is constant on every frame rate. **glutGet** function with **GLUT_ELAPSED_TIME** parameter returns time in milliseconds from glutInit is called. By dividing that value with 1000, we get time in seconds.
500283
501-glRotatef function create rotation matrix. First parameter is angle in degrees, and last 3 parameters defines axis around which rotation will be done. Since you multiplied angle with T, object will be rotated by that angle in exactly 1 second.
284+**glRotatef** function create rotation matrix. First parameter is angle in degrees, and last 3 parameters defines axis around which rotation will be done. Since you multiplied angle with T, object will be rotated by that angle in exactly 1 second.
502285
503-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
286+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
504287
505288# Light
506289
507-This tutorial will introduce some light to the scene. You'll make rotating cube and one light which will add some realism to the scene, but first let's make some utility unit.
508-
509-For now it will have only basic functions to help us getting current and delta (time that elapsed from one render to other render call) times and for calculating frames per second.
290+This tutorial will introduce some light to the scene. You'll make rotating cube and one light which will add some realism to the scene, but first let's make some utility unit.
510291
511-``` pascal
292+For now it will have only basic functions to help us getting current and delta (time that elapsed from one render to other render call) times and for calculating frames per second.
293+```
512294unit utils;
513-
514-{$mode objfpc}{$H+}
515-
516-interface
517-
518-uses
519- glut;
520-
521-function GetTotalTime: Single;
522-function GetDeltaTime: Single;
523-procedure FrameRendered(Count: Integer = 1);
524-function GetFPS: Single;
525-
526-implementation
527-
528-var
529- OldTime: Integer = 0;
530- FPSTime: Integer = 0;
531- FPSCount: Integer = 0;
532-
533-function GetTotalTime: Single;
534-begin
535- Result := glutGet(GLUT_ELAPSED_TIME) / 1000;
536-end;
537-
538-function GetDeltaTime: Single;
539-var
540- NewTime: Integer;
541-begin
542- NewTime := glutGet(GLUT_ELAPSED_TIME);
543- Result := (NewTime - OldTime) / 1000;
544- OldTime := NewTime;
545-end;
546-
547-procedure FrameRendered(Count: Integer);
548-begin
549- Inc(FPSCount, Count);
550-end;
551-
552-function GetFPS: Single;
553-var
554- NewTime: Integer;
555-begin
556- NewTime := glutGet(GLUT_ELAPSED_TIME);
557-
558- Result := FPSCount / ((NewTime - FPSTime) / 1000);
559-
560- FPSTime := NewTime;
561- FPSCount := 0;
562-end;
563-
564-end.
295+
296+ {$mode objfpc}{$H+}
297+
298+ interface
299+
300+ uses
301+ glut;
302+
303+ function GetTotalTime: Single;
304+ function GetDeltaTime: Single;
305+ procedure FrameRendered(Count: Integer = 1);
306+ function GetFPS: Single;
307+
308+ implementation
309+
310+ var
311+ OldTime: Integer = 0;
312+ FPSTime: Integer = 0;
313+ FPSCount: Integer = 0;
314+
315+ function GetTotalTime: Single;
316+ begin
317+ Result := glutGet(GLUT_ELAPSED_TIME) / 1000;
318+ end;
319+
320+ function GetDeltaTime: Single;
321+ var
322+ NewTime: Integer;
323+ begin
324+ NewTime := glutGet(GLUT_ELAPSED_TIME);
325+ Result := (NewTime - OldTime) / 1000;
326+ OldTime := NewTime;
327+ end;
328+
329+ procedure FrameRendered(Count: Integer);
330+ begin
331+ Inc(FPSCount, Count);
332+ end;
333+
334+ function GetFPS: Single;
335+ var
336+ NewTime: Integer;
337+ begin
338+ NewTime := glutGet(GLUT_ELAPSED_TIME);
339+
340+ Result := FPSCount / ((NewTime - FPSTime) / 1000);
341+
342+ FPSTime := NewTime;
343+ FPSCount := 0;
344+ end;
345+
346+ end.
565347```
566348
567-As you can see, there is nothing complicated in this unit. Time is simply saved betwen calls and difference is returned. FrameRendered should be called every time you draw scene so function can calculate FPS.
568-
569-Now, let's have fun with lights.
349+As you can see, there is nothing complicated in this unit. Time is simply saved betwen calls and difference is returned. FrameRendered should be called every time you draw scene so function can calculate FPS.
570350
571-OpenGL have several types of light... ambient, diffuse, point, spot, specular and emissive light.
351+Now, let's have fun with lights.
572352
573-Ambient light is something like Sun. When sun rays pass through the window of a room they hit the walls and are reflected and scattered into all different directions which averagely brightens up the whole room. All vertices are lit with ambient light.
353+OpenGL have several types of light... ambient, diffuse, point, spot, specular and emissive light.
574354
575-Diffuse light can be represented as parallel light rays comming from far away. They will lit only vertices that are oriented towards the light source.
355+Ambient light is something like Sun. When sun rays pass through the window of a room they hit the walls and are reflected and scattered into all different directions which averagely brightens up the whole room. All vertices are lit with ambient light.
576356
577-Point light lights all around it. It is like a fire ball, it send light rays all around it and lights vertices that are oriented towards light source and that are close enough.
357+Diffuse light can be represented as parallel light rays comming from far away. They will lit only vertices that are oriented towards the light source.
578358
579-Spot light is like light from flashlight. It is simply a point light source with a small light cone radius. All vertices that falls inside of cone and are close enough are lit.
359+Point light lights all around it. It is like a fire ball, it send light rays all around it and lights vertices that are oriented towards light source and that are close enough.
580360
581-Just like Diffuse light, Specular light is a directional type of light. It comes from one particular direction. The difference between the two is that specular light reflects off the surface in a sharp and uniform way. The rendering of specular light relies on the angle between the viewer and the light source. From the viewer’s standpoint specular light creates a highlighted area on the surface of the viewed object known as specular highlight or specular reflection.
361+Spot light is like light from flashlight. It is simply a point light source with a small light cone radius. All vertices that falls inside of cone and are close enough are lit.
582362
583-Emissive light is a little different than any other previously explained light components. This light comes out of object you draw but don't lit other objects in nearby.
363+Just like Diffuse light, Specular light is a directional type of light. It comes from one particular direction. The difference between the two is that specular light reflects off the surface in a sharp and uniform way. The rendering of specular light relies on the angle between the viewer and the light source. From the viewer’s standpoint specular light creates a highlighted area on the surface of the viewed object known as specular highlight or specular reflection.
584364
585-For simplicity we'll use only diffuse light in this tutorial. Later on, some other lights may appear in tutorials :)
365+Emissive light is a little different than any other previously explained light components. This light comes out of object you draw but don't lit other objects in nearby.
586366
587-Let's see how to enable light in scene:
367+For simplicity we'll use only diffuse light in this tutorial. Later on, some other lights may appear in tutorials :)
588368
589-``` pascal
369+Let's see how to enable light in scene:
370+```
590371const
591- DiffuseLight: array[0..3] of GLfloat = (0.8, 0.8, 0.8, 1);
592-
593- glEnable(GL_LIGHTING);
594- glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
595- glEnable(GL_LIGHT0);
372+ DiffuseLight: array[0..3] of GLfloat = (0.8, 0.8, 0.8, 1);
373+
374+ glEnable(GL_LIGHTING);
375+ glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
376+ glEnable(GL_LIGHT0);
596377```
597378
598-As you see, we enable lighting in OpenGL so lights affect scene you are rendering. Light parameters are set with glLightfv function. It takes 3 parameters... one for light number you want to change (OpenGL suports up to 8 lights), next tells OpenGL what light parameter to change, and the last one is new parameter for light. You'll set just diffuse color for light in this tutorial. After that, you can enable light and there will be light in the scene... but... that is not all.
379+As you see, we enable lighting in OpenGL so lights affect scene you are rendering. Light parameters are set with **glLightfv** function. It takes 3 parameters... one for light number you want to change (OpenGL suports up to 8 lights), next tells OpenGL what light parameter to change, and the last one is new parameter for light. You'll set just diffuse color for light in this tutorial. After that, you can enable light and there will be light in the scene... but... that is not all.
599380
600381More about glLightfv: <http://www.opengl.org//documentation/specs/man_pages/hardcopy/GL/html/gl/light.html>
601382
602-If you want to use lights you can't just set color for vertex... you must set material for vertices. Let's setup material for drawing:
603-
604-```text
383+If you want to use lights you can't just set color for vertex... you must set material for vertices. Let's setup material for drawing:
384+```
605385glEnable(GL_COLOR_MATERIAL);
606-glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
386+ glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
607387```
608388
609-![](/wiki-images/e/ed/LightPic1.jpg) You expected something more complicated, do you? :) Well, this code allows us to use glColor function to set material to vertices. By using glEnable function and GL_COLOR_MATERIAL flag, you can define what material properties will glColor change. glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE) tells OpenGL that glColor changes ambient and diffuse material. We'll discus materials more in later tutorials.
389+[![LightPic1.jpg](/wiki-images/e/ed/LightPic1.jpg)](</File:LightPic1.jpg>)
610390
611-One more thing that is important when using lights... every vertex must have normal associated with it. Normal is used to find the direction of vertex so light can be calculated properly. You'll use GLUT function to draw cube and it provides normals for us, so this time we'll just walk by normals.
391+[](</File:LightPic1.jpg> "Enlarge")
612392
613-After all those setting ups, light will shine up your cube :)
393+You expected something more complicated, do you? :) Well, this code allows us to use glColor function to set material to vertices. By using glEnable function and GL_COLOR_MATERIAL flag, you can define what material properties will glColor change. **glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)** tells OpenGL that glColor changes ambient and diffuse material. We'll discus materials more in later tutorials.
614394
615-Part of the text is copied from [The OpenGL Light Bible](http://www.falloutsoftware.com/tutorials/gl/gl8.htm)
395+One more thing that is important when using lights... every vertex must have normal associated with it. Normal is used to find the direction of vertex so light can be calculated properly. You'll use GLUT function to draw cube and it provides normals for us, so this time we'll just walk by normals.
616396
617-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
397+After all those setting ups, light will shine up your cube :)
618398
619-# Bitmap fonts
399+Part of the text is copied from [The OpenGL Light Bible](<http://www.falloutsoftware.com/tutorials/gl/gl8.htm>)
620400
621-Games and programs usually need to write some text on screen. GLUT provides several functions for drawing chars that are platform independent.
401+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
622402
623-First, we'll show how to use default bitmap fonts. Almost all code additions will be made to utils.pas unit.
403+# Bitmap fonts
624404
625-Since text will be drawn in 2D, we'll need to know width and height of viewport... so, we'll write two functions for that:
405+Games and programs usually need to write some text on screen. GLUT provides several functions for drawing chars that are platform independent.
626406
627-``` pascal
628-function glGetViewportWidth: Integer;
629-var
630- Rect: array[0..3] of Integer;
631-begin
632- glGetIntegerv(GL_VIEWPORT, @Rect);
633- Result := Rect[2] - Rect[0];
634-end;
407+First, we'll show how to use default bitmap fonts. Almost all code additions will be made to utils.pas unit.
635408
636-function glGetViewportHeight: Integer;
637-var
638- Rect: array[0..3] of Integer;
639-begin
640- glGetIntegerv(GL_VIEWPORT, @Rect);
641- Result := Rect[3] - Rect[1];
642-end;
409+Since text will be drawn in 2D, we'll need to know width and height of viewport... so, we'll write two functions for that:
643410```
644-
645-We just get left/right, top/bottom and calculate width/height by subtracting them.
411+function glGetViewportWidth: Integer;
412+ var
413+ Rect: array[0..3] of Integer;
414+ begin
415+ glGetIntegerv(GL_VIEWPORT, @Rect);
416+ Result := Rect[2] - Rect[0];
417+ end;
418+
419+ function glGetViewportHeight: Integer;
420+ var
421+ Rect: array[0..3] of Integer;
422+ begin
423+ glGetIntegerv(GL_VIEWPORT, @Rect);
424+ Result := Rect[3] - Rect[1];
425+ end;
426+```
646427
647-There must be functions for entering and leaving 2D mode:
428+We just get left/right, top/bottom and calculate width/height by subtracting them.
648429
649-``` pascal
430+There must be functions for entering and leaving 2D mode:
431+```
650432procedure glEnter2D;
651-begin
652- glMatrixMode(GL_PROJECTION);
653- glPushMatrix;
654- glLoadIdentity;
655- gluOrtho2D(0, glGetViewportWidth, 0, glGetViewportHeight);
656-
657- glMatrixMode(GL_MODELVIEW);
658- glPushMatrix;
659- glLoadIdentity;
660-
661- glDisable(GL_DEPTH_TEST);
662-end;
663-
664-procedure glLeave2D;
665-begin
666- glMatrixMode(GL_PROJECTION);
667- glPopMatrix;
668- glMatrixMode(GL_MODELVIEW);
669- glPopMatrix;
670-
671- glEnable(GL_DEPTH_TEST);
672-end;
433+ begin
434+ glMatrixMode(GL_PROJECTION);
435+ glPushMatrix;
436+ glLoadIdentity;
437+ gluOrtho2D(0, glGetViewportWidth, 0, glGetViewportHeight);
438+
439+ glMatrixMode(GL_MODELVIEW);
440+ glPushMatrix;
441+ glLoadIdentity;
442+
443+ glDisable(GL_DEPTH_TEST);
444+ end;
445+
446+ procedure glLeave2D;
447+ begin
448+ glMatrixMode(GL_PROJECTION);
449+ glPopMatrix;
450+ glMatrixMode(GL_MODELVIEW);
451+ glPopMatrix;
452+
453+ glEnable(GL_DEPTH_TEST);
454+ end;
673455```
674456
675-When entering 2D mode, we save current matrices and set 2D matrix using gluOrtho2D function. This way if we draw some thing on 100, 100 it will be drawn on exactly 100 pixels from left edge of window, and 100 pixels form bottom edge (positive Y is up). Also, we disable ZBuffer. This way text won't alter ZBuffer.
676-
677-Leaving 2D mode just returns old matrices and enable ZBuffer.
457+When entering 2D mode, we save current matrices and set 2D matrix using **gluOrtho2D** function. This way if we draw some thing on 100, 100 it will be drawn on exactly 100 pixels from left edge of window, and 100 pixels form bottom edge (positive Y is up). Also, we disable ZBuffer. This way text won't alter ZBuffer.
678458
679-Now, we can create function for text drawing:
459+Leaving 2D mode just returns old matrices and enable ZBuffer.
680460
681-``` pascal
461+Now, we can create function for text drawing:
462+```
682463procedure glWrite(X, Y: GLfloat; Font: Pointer; Text: String);
683-var
684- I: Integer;
685-begin
686- glRasterPos2f(X, Y);
687- for I := 1 to Length(Text) do
688- glutBitmapCharacter(Font, Integer(Text[I]));
689-end;
464+ var
465+ I: Integer;
466+ begin
467+ glRasterPos2f(X, Y);
468+ for I := 1 to Length(Text) do
469+ glutBitmapCharacter(Font, Integer(Text[I]));
470+ end;
690471```
691472
692-glutBitmapCharacter can draw only one character of selected font. First parameter is desired font (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) and other one is character.
693-
694-Character will be drawn at current raster position. To set desired raster position we call glRasterPos function. glRasterPos can handle different number and types of parameters just like glVertex function. Coordinate specified is transformed by model and projection matrix to get 2D coordinate where new raster position will be. Since we entered 2D mode, X and Y coordinates are actual 2D coordinates where drawing will occur.
473+**glutBitmapCharacter** can draw only one character of selected font. First parameter is desired font (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) and other one is character.
695474
696-This new functions will make text drawing very easy:
475+Character will be drawn at current raster position. To set desired raster position we call **glRasterPos** function. glRasterPos can handle different number and types of parameters just like glVertex function. Coordinate specified is transformed by model and projection matrix to get 2D coordinate where new raster position will be. Since we entered 2D mode, X and Y coordinates are actual 2D coordinates where drawing will occur.
697476
698-``` pascal
477+This new functions will make text drawing very easy:
478+```
699479procedure DrawGLScene; cdecl;
700-begin
701- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
702-
703- glLoadIdentity;
704- glTranslatef(0, 0, -5);
705- glRotatef(GetTotalTime * 10, 0, 0.5, 0.5);
706-
707- glColor3f(1, 0, 0);
708- glutSolidCube(2);
709-
710- glEnter2D;
711-
712- glColor3f(0.2, 0.8 + 0.2 * Sin(GetTotalTime * 5), 0);
713- glWrite(20, glGetViewportHeight - 20, GLUT_BITMAP_8_BY_13,
714- Format('OpenGL Tutorial :: Bitmap Fonts :: FPS - %.2f FPS', [FPS]));
715-
716- glColor3f(1, 1, 1);
717- glWrite(50, glGetViewportHeight - 60, GLUT_BITMAP_9_BY_15, 'GLUT_BITMAP_9_BY_15');
718- glWrite(50, glGetViewportHeight - 90, GLUT_BITMAP_8_BY_13, 'GLUT_BITMAP_8_BY_13');
719- glWrite(50, glGetViewportHeight - 120, GLUT_BITMAP_TIMES_ROMAN_10, 'GLUT_BITMAP_TIMES_ROMAN_10');
720- glWrite(50, glGetViewportHeight - 150, GLUT_BITMAP_TIMES_ROMAN_24, 'GLUT_BITMAP_TIMES_ROMAN_24');
721- glWrite(50, glGetViewportHeight - 180, GLUT_BITMAP_HELVETICA_10, 'GLUT_BITMAP_HELVETICA_10');
722- glWrite(50, glGetViewportHeight - 210, GLUT_BITMAP_HELVETICA_12, 'GLUT_BITMAP_HELVETICA_12');
723- glWrite(50, glGetViewportHeight - 240, GLUT_BITMAP_HELVETICA_18, 'GLUT_BITMAP_HELVETICA_18');
724-
725- glColor3f(0.5, 0.5, 1);
726- glWrite(
727- glGetViewportWidth - glutBitmapLength(GLUT_BITMAP_9_BY_15, LazText) - 5,
728- 10, GLUT_BITMAP_9_BY_15, LazText);
729-
730- glLeave2D;
480+ begin
481+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
482+
483+ glLoadIdentity;
484+ glTranslatef(0, 0, -5);
485+ glRotatef(GetTotalTime * 10, 0, 0.5, 0.5);
486+
487+ glColor3f(1, 0, 0);
488+ glutSolidCube(2);
489+
490+ glEnter2D;
491+
492+ glColor3f(0.2, 0.8 + 0.2 * Sin(GetTotalTime * 5), 0);
493+ glWrite(20, glGetViewportHeight - 20, GLUT_BITMAP_8_BY_13,
494+ Format('OpenGL Tutorial :: Bitmap Fonts :: FPS - %.2f FPS', [FPS]));
495+
496+ glColor3f(1, 1, 1);
497+ glWrite(50, glGetViewportHeight - 60, GLUT_BITMAP_9_BY_15, 'GLUT_BITMAP_9_BY_15');
498+ glWrite(50, glGetViewportHeight - 90, GLUT_BITMAP_8_BY_13, 'GLUT_BITMAP_8_BY_13');
499+ glWrite(50, glGetViewportHeight - 120, GLUT_BITMAP_TIMES_ROMAN_10, 'GLUT_BITMAP_TIMES_ROMAN_10');
500+ glWrite(50, glGetViewportHeight - 150, GLUT_BITMAP_TIMES_ROMAN_24, 'GLUT_BITMAP_TIMES_ROMAN_24');
501+ glWrite(50, glGetViewportHeight - 180, GLUT_BITMAP_HELVETICA_10, 'GLUT_BITMAP_HELVETICA_10');
502+ glWrite(50, glGetViewportHeight - 210, GLUT_BITMAP_HELVETICA_12, 'GLUT_BITMAP_HELVETICA_12');
503+ glWrite(50, glGetViewportHeight - 240, GLUT_BITMAP_HELVETICA_18, 'GLUT_BITMAP_HELVETICA_18');
504+
505+ glColor3f(0.5, 0.5, 1);
506+ glWrite(
507+ glGetViewportWidth - glutBitmapLength(GLUT_BITMAP_9_BY_15, LazText) - 5,
508+ 10, GLUT_BITMAP_9_BY_15, LazText);
509+
510+ glLeave2D;
511+
512+ glutSwapBuffers;
513+
514+ FrameRendered;
515+ end;
516+```
731517
732- glutSwapBuffers;
518+[![BitmapFontsPic1.jpg](/wiki-images/b/ba/BitmapFontsPic1.jpg)](</File:BitmapFontsPic1.jpg>)
733519
734- FrameRendered;
735-end;
736-```
520+[](</File:BitmapFontsPic1.jpg> "Enlarge")
737521
738-![](/wiki-images/b/ba/BitmapFontsPic1.jpg) We draw red cube and rotate it, and some text to show how various bitmap fonts look like. glutBitmapLength function is used to find width of string so it could be aligned to right. Code can easily be altered to center text.
522+We draw red cube and rotate it, and some text to show how various bitmap fonts look like. **glutBitmapLength** function is used to find width of string so it could be aligned to right. Code can easily be altered to center text.
739523
740-Note: See how cube looks without light.
524+Note: See how cube looks without light.
741525
742-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
526+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
743527
744528# Textures
745529
746-It's time to use textures :)
747-
748-This tutorial will show how to draw textured polygons and how to blend textures using multipass technic. Since OpenGL has no builtin mechanism for loading textures, we'll use external library: [Vampyre Imaging Library](http://imaginglib.sourceforge.net/). We'll use just OpenGL helper functions, but you may find this lib handy for some other things to.
530+It's time to use textures :)
749531
750-Let's get started... we'll create display list for drawing textured rectangle:
532+This tutorial will show how to draw textured polygons and how to blend textures using multipass technic. Since OpenGL has no builtin mechanism for loading textures, we'll use external library: [Vampyre Imaging Library](<http://imaginglib.sourceforge.net/>). We'll use just OpenGL helper functions, but you may find this lib handy for some other things to.
751533
752-``` pascal
534+Let's get started... we'll create display list for drawing textured rectangle:
535+```
753536procedure CreateList;
754-begin
755- glNewList(LIST_OBJECT, GL_COMPILE);
756- glBegin(GL_QUADS);
757- glTexCoord2f(1, 0);
758- glVertex3f( 2, 2, 0);
759- glTexCoord2f(0, 0);
760- glVertex3f(-2, 2, 0);
761- glTexCoord2f(0, 1);
762- glVertex3f(-2,-2, 0);
763- glTexCoord2f(1, 1);
764- glVertex3f( 2,-2, 0);
765- glEnd;
766- glEndList;
767-end;
537+ begin
538+ glNewList(LIST_OBJECT, GL_COMPILE);
539+ glBegin(GL_QUADS);
540+ glTexCoord2f(1, 0);
541+ glVertex3f( 2, 2, 0);
542+ glTexCoord2f(0, 0);
543+ glVertex3f(-2, 2, 0);
544+ glTexCoord2f(0, 1);
545+ glVertex3f(-2,-2, 0);
546+ glTexCoord2f(1, 1);
547+ glVertex3f( 2,-2, 0);
548+ glEnd;
549+ glEndList;
550+ end;
768551```
769552
770-Notice glTexCoord functions. They are used to specify which part of texture is assigned to vertex. Coordinates defined in this functions are from 0 to 1 (values greater than 1 are allowed but can generate different results). 0 is first pixel and 1 is last pixel. So, 0.5 will be right in the middle of texture.
771-
772-Texture loading is extremely easy with Vampyre Imaging Library:
553+Notice **glTexCoord** functions. They are used to specify which part of texture is assigned to vertex. Coordinates defined in this functions are from 0 to 1 (values greater than 1 are allowed but can generate different results). 0 is first pixel and 1 is last pixel. So, 0.5 will be right in the middle of texture.
773554
774-``` pascal
555+Texture loading is extremely easy with Vampyre Imaging Library:
556+```
775557var
776- Tex1, Tex2: GLuint;
777-
778-procedure InitializeGL;
779-begin
780- glClearColor(0, 0, 0, 0);
781- Tex1 := LoadGLTextureFromFile('ashwood.bmp');
782- Tex2 := LoadGLTextureFromFile('Flare.bmp');
783- glEnable(GL_TEXTURE_2D);
784-end;
558+ Tex1, Tex2: GLuint;
559+
560+ procedure InitializeGL;
561+ begin
562+ glClearColor(0, 0, 0, 0);
563+ Tex1 := LoadGLTextureFromFile('ashwood.bmp');
564+ Tex2 := LoadGLTextureFromFile('Flare.bmp');
565+ glEnable(GL_TEXTURE_2D);
566+ end;
785567```
786568
787-LoadGLTextureFromFile loads texture from file and returns it's ID. When texture is loaded it is allready setup for rendering. Last line just enables 2D textures.
788-
789-To draw textured polygon you have to bind texture and setup texture coordinations (texture coordinations are set in display list in this tutorial):
569+**LoadGLTextureFromFile** loads texture from file and returns it's ID. When texture is loaded it is allready setup for rendering. Last line just enables 2D textures.
790570
791-```text
792- ...
793- glLoadIdentity;
794- glTranslatef(-5, 0, -15);
795- glBindTexture(GL_TEXTURE_2D, Tex1);
796- glCallList(LIST_OBJECT);
797- ...
571+To draw textured polygon you have to bind texture and setup texture coordinations (texture coordinations are set in display list in this tutorial):
798572```
799-
800-glBindTexture function is used to select texture. When you draw polygins they will have selected texture on them. It's that easy :)
801-
802-So, using one texture is easy... but how to blend two textures. Basicly you draw polygon once with one texture, setup blending parameters, and draw polygon once more time with other texture. You can blend houndreds of textures this way. Let's see how code for this looks:
573+...
574+ glLoadIdentity;
575+ glTranslatef(-5, 0, -15);
576+ glBindTexture(GL_TEXTURE_2D, Tex1);
577+ glCallList(LIST_OBJECT);
578+ ...
579+```
803580
804-```text
805- ...
806- glLoadIdentity;
807- glTranslatef(5, 0, -15);
808- glBindTexture(GL_TEXTURE_2D, Tex1);
809- glCallList(LIST_OBJECT);
581+**glBindTexture** function is used to select texture. When you draw polygins they will have selected texture on them. It's that easy :)
810582
811- glEnable(GL_BLEND);
812- glBlendFunc(GL_ZERO, GL_SRC_COLOR);
813- glLoadIdentity;
814- glTranslatef(5, 0, -15);
815- glBindTexture(GL_TEXTURE_2D, Tex2);
816- glCallList(LIST_OBJECT);
817- glDisable(GL_BLEND);
583+So, using one texture is easy... but how to blend two textures. Basicly you draw polygon once with one texture, setup blending parameters, and draw polygon once more time with other texture. You can blend houndreds of textures this way. Let's see how code for this looks:
584+```
818585...
586+ glLoadIdentity;
587+ glTranslatef(5, 0, -15);
588+ glBindTexture(GL_TEXTURE_2D, Tex1);
589+ glCallList(LIST_OBJECT);
590+
591+ glEnable(GL_BLEND);
592+ glBlendFunc(GL_ZERO, GL_SRC_COLOR);
593+ glLoadIdentity;
594+ glTranslatef(5, 0, -15);
595+ glBindTexture(GL_TEXTURE_2D, Tex2);
596+ glCallList(LIST_OBJECT);
597+ glDisable(GL_BLEND);
598+ ...
819599```
820600
821-As you can see, polygon is drawn first time like we allready know. Before second drawing we enable blending by calling glEnable(GL_BLEND). Blending means that finall pixel color is calculated like this:
822-
823-```text
601+As you can see, polygon is drawn first time like we allready know. Before second drawing we enable blending by calling **glEnable(GL_BLEND)**. Blending means that finall pixel color is calculated like this:
602+```
824603DrawingColor * SRCBLEND + BackgroundColor * DESTBLEND
825604```
826605
827-SRCBLEND and DESTBLEND are defined using glBlendFunc function. In this tutorial we set SRCBLEND to GL_ZERO (zero) and DESTBLENT to GL_SRC_COLOR (DrawingColor) and finall color is then:
828-
829-```text
606+SRCBLEND and DESTBLEND are defined using **glBlendFunc** function. In this tutorial we set SRCBLEND to GL_ZERO (zero) and DESTBLENT to GL_SRC_COLOR (DrawingColor) and finall color is then:
607+```
830608DrawingColor * 0 + BackgroundColor * DrawingColor
831609```
832610
833-![](/wiki-images/d/d4/TexturesPic1.jpg)
611+[![TexturesPic1.jpg](/wiki-images/d/d4/TexturesPic1.jpg)](</File:TexturesPic1.jpg>)
834612
835-This means that background will get darker when you draw with dark colors... when you draw with white color, background color will not be changed. The result will look like this
613+[](</File:TexturesPic1.jpg> "Enlarge")
836614
837-Next time, we'll use extensions to show how to use singlepass multitexturing.
615+This means that background will get darker when you draw with dark colors... when you draw with white color, background color will not be changed. The result will look like this
838616
839-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
617+Next time, we'll use extensions to show how to use singlepass multitexturing.
840618
841-# Multitexturing (extensions)
619+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
842620
843-When youknow multipass multi texturing, singlepass is very easy. Texturing is separated in stages. First stage setup and draw first texture, second stage draws another one and so on. All you have to do is to setup texture stages and to render object.
621+# Multitexturing (extensions)
844622
845-Let's see how code looks like:
623+When youknow multipass multi texturing, singlepass is very easy. Texturing is separated in stages. First stage setup and draw first texture, second stage draws another one and so on. All you have to do is to setup texture stages and to render object.
846624
847-``` pascal
625+Let's see how code looks like:
626+```
848627procedure InitializeGL;
849-begin
850- Load_GL_ARB_multitexture;
851- glClearColor(0, 0, 0, 0);
852- Tex1 := LoadGLTextureFromFile('Lazarus.bmp');
853- Tex2 := LoadGLTextureFromFile('Mask.bmp');
854- glActiveTextureARB(GL_TEXTURE0_ARB);
855- glEnable(GL_TEXTURE_2D);
856- glBindTexture(GL_TEXTURE_2D, Tex1);
857- glActiveTextureARB(GL_TEXTURE1_ARB);
858- glEnable(GL_TEXTURE_2D);
859- glBindTexture(GL_TEXTURE_2D, Tex2);
860-end;
628+ begin
629+ Load_GL_ARB_multitexture;
630+ glClearColor(0, 0, 0, 0);
631+ Tex1 := LoadGLTextureFromFile('Lazarus.bmp');
632+ Tex2 := LoadGLTextureFromFile('Mask.bmp');
633+ glActiveTextureARB(GL_TEXTURE0_ARB);
634+ glEnable(GL_TEXTURE_2D);
635+ glBindTexture(GL_TEXTURE_2D, Tex1);
636+ glActiveTextureARB(GL_TEXTURE1_ARB);
637+ glEnable(GL_TEXTURE_2D);
638+ glBindTexture(GL_TEXTURE_2D, Tex2);
639+ end;
861640```
862641
863-First we need load OpenGL extension that will allow us to use multitexture functions. Load_GL_ARB_multitexture will try to load those extensions and will return TRUE if operation was successful.
864-
865-To select texture stage you want to work on, use glActiveTextureARB function. It takes only one parameter that define which stage you want. After that all texture functions (enabling, disabling, binding, creating...) will affect that stage.
642+First we need load OpenGL extension that will allow us to use multitexture functions. **Load_GL_ARB_multitexture** will try to load those extensions and will return TRUE if operation was successful.
866643
867-Since we setup every thing in initialization function, all we have to do is to draw object:
644+To select texture stage you want to work on, use **glActiveTextureARB** function. It takes only one parameter that define which stage you want. After that all texture functions (enabling, disabling, binding, creating...) will affect that stage.
868645
869-``` pascal
646+Since we setup every thing in initialization function, all we have to do is to draw object:
647+```
870648procedure DrawGLScene; cdecl;
871-begin
872- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
873-
874- glLoadIdentity;
875- glTranslatef(0, 0, -5);
649+ begin
650+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
651+
652+ glLoadIdentity;
653+ glTranslatef(0, 0, -5);
654+
655+ glBegin(GL_QUADS);
656+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 0);
657+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);
658+ glVertex3f(2.516, 2, 0);
659+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);
660+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
661+ glVertex3f(-2.516, 2, 0);
662+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 1);
663+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);
664+ glVertex3f(-2.516,-2, 0);
665+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 1);
666+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
667+ glVertex3f(2.516,-2, 0);
668+ glEnd;
669+
670+ glutSwapBuffers;
671+ end;
672+```
876673
877- glBegin(GL_QUADS);
878- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 0);
879- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 0);
880- glVertex3f(2.516, 2, 0);
881- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0);
882- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 0);
883- glVertex3f(-2.516, 2, 0);
884- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 1);
885- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0, 1);
886- glVertex3f(-2.516,-2, 0);
887- glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1, 1);
888- glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1, 1);
889- glVertex3f(2.516,-2, 0);
890- glEnd;
674+[![MultitexturePic1.jpg](/wiki-images/5/52/MultitexturePic1.jpg)](</File:MultitexturePic1.jpg>)
891675
892- glutSwapBuffers;
893-end;
894-```
676+[](</File:MultitexturePic1.jpg> "Enlarge")
895677
896-![](/wiki-images/5/52/MultitexturePic1.jpg) As you can see, difference is only in defining texture coordinations. We now use glMultiTexCoord2fARB function that takes texture stage and texture coordinations. Every thing else is unchanged.
678+As you can see, difference is only in defining texture coordinations. We now use **glMultiTexCoord2fARB** function that takes texture stage and texture coordinations. Every thing else is unchanged.
897679
898-Today almost all graphic cards supports at least 2 texture stages. Using singlepass multitexturing is faster than multipass version since you draw objects only once. If hardware supports singlepass multitexturing (Load_GL_ARB_multitexture returns TRUE) use it.
680+Today almost all graphic cards supports at least 2 texture stages. Using singlepass multitexturing is faster than multipass version since you draw objects only once. If hardware supports singlepass multitexturing (Load_GL_ARB_multitexture returns TRUE) use it.
899681
900-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
682+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
901683
902684# Render to texture
903685
904-This one will be short. OpenGL can capture current scene to texture so you can use it for texturing other objects (TV screen, mirror or some thing else). Well just render scene to texture and apply it to rotating plane.
905-
906-First, we must create empty texture which well use to capture scene:
686+This one will be short. OpenGL can capture current scene to texture so you can use it for texturing other objects (TV screen, mirror or some thing else). Well just render scene to texture and apply it to rotating plane.
907687
908-``` pascal
688+First, we must create empty texture which well use to capture scene:
689+```
909690procedure SetupRenderTexture;
910-var
911- Data: Pointer;
912-begin
913- GetMem(Data, 256*256*3);
914- glGenTextures(1, @RenderTexture);
915- glBindTexture(GL_TEXTURE_2D, RenderTexture);
916- glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
917- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
918- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
919- FreeMem(Data);
920-end;
691+ var
692+ Data: Pointer;
693+ begin
694+ GetMem(Data, 256*256*3);
695+ glGenTextures(1, @RenderTexture);
696+ glBindTexture(GL_TEXTURE_2D, RenderTexture);
697+ glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
698+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
699+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
700+ FreeMem(Data);
701+ end;
921702```
922703
923-Buffer for 256*256 RGB image is created and it is used to setup 2D texture.
924-
925-Main part is in drawing function:
704+Buffer for 256*256 RGB image is created and it is used to setup 2D texture.
926705
927-``` pascal
706+Main part is in drawing function:
707+```
928708procedure DrawGLScene; cdecl;
929-var
930- TotalTime: Single;
931-begin
932- glClearColor(0, 0, 0, 0);
933- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
934- glEnable(GL_LIGHTING);
935- glDisable(GL_TEXTURE_2D);
936- glViewport(0, 0, 256, 256);
937-
938- TotalTime := GetTotalTime;
939-
940- glLoadIdentity;
941- glTranslatef(0, 0, -5);
942- glRotatef(50 * TotalTime, 1, 0, 0);
943- glRotatef(100 * TotalTime, 0, 1, 0);
944- glRotatef(50 * TotalTime, 0, 0, 1);
945-
946- glColor3f(1, 1, 1);
947- glutSolidCube(2);
948-
949- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 256, 256, 0);
950-
951- glClearColor(0.18, 0.20, 0.66, 0);
952- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
953- glDisable(GL_LIGHTING);
954- glEnable(GL_TEXTURE_2D);
955- glViewport(0, 0, AppWidth, AppHeight);
956-
957- glLoadIdentity;
958- glTranslatef(0, 0, -7);
959- glRotatef(20 * TotalTime, 1, 0, 0);
960- glRotatef(50 * TotalTime, 0, 1, 0);
709+ var
710+ TotalTime: Single;
711+ begin
712+ glClearColor(0, 0, 0, 0);
713+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
714+ glEnable(GL_LIGHTING);
715+ glDisable(GL_TEXTURE_2D);
716+ glViewport(0, 0, 256, 256);
717+
718+ TotalTime := GetTotalTime;
719+
720+ glLoadIdentity;
721+ glTranslatef(0, 0, -5);
722+ glRotatef(50 * TotalTime, 1, 0, 0);
723+ glRotatef(100 * TotalTime, 0, 1, 0);
724+ glRotatef(50 * TotalTime, 0, 0, 1);
725+
726+ glColor3f(1, 1, 1);
727+ glutSolidCube(2);
728+
729+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 256, 256, 0);
730+
731+ glClearColor(0.18, 0.20, 0.66, 0);
732+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
733+ glDisable(GL_LIGHTING);
734+ glEnable(GL_TEXTURE_2D);
735+ glViewport(0, 0, AppWidth, AppHeight);
736+
737+ glLoadIdentity;
738+ glTranslatef(0, 0, -7);
739+ glRotatef(20 * TotalTime, 1, 0, 0);
740+ glRotatef(50 * TotalTime, 0, 1, 0);
741+
742+ glBegin(GL_QUADS);
743+ glTexCoord2f(1, 0);
744+ glVertex3f(2, 2, 0);
745+ glTexCoord2f(0, 0);
746+ glVertex3f(-2, 2, 0);
747+ glTexCoord2f(0, 1);
748+ glVertex3f(-2,-2, 0);
749+ glTexCoord2f(1, 1);
750+ glVertex3f(2,-2, 0);
751+ glEnd;
752+
753+ glutSwapBuffers;
754+ end;
755+```
961756
962- glBegin(GL_QUADS);
963- glTexCoord2f(1, 0);
964- glVertex3f(2, 2, 0);
965- glTexCoord2f(0, 0);
966- glVertex3f(-2, 2, 0);
967- glTexCoord2f(0, 1);
968- glVertex3f(-2,-2, 0);
969- glTexCoord2f(1, 1);
970- glVertex3f(2,-2, 0);
971- glEnd;
757+[![RenderToTexturePic1.jpg](/wiki-images/6/6e/RenderToTexturePic1.jpg)](</File:RenderToTexturePic1.jpg>)
972758
973- glutSwapBuffers;
974-end;
975-```
759+[](</File:RenderToTexturePic1.jpg> "Enlarge")
976760
977-![](/wiki-images/6/6e/RenderToTexturePic1.jpg) First, everything is setup for scene that will be captured. Viewport is reduced to 256*256 so it will fit into texture and scene is drawn. glCopyTexImage2D is used to capture scene to currently selected texture.
761+First, everything is setup for scene that will be captured. Viewport is reduced to 256*256 so it will fit into texture and scene is drawn. **glCopyTexImage2D** is used to capture scene to currently selected texture.
978762
979-When we have scene captured to texture, everything can be cleared again, viewport can be returned to original size and final scene is drawn using previous scene as texture.
763+When we have scene captured to texture, everything can be cleared again, viewport can be returned to original size and final scene is drawn using previous scene as texture.
980764
981-P.S. Captured texture can be saved using SaveGLTextureToFile function from [Vampyre Imaging Library](http://imaginglib.sourceforge.net/).
765+P.S. Captured texture can be saved using **SaveGLTextureToFile** function from [Vampyre Imaging Library](<http://imaginglib.sourceforge.net/>).
982766
983-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
767+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
984768
985769# Vertex array
986770
987-OpenGL is capable of rendering primitives using data that is stored in buffers insted of calling glVertex. Buffers can be used to define vertex and texture coordinates, and colors (index and RGBA), normals and edge flags.
988-
989-In this tutorial well use only vertex and color buffers, and we'll show non-indexed and indexed drawing. Non-indexed mode draws buffers as streams. Indexed mode will draw buffer elements in order that is defined in index buffer. But enough talking... let's start coding.
771+OpenGL is capable of rendering primitives using data that is stored in buffers insted of calling glVertex. Buffers can be used to define vertex and texture coordinates, and colors (index and RGBA), normals and edge flags.
990772
991-First, let's define some types and constants:
773+In this tutorial well use only vertex and color buffers, and we'll show non-indexed and indexed drawing. Non-indexed mode draws buffers as streams. Indexed mode will draw buffer elements in order that is defined in index buffer. But enough talking... let's start coding.
992774
993-``` pascal
775+First, let's define some types and constants:
776+```
994777type
995- TVertex3f = record
996- X, Y, Z: Single;
997- end;
998-
999- TColor3f = record
1000- R, G, B: Single;
1001- end;
1002-
1003- VertexBuffer: array [0..5] of TVertex3f = (
1004- (X : 1; Y : 1; Z : 0),
1005- (X : -1; Y : 1; Z : 0),
1006- (X : -1; Y : -1; Z : 0),
1007- (X : 1; Y : 1; Z : 0),
1008- (X : -1; Y : -1; Z : 0),
1009- (X : 1; Y : -1; Z : 0)
1010- );
1011- ColorBuffer: array [0..5] of TColor3f = (
1012- (R : 1; G : 0; B : 1),
1013- (R : 0; G : 0; B : 1),
1014- (R : 0; G : 1; B : 0),
1015- (R : 1; G : 0; B : 1),
1016- (R : 0; G : 1; B : 0),
1017- (R : 1; G : 1; B : 0)
1018- );
778+ TVertex3f = record
779+ X, Y, Z: Single;
780+ end;
781+
782+ TColor3f = record
783+ R, G, B: Single;
784+ end;
785+
786+ VertexBuffer: array [0..5] of TVertex3f = (
787+ (X : 1; Y : 1; Z : 0),
788+ (X : -1; Y : 1; Z : 0),
789+ (X : -1; Y : -1; Z : 0),
790+ (X : 1; Y : 1; Z : 0),
791+ (X : -1; Y : -1; Z : 0),
792+ (X : 1; Y : -1; Z : 0)
793+ );
794+ ColorBuffer: array [0..5] of TColor3f = (
795+ (R : 1; G : 0; B : 1),
796+ (R : 0; G : 0; B : 1),
797+ (R : 0; G : 1; B : 0),
798+ (R : 1; G : 0; B : 1),
799+ (R : 0; G : 1; B : 0),
800+ (R : 1; G : 1; B : 0)
801+ );
1019802```
1020803
1021-We have two buffers. One for vertex coordinates and one for vertex colors. This 6 vertices defines 2 triangles that forms rectangle.
1022-
1023-Drawing primitives using buffers is easy:
1024-
1025-```text
1026- glEnableClientState(GL_VERTEX_ARRAY);
1027- glEnableClientState(GL_COLOR_ARRAY);
1028- glVertexPointer(3, GL_FLOAT, 0, @VertexBuffer[0]);
1029- glColorPointer(3, GL_FLOAT, 0, @ColorBuffer[0]);
1030-
1031- glDrawArrays(GL_TRIANGLES, 0, Length(VertexBuffer));
804+We have two buffers. One for vertex coordinates and one for vertex colors. This 6 vertices defines 2 triangles that forms rectangle.
1032805
1033- glDisableClientState(GL_VERTEX_ARRAY);
1034- glDisableClientState(GL_COLOR_ARRAY);
806+Drawing primitives using buffers is easy:
1035807```
1036-
1037-First we enable buffers we want to use using glEnableClientState function. Than we can select buffers we want to use. Every buffer type has own function for selecting (glColorPointer, glEdgeFlagPointer, glIndexPointer, glNormalPointer, glTexCoordPointer, glVertexPointer). First parameter in those functions defines how many numbers every element contains. For example, let's take vertex buffer. If this parameter is 2 than OpenGL expects that every element in buffer contains x and y coordinate. If this parameter is, for example, 4, than every element should contains x, y, z and w coordinate. Next parameter defines what type of data element contains (GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT or GL_DOUBLE). Next one defines how many bytes are between each element. This way you can have buffer that contains vertex coordinates and some custom data. For arbitrary data type, this parameter can be calculated like this:
808+glEnableClientState(GL_VERTEX_ARRAY);
809+ glEnableClientState(GL_COLOR_ARRAY);
810+ glVertexPointer(3, GL_FLOAT, 0, @VertexBuffer[0]);
811+ glColorPointer(3, GL_FLOAT, 0, @ColorBuffer[0]);
812+
813+ glDrawArrays(GL_TRIANGLES, 0, Length(VertexBuffer));
814+
815+ glDisableClientState(GL_VERTEX_ARRAY);
816+ glDisableClientState(GL_COLOR_ARRAY);
817+```
1038818
1039-``` pascal
819+First we enable buffers we want to use using **glEnableClientState** function. Than we can select buffers we want to use. Every buffer type has own function for selecting (**glColorPointer** , **glEdgeFlagPointer** , **glIndexPointer** , **glNormalPointer** , **glTexCoordPointer** , **glVertexPointer**). First parameter in those functions defines how many numbers every element contains. For example, let's take vertex buffer. If this parameter is 2 than OpenGL expects that every element in buffer contains x and y coordinate. If this parameter is, for example, 4, than every element should contains x, y, z and w coordinate. Next parameter defines what type of data element contains (GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT or GL_DOUBLE). Next one defines how many bytes are between each element. This way you can have buffer that contains vertex coordinates and some custom data. For arbitrary data type, this parameter can be calculated like this:
820+```
1040821type
1041- TBufferData = record
1042- DataBefore: TDataBefore;
1043- Vertex: TVertex;
1044- DataAfter: TDataAfter;
1045- end;
1046-
1047-Bytes between elements = SizeOf(TDataBefore) + SizeOf(TDataAfter)
822+ TBufferData = record
823+ DataBefore: TDataBefore;
824+ Vertex: TVertex;
825+ DataAfter: TDataAfter;
826+ end;
827+
828+ Bytes between elements = SizeOf(TDataBefore) + SizeOf(TDataAfter)
1048829```
1049830
1050-Last parameter if pointer to the begginig of buffer.
1051-
1052-When buffers are selected we can draw them using glDrawArrays functions. All enabled buffers are used to draw primitives. What kind of polygons are being generated is defined in first parameter (same as in glBegin function). Next two defines subset of buffer which is used for drawing (start and count).
831+Last parameter if pointer to the begginig of buffer.
1053832
1054-When buffers are not needed you can disable them.
833+When buffers are selected we can draw them using **glDrawArrays** functions. All enabled buffers are used to draw primitives. What kind of polygons are being generated is defined in first parameter (same as in glBegin function). Next two defines subset of buffer which is used for drawing (start and count).
1055834
1056-To demonstrate indexed mode, I made some simple mesh class that can load vertex, color and index data from external files:
835+When buffers are not needed you can disable them.
1057836
1058-``` pascal
837+To demonstrate indexed mode, I made some simple mesh class that can load vertex, color and index data from external files:
838+```
1059839type
1060- TMesh = class
1061- private
1062- FVertices: array of TVertex3f;
1063- FColors: array of TColor3f;
1064- FIndices: array of Integer;
1065- procedure FreeBuffers;
1066- public
1067- constructor Create;
1068- destructor Destroy; override;
1069- procedure LoadMesh(FileName: String);
1070- procedure DrawMesh;
1071- end;
840+ TMesh = class
841+ private
842+ FVertices: array of TVertex3f;
843+ FColors: array of TColor3f;
844+ FIndices: array of Integer;
845+ procedure FreeBuffers;
846+ public
847+ constructor Create;
848+ destructor Destroy; override;
849+ procedure LoadMesh(FileName: String);
850+ procedure DrawMesh;
851+ end;
1072852```
1073853
1074-FVertices will contain data about vertices, FColors data about color and FIndices data about indices when external file is loaded.
1075-
1076-First we'll write some code that deals with creation and destruction of class:
854+FVertices will contain data about vertices, FColors data about color and FIndices data about indices when external file is loaded.
1077855
1078-``` pascal
856+First we'll write some code that deals with creation and destruction of class:
857+```
1079858procedure TMesh.FreeBuffers;
1080-begin
1081- FVertices := nil;
1082- FColors := nil;
1083- FIndices := nil;
1084-end;
1085-
1086-constructor TMesh.Create;
1087-begin
1088- FreeBuffers;
1089-end;
1090-
1091-destructor TMesh.Destroy;
1092-begin
1093- FreeBuffers;
1094- inherited Destroy;
1095-end;
859+ begin
860+ FVertices := nil;
861+ FColors := nil;
862+ FIndices := nil;
863+ end;
864+
865+ constructor TMesh.Create;
866+ begin
867+ FreeBuffers;
868+ end;
869+
870+ destructor TMesh.Destroy;
871+ begin
872+ FreeBuffers;
873+ inherited Destroy;
874+ end;
1096875```
1097876
1098-File that will contain mesh data is simple text file. First row will contain number of vertices and indices separated by space character. After that row will come rows for every vertex and color. X, Y, Z, R, G and B all separated by space character. In the end, there will be rows for indices... every index number is written in its own row... so, for one triangle, data file will look like this:
1099-
1100-```text
877+File that will contain mesh data is simple text file. First row will contain number of vertices and indices separated by space character. After that row will come rows for every vertex and color. X, Y, Z, R, G and B all separated by space character. In the end, there will be rows for indices... every index number is written in its own row... so, for one triangle, data file will look like this:
878+```
11018793 3
1102--1 -1 0 1 1 1
1103-1 -1 0 1 1 1
1104-0 1 0 1 1 1
1105-0
1106-1
1107-2
880+ -1 -1 0 1 1 1
881+ 1 -1 0 1 1 1
882+ 0 1 0 1 1 1
883+ 0
884+ 1
885+ 2
1108886```
1109887
1110-This means that there is 3 vertices and 3 indices defined in file. First vrtex is at -1, -1, 0 and has color 1, 1, 1 and so on. Indices defines that order in which vertices are drawn (in this case vertices are drawn in the same order as they are defined).
1111-
1112-Code for loading this data will loke like this:
888+This means that there is 3 vertices and 3 indices defined in file. First vrtex is at -1, -1, 0 and has color 1, 1, 1 and so on. Indices defines that order in which vertices are drawn (in this case vertices are drawn in the same order as they are defined).
1113889
1114-``` pascal
890+Code for loading this data will loke like this:
891+```
1115892procedure TMesh.LoadMesh(FileName: String);
1116-var
1117- MeshFile: TextFile;
1118- VertexCount, IndexCount: Integer;
1119- iV, iI: Integer;
1120-begin
1121- FreeBuffers;
1122-
1123- AssignFile(MeshFile, FileName);
1124- Reset(MeshFile);
1125-
1126- ReadLn(MeshFile, VertexCount, IndexCount);
1127-
1128- SetLength(FVertices, VertexCount);
1129- SetLength(FColors, VertexCount);
1130- SetLength(FIndices, IndexCount);
1131-
1132- for iV := 0 to VertexCount - 1 do
1133- ReadLn(MeshFile,
1134- FVertices[iV].X, FVertices[iV].Y, FVertices[iV].Z,
1135- FColors[iV].R, FColors[iV].G, FColors[iV].B);
1136-
1137- for iI := 0 to IndexCount - 1 do
1138- ReadLn(MeshFile, FIndices[iI]);
1139-
1140- CloseFile(MeshFile);
1141-end;
893+ var
894+ MeshFile: TextFile;
895+ VertexCount, IndexCount: Integer;
896+ iV, iI: Integer;
897+ begin
898+ FreeBuffers;
899+
900+ AssignFile(MeshFile, FileName);
901+ Reset(MeshFile);
902+
903+ ReadLn(MeshFile, VertexCount, IndexCount);
904+
905+ SetLength(FVertices, VertexCount);
906+ SetLength(FColors, VertexCount);
907+ SetLength(FIndices, IndexCount);
908+
909+ for iV := 0 to VertexCount - 1 do
910+ ReadLn(MeshFile,
911+ FVertices[iV].X, FVertices[iV].Y, FVertices[iV].Z,
912+ FColors[iV].R, FColors[iV].G, FColors[iV].B);
913+
914+ for iI := 0 to IndexCount - 1 do
915+ ReadLn(MeshFile, FIndices[iI]);
916+
917+ CloseFile(MeshFile);
918+ end;
1142919```
1143920
1144-After loading data, we have everything for drawing:
1145-
1146-``` pascal
921+After loading data, we have everything for drawing:
922+```
1147923procedure TMesh.DrawMesh;
1148-begin
1149- glEnableClientState(GL_VERTEX_ARRAY);
1150- glEnableClientState(GL_COLOR_ARRAY);
1151- glVertexPointer(3, GL_FLOAT, 0, @FVertices[0]);
1152- glColorPointer(3, GL_FLOAT, 0, @FColors[0]);
1153-
1154- glDrawElements(GL_TRIANGLES, Length(FIndices), GL_UNSIGNED_INT, @FIndices[0]);
1155-
1156- glDisableClientState(GL_VERTEX_ARRAY);
1157- glDisableClientState(GL_COLOR_ARRAY);
1158-end;
924+ begin
925+ glEnableClientState(GL_VERTEX_ARRAY);
926+ glEnableClientState(GL_COLOR_ARRAY);
927+ glVertexPointer(3, GL_FLOAT, 0, @FVertices[0]);
928+ glColorPointer(3, GL_FLOAT, 0, @FColors[0]);
929+
930+ glDrawElements(GL_TRIANGLES, Length(FIndices), GL_UNSIGNED_INT, @FIndices[0]);
931+
932+ glDisableClientState(GL_VERTEX_ARRAY);
933+ glDisableClientState(GL_COLOR_ARRAY);
934+ end;
1159935```
1160936
1161-As you can see, allmost everything is the same as for non-indexed drawing, except function that actually draw polygons. In this case we use glDrawElements function. For this one we specify what kind of polygons we want, how many indices are in index buffer, type of data in index buffer and pointer to the beginning of index buffer.
937+As you can see, allmost everything is the same as for non-indexed drawing, except function that actually draw polygons. In this case we use **glDrawElements** function. For this one we specify what kind of polygons we want, how many indices are in index buffer, type of data in index buffer and pointer to the beginning of index buffer.
1162938
1163-![](/wiki-images/7/77/VertexArrayPic1.jpg)Full source code comes with mesh data file that this class can use to generates rectangle that is identical with one that is drawn using non-indexed mode. Mesh data file looks like this:
939+[![VertexArrayPic1.jpg](/wiki-images/7/77/VertexArrayPic1.jpg)](</File:VertexArrayPic1.jpg>)
1164940
1165-```text
941+[](</File:VertexArrayPic1.jpg> "Enlarge")
942+
943+Full source code comes with mesh data file that this class can use to generates rectangle that is identical with one that is drawn using non-indexed mode. Mesh data file looks like this:
944+```
11669454 6
1167-1 1 0 1 0 1
1168--1 1 0 0 0 1
1169--1 -1 0 0 1 0
1170-1 -1 0 1 1 0
1171-0
1172-1
1173-2
1174-0
1175-2
1176-3
946+ 1 1 0 1 0 1
947+ -1 1 0 0 0 1
948+ -1 -1 0 0 1 0
949+ 1 -1 0 1 1 0
950+ 0
951+ 1
952+ 2
953+ 0
954+ 2
955+ 3
1177956```
1178957
1179-As you can see, there is data for only 4 vertices and 6 indices. So, first triangle is defined by vertices 0, 1 and 2, and the seccond one by vertices 0, 2 and 3. By using indexed mode we don't have to duplicate vertices.
958+As you can see, there is data for only 4 vertices and 6 indices. So, first triangle is defined by vertices 0, 1 and 2, and the seccond one by vertices 0, 2 and 3. By using indexed mode we don't have to duplicate vertices.
1180959
1181-Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145).
960+Download source code, linux executable or windows executable from [Lazarus CCR SourceForge](<http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=199145>).
1182961
1183962---
1184-*From the Free Pascal wiki, page "OpenGL Tutorial/ja", as it stood on 2009-01-29 after a change by Saeka-jp, 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).*
963+*From the Free Pascal wiki, page "OpenGL Tutorial/ja", as the Internet Archive kept it on 2025-01-17, last changed on 2009-01-30. 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