@@ -21,7 +21,7 @@ OpenGL is 25 years old! Since the first release in 1992, a lot has happened
21
21
(and is still happening actually, with the newly released Vulkan _ API and the
22
22
4.6 GL release) and consequently, before diving into the book, it is important
23
23
to understand OpenGL API evolution over the years. If the first API (1.xx) has
24
- not changed too much in the first twelve years, a big change occured in 2004
24
+ not changed too much in the first twelve years, a big change occurred in 2004
25
25
with the introduction of the dynamic pipeline (OpenGL 2.x), i.e. the use of
26
26
shaders that allow to have direct access to the GPU. Before this version,
27
27
OpenGL was using a fixed pipeline that made it easy to rapidly prototype some
@@ -130,8 +130,8 @@ API).
130
130
.. note ::
131
131
132
132
The number of functions and constants have been computed using the
133
- `<code/registry.py >`_ program that parses the gl.xml _ file that defines the
134
- OpenGL and OpenGL API Registry
133
+ `<code/chapter-02/ registry.py >`_ program that parses the gl.xml _ file that
134
+ defines the OpenGL and OpenGL API Registry
135
135
136
136
======== ========= ========= === ============ ========= =========
137
137
Version Constants Functions Version Constants Functions
@@ -167,7 +167,7 @@ The graphic pipeline
167
167
.. Note ::
168
168
169
169
The shader language is called glsl. There are many versions that goes from 1.0
170
- to 1.5 and subsequents version get the number of OpenGL version. Last version
170
+ to 1.5 and subsequent version get the number of OpenGL version. Last version
171
171
is 4.6 (June 2017).
172
172
173
173
If you want to understand modern OpenGL, you have to understand the graphic
@@ -178,7 +178,7 @@ depending on the version of OpenGL you're using), they will act at different
178
178
stage of the rendering pipeline. To simplify this tutorial, we'll use only
179
179
**vertex ** and **fragment ** shaders as shown below:
180
180
181
- .. image :: data /gl-pipeline.png
181
+ .. image :: images/chapter-02 /gl-pipeline.png
182
182
:width: 100%
183
183
184
184
A vertex shader acts on vertices and is supposed to output the vertex
@@ -207,7 +207,7 @@ output the null vertex (`gl_Position` is a special variable) while the second
207
207
will only output the black color for any fragment (`gl_FragColor ` is also a
208
208
special variable). We'll see later how to make them to do more useful things.
209
209
210
- One question remains: when are those shaders exectuted exactly ? The vertex
210
+ One question remains: when are those shaders executed exactly ? The vertex
211
211
shader is executed for each vertex that is given to the rendering pipeline
212
212
(we'll see what does that mean exactly later) and the fragment shader is
213
213
executed on each fragment (= pixel) that is generated after the vertex
@@ -246,7 +246,7 @@ structured array using numpy_:
246
246
247
247
We just created a CPU buffer with 4 vertices, each of them having a
248
248
`position ` (3 floats for x,y,z coordinates) and a `color ` (4 floats for
249
- red, blue, green and alpha channels). Note that we explicitely chose to have 3
249
+ red, blue, green and alpha channels). Note that we explicitly chose to have 3
250
250
coordinates for `position ` but we may have chosen to have only 2 if were to
251
251
work in two-dimensions. Same holds true for `color `. We could have used
252
252
only 3 channels (r,g,b) if we did not want to use transparency. This would save
@@ -263,8 +263,8 @@ using 2 floats for position and 4 floats for color:
263
263
264
264
.. code :: python
265
265
266
- data = numpy.zeros(4 , dtype = [ (" position" , np.float32, 2 ),
267
- (" color" , np.float32, 4 )] )
266
+ data = numpy.zeros(4 , dtype = [ (" position" , np.float32, 2 ),
267
+ (" color" , np.float32, 4 )] )
268
268
269
269
We need to tell the vertex shader that it will have to handle vertices where a
270
270
position is a tuple of 2 floats and color is a tuple of 4 floats. This is
@@ -273,19 +273,19 @@ vertex shader:
273
273
274
274
.. code :: glsl
275
275
276
- attribute vec2 position;
277
- attribute vec4 color;
278
- void main()
279
- {
280
- gl_Position = vec4(position, 0.0, 1.0);
281
- }
276
+ attribute vec2 position;
277
+ attribute vec4 color;
278
+ void main()
279
+ {
280
+ gl_Position = vec4(position, 0.0, 1.0);
281
+ }
282
282
283
283
This vertex shader now expects a vertex to possess 2 attributes, one named
284
284
`position ` and one named `color ` with specified types (vec3 means tuple of
285
285
3 floats and vec4 means tuple of 4 floats). It is important to note that even
286
286
if we labeled the first attribute `position `, this attribute is not yet bound
287
287
to the actual `position ` in the numpy array. We'll need to do it explicitly
288
- at some point in our program and there is no omagic that will bind the numpy
288
+ at some point in our program and there is no magic that will bind the numpy
289
289
array field to the right attribute, you'll have to do it yourself, but we'll
290
290
see that later.
291
291
@@ -296,44 +296,44 @@ we would thus write:
296
296
297
297
.. code :: glsl
298
298
299
- uniform float scale;
300
- attribute vec2 position;
301
- attribute vec4 color;
302
- void main()
303
- {
304
- gl_Position = vec4(position*scale, 0.0, 1.0);
305
- }
299
+ uniform float scale;
300
+ attribute vec2 position;
301
+ attribute vec4 color;
302
+ void main()
303
+ {
304
+ gl_Position = vec4(position*scale, 0.0, 1.0);
305
+ }
306
306
307
307
Last type is the varying type that is used to pass information between the
308
308
vertex stage and the fragment stage. So let us suppose (again) we want to pass
309
309
the vertex color to the fragment shader, we now write:
310
310
311
311
.. code :: glsl
312
312
313
- uniform float scale;
314
- attribute vec2 position;
315
- attribute vec4 color;
316
- varying vec4 v_color;
313
+ uniform float scale;
314
+ attribute vec2 position;
315
+ attribute vec4 color;
316
+ varying vec4 v_color;
317
317
318
- void main()
319
- {
320
- gl_Position = vec4(position*scale, 0.0, 1.0);
321
- v_color = color;
322
- }
318
+ void main()
319
+ {
320
+ gl_Position = vec4(position*scale, 0.0, 1.0);
321
+ v_color = color;
322
+ }
323
323
324
324
and then in the fragment shader, we write:
325
325
326
326
.. code :: glsl
327
327
328
- varying vec4 v_color;
328
+ varying vec4 v_color;
329
329
330
- void main()
331
- {
332
- gl_FragColor = v_color;
333
- }
330
+ void main()
331
+ {
332
+ gl_FragColor = v_color;
333
+ }
334
334
335
335
The question is what is the value of `v_color ` inside the fragment shader ?
336
- If you look at the figure that introduced the gl pipleline , we have 3 vertices
336
+ If you look at the figure that introduced the gl pipeline , we have 3 vertices
337
337
and 21 fragments. What is the color of each individual fragment ?
338
338
339
339
The answer is *the interpolation of all 3 vertices color *. This interpolation
@@ -350,7 +350,7 @@ State of the union
350
350
Last, but not least, we need to access the OpenGL library from within Python
351
351
and we have mostly two solutions at our disposal. Either we use pure bindings
352
352
and we have to program everything (see next chapter) or we use an engine that
353
- provide a lot oc convenient functions that ease the development. We'll first
353
+ provide a lot of convenient functions that ease the development. We'll first
354
354
use the PyOpenGL bindings before using the glumpy _ library that offers a tight
355
355
integration with numpy.
356
356
@@ -476,6 +476,6 @@ Libraries
476
476
.. _gl.xml :
477
477
https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/gl.xml
478
478
.. _registry.py :
479
- code/registry.py
479
+ code/chapter-02/ registry.py
480
480
481
481
.. ----------------------------------------------------------------------------
0 commit comments