Line data Source code
1 : /**
2 : * @file hdr.cpp: hdr, tonemapping, and bloom
3 : *
4 : * Libprimis supports a type of high dynamic range by calculating the average
5 : * brightness of the scene and slowly changing the calibration point for the
6 : * viewed image, much as human eyes do. This results in colors being washed out
7 : * bright, e.g., when stepping into the sunlight, and time being required before
8 : * a dark area can be seen after being "used to" bright light.
9 : *
10 : * Additionally, bloom, or bleed from bright light sources, is calculated in the
11 : * process of sampling the screen for HDR purposes. This allows very bright
12 : * objects to appear more overbright (and realistic) than the light entities can
13 : * project on their own.
14 : */
15 : #include "../libprimis-headers/cube.h"
16 : #include "../../shared/geomexts.h"
17 : #include "../../shared/glemu.h"
18 : #include "../../shared/glexts.h"
19 :
20 : #include "aa.h"
21 : #include "hdr.h"
22 : #include "rendergl.h"
23 : #include "renderlights.h"
24 : #include "rendertimers.h"
25 : #include "shader.h"
26 : #include "shaderparam.h"
27 : #include "texture.h"
28 :
29 : #include "interface/control.h"
30 :
31 :
32 : GLenum hdrformat = 0;
33 :
34 : int bloomw = -1,
35 : bloomh = -1;
36 :
37 : //gl buffers needed for bloom effect
38 : GLuint hdrfbo = 0,
39 : hdrtex = 0;
40 :
41 : namespace
42 : {
43 : GLuint bloompbo = 0;
44 : std::array<GLuint, 6> bloomfbo = { 0, 0, 0, 0, 0, 0 },
45 : bloomtex = { 0, 0, 0, 0, 0, 0 };
46 :
47 : GLenum bloomformat = 0;
48 : int lasthdraccum = 0;
49 :
50 : FVAR(bloomthreshold, 1e-3f, 0.8f, 1e3f);
51 : FVARP(bloomscale, 0, 1.0f, 1e3f); //scale factor for bloom effect
52 : VARP(bloomblur, 0, 7, 7); //blur factor for bloom effect
53 : VARP(bloomiter, 0, 0, 4); //number of interations for bloom generation
54 0 : VARFP(bloomsize, 6, 9, 11, cleanupbloom()); //size of HDR buffer: 6 -> 2^6 = 64x64 ... 11 -> 2^11 = 2048x2048
55 0 : VARFP(bloomprec, 0, 2, 3, cleanupbloom()); //HDR buffer bit depth: 3: RGB16 2: R11G11B10 1:RGB10 0: RGB8
56 :
57 : FVAR(hdraccumscale, 0, 0.98f, 1); //for hdr, exponent base for time decay of accumulation buffer (always <= 1 so decaying with time)
58 : VAR(hdraccummillis, 1, 33, 1000); //number of ms between samplings for the hdr buffer
59 : VAR(hdrreduce, 0, 2, 2); //number of powers to reduce hdr buffer size relative to g buffer (2 = 1/4, 1 = 1/2, 0 = g-buffer size)
60 : FVARR(hdrbright, 1e-4f, 1.0f, 1e4f); //brightness factor for high dynamic range rendering
61 : FVAR(hdrsaturate, 1e-3f, 0.8f, 1e3f);
62 : }
63 :
64 0 : int gethdrformat(int prec, int fallback)
65 : {
66 0 : if(prec >= 3)
67 : {
68 0 : return GL_RGB16F;
69 : }
70 0 : if(prec >= 2)
71 : {
72 0 : return GL_R11F_G11F_B10F;
73 : }
74 0 : if(prec >= 1)
75 : {
76 0 : return GL_RGB10;
77 : }
78 0 : return fallback;
79 : }
80 :
81 0 : void setupbloom(int w, int h)
82 : {
83 0 : int maxsize = ((1<<bloomsize)*5)/4;
84 0 : while(w >= maxsize || h >= maxsize)
85 : {
86 0 : w /= 2;
87 0 : h /= 2;
88 : }
89 0 : w = std::max(w, 1);
90 0 : h = std::max(h, 1);
91 0 : if(w == bloomw && h == bloomh)
92 : {
93 0 : return;
94 : }
95 0 : bloomw = w;
96 0 : bloomh = h;
97 :
98 0 : for(int i = 0; i < 5; ++i)
99 : {
100 0 : if(!bloomtex[i])
101 : {
102 0 : glGenTextures(1, &bloomtex[i]);
103 : }
104 : }
105 :
106 0 : for(int i = 0; i < 5; ++i)
107 : {
108 0 : if(!bloomfbo[i])
109 : {
110 0 : glGenFramebuffers(1, &bloomfbo[i]);
111 : }
112 : }
113 :
114 0 : bloomformat = gethdrformat(bloomprec);
115 0 : createtexture(bloomtex[0], std::max(gw/2, bloomw), std::max(gh/2, bloomh), nullptr, 3, 1, bloomformat, GL_TEXTURE_RECTANGLE);
116 0 : createtexture(bloomtex[1], std::max(gw/4, bloomw), std::max(gh/4, bloomh), nullptr, 3, 1, bloomformat, GL_TEXTURE_RECTANGLE);
117 0 : createtexture(bloomtex[2], bloomw, bloomh, nullptr, 3, 1, GL_RGB, GL_TEXTURE_RECTANGLE);
118 0 : createtexture(bloomtex[3], bloomw, bloomh, nullptr, 3, 1, GL_RGB, GL_TEXTURE_RECTANGLE);
119 0 : if(bloomformat != GL_RGB)
120 : {
121 0 : if(!bloomtex[5])
122 : {
123 0 : glGenTextures(1, &bloomtex[5]);
124 : }
125 0 : if(!bloomfbo[5])
126 : {
127 0 : glGenFramebuffers(1, &bloomfbo[5]);
128 : }
129 0 : createtexture(bloomtex[5], bloomw, bloomh, nullptr, 3, 1, bloomformat, GL_TEXTURE_RECTANGLE);
130 : }
131 : static constexpr std::array<float, 12> grayf = { 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f };
132 0 : createtexture(bloomtex[4], bloompbo ? 4 : 1, 1, reinterpret_cast<const void *>(grayf.data()), 3, 1, GL_R16F);
133 0 : for(int i = 0; i < (5 + (bloomformat != GL_RGB ? 1 : 0)); ++i)
134 : {
135 0 : glBindFramebuffer(GL_FRAMEBUFFER, bloomfbo[i]);
136 0 : glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, i==4 ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE, bloomtex[i], 0);
137 0 : if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
138 : {
139 0 : fatal("failed allocating bloom buffer!");
140 : }
141 : }
142 :
143 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
144 : }
145 :
146 0 : void cleanupbloom()
147 : {
148 0 : if(bloompbo)
149 : {
150 0 : glDeleteBuffers(1, &bloompbo);
151 0 : bloompbo = 0;
152 : }
153 0 : for(int i = 0; i < 6; ++i)
154 : {
155 0 : if(bloomfbo[i])
156 : {
157 0 : glDeleteFramebuffers(1, &bloomfbo[i]);
158 0 : bloomfbo[i] = 0;
159 : }
160 : }
161 0 : for(int i = 0; i < 6; ++i)
162 : {
163 0 : if(bloomtex[i])
164 : {
165 0 : glDeleteTextures(1, &bloomtex[i]);
166 0 : bloomtex[i] = 0;
167 : }
168 : }
169 0 : bloomw = bloomh = -1;
170 0 : lasthdraccum = 0;
171 0 : }
172 :
173 0 : FVARFP(hdrgamma, 1e-3f, 2, 1e3f, initwarning("HDR setup", Init_Load, Change_Shaders));
174 0 : VARFP(hdrprec, 0, 2, 3, gbuf.cleanupgbuffer()); //precision of hdr buffer
175 :
176 0 : void copyhdr(int sw, int sh, GLuint fbo, int dw, int dh, bool flipx, bool flipy, bool swapxy)
177 : {
178 0 : if(!dw)
179 : {
180 0 : dw = sw;
181 : }
182 0 : if(!dh)
183 : {
184 0 : dh = sh;
185 : }
186 :
187 0 : if(msaalight)
188 : {
189 0 : gbuf.resolvemsaacolor(sw, sh);
190 : }
191 0 : glerror();
192 :
193 0 : glBindFramebuffer(GL_FRAMEBUFFER, fbo);
194 0 : glViewport(0, 0, dw, dh);
195 :
196 0 : SETSHADER(reorient);
197 0 : vec reorientx(flipx ? -0.5f : 0.5f, 0, 0.5f),
198 0 : reorienty(0, flipy ? -0.5f : 0.5f, 0.5f);
199 0 : if(swapxy)
200 : {
201 0 : std::swap(reorientx, reorienty);
202 : }
203 0 : reorientx.mul(sw);
204 0 : reorienty.mul(sh);
205 0 : LOCALPARAM(reorientx, reorientx);
206 0 : LOCALPARAM(reorienty, reorienty);
207 :
208 0 : glBindTexture(GL_TEXTURE_RECTANGLE, hdrtex);
209 0 : screenquad();
210 0 : glerror();
211 :
212 0 : hdrclear = 3;
213 0 : }
214 :
215 0 : void loadhdrshaders(int aa)
216 : {
217 0 : switch(aa)
218 : {
219 0 : case AA_Luma:
220 : {
221 0 : useshaderbyname("hdrtonemapluma");
222 0 : useshaderbyname("hdrnopluma");
223 0 : if(msaalight > 1 && msaatonemap)
224 : {
225 0 : useshaderbyname("msaatonemapluma");
226 : }
227 0 : break;
228 : }
229 0 : case AA_Masked:
230 : {
231 0 : if(!msaasamples && ghasstencil)
232 : {
233 0 : useshaderbyname("hdrtonemapstencil");
234 : }
235 : else
236 : {
237 0 : useshaderbyname("hdrtonemapmasked");
238 0 : useshaderbyname("hdrnopmasked");
239 0 : if(msaalight > 1 && msaatonemap)
240 : {
241 0 : useshaderbyname("msaatonemapmasked");
242 : }
243 : }
244 0 : break;
245 : }
246 0 : case AA_Split:
247 : {
248 0 : useshaderbyname("msaatonemapsplit");
249 0 : break;
250 : }
251 0 : case AA_SplitLuma:
252 : {
253 0 : useshaderbyname("msaatonemapsplitluma");
254 0 : break;
255 : }
256 0 : case AA_SplitMasked:
257 : {
258 0 : useshaderbyname("msaatonemapsplitmasked");
259 0 : break;
260 : }
261 0 : default:
262 : {
263 0 : break;
264 : }
265 : }
266 0 : }
267 :
268 0 : void GBuffer::processhdr(GLuint outfbo, int aa)
269 : {
270 0 : timer *hdrtimer = begintimer("hdr processing");
271 :
272 0 : GLOBALPARAMF(hdrparams, hdrbright, hdrsaturate, bloomthreshold, bloomscale);
273 :
274 0 : GLuint b0fbo = bloomfbo[1],
275 0 : b0tex = bloomtex[1],
276 0 : b1fbo = bloomfbo[0],
277 0 : b1tex = bloomtex[0],
278 0 : ptex = hdrtex;
279 0 : int b0w = std::max(vieww/4, bloomw),
280 0 : b0h = std::max(viewh/4, bloomh),
281 0 : b1w = std::max(vieww/2, bloomw),
282 0 : b1h = std::max(viewh/2, bloomh),
283 0 : pw = vieww,
284 0 : ph = viewh;
285 0 : if(msaalight)
286 : {
287 0 : if(aa < AA_Split && (msaalight <= 1 || !msaatonemap)) //only bind relevant framebuffers
288 : {
289 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, mshdrfbo);
290 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrfbo);
291 0 : glBlitFramebuffer(0, 0, vieww, viewh, 0, 0, vieww, viewh, GL_COLOR_BUFFER_BIT, GL_NEAREST);
292 : }
293 0 : else if(hasFBMSBS && (vieww > bloomw || viewh > bloomh))
294 : {
295 0 : int cw = std::max(vieww/2, bloomw),
296 0 : ch = std::max(viewh/2, bloomh);
297 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, mshdrfbo);
298 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrfbo);
299 0 : glBlitFramebuffer(0, 0, vieww, viewh, 0, 0, cw, ch, GL_COLOR_BUFFER_BIT, GL_SCALED_RESOLVE_FASTEST_EXT);
300 0 : pw = cw;
301 0 : ph = ch;
302 0 : }
303 : else
304 : {
305 0 : glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
306 0 : if(vieww/2 >= bloomw)
307 : {
308 0 : pw = vieww/2;
309 0 : if(viewh/2 >= bloomh)
310 : {
311 0 : ph = viewh/2;
312 0 : glViewport(0, 0, pw, ph);
313 0 : SETSHADER(msaareduce);
314 : }
315 : else
316 : {
317 0 : glViewport(0, 0, pw, viewh);
318 0 : SETSHADER(msaareducew);
319 : }
320 : }
321 : else
322 : {
323 0 : glViewport(0, 0, vieww, viewh);
324 0 : SETSHADER(msaaresolve);
325 : }
326 0 : glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
327 0 : screenquad(vieww, viewh);
328 : }
329 : }
330 0 : if(hdrreduce)
331 : {
332 0 : while(pw > bloomw || ph > bloomh)
333 : {
334 0 : GLuint cfbo = b1fbo,
335 0 : ctex = b1tex;
336 0 : int cw = std::max(pw/2, bloomw),
337 0 : ch = std::max(ph/2, bloomh);
338 :
339 0 : if(hdrreduce > 1 && cw/2 >= bloomw)
340 : {
341 0 : cw /= 2;
342 0 : if(ch/2 >= bloomh)
343 : {
344 0 : ch /= 2;
345 0 : SETSHADER(hdrreduce2);
346 : }
347 0 : else SETSHADER(hdrreduce2w);
348 0 : }
349 : else
350 : {
351 0 : SETSHADER(hdrreduce);
352 : }
353 0 : if(cw == bloomw && ch == bloomh)
354 : {
355 0 : if(bloomfbo[5])
356 : {
357 0 : cfbo = bloomfbo[5];
358 0 : ctex = bloomtex[5];
359 : }
360 : else
361 : {
362 0 : cfbo = bloomfbo[2];
363 0 : ctex = bloomtex[2];
364 : }
365 : }
366 0 : glBindFramebuffer(GL_FRAMEBUFFER, cfbo);
367 0 : glViewport(0, 0, cw, ch);
368 0 : glBindTexture(GL_TEXTURE_RECTANGLE, ptex);
369 0 : screenquad(pw, ph);
370 :
371 0 : ptex = ctex;
372 0 : pw = cw;
373 0 : ph = ch;
374 0 : std::swap(b0fbo, b1fbo);
375 0 : std::swap(b0tex, b1tex);
376 0 : std::swap(b0w, b1w);
377 0 : std::swap(b0h, b1h);
378 : }
379 : }
380 0 : if(!lasthdraccum || lastmillis - lasthdraccum >= hdraccummillis)
381 : {
382 0 : GLuint ltex = ptex;
383 0 : int lw = pw,
384 0 : lh = ph;
385 0 : for(int i = 0; lw > 2 || lh > 2; i++)
386 : {
387 0 : int cw = std::max(lw/2, 2),
388 0 : ch = std::max(lh/2, 2);
389 :
390 0 : if(hdrreduce > 1 && cw/2 >= 2)
391 : {
392 0 : cw /= 2;
393 0 : if(ch/2 >= 2)
394 : {
395 0 : ch /= 2;
396 0 : if(i)
397 : {
398 0 : SETSHADER(hdrreduce2);
399 : }
400 : else
401 : {
402 0 : SETSHADER(hdrluminance2);
403 : }
404 : }
405 0 : else if(i)
406 : {
407 0 : SETSHADER(hdrreduce2w);
408 : }
409 : else
410 : {
411 0 : SETSHADER(hdrluminance2w);
412 : }
413 0 : }
414 0 : else if(i)
415 : {
416 0 : SETSHADER(hdrreduce);
417 : }
418 : else
419 : {
420 0 : SETSHADER(hdrluminance);
421 : }
422 0 : glBindFramebuffer(GL_FRAMEBUFFER, b1fbo);
423 0 : glViewport(0, 0, cw, ch);
424 0 : glBindTexture(GL_TEXTURE_RECTANGLE, ltex);
425 0 : screenquad(lw, lh);
426 :
427 0 : ltex = b1tex;
428 0 : lw = cw;
429 0 : lh = ch;
430 0 : std::swap(b0fbo, b1fbo);
431 0 : std::swap(b0tex, b1tex);
432 0 : std::swap(b0w, b1w);
433 0 : std::swap(b0h, b1h);
434 : }
435 :
436 0 : glBindFramebuffer(GL_FRAMEBUFFER, bloomfbo[4]);
437 0 : glViewport(0, 0, bloompbo ? 4 : 1, 1);
438 0 : glEnable(GL_BLEND);
439 0 : glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
440 0 : SETSHADER(hdraccum);
441 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
442 0 : LOCALPARAMF(accumscale, lasthdraccum ? std::pow(hdraccumscale, static_cast<float>(lastmillis - lasthdraccum)/hdraccummillis) : 0);
443 0 : screenquad(2, 2);
444 0 : glDisable(GL_BLEND);
445 :
446 0 : if(bloompbo)
447 : {
448 0 : glBindBuffer(GL_PIXEL_PACK_BUFFER, bloompbo);
449 0 : glPixelStorei(GL_PACK_ALIGNMENT, 1);
450 0 : glReadPixels(0, 0, 4, 1, GL_RED, GL_FLOAT, nullptr);
451 0 : glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
452 : }
453 :
454 0 : lasthdraccum = lastmillis;
455 : }
456 :
457 0 : if(bloompbo)
458 : {
459 0 : gle::bindvbo(bloompbo);
460 0 : gle::enablecolor();
461 0 : gle::colorpointer(sizeof(GLfloat), nullptr, GL_FLOAT, 1);
462 0 : gle::clearvbo();
463 : }
464 :
465 0 : b0fbo = bloomfbo[3];
466 0 : b0tex = bloomtex[3];
467 0 : b1fbo = bloomfbo[2];
468 0 : b1tex = bloomtex[2];
469 0 : b0w = b1w = bloomw;
470 0 : b0h = b1h = bloomh;
471 :
472 0 : glActiveTexture(GL_TEXTURE2);
473 0 : glBindTexture(GL_TEXTURE_2D, bloomtex[4]);
474 0 : glActiveTexture(GL_TEXTURE0);
475 :
476 0 : glBindFramebuffer(GL_FRAMEBUFFER, b0fbo);
477 0 : glViewport(0, 0, b0w, b0h);
478 0 : SETSHADER(hdrbloom);
479 0 : glBindTexture(GL_TEXTURE_RECTANGLE, ptex);
480 0 : screenquad(pw, ph);
481 :
482 0 : if(bloomblur)
483 : {
484 : std::array<float, maxblurradius+1> blurweights,
485 : bluroffsets;
486 0 : setupblurkernel(bloomblur, blurweights.data(), bluroffsets.data());
487 0 : for(int i = 0; i < (2 + 2*bloomiter); ++i)
488 : {
489 0 : glBindFramebuffer(GL_FRAMEBUFFER, b1fbo);
490 0 : glViewport(0, 0, b1w, b1h);
491 0 : setblurshader(i%2, 1, bloomblur, blurweights.data(), bluroffsets.data(), GL_TEXTURE_RECTANGLE);
492 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
493 0 : screenquad(b0w, b0h);
494 0 : std::swap(b0w, b1w);
495 0 : std::swap(b0h, b1h);
496 0 : std::swap(b0tex, b1tex);
497 0 : std::swap(b0fbo, b1fbo);
498 : }
499 : }
500 :
501 0 : if(aa >= AA_Split)
502 : {
503 0 : glBindFramebuffer(GL_FRAMEBUFFER, outfbo);
504 0 : glViewport(0, 0, vieww, viewh);
505 0 : glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
506 0 : glActiveTexture(GL_TEXTURE1);
507 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
508 0 : glActiveTexture(GL_TEXTURE0);
509 0 : switch(aa)
510 : {
511 0 : case AA_SplitLuma:
512 : {
513 0 : SETSHADER(msaatonemapsplitluma);
514 0 : break;
515 : }
516 0 : case AA_SplitMasked:
517 : {
518 0 : SETSHADER(msaatonemapsplitmasked);
519 0 : setaavelocityparams(GL_TEXTURE3);
520 0 : break;
521 : }
522 0 : default:
523 : {
524 0 : SETSHADER(msaatonemapsplit);
525 0 : break;
526 : }
527 : }
528 0 : screenquad(vieww, viewh, b0w, b0h);
529 : }
530 0 : else if(msaalight <= 1 || !msaatonemap)
531 : {
532 0 : glBindFramebuffer(GL_FRAMEBUFFER, outfbo);
533 0 : glViewport(0, 0, vieww, viewh);
534 0 : glBindTexture(GL_TEXTURE_RECTANGLE, hdrtex);
535 0 : glActiveTexture(GL_TEXTURE1);
536 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
537 0 : glActiveTexture(GL_TEXTURE0);
538 0 : switch(aa)
539 : {
540 0 : case AA_Luma:
541 : {
542 0 : SETSHADER(hdrtonemapluma);
543 0 : break;
544 : }
545 0 : case AA_Masked:
546 : {
547 0 : if(!msaasamples && ghasstencil)
548 : {
549 0 : glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
550 0 : glStencilFunc(GL_EQUAL, 0, 0x80);
551 0 : glEnable(GL_STENCIL_TEST);
552 0 : SETSHADER(hdrtonemap);
553 0 : screenquad(vieww, viewh, b0w, b0h);
554 :
555 0 : glStencilFunc(GL_EQUAL, 0x80, 0x80);
556 0 : SETSHADER(hdrtonemapstencil);
557 0 : screenquad(vieww, viewh, b0w, b0h);
558 0 : glDisable(GL_STENCIL_TEST);
559 0 : goto done; //see bottom of fxn
560 : }
561 0 : SETSHADER(hdrtonemapmasked);
562 0 : setaavelocityparams(GL_TEXTURE3);
563 0 : break;
564 : }
565 0 : default:
566 : {
567 0 : SETSHADER(hdrtonemap);
568 0 : break;
569 : }
570 : }
571 0 : screenquad(vieww, viewh, b0w, b0h);
572 0 : }
573 : else
574 : {
575 0 : bool blit = msaalight > 2 && msaatonemapblit && (!aa || !outfbo);
576 :
577 0 : glBindFramebuffer(GL_FRAMEBUFFER, blit ? msrefractfbo : outfbo);
578 0 : glViewport(0, 0, vieww, viewh);
579 0 : glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
580 0 : glActiveTexture(GL_TEXTURE1);
581 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
582 0 : glActiveTexture(GL_TEXTURE0);
583 :
584 0 : if(blit)
585 : {
586 0 : SETSHADER(msaatonemapsample);
587 : }
588 : else
589 : {
590 0 : switch(aa)
591 : {
592 0 : case AA_Luma:
593 : {
594 0 : SETSHADER(msaatonemapluma);
595 0 : break;
596 : }
597 0 : case AA_Masked:
598 : {
599 0 : SETSHADER(msaatonemapmasked);
600 0 : setaavelocityparams(GL_TEXTURE3);
601 0 : break;
602 : }
603 0 : default:
604 : {
605 0 : SETSHADER(msaatonemap);
606 0 : break;
607 : }
608 : }
609 : }
610 0 : screenquad(vieww, viewh, b0w, b0h);
611 :
612 0 : if(blit)
613 : {
614 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, msrefractfbo);
615 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa || !outfbo ? refractfbo : outfbo);
616 0 : glBlitFramebuffer(0, 0, vieww, viewh, 0, 0, vieww, viewh, GL_COLOR_BUFFER_BIT, GL_NEAREST);
617 :
618 0 : if(!outfbo)
619 : {
620 0 : glBindFramebuffer(GL_FRAMEBUFFER, outfbo);
621 0 : glViewport(0, 0, vieww, viewh);
622 0 : if(!blit)
623 : {
624 0 : SETSHADER(hdrnop);
625 : }
626 : else
627 : {
628 0 : switch(aa)
629 : {
630 0 : case AA_Luma:
631 : {
632 0 : SETSHADER(hdrnopluma);
633 0 : break;
634 : }
635 0 : case AA_Masked:
636 : {
637 0 : SETSHADER(hdrnopmasked);
638 0 : setaavelocityparams(GL_TEXTURE3);
639 0 : break;
640 : }
641 0 : default:
642 : {
643 0 : SETSHADER(hdrnop);
644 0 : break;
645 : }
646 : }
647 : }
648 0 : glBindTexture(GL_TEXTURE_RECTANGLE, refracttex);
649 0 : screenquad(vieww, viewh);
650 : }
651 : }
652 : }
653 :
654 0 : done:
655 0 : if(bloompbo)
656 : {
657 0 : gle::disablecolor();
658 : }
659 :
660 0 : endtimer(hdrtimer);
661 0 : }
|