Commit | Line | Data |
---|---|---|
22c0d71c AW |
1 | |
2 | @node GL | |
3 | @chapter GL | |
4 | ||
5 | ||
6 | @menu | |
7 | * About OpenGL:: Know the past to understand the present. | |
8 | * GL Contexts:: Finding a square of pixels. | |
9 | * Rendering:: How to paint. | |
10 | * GL API:: The OpenGL interface, organized by section. | |
11 | * GL Enumerations:: Enumerated values. | |
12 | * Low-Level GL:: Primitive interface to OpenGL. | |
13 | * GL Extensions:: Beyond core OpenGL. | |
14 | @end menu | |
15 | ||
16 | ||
17 | @node About OpenGL | |
18 | @section About OpenGL | |
19 | ||
20 | OpenGL is a standard API for drawing three-dimensional graphics. From | |
21 | its origin in Silicon Graphics's workstations the early 1990s, today | |
22 | it has become ubiquitous, with implementations on mobile phones, | |
23 | televisions, tablets, desktops, and even web browsers. | |
24 | ||
25 | OpenGL has been able to achieve such widespread adoption not just | |
26 | because it co-evolved with powerful graphics hardware, but also | |
27 | because it was conceived of as an interface specification and not a | |
28 | piece of source code. In fact, these days it is a family of APIs, | |
29 | available in several flavors and versions: | |
30 | ||
31 | @table @asis | |
32 | @item OpenGL 1.x | |
33 | This series of specifications started with the original releases in | |
34 | 1992, and ended with OpenGL 1.5 in 2003. This era corresponds to a | |
35 | time when graphics cards were less powerful and more special-purpose, | |
36 | with dedicated hardware to handle such details as fog and lighting. | |
37 | As such the OpenGL 1.x API reflects the capabilities of these special | |
38 | units. | |
39 | ||
40 | @item OpenGL 2.x | |
41 | By the early 2000s, graphics hardware had become much more | |
42 | general-purpose and needed a more general-purpose API. The so-called | |
43 | @dfn{fixed-function rendering pipeline} of the earlier years was | |
44 | replaced with a @dfn{programmable rendering pipeline}, in which | |
45 | effects that would have required special hardware were instead | |
46 | performed by custom programs running on the graphics card. OpenGL | |
47 | added support for allocating @dfn{buffer objects} on the graphics | |
48 | card, and for @dfn{shader programs}, which did the actual rendering. | |
49 | In time, this buffer-focused API came to be the preferred form of | |
50 | talking to the GL. | |
51 | ||
52 | @item OpenGL ES | |
53 | OpenGL ES was a ``cut-down'' version of OpenGL 2.x, designed to be | |
54 | small enough to appeal to embedded device vendors. OpenGL ES 1.x | |
55 | removed some of the legacy functionality from OpenGL, while adding | |
56 | interfaces to use fixed-point math, for devices without floating-point | |
57 | units. OpenGL ES 2.x went farther still, removing the fixed-function | |
58 | pipeline entirely. OpenGL ES 2.x is common on current smart phone | |
59 | platforms. | |
60 | ||
61 | @item OpenGL 3.x and above | |
62 | The OpenGL 3.x series followed the lead of OpenGL ES, first | |
63 | deprecating (in 3.0) and then removing (in 3.1) the fixed-function | |
64 | pipeline. OpenGL 3.0 was released in 2008, but the free Mesa | |
65 | impementation only began supporting it in 2012, so it is currently | |
66 | (@value{UPDATED}) less common. | |
67 | @end table | |
68 | ||
69 | Figl wraps the OpenGL 2.1 API. It's a ubiquitous subset of the OpenGL | |
70 | implementations that are actually deployed in the wild; its legacy API | |
71 | looks back to OpenGL 1.x, while the buffer-oriented API is compatible | |
72 | with OpenGL ES. | |
73 | ||
74 | The full OpenGL 2.1 specification is available at | |
75 | @uref{http://www.opengl.org/registry/doc/glspec21.20061201.pdf}. | |
76 | ||
77 | ||
78 | @node GL Contexts | |
79 | @section GL Contexts | |
80 | ||
81 | All this talk about drawing is very well and good, but how do you | |
82 | actually get a canvas? Interestingly enough, this is outside the | |
83 | purview of the OpenGL specification. There are specific ways to get | |
84 | an @dfn{OpenGL context} for each different windowing system that is | |
85 | out there. OpenGL is all crayons and no paper. | |
86 | ||
87 | For the X window system, there is a standard API for creating a GL | |
88 | context given a window (or a drawable), @dfn{GLX}. @xref{GLX}, for | |
89 | more information on its binding in Guile. | |
90 | ||
91 | Bseides creating contexts from native windows or drawables, each | |
92 | backend also supports functions to make a context @dfn{current}. The | |
93 | OpenGL API is stateful; you can think of each call as taking an | |
94 | implicit @dfn{current context} parameter, which holds the current | |
95 | state of the GL and is operated on by the function in question. | |
96 | Contexts are thread-specific, and one context should not be active on | |
97 | more than one thread at a time. | |
98 | ||
99 | All calls to OpenGL functions must be made while a context is active; | |
100 | otherwise the result is undefined. Hopefully while you are getting | |
101 | used to this rule, your driver is nice enough not to crash on you if | |
102 | you call a function outside a GL context, but it's not even required | |
103 | to do that. Backend-specific functions may or may not require a | |
104 | context to be current; for example, Windows requires a context to be | |
105 | current, wheras GLX does not. | |
106 | ||
107 | There have been a few attempts at abstracting away the need for | |
108 | calling API specific to a given windowing system, notably GLUT and | |
109 | EGL. GLUT is the older of the two, and though it is practically | |
110 | unchanged since the mid-1990s, it is still widely used on desktops. | |
111 | @xref{GLUT}, for more on GLUT. | |
112 | ||
113 | EGL is technically part of OpenGL ES, and was designed with the modern | |
114 | OpenGL API and mobile hardware in mind, though it also works on the | |
115 | desktop. Figl does not yet have an EGL binding. | |
116 | ||
117 | ||
118 | @node Rendering | |
119 | @section Rendering | |
120 | ||
121 | To draw with OpenGL, you obtain a drawing context (@pxref{GL | |
122 | Contexts}) and send @dfn{the GL} some geometry. (You can think of the | |
123 | GL as a layer over your graphics card.) You can give the GL points, | |
124 | lines, and triangles in three-dimensional space. You configure your | |
125 | GL to render a certain part of space, and it takes your geometry, | |
126 | rasterizes it, and writes it to the screen (when you tell it to). | |
127 | ||
128 | That's the basic idea. You can customize most parts of this | |
129 | @dfn{rendering pipeline}, by specifying attributes of your geometry | |
130 | with the OpenGL API, and by programmatically operating on the geometry | |
131 | and the pixels with programs called @dfn{shaders}. | |
132 | ||
133 | GL is an @dfn{immediate-mode} graphics API, which is to say that it | |
134 | doesn't keep around a scene graph of objects. Instead, at every frame | |
135 | you as the OpenGL user have to tell the GL what is in the world, and | |
136 | how to paint it. It's a fairly low-level interface, but a powerful | |
137 | one. See | |
138 | @uref{http://www.opengl.org/wiki/Rendering_Pipeline_Overview}, for | |
139 | more details. | |
140 | ||
141 | In the old days of OpenGL 1.0, it was common to call a function to | |
142 | paint each individual vertex. You'll still see this style in some old | |
143 | tutorials. This quickly gets expensive if you have a lot of vertexes, | |
144 | though. This style, known as @dfn{Legacy OpenGL}, was deprecated and | |
145 | even removed from some versions of OpenGL. See | |
146 | @uref{http://www.opengl.org/wiki/Legacy_OpenGL}, for more on the older | |
147 | APIs. | |
148 | ||
149 | Instead, the newer thing to do is to send the geometry to the GL in a | |
150 | big array buffer, and have the GL draw geometry from the buffer. The | |
151 | newer functions like @code{glGenBuffers} allocate buffers, returning | |
152 | an integer that @dfn{names} a buffer managed by the GL. You as a user | |
153 | can update the contents of the buffer, but when drawing you reference | |
154 | the buffer by name. This has the advantage of reducing the chatter | |
155 | and data transfer between you and the GL, though it can be less | |
156 | convenient to use. | |
157 | ||
158 | So which API should you use? Use what you feel like using, if you | |
159 | have a choice. Legacy OpenGL isn't going away any time soon on the | |
160 | desktop. Sometimes you don't have a choice, though; for example, when | |
161 | targeting a device that only supports OpenGL ES 2.x, legacy OpenGL is | |
162 | unavailable. | |
163 | ||
164 | But if you want some advice, we suggest that you use the newer APIs. | |
165 | Not only will your code be future-proof and more efficient on the GL | |
166 | level, reducing the number of API calls improves performance, and it | |
167 | can reduce the amount of heap allocation in your program. All | |
168 | floating-point numbers are currently allocated on the heap in Guile, | |
169 | and doing less floating-point math in tight loops can only be a good | |
170 | thing. | |
171 | ||
172 | ||
173 | @node GL API | |
174 | @section GL API | |
175 | ||
176 | The procedures exported from the @code{(figl gl)} module are | |
177 | documented below, organized by their corresponding section in the | |
178 | OpenGL 2.1 specification. | |
179 | ||
180 | @example | |
181 | (use-modules (figl gl)) | |
182 | @end example | |
183 | ||
184 | See @uref{http://www.opengl.org/registry/doc/glspec21.20061201.pdf}, | |
185 | for more information. | |
186 | ||
187 | @menu | |
188 | * OpenGL Operation:: | |
189 | * Rasterization:: | |
190 | * Per Fragment Operations:: | |
191 | * Special Functions:: | |
192 | * State and State Requests:: | |
193 | @end menu | |
194 | ||
195 | ||
196 | @node OpenGL Operation | |
197 | @subsection OpenGL Operation | |
198 | ||
199 | @subsubsection Begin/End Paradigm | |
200 | ||
201 | @defmac gl-begin begin-mode body ... | |
202 | Begin immediate-mode drawing with @var{begin-mode}, evaluate | |
203 | the sequence of @var{body} expressions, and then end drawing (as with | |
204 | @code{glBegin} and @code{glEnd}). | |
205 | ||
206 | The values produced by the last @var{body} expression are returned to | |
207 | the continuation of the @code{gl-begin}. | |
208 | @end defmac | |
209 | ||
210 | @defun gl-edge-flag boundary? | |
211 | Flag edges as either boundary or nonboundary. Note that the edge mode | |
212 | is only significant if the @code{polygon-mode} is @code{line} or | |
213 | @code{point}. | |
214 | @end defun | |
215 | ||
216 | @subsubsection Vertex Specification | |
217 | ||
218 | @defun gl-vertex x y [z=0.0] [w=1.0] | |
219 | Draw a vertex at the given coordinates. | |
220 | @end defun | |
221 | ||
222 | The following procedures modify the current per-vertex state. Drawing | |
223 | a vertex captures the current state and associates it with the | |
224 | vertex. | |
225 | ||
226 | @defun gl-texture-coordinate s [t=0.0] [r=0.0] [q=1.0] | |
227 | Set the current texture coordinate. | |
228 | @end defun | |
229 | ||
230 | @defun gl-multi-texture-coordinate texture s [t=0.0] [r=0.0] [q=1.0] | |
231 | Set the current texture coordinate for a specific texture unit. | |
232 | @end defun | |
233 | ||
234 | @defun gl-color red green blue [alpha=1.0] | |
235 | Set the current color. | |
236 | @end defun | |
237 | ||
238 | @defun gl-vertex-attribute index x [y=0.0] [z=0.0] [w=1.0] | |
239 | Set the current value of a generic vertex attribute. | |
240 | @end defun | |
241 | ||
242 | @defun gl-normal x y z | |
243 | Set the current normal vector. By default the normal should have unit | |
244 | length, though setting @code{(enable-cap rescale-normal)} or | |
245 | @code{(enable-cap normalize)} can change this. | |
246 | @end defun | |
247 | ||
248 | @defun gl-fog-coordinate coord | |
249 | Set the current fog coordinate. | |
250 | @end defun | |
251 | ||
252 | @defun gl-secondary-color red green blue | |
253 | Set the current secondary color. | |
254 | @end defun | |
255 | ||
256 | @defun gl-index c | |
257 | Set the current color index. | |
258 | @end defun | |
259 | ||
260 | @subsubsection Rectangles | |
261 | ||
262 | @defun gl-rectangle x1 y1 x2 y2 | |
263 | Draw a rectangle in immediate-mode with a given pair of corner | |
264 | points. | |
265 | @end defun | |
266 | ||
267 | @subsubsection Coordinate Transformation | |
268 | ||
269 | @defun gl-depth-range near-val far-val | |
270 | Specify the mapping of the near and far clipping planes, respectively, | |
271 | to window coordinates. | |
272 | @end defun | |
273 | ||
274 | @defun gl-viewport x y width height | |
275 | Set the viewport: the pixel position of the lower-left corner of the | |
276 | viewport rectangle, and the width and height of the viewport. | |
277 | @end defun | |
278 | ||
279 | @defun gl-load-matrix m [#:transpose=#f] | |
280 | Load a matrix. @var{m} should be a packed vector in column-major | |
281 | order. | |
282 | ||
283 | Note that Guile's two-dimensional arrays are stored in row-major | |
284 | order, so you might need to transpose the matrix as it is loaded (via | |
285 | the @code{#:transpose} keyword argument). | |
286 | @end defun | |
287 | ||
288 | @defun gl-multiply-matrix m [#:transpose=#f] | |
289 | Multiply the current matrix by @var{m}. As with | |
290 | @code{gl-load-matrix}, you might need to transpose the matrix first. | |
291 | @end defun | |
292 | ||
293 | @defun set-gl-matrix-mode matrix-mode | |
294 | Set the current matrix mode. See the @code{matrix-mode} enumerator. | |
295 | @end defun | |
296 | ||
297 | @defmac with-gl-push-matrix body ... | |
298 | Save the current matrix, evaluate the sequence of @var{body} | |
299 | expressions, and restore the saved matrix. | |
300 | @end defmac | |
301 | ||
302 | @defun gl-load-identity | |
303 | Load the identity matrix. | |
304 | @end defun | |
305 | ||
306 | @defun gl-rotate angle x y z | |
307 | Rotate the current matrix about the vector | |
308 | @code{(@var{x},@var{y},@var{z})}. @var{angle} should be specified in | |
309 | degrees. | |
310 | @end defun | |
311 | ||
312 | @defun gl-translate x y z | |
313 | Translate the current matrix. | |
314 | @end defun | |
315 | ||
316 | @defun gl-scale x y z | |
317 | Scale the current matrix. | |
318 | @end defun | |
319 | ||
320 | @defun gl-frustum left right bottom top near-val far-val | |
321 | Multiply the current matrix by a perspective matrix. @var{left}, | |
322 | @var{right}, @var{bottom}, and @var{top} are the coordinates of the | |
323 | corresponding clipping planes. @var{near-val} and @var{far-val} | |
324 | specify the distances to the near and far clipping planes. | |
325 | @end defun | |
326 | ||
327 | @defun gl-ortho left right bottom top near-val far-val | |
328 | Multiply the current matrix by a perspective matrix. @var{left}, | |
329 | @var{right}, @var{bottom}, and @var{top} are the coordinates of the | |
330 | corresponding clipping planes. @var{near-val} and @var{far-val} | |
331 | specify the distances to the near and far clipping planes. | |
332 | @end defun | |
333 | ||
334 | @defun set-gl-active-texture texture | |
335 | Set the active texture unit. | |
336 | @end defun | |
337 | ||
338 | @defun gl-enable enable-cap | |
339 | @defunx gl-disable enable-cap | |
340 | Enable or disable server-side GL capabilities. | |
341 | @end defun | |
342 | ||
343 | @subsubsection Colors and Coloring | |
344 | ||
345 | @defun set-gl-shade-model mode | |
346 | Select flat or smooth shading. | |
347 | @end defun | |
348 | ||
349 | ||
350 | @node Rasterization | |
351 | @subsection Rasterization | |
352 | ||
353 | ||
354 | @node Per Fragment Operations | |
355 | @subsection Per-Fragment Operations | |
356 | ||
357 | @defun set-gl-stencil-function stencil-function k [#:mask] [#:face] | |
358 | Set the front and/or back function and the reference value @var{k} for | |
359 | stencil testing. Without the @var{face} keyword argument, both | |
360 | functions are set. The default @var{mask} is all-inclusive. | |
361 | @end defun | |
362 | ||
363 | @defun set-gl-stencil-operation stencil-fail depth-fail depth-pass [#:face] | |
364 | Set the front and/or back stencil test actions. Without the | |
365 | @var{face} keyword argument, both stencil test actions are set. See | |
366 | the @code{stencil-op} enumeration for possible values for | |
367 | @var{stencil-fail}, @var{depth-fail}, and @var{depth-pass}. | |
368 | @end defun | |
369 | ||
370 | @defun set-gl-blend-equation mode-rgb [mode-alpha=mode-rgb] | |
371 | Set the blend equation. With one argument, set the same blend | |
372 | equation for all components. Pass two arguments to specify a separate | |
373 | equation for the alpha component. | |
374 | @end defun | |
375 | ||
376 | @defun set-gl-blend-function src-rgb dest-rgb [src-alpha=src-rgb] [dest-alpha=dest-rgb] | |
377 | Set the blend function. With two arguments, set the same blend | |
378 | function for all components. Pass an additional two arguments to | |
379 | specify separate functions for the alpha components. | |
380 | @end defun | |
381 | ||
382 | @defun set-gl-scissor x y width height | |
383 | Define the scissor box. The box is defined in window coordinates, | |
384 | with (@var{x},@var{y}) being the lower-left corner of the box. | |
385 | @end defun | |
386 | ||
387 | @defun set-gl-sample-coverage value invert | |
388 | Specify multisample coverage parameters. | |
389 | @end defun | |
390 | ||
391 | @defun set-gl-alpha-function func ref | |
392 | Specify the alpha test function. See the @code{alpha-function} | |
393 | enumerator. | |
394 | @end defun | |
395 | ||
396 | @defun set-gl-depth-function func | |
397 | Specify the depth test function. See the @code{depth-function} | |
398 | enumerator. | |
399 | p@end defun | |
400 | ||
401 | @defun set-gl-blend-color r g b a | |
402 | Specify the blend color. | |
403 | @end defun | |
404 | ||
405 | @defun set-gl-logic-operation opcode | |
406 | Specify a logical pixel operation for color index rendering. | |
407 | @end defun | |
408 | ||
409 | @subsubsection Whole Framebuffer Operations | |
410 | ||
411 | @defun set-gl-draw-buffers buffers | |
412 | Specify a list of color buffers to be drawn into. @var{buffers} | |
413 | should be a list of @code{draw-buffer-mode} enumerated values. | |
414 | @end defun | |
415 | ||
416 | @defun set-gl-stencil-mask mask [#:face] | |
417 | Control the writing of individual bits into the front and/or back | |
418 | stencil planes. With one argument, the stencil mask for both states | |
419 | are set. | |
420 | @end defun | |
421 | ||
422 | @defun set-gl-draw-buffer mode | |
423 | Specify the buffer or buffers to draw into. | |
424 | @end defun | |
425 | ||
426 | @defun set-gl-index-mask mask | |
427 | Control the writing of individual bits into the color index buffers. | |
428 | @end defun | |
429 | ||
430 | @defun set-gl-color-mask red? green? blue? alpha? | |
431 | Enable and disable writing of frame buffer color components. | |
432 | @end defun | |
433 | ||
434 | @defun set-gl-depth-mask enable? | |
435 | Enable and disable writing into the depth buffer. | |
436 | @end defun | |
437 | ||
438 | @defun gl-clear mask | |
439 | Clear a set of buffers to pre-set values. Use the | |
440 | @code{clear-buffer-mask} enumerator to specify which buffers to clear. | |
441 | @end defun | |
442 | ||
443 | @defun set-gl-clear-color r g b a | |
444 | Set the clear color for the color buffers. | |
445 | @end defun | |
446 | ||
447 | @defun set-gl-clear-index c | |
448 | Set the clear index for the color index buffers. | |
449 | @end defun | |
450 | ||
451 | @defun set-gl-clear-depth depth | |
452 | Set the clear value for the depth buffer. | |
453 | @end defun | |
454 | ||
455 | @defun set-gl-clear-stencil-value s | |
456 | Set the clear value for the stencil buffer. | |
457 | @end defun | |
458 | ||
459 | @defun set-gl-clear-accumulation-color r g b a | |
460 | Set the clear color for the accumulation buffer. | |
461 | @end defun | |
462 | ||
463 | @defun set-gl-accumulation-buffer-operation op value | |
464 | Operate on the accumulation buffer. @var{op} may be one of the | |
465 | @code{accum-op} enumerated values. The interpretation of @var{value} | |
466 | depends on @var{op}. | |
467 | @end defun | |
468 | ||
469 | @subsubsection Drawing, Reading and Copying Pixels | |
470 | ||
471 | @defun set-gl-read-buffer mode | |
472 | Select a color buffer source for pixels. Use @code{read-buffer-mode} | |
473 | to select a mode. | |
474 | @end defun | |
475 | ||
476 | @defun gl-copy-pixels x y width height type | |
477 | Copy pixels from a screen-aligned rectangle in the frame buffer to a | |
478 | region relative to the current raster position. @var{type} selects | |
479 | which buffer to copy from. | |
480 | @end defun | |
481 | ||
482 | ||
483 | @node Special Functions | |
484 | @subsection Special Functions | |
485 | ||
486 | ||
487 | @node State and State Requests | |
488 | @subsection State and State Requests | |
489 | ||
490 | @subsubsection Querying GL State | |
491 | ||
492 | @defmac with-gl-push-attrib bits body ... | |
493 | Save part of the current state, evaluation the sequence of @var{body} | |
494 | expressions, then restore the state. Use @code{attrib-mask} to | |
495 | specify which parts of the state to save. | |
496 | @end defmac | |
497 | ||
498 | ||
499 | @node GL Enumerations | |
500 | @section GL Enumerations | |
501 | @include low-level-gl-enums.texi | |
502 | ||
503 | ||
504 | @node Low-Level GL | |
505 | @section Low-Level GL | |
506 | @include low-level-gl.texi | |
507 | ||
508 | ||
509 | @node GL Extensions | |
510 | @section GL Extensions | |
511 | ||
512 | @quotation | |
513 | The future is already here -- it's just not very evenly distributed. | |
514 | ||
515 | -- William Gibson | |
516 | @end quotation | |
517 | ||
518 | Before interfaces end up in core OpenGL, the are usually present as | |
519 | vendor-specific or candidate extensions. Indeed, the making of an | |
520 | OpenGL standard these days seems to be a matter of simply collecting a | |
521 | set of mature extensions and making them coherent. | |
522 | ||
523 | Figl doesn't currently provide specific interfaces for extensions. | |
524 | Perhaps it should, but that's a lot of work that we haven't had time | |
525 | to do. Contributions are welcome. | |
526 | ||
527 | In the meantime, if you know enough about GL to know that you need an | |
528 | extension, you can define one yourself -- after all, Figl is all a | |
529 | bunch of Scheme code anyway. | |
530 | ||
531 | For example, let's say you decide that you need to render to a | |
532 | framebuffer object. You go to @uref{http://www.opengl.org/registry/} | |
533 | and pick out an extension, say | |
534 | @uref{http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt}. | |
535 | ||
536 | This extension defines a procedure, @code{GLboolean | |
537 | glIsRenderBuffer(GLuint)}. So you define it: | |
538 | ||
539 | @example | |
540 | (use-modules (figl gl runtime) (figl gl types)) | |
541 | (define-gl-procedure (glIsRenderBuffer (buf GLuint) -> GLboolean) | |
542 | "Render buffer predicate. Other docs here.") | |
543 | @end example | |
544 | ||
545 | And that's that. It's a low-level binding, but what did you expect? | |
546 | ||
547 | Note that you'll still need to check for the availability of this | |
548 | extension at runtime with @code{(glGetString GL_EXTENSIONS)}. | |
549 |