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