Repository navigation
Expand file tree
/
Copy pathDeferredShadingMSAASample.htm
More file actions
390 lines (269 loc) · 13.2 KB
/
Copy pathDeferredShadingMSAASample.htm
File metadata and controls
390 lines (269 loc) · 13.2 KB
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
<!doctype html>
<html class="csstransforms csstransforms3d csstransitions" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="utf-8" />
<title>Deferred Shading MSAA Sample</title>
<meta name="description" content="Deferred Shading MSAA Sample" />
<!-- CSS files -->
<link href="./css/application.css" rel="stylesheet" type="text/css" />
<link href="./css/styleguide.css" rel="stylesheet" type="text/css" />
<!--<link rel="stylesheet" type="text/css" href="sdk_samples.css" />-->
<!-- scripts to include -->
<script src="./js/jquery.js"></script>
<script src="./js/owl.carousel.js"></script>
<script src="./js/jquery.fitvids.js"></script>
<script src="./js/jquery.colorbox.js"></script>
<script src="./js/jquery.isotope.js"></script>
<script src="./js/jquery.sidr.js"></script>
<script src="./js/bootstrap.js"></script>
<script src="./js/application.js"></script>
<script src="./js/prettify.js"></script>
</head>
<body style="">
<!--Navbar-->
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="row">
<!--<button class="navbar-toggle" type="button"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button>-->
<div class="logo-header col-sm-8 col-md-9">
<a class="navbar-brand logo" href="http://developer.nvidia.com/gameworks"><img alt="NVidia GameWorks" height="21" src="./images/developerzone_gameworks_logo.png" width="245"></a>
</div>
<div class="logo-header navbar-right col-sm-4 col-md-3">
<a class="navbar-brand logo" href="https://github.com/NVIDIAGameWorks/GraphicsSamples"><img src="./images/gameworks_at_github.png" alt="GameWorks at GitHub" height="21" width="226"/></a>
</div>
</div>
</div>
</nav>
<!-- main body block -->
<div id="content" class="container">
<div class="row" id="subprojcontent">
<div class="col-xs-12">
<ol class="breadcrumb"><br/>
<li><a href="./index.html">Home</a></li>
<li><a href="./gfx_samples_gl.htm">GameWorks OpenGL Graphics Samples</a></li>
<li class="active">Deferred Shading MSAA Sample</li>
</ol>
<div class="page-header">
<h1>Deferred Shading MSAA Sample</h1>
</div>
<div class="row">
<div class="subprojmetadata">
<b class="small">Category:</b>
<span class="btn btn-primary btn-xs subprojmetacat"> Visuals </span>
</div>
<div class="subprojmetadata">
<b class="small">Min PC GPU:</b>
<span class="subprojmetagpu">GeForce Kepler-class</span>
</div>
<div class="subprojmetadata">
<b class="small">Min Tegra Device:</b>
<span class="subprojmetagpu">Tegra K1</span>
</div>
<div class="subprojmetadata">
<b class="small">@ GitHub:</b>
<span class="subprojmetagpu"><a target="_blank" href="https://github.com/NVIDIAGameWorks/GraphicsSamples/tree/master/samples/gl4-kepler/DeferredShadingMSAA">Deferred Shading MSAA Sample Source Code</a></span>
</div>
</div>
<div class="row">
<h3>Description</h3>
<p>This sample demonstrates how to render anti-aliased geometry when using a deferred shading pipeline.</p>
<a data-colorbox="true" href="images/deferredshadingmsaa-screenshot.png"><img class="subprojscreen" src="images/deferredshadingmsaa-screenshot.png" width="400" alt="Screenshot" /></a>
</div>
<div class="row">
<h3>APIs Used</h3>
<ul>
<li class="odd">OpenGL 4.0</li>
</ul>
</div>
<div class="row">
<h3>Shared User Interface</h3>
<p>The Graphics samples all share a common app framework and certain user interface elements, centered around the "Tweakbar" panel on the left side of the screen which lets you interactively control certain variables in each sample.</p>
<p>To show and hide the Tweakbar, simply click or touch the triangular button positioned in the top-left of the view.</p>
<div class="subprojmetadata">
<p>Other controls are listed below.</p>
<table class="table table-striped small subprojcontrolstable" id="sharedcontrolstable">
<tr>
<th class="subprojcontrolsdevice">Device</th>
<th class="subprojcontrolsinput">Input</th>
<th class="subprojcontrolsresult">Result</th>
</tr>
<tr class="odd">
<td class="subprojcontrolsdevicekind">touch</td>
<td>1-Finger Drag</td> <td>Orbit-rotate the camera</td>
</tr>
<tr class="even">
<td> </td>
<td>2-Finger Drag</td> <td>Move up/down/left/right</td>
</tr>
<tr class="odd">
<td> </td>
<td>2-Finger Pinch</td> <td>Scale the view</td>
</tr>
<tr class="even">
<td class="subprojcontrolsdevicekind">mouse</td>
<td>Left-Button Drag</td> <td>Orbit-rotate the camera</td>
</tr>
<tr class="odd">
<td> </td>
<td>Right-Button Drag</td> <td>Move up/down/left/right</td>
</tr>
<tr class="even">
<td> </td>
<td>Middle-Click Drag</td> <td>Scale the view (up:out, down:in)</td>
</tr>
<tr class="odd">
<td class="subprojcontrolsdevicekind">keyboard</td>
<td>Escape</td> <td>Quit the application</td>
</tr>
<tr class="even">
<td> </td>
<td>Tab</td> <td>Toggle TweakBar visibility</td>
</tr>
<tr class="odd">
<td class="subprojcontrolsdevicekind">gamepad</td>
<td>Start</td> <td>Toggle TweakBar visibility</td>
</tr>
<tr class="even">
<td> </td>
<td>Right ThumbStick</td> <td>Orbit-rotate the camera</td>
</tr>
<tr class="odd">
<td> </td>
<td>Left ThumbStick</td> <td>Move forward/backward, Slide left/right</td>
</tr>
<tr class="even">
<td> </td>
<td>Left/Right Triggers</td> <td>Move up/down</td>
</tr>
<tr class="odd">
<td> </td>
<td>A</td> <td>Show TweakBar, Toggle Focused Item</td>
</tr>
<tr class="even">
<td> </td>
<td>B</td> <td>Close Focused UI, Hide TweakBar</td>
</tr>
<tr class="odd">
<td> </td>
<td>DPAD Up/Down</td> <td>Move Focus to Prev/Next Item</td>
</tr>
<tr class="even">
<td> </td>
<td>DPAD Left/Right</td> <td>Decrease/Increase Focused Item</td>
</tr>
</table>
</div>
</div>
<div class="row" id="subprojfulldoc">
<h3>Technical Details</h3>
<?xml version="1.0" encoding="us-ascii"?>
<div id="detaileddoc">
<h4>Overview</h4>
<p>
This OpenGL sample demonstrates how to implement multisample antialiasing (MSAA) on top of deferred shading. The general idea is to first render the scene geometry to a multisample-enabled g-buffer, then determine which pixels are complex (meaning they contain more than one fragment) and should be shaded at sample frequency, (a.k.a. supersampled), and finally perform shading accordingly. This sample implements an array of approaches to achieve these goals. We can simply use gl_SampleMaskIn or we can check the discontinuities between samples within a pixel to determine whether a pixel has multiple different fragments. We can also perform shading normal and complex pixels in two separate passes, which results in better thread coherency. Finally, we can determine the number of unique fragments in a complex pixel, and perform shading adaptively based on unique fragment count. This sample implements 4x MSAA, but the idea can be easily extended to support more sample count.</p>
<div class="row text-center"><div class="col-md-2"></div>
<div class="col-md-8 text-center small">
<p></p>
<p><a data-colorbox="true" href="images/MSAA_deferred.jpg"><img src="images/MSAA_deferred.jpg" width="360px"/></a></p>
<p>Figure 1: Sponza Atrium rendered with 4x MSAA with deferred shading<br/>(Click to enlarge)</p>
<p></p>
</div><div class="col-md-2"></div></div>
<h4>Deferred Shading with MSAA</h4>
<h5>Introduction</h5>
<p>
MSAA has always been a major drawback of deferred shading, since the geometry for lighting (in this sample, a full-screen quad) is separated from the scene geometry. Therefore we don't get the benefit of hardware determining which pixels are edges as it does in traditional forward MSAA rendering. In the deferred scenario, we have to be able to determine which pixels are complex and only shade them on per-sample frequency, with the least computation and in the least divergent way possible.
</p>
<h5>Complex Pixel Detection</h5>
<p>
The first important task in doing MSAA with deferred shading is to detect complex pixels, which are pixels containing more than one unique fragment. This sample implements two approaches to do this. The first one uses gl_SampleMaskIn, which computes the pixel samples covered by the current fragment. The following figure shows an example of gl_SampleMaskIn.
</p>
<div class="row text-center">
<div class="col-md-2"></div>
<div class="col-md-8 text-center small">
<p></p>
<p>
<a data-colorbox="true" href="images/MSAA_coverage.jpg">
<img src="images/MSAA_coverage.jpg" width="360px"/>
</a>
</p>
<p>
Figure 2: gl_SampleMaskIn shows which samples the current fragment covers.<br/>(Click to enlarge)
</p>
<p></p>
</div>
<div class="col-md-2"></div>
</div>
<p>
If there is one sample in a pixel whose coverage mask is not 1111, we can mark the pixel as complex. We store whether each sample coverage mask is 1111 to the multisampled buffer, then explicitly resolve the buffer so that we don't have to loop through each sample to tell whether the pixel is complex.
</p>
<p>
This approach can very efficiently detect complex pixels, but it does have a drawback of marking some non-edge pixels as complex, since it relies on underlying geometry rather than screen space discontinuities.
</p>
<p>
Another approach we have in this sample is to search for discontinuities in normals, colors, and depths between samples in a pixel, and if the discontinuity is larger than a certain threshold, we mark the pixel as complex. This approach has the advantage of producing complex pixels only at edges, which means but we need to loop through samples in a pixel during detection.
</p>
<div class="row text-center">
<div class="col-md-2"></div>
<div class="col-md-8 text-center small">
<p></p>
<p>
<a data-colorbox="true" href="images/complex_pixels.jpg">
<img src="images/complex_pixels.jpg" width="360px"/>
</a>
</p>
<p>
Figure 3: gl_SampleMaskIn shows which samples the current fragment covers. The top approach results in more complex pixels but the detection process takes less time.<br/>(Click to enlarge)
</p>
<p></p>
</div>
<div class="col-md-2"></div>
</div>
<h5>Separate Pass for Complex Pixels</h5>
<p>
In the lighting pass, we use the complex pixel mask to differentiate normal pixels and complex pixels. If the pixel is complex we then perform super sampling, and output the average color of each sample. The problem with this is thread coherency. For pixels packed in a warp, the normal pixels, which perform shading once, would have to wait for complex pixels to complete since they are doing super sampling. Alternately, we can separate normal and complex pixels into 2 separate passes with stencil masks. The downside of separated passes is that it introduces the overhead of generating the stencil masks and an additional draw call each frame.
</p>
<p>
This sample also implements the option of computing hardware-based super sampling for complex pixels. Instead of shading multiple samples in a single pixel shader invocation, we invoke the pixel shader at per-sample level to achieve fully super-sampled complex pixels.
</p>
<h5>Adaptive Shading of Complex Pixels</h5>
<p>
One important observation is that the majority of complex pixels only contain 2 unique fragments, which means we can potentially perform less shading at complex pixels and still achieve the same visual quality.
</p>
<div class="row text-center">
<div class="col-md-2"></div>
<div class="col-md-8 text-center small">
<p></p>
<p><a data-colorbox="true" href="images/adaptive_shading.jpg"><img src="images/adaptive_shading.jpg" width="360px"/></a></p>
<p>Figure 4: Complex pixel color coded based on unique fragment counts. Green means 2 fragments, blue means three and red means four.<br/>(Click to enlarge)</p>
<p></p>
</div><div class="col-md-2"></div>
</div>
<p>
Again, this application uses coverage masks to compute the number of unique fragments in each complex pixel. We count the number of unique coverage masks per pixel, and weight each unique fragment in the pixel by the number of samples covered. For example, in figure 4 there are 3 unique fragments. The red fragment is weighted 2/4, while blue and grey fragments are each weighted 1/4.
</p>
<p>
This saves the cost of shading, but introduces additional cost of counting and weighting unique fragments in complex pixels.
</p>
<h4>Acknowledgments</h4>
<p>
The Sponza model was created by Marko Dabrovic.
</p>
</div>
</div>
</div>
</div>
</div> <!--content-->
<!-- footer block-->
<div id="footer" class="container">
<div class="seperator"></div>
<div class="seperator"></div>
<footer>
<div class="row">
<div class="text-center">©2016 NVIDIA Corporation.</div>
<div class="seperator"></div>
</div>
</footer>
</div> <!--footer-->
</body>
</html>