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