-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdiscovering.html
524 lines (515 loc) · 25.3 KB
/
discovering.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>OpenGL Insights</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<style type="text/css">
hr {
width: 630px;
margin-left: 0;
}
td.sectionName a,
td.sectionName a:active,
td.sectionName a:visited {
text-decoration: none;
color: #5482AB;
}
td.sectionName a:hover {
text-decoration: underline;
}
td.sectionName span {
font-family: serif;
}
</style>
</head>
<body>
<div class="page">
<a href="index.html"><img class="title" src="http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/images/strip.png" width="639" height="140" alt="OpenGL Insights" /></a>
<table summary="" border="0" width="630">
<tr align="center" class="sitemap">
<td><a href="cover.html">Cover</a></td>
<td><a href="toc.html">Table of Contents</a></td>
<td><a href="pipeline.html">Pipeline Map</a></td>
<td><a href="tips.html">Tips</a></td>
<td><a href="contributors.html">Contributors</a></td>
<td><a href="reviews.html">Reviews</a></td>
<!--
<td><a href="figures.html">Figures</a></td>
<td><a href="bibliography.html">Bibliography</a></td>
-->
<td><a href="bibtex.html">BibTeX</a></td>
<td><a href="errata.html">Errata</a></td>
<td><a href="https://github.com/OpenGLInsights/OpenGLInsightsCode">Code</a></td>
<td><a href="http://blog.openglinsights.com/">Blog</a></td>
<td><a href="http://www.amazon.com/gp/product/1439893764/ref=as_li_tf_il?ie=UTF8&camp=1789&creative=9325&creativeASIN=1439893764&linkCode=as2&tag=opeins-20">Buy</a></td>
</tr>
</table>
<h1>I Discovering</h1>
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td colspan="2">
<p>
In this section, we discover many facets of OpenGL: teaching modern OpenGL in academia; using OpenGL on the web with WebGL; tessellation shaders in OpenGL 4.0; procedural textures; the safety critical variant, OpenGL SC; and multi-GPU OpenGL and CUDA interop.
</p>
<p>
OpenGL enjoys widespread use in computer graphics courses around the world. Now-depreciated OpenGL features such as fixed-function lighting, immediate mode, and built-in transforms made the barrier to entry low. However, modern OpenGL has removed many of these features, resulting in a lean API that exposes the functionality of the underlying hardware. Academia has taken these changes in stride, updating their graphics courses to modern OpenGL. In Chapter 1, "Teaching Computer Graphics Starting With Shader-Based OpenGL," Edward Angel discusses how an introductory computer graphics course can be taught using modern OpenGL. In Chapter 2, "Transitioning Students to Post-Deprecation OpenGL," Mike Bailey presents C++ abstractions and GLSL naming conventions to bridge the gap between depreciated and modern OpenGL for use in course assignments.
</p>
<p>
When we announced our call for authors for OpenGL Insights in May 2011, we included WebGL as a desired topic. Since then, WebGL has gained such traction that an entire book could easily be justified. In Chapter 3, "WebGL for OpenGL Developers," Patrick Cozzi and Scott Hunter present WebGL for those who already know OpenGL. In the following chapter, "Porting Mobile Apps to WebGL," Ashraf Samy Hegab shows the benefits, differences, and trade-offs of using WebGL for mobile applications. Several chapters in later sections continue our WebGL exploration.
</p>
<p>
Christophe Riccio takes a rigorous look at communication between the OpenGL API and GLSL and different shader stages in Chapter 5, "The GLSL Shader Interfaces." He carefully examines using varying blocks; attribute, varying, and fragment output variable locations; linked and separated programs; using semantics in our designs; and more.
</p>
<p>
Today, one of the differences between movie-quality rendering and real-time rendering is geometric complexity; movies generally have much higher geometric detail. To improve geometric detail in real-time rendering, tessellation can be done in hardware. Although this has been available on ATI cards since the ATI Radeon 8500 in 2001, tessellation shaders were recently standardized and made part of OpenGL 4.0. In Chapter 6, "An Introduction to Tessellation Shaders," Philip Rideout and Dirk Van Gelder introduce the new fixed and programmable tessellation stages.
</p>
<p>
As the gap between compute power and memory bandwidth continues to widen, procedural techniques become increasingly important. Small size is speed. Procedural textures not only have trivial memory requirements, but can also have excellent visual quality, allowing for analytic derivatives and anisotropic antialiasing. Stefan Gustavson introduces procedural textures, including antialiasing and using Perlin and Worley noise in Chapter 7, "Procedural Textures in GLSL." Best of all, he provides GLSL noise functions for OpenGL, OpenGL ES, and WebGL.
</p>
<p>
OpenGL SC, for safety critical, may be one of the lesser-known OpenGL variants. In Chapter 8, "OpenGL SC Emulation Based on OpenGL and OpenGL ES," Hwanyong Lee and Nakhoon Baek explain the motivation for OpenGL SC and describe the benefits of implementing it based on other OpenGL variants, instead of creating custom drivers or a software implementation.
</p>
<p>
In the past 15 years, consumer GPUs have transformed from dedicated fixed-function graphics processors to general-purpose massively-parallel processors. Technologies like CUDA and OpenCL have emerged for developing general data-parallel algorithms on the GPU. There is, of course, a need for these general algorithms, like particle systems and physical simulation, to interop efficiently with OpenGL for rendering. In the final chapter of this section, "Mixing Graphics and Compute with Multiple GPUs," Alina Alt reviews interoperability between CUDA and OpenGL and presents interoperability between multiple GPUs where one GPU is used for CUDA and another for OpenGL.
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="TeachingComputerGraphicsStartingwithShaderBasedOpenGL">
1. <em>Teaching Computer Graphics Starting with Shader-Based OpenGL</em></a>
<br />
<a href="contributors.html#EdwardAngel">Edward Angel</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
For at least ten years, OpenGL has been used in the first computer graphics course
taught to students in computer science and engineering, other branches of engineering,
mathematics, and the sciences. Whether the course stresses basic graphics
principles or takes a programming approach, OpenGL provides students with an API
to support their learning. One of the many features of the OpenGL API that makes
it popular for teaching is its stability and backward compatibility. Hence, instructors
needed to make only minor changes in their courses as OpenGL evolved. At
least that used to be true: over the last few years, OpenGL has changed rapidly and
dramatically.
</p>
<p>
Starting with version 3.1, the fixed function pipeline was eliminated, an action
that deprecated immediate mode and many of the familiar OpenGL functions and
state variables. Every application must provide at least a vertex shader and a fragment
shader. For those of us who use OpenGL to teach our graphics courses, these
changes and the introduction of three additional shader stages in subsequent releases
of OpenGL have led to a reexamination of how we can best teach computer graphics.
As the authors of a popular textbook [Angel 09] used for the first course, we
realized that this reexamination was both urgent and deep, requiring input from instructors
at a variety of institutions. In the end, we wrote a new edition [Angel and
Shreiner 12] that was entirely shader-based. Some of the key issues were addressed
briefly in [Angel and Shreiner 11] but this chapter will not only discuss the reasons
for the change but will also include practical observations and issues based on the
actual teaching of a fully shader-based course.
</p>
<p>
I start with a historical overview, stressing how the software used in the first
computer graphics course has changed over the years while the concepts we teach
have remained largely unchanged. I review the key elements of a first course in
computer graphics. Then I present a typical first <em>Hello World</em> program using the
fixed-function pipeline. Next, the reader will see how we have to change that first
program when moving to a shader-based course. Finally, I examine how each of the
major topics in our standard course is affected by use of a shader-based OpenGL.
</p>
<p>
...
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="TransitioningStudentstoPostDeprecationOpenGL">
2. <em>Transitioning Students to Post-Deprecation OpenGL</em></a>
<br />
<a href="contributors.html#MikeBailey">Mike Bailey</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
From an educator's perspective, teaching OpenGL in the past has been a snap. The
separation of geometry from topology in the glBegin-glEnd, the simplicity of
glVertex3f, and the classic organization of the postmultiplied transformation matrices
has been fast and easy to explain. This has considerably excited the students
because going from zero knowledge to "cool 3D program you can smugly show your
friends" was the task of a single lesson. This made motivation easy.
</p>
<p>
The Great OpenGL Deprecation has changed that. Creating and using vertex
buffer objects is a lot more time consuming to explain than glBegin-glEnd [Angel
11]. It's also much more error-prone. Creating and maintaining matrices and matrix
stacks now requires deft handling of matrix components and multiplication order
[GLM 11]. In short, while post-deprecation OpenGL might be more streamlined
and efficient, it has wreaked havoc on those who need to teach it and even more on
those who need to learn it.
</p>
<p>
So the "old way" is not current, but the "new way" takes a long time to learn before
one can see a single pixel. How can we keep students enthusiastic and motivated
but still move them along the road to learning things the new way? This chapter
discusses intermediate solutions to this problem by presenting C++ classes that ease
the transition to post-deprecation OpenGL. These C++ classes are
<ol>
<li>Create vertex buffers with methods that look suspiciously like glBegin-glEnd.</li>
<li>Load, compile, link, and use shaders.</li>
</ol>
This chapter also suggests a naming convention that can be instrumental in keeping
shader variables untangled from each other.
</p>
<p>
...
</p>
</td>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="WebGLforOpenGLDevelopers">
3. <em>WebGL for OpenGL Developers</em></a>
<br />
<a href="contributors.html#PatrickCozzi">Patrick Cozzi</a> and <a href="contributors.html#ScottHunter">Scott Hunter</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL<br />WebGL</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
Don't get us wrong — we are C++ developers at heart. We've battled triple-pointers,
partial template specialization, and vtable layouts under multiple inheritance. Yet,
through a strange series of events, we are now full-time JavaScript developers. This
is our story.
</p>
<p>
At the SIGGRAPH 2009 OpenGL BOF, we first heard about WebGL, an upcoming
web standard for a graphics API based on OpenGL ES 2.0 available to
JavaScript through the HTML5 canvas element, basically OpenGL for JavaScript.
We had mixed feelings. On the one hand, WebGL brought the promise of developing
zero-footprint, cross-platform, cross-device, hardware-accelerated 3D applications.
On the other, it requires us to develop in JavaScript. Could we do large-scale
software development in JavaScript? Could we write high-performance graphics code
in JavaScript?
</p>
<p>
After nearly a year of development resulting in over 50,000 lines of JavaScript
and WebGL code, we have answered our own questions: properly written JavaScript
scales well, and WebGL is a very capable API with tremendous momentum. This
chapter shares our experience moving from developing with C++ and OpenGL for
the desktop to developing with JavaScript and WebGL for the web. We focus on
the unique aspects of moving OpenGL to the web, not on porting OpenGL code to
OpenGL ES.
</p>
<p>
...
</p>
</td>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="PortingMobileAppstoWebGL">
4. <em>Porting Mobile Apps to WebGL</em></a>
<br />
<a href="contributors.html#AshrafSamyHegab">Ashraf Samy Hegab</a>
</td>
<td width="15%" align="right" class="tipsAPI">WebGL<br />OpenGL ES</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
WebGL provides direct graphics hardware acceleration hooks into web browsers, allowing
for a richer application experience. This experience is now becoming comparable
with native applications. However, the development environment for creating
these new types of rich web apps using WebGL is different.
</p>
<p>
This chapter walks us through the aspects of porting a typical OpenGL mobile
app from Android and iOS to the web, covering steps from setting up your GL
context to drawing a textured button or handling the camera and controls to finally
debugging and maintaining your application.
</p>
<p>
This chapter includes accompanying source code that demonstrates the concepts
introduced in iOS, Android, Qt, and WebGL to help developers get up to speed on
web development using WebGL.
</p>
<p>
...
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="TheGLSLShaderInterfaces">
5. <em>The GLSL Shader Interfaces</em></a>
<br />
<a href="contributors.html#ChristopheRiccio">Christophe Riccio</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
The shader system is a central module of a graphics engine, providing flexibility,
performance, and reliability to an application. In this chapter we explore various
aspects of the GLSL shader interfaces to improve its quality.
</p>
<p>
These interfaces are the elements of the language that expose buffers and textures
within a shader stage. They allow communication between shader stages and between
the application and the shader stages. This includes input interfaces, output interfaces,
interface blocks, atomic counters, samplers, and image units [Kessenich 12].
</p>
<p>
On the OpenGL Insights website, www.openglinsights.com, code samples are provided
to illustrate each section. A direct output from this chapter is a series of functions
that can be directly used in any OpenGL program for detecting <em>silent errors</em>,
errors that OpenGL doesn't catch by design, but eventually result in an unexpected
rendering.
</p>
<p>
I target three main goals:
<ul>
<li><span class="glColor">Performance</span>. Description of some effects of the shader interface on memory
consumption, bandwidth, and reduction of the CPU overhead.</li>
<li><span class="glColor">Flexibility</span>. Exploration of cases to ensure the reuse of a maximum number
of objects.</li>
<li><span class="glColor">Reliability</span>. Options in debug mode for detecting silent errors.</li>
</ul>
</p>
<p>
...
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="AnIntroductiontoTessellationShaders">
6. <em>An Introduction to Tessellation Shaders</em></a>
<br />
<a href="contributors.html#PhilipRideout">Philip Rideout</a> and <a href="contributors.html#DirkVanGelder">Dirk Van Gelder</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
Tessellation shaders open new doors for real-time graphics programming. GPU-based
tessellation was possible in the past only through trickery, relying on multiple
passes and misappropriation of existing shader units.
</p>
<p>
OpenGL 4.0 finally provides first-class support for GPU tessellation, but the new
shading stages can seem nonintuitive at first. This chapter explains the distinct roles
of those stages in the new pipeline and gives an overview of some common rendering
techniques that leverage them.
</p>
<p>
GPUs tend to be better at "streamable" amplification; rather than storing an
entire post-subdivided mesh in memory, tessellation shaders allow vertex data to be
amplified on the fly, discarding the data when they reach the rasterizer. The system
never bothers to store a highly-refined vertex buffer, which would have an impractical
memory footprint for a GPU.
</p>
<p>
Pretessellation graphics hardware was already quite good at rendering huge
meshes, and CPU-side refinement was often perfectly acceptable for static meshes.
So why move tessellation to the GPU?
</p>
<p>
The gains are obvious for animation. On a per-frame basis, only the control
points get sent to the GPU, greatly alleviating bandwidth requirements for highdensity
surfaces.
</p>
<p>
Animation isn't the only killer application of subdivision surfaces. <em>Displacement
mapping</em> allows for staggering geometric level-of-detail. Previous GPU techniques
required multiple passes over the geometry shader, proving awkward and slow. Tessellation
shaders allow displacement mapping to occur in a single pass [Casta˜no 08].
</p>
<p>
Tessellation shaders can also compute geometric level-of-detail on the fly, which
we'll explore later in the chapter. Previous techniques required the CPU to resubmit
new vertex buffers when changing the level-of-detail.
</p>
<p>
...
</p>
<p>
<a href="https://github.com/prideout/opengl-insights">code</a>
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="ProceduralTexturesinGLSL">
7. <em>Procedural Textures in GLSL</em></a>
<br />
<a href="contributors.html#StefanGustavson">Stefan Gustavson</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL<br />WebGL<br />OpenGL ES</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
<em>Procedural textures</em> are textures that are computed on the fly during rendering as opposed
to precomputed image-based textures. At first glance, computing a texture
from scratch for each frame may seem like a stupid idea, but procedural textures
have been a staple of software rendering for decades, for good reason. With the ever increasing
levels of performance for programmable shading in GPU architectures,
hardware-accelerated procedural texturing in GLSL is now becoming quite useful
and deserves more consideration. An example of what can be done is shown in Figure
7.1.
</p>
<p>
<img src="http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/chapterfigures/71.jpg" width="639" alt="Figure 7.1" />
</p>
<p>
Writing a good procedural shader is more complicated than using image editing
software to paint a texture or edit a photographic image to suit our needs, but with
procedural shaders, the pattern and the colors can be varied with a simple change of
parameters. This allows extensive reuse of data for many different purposes, as well
as fine-tuning or even complete overhauls of surface appearance very late in a production
process. A procedural pattern allows for analytic derivatives, which makes it
less complicated to generate the corresponding surface normals, as compared to traditional
bump mapping or normal mapping, and enables analytic anisotropic antialiasing.
Procedural patterns require very little storage, and they can be rendered at
an arbitrary resolution without jagged edges or blurring, which is particularly useful
when rendering close-up details in real-time applications where the viewpoint is often
unrestricted. A procedural texture can be designed to avoid problems with seams
and periodic artifacts when applied to a large area, and random-looking detail patterns
can be generated automatically instead of having artists paint them. Procedural
shading also removes the memory restrictions for 3D textures and animated patterns.
3D procedural textures, <em>solid textures</em>, can be applied to objects of any shape without
requiring 2D texture coordinates.
</p>
<p>
While all these advantages have made procedural shading popular for offline rendering,
real-time applications have been slow to adopt the practice. One obvious
reason is that the GPU is a limited resource, and quality often has to be sacrificed for
performance. However, recent developments have given us lots of computing power
even on typical consumer-level GPUs, and given their massively parallel architectures,
memory access is becoming a major bottleneck. A modern GPU has an abundance
of texture units and uses caching strategies to reduce the number of accesses to global
memory, but many real-time applications now have an imbalance between texture
bandwidth and processing bandwidth. ALU instructions can essentially be "free"
and cause no slowdown at all when executed in parallel to memory reads, and imagebased
textures can be augmented with procedural elements. Somewhat surprisingly,
procedural texturing is also useful at the opposite end of the performance scale. GPU
hardware for mobile devices can incur a considerable penalty for texture download
and texture access, and this can sometimes be alleviated by procedural texturing. A
procedural shader does not necessarily have to be complex, as demonstrated by some
of the examples in this chapter.
</p>
<p>
Procedural methods are not limited to fragment shading. With the everincreasing
complexity of real-time geometry and the recent introduction of GPUhosted
tessellation as discussed in Chapter 6, tasks like surface displacements and
secondary animations are best performed on the GPU. The tight interaction between
procedural displacement shaders and procedural surface shaders has proven
very fruitful for creating complex and impressive visuals in offline shading environments,
and there is no reason to assume that real-time shading would be fundamentally
different in that respect.
</p>
<p>
This chapter is meant as an introduction to procedural shader programming in
GLSL. First, I present some fundamentals of procedural patterns, including antialiasing.
A significant portion of the chapter presents recently developed, efficient methods
for generating Perlin noise and other noise-like patterns entirely on the GPU,
along with some benchmarks to demonstrate their performance. The code repository
on the OpenGL Insights website, www.openglinsights.com, contains a cross-platform
demo program and a library of useful GLSL functions for procedural texturing.
</p>
<p>
...
</p>
<p>
<a href="https://github.com/OpenGLInsights/OpenGLInsightsCode/tree/master/Chapter%2007%20Procedural%20Textures%20in%20GLSL">code</a> •
<a href="http://webstaff.itn.liu.se/~stegu/OpenGLinsights/shadertutorial.html">demo</a>
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="OpenGLSCEmulationBasedonOpenGLandOpenGLES">
8. <em>OpenGL SC Emulation Based on OpenGL and OpenGL ES</em></a>
<br />
<a href="contributors.html#HwanyongLee">Hwanyong Lee</a> and <a href="contributors.html#NakhoonBaek">Nakhoon Baek</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL<br />OpenGL ES<br />OpenGL SC</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
...
</p>
</td>
</tr>
</table>
<hr />
<table summary="" border="0" width="639">
<tr class="spaceUnder">
<td>
<a name ="MixingGraphicsandComputewithMultipleGPUs">
9. <em>Mixing Graphics and Compute with Multiple GPUs</em></a>
<br />
<a href="contributors.html#AlinaAlt">Alina Alt</a>
</td>
<td width="15%" align="right" class="tipsAPI">OpenGL</td>
</tr>
<tr class="spaceUnder">
<td colspan="2">
<p>
...
</p>
<p>
<a href="https://github.com/OpenGLInsights/OpenGLInsightsCode/tree/master/Chapter%2009%20Mixing%20Graphics%20and%20Compute%20with%20Multiple%20GPUs">code</a>
</p>
</td>
</tr>
</table>
<hr />
<h1>Sections</h1>
<ul>
<li>I Discovering</li>
<li><a href="renderingtechniques.html">II Rendering Techniques</a></li>
<li><a href="bendingthepipeline.html">III Bending the Pipeline</a></li>
<li><a href="performance.html">IV Performance</a></li>
<li><a href="transfers.html">V Transfers</a></li>
<li><a href="debuggingandprofiling.html">VI Debugging and Profiling</a></li>
<li><a href="softwaredesign.html">VII Software Design</a></li>
</ul>
</div>
</body>
</html>