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(size_t i = 0; i < bloomtex.size() - 1; ++i)
99 : {
100 0 : if(!bloomtex[i])
101 : {
102 0 : glGenTextures(1, &bloomtex[i]);
103 : }
104 : }
105 :
106 0 : for(size_t i = 0; i < bloomfbo.size() - 1; ++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(size_t i = 0; i < bloomfbo.size(); ++i)
154 : {
155 0 : if(bloomfbo[i])
156 : {
157 0 : glDeleteFramebuffers(1, &bloomfbo[i]);
158 0 : bloomfbo[i] = 0;
159 : }
160 : }
161 0 : for(size_t i = 0; i < bloomtex.size(); ++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 : //both of these vars used in hdr.h
174 0 : FVARFP(hdrgamma, 1e-3f, 2, 1e3f, initwarning("HDR setup", Init_Load, Change_Shaders));
175 0 : VARFP(hdrprec, 0, 2, 3, gbuf.cleanupgbuffer()); //precision of hdr buffer
176 :
177 0 : void copyhdr(int sw, int sh, GLuint fbo)
178 : {
179 0 : if(msaalight)
180 : {
181 0 : gbuf.resolvemsaacolor(sw, sh);
182 : }
183 0 : glerror();
184 :
185 0 : glBindFramebuffer(GL_FRAMEBUFFER, fbo);
186 0 : glViewport(0, 0, sw, sh);
187 :
188 0 : SETSHADER(reorient);
189 0 : vec reorientx(0.5f, 0, 0.5f),
190 0 : reorienty(0, 0.5f, 0.5f);
191 0 : reorientx.mul(sw);
192 0 : reorienty.mul(sh);
193 0 : LOCALPARAM(reorientx, reorientx);
194 0 : LOCALPARAM(reorienty, reorienty);
195 :
196 0 : glBindTexture(GL_TEXTURE_RECTANGLE, hdrtex);
197 0 : screenquad();
198 0 : glerror();
199 :
200 0 : hdrclear = 3;
201 0 : }
202 :
203 0 : void loadhdrshaders(int aa)
204 : {
205 0 : switch(aa)
206 : {
207 0 : case AA_Luma:
208 : {
209 0 : useshaderbyname("hdrtonemapluma");
210 0 : useshaderbyname("hdrnopluma");
211 0 : if(msaalight > 1 && msaatonemap)
212 : {
213 0 : useshaderbyname("msaatonemapluma");
214 : }
215 0 : break;
216 : }
217 0 : case AA_Masked:
218 : {
219 0 : if(!msaasamples && ghasstencil)
220 : {
221 0 : useshaderbyname("hdrtonemapstencil");
222 : }
223 : else
224 : {
225 0 : useshaderbyname("hdrtonemapmasked");
226 0 : useshaderbyname("hdrnopmasked");
227 0 : if(msaalight > 1 && msaatonemap)
228 : {
229 0 : useshaderbyname("msaatonemapmasked");
230 : }
231 : }
232 0 : break;
233 : }
234 0 : case AA_Split:
235 : {
236 0 : useshaderbyname("msaatonemapsplit");
237 0 : break;
238 : }
239 0 : case AA_SplitLuma:
240 : {
241 0 : useshaderbyname("msaatonemapsplitluma");
242 0 : break;
243 : }
244 0 : case AA_SplitMasked:
245 : {
246 0 : useshaderbyname("msaatonemapsplitmasked");
247 0 : break;
248 : }
249 0 : default:
250 : {
251 0 : break;
252 : }
253 : }
254 0 : }
255 :
256 0 : void GBuffer::processhdr(GLuint outfbo, int aa)
257 : {
258 0 : timer *hdrtimer = begintimer("hdr processing");
259 :
260 0 : GLOBALPARAMF(hdrparams, hdrbright, hdrsaturate, bloomthreshold, bloomscale);
261 :
262 0 : GLuint b0fbo = bloomfbo[1],
263 0 : b0tex = bloomtex[1],
264 0 : b1fbo = bloomfbo[0],
265 0 : b1tex = bloomtex[0],
266 0 : ptex = hdrtex;
267 0 : int b0w = std::max(vieww/4, bloomw),
268 0 : b0h = std::max(viewh/4, bloomh),
269 0 : b1w = std::max(vieww/2, bloomw),
270 0 : b1h = std::max(viewh/2, bloomh),
271 0 : pw = vieww,
272 0 : ph = viewh;
273 0 : if(msaalight)
274 : {
275 0 : if(aa < AA_Split && (msaalight <= 1 || !msaatonemap)) //only bind relevant framebuffers
276 : {
277 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, mshdrfbo);
278 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrfbo);
279 0 : glBlitFramebuffer(0, 0, vieww, viewh, 0, 0, vieww, viewh, GL_COLOR_BUFFER_BIT, GL_NEAREST);
280 : }
281 0 : else if(hasFBMSBS && (vieww > bloomw || viewh > bloomh))
282 : {
283 0 : int cw = std::max(vieww/2, bloomw),
284 0 : ch = std::max(viewh/2, bloomh);
285 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, mshdrfbo);
286 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrfbo);
287 0 : glBlitFramebuffer(0, 0, vieww, viewh, 0, 0, cw, ch, GL_COLOR_BUFFER_BIT, GL_SCALED_RESOLVE_FASTEST_EXT);
288 0 : pw = cw;
289 0 : ph = ch;
290 0 : }
291 : else
292 : {
293 0 : glBindFramebuffer(GL_FRAMEBUFFER, hdrfbo);
294 0 : if(vieww/2 >= bloomw)
295 : {
296 0 : pw = vieww/2;
297 0 : if(viewh/2 >= bloomh)
298 : {
299 0 : ph = viewh/2;
300 0 : glViewport(0, 0, pw, ph);
301 0 : SETSHADER(msaareduce);
302 : }
303 : else
304 : {
305 0 : glViewport(0, 0, pw, viewh);
306 0 : SETSHADER(msaareducew);
307 : }
308 : }
309 : else
310 : {
311 0 : glViewport(0, 0, vieww, viewh);
312 0 : SETSHADER(msaaresolve);
313 : }
314 0 : glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
315 0 : screenquad(vieww, viewh);
316 : }
317 : }
318 0 : if(hdrreduce)
319 : {
320 0 : while(pw > bloomw || ph > bloomh)
321 : {
322 0 : GLuint cfbo = b1fbo,
323 0 : ctex = b1tex;
324 0 : int cw = std::max(pw/2, bloomw),
325 0 : ch = std::max(ph/2, bloomh);
326 :
327 0 : if(hdrreduce > 1 && cw/2 >= bloomw)
328 : {
329 0 : cw /= 2;
330 0 : if(ch/2 >= bloomh)
331 : {
332 0 : ch /= 2;
333 0 : SETSHADER(hdrreduce2);
334 : }
335 0 : else SETSHADER(hdrreduce2w);
336 0 : }
337 : else
338 : {
339 0 : SETSHADER(hdrreduce);
340 : }
341 0 : if(cw == bloomw && ch == bloomh)
342 : {
343 0 : if(bloomfbo[5])
344 : {
345 0 : cfbo = bloomfbo[5];
346 0 : ctex = bloomtex[5];
347 : }
348 : else
349 : {
350 0 : cfbo = bloomfbo[2];
351 0 : ctex = bloomtex[2];
352 : }
353 : }
354 0 : glBindFramebuffer(GL_FRAMEBUFFER, cfbo);
355 0 : glViewport(0, 0, cw, ch);
356 0 : glBindTexture(GL_TEXTURE_RECTANGLE, ptex);
357 0 : screenquad(pw, ph);
358 :
359 0 : ptex = ctex;
360 0 : pw = cw;
361 0 : ph = ch;
362 0 : std::swap(b0fbo, b1fbo);
363 0 : std::swap(b0tex, b1tex);
364 0 : std::swap(b0w, b1w);
365 0 : std::swap(b0h, b1h);
366 : }
367 : }
368 0 : if(!lasthdraccum || lastmillis - lasthdraccum >= hdraccummillis)
369 : {
370 0 : GLuint ltex = ptex;
371 0 : int lw = pw,
372 0 : lh = ph;
373 0 : for(int i = 0; lw > 2 || lh > 2; i++)
374 : {
375 0 : int cw = std::max(lw/2, 2),
376 0 : ch = std::max(lh/2, 2);
377 :
378 0 : if(hdrreduce > 1 && cw/2 >= 2)
379 : {
380 0 : cw /= 2;
381 0 : if(ch/2 >= 2)
382 : {
383 0 : ch /= 2;
384 0 : if(i)
385 : {
386 0 : SETSHADER(hdrreduce2);
387 : }
388 : else
389 : {
390 0 : SETSHADER(hdrluminance2);
391 : }
392 : }
393 0 : else if(i)
394 : {
395 0 : SETSHADER(hdrreduce2w);
396 : }
397 : else
398 : {
399 0 : SETSHADER(hdrluminance2w);
400 : }
401 0 : }
402 0 : else if(i)
403 : {
404 0 : SETSHADER(hdrreduce);
405 : }
406 : else
407 : {
408 0 : SETSHADER(hdrluminance);
409 : }
410 0 : glBindFramebuffer(GL_FRAMEBUFFER, b1fbo);
411 0 : glViewport(0, 0, cw, ch);
412 0 : glBindTexture(GL_TEXTURE_RECTANGLE, ltex);
413 0 : screenquad(lw, lh);
414 :
415 0 : ltex = b1tex;
416 0 : lw = cw;
417 0 : lh = ch;
418 0 : std::swap(b0fbo, b1fbo);
419 0 : std::swap(b0tex, b1tex);
420 0 : std::swap(b0w, b1w);
421 0 : std::swap(b0h, b1h);
422 : }
423 :
424 0 : glBindFramebuffer(GL_FRAMEBUFFER, bloomfbo[4]);
425 0 : glViewport(0, 0, bloompbo ? 4 : 1, 1);
426 0 : glEnable(GL_BLEND);
427 0 : glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
428 0 : SETSHADER(hdraccum);
429 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
430 0 : LOCALPARAMF(accumscale, lasthdraccum ? std::pow(hdraccumscale, static_cast<float>(lastmillis - lasthdraccum)/hdraccummillis) : 0);
431 0 : screenquad(2, 2);
432 0 : glDisable(GL_BLEND);
433 :
434 0 : if(bloompbo)
435 : {
436 0 : glBindBuffer(GL_PIXEL_PACK_BUFFER, bloompbo);
437 0 : glPixelStorei(GL_PACK_ALIGNMENT, 1);
438 0 : glReadPixels(0, 0, 4, 1, GL_RED, GL_FLOAT, nullptr);
439 0 : glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
440 : }
441 :
442 0 : lasthdraccum = lastmillis;
443 : }
444 :
445 0 : if(bloompbo)
446 : {
447 0 : gle::bindvbo(bloompbo);
448 0 : gle::enablecolor();
449 0 : gle::colorpointer(sizeof(GLfloat), nullptr, GL_FLOAT, 1);
450 0 : gle::clearvbo();
451 : }
452 :
453 0 : b0fbo = bloomfbo[3];
454 0 : b0tex = bloomtex[3];
455 0 : b1fbo = bloomfbo[2];
456 0 : b1tex = bloomtex[2];
457 0 : b0w = b1w = bloomw;
458 0 : b0h = b1h = bloomh;
459 :
460 0 : glActiveTexture(GL_TEXTURE2);
461 0 : glBindTexture(GL_TEXTURE_2D, bloomtex[4]);
462 0 : glActiveTexture(GL_TEXTURE0);
463 :
464 0 : glBindFramebuffer(GL_FRAMEBUFFER, b0fbo);
465 0 : glViewport(0, 0, b0w, b0h);
466 0 : SETSHADER(hdrbloom);
467 0 : glBindTexture(GL_TEXTURE_RECTANGLE, ptex);
468 0 : screenquad(pw, ph);
469 :
470 0 : if(bloomblur)
471 : {
472 : std::array<float, maxblurradius+1> blurweights,
473 : bluroffsets;
474 0 : setupblurkernel(bloomblur, blurweights.data(), bluroffsets.data());
475 0 : for(int i = 0; i < (2 + 2*bloomiter); ++i)
476 : {
477 0 : glBindFramebuffer(GL_FRAMEBUFFER, b1fbo);
478 0 : glViewport(0, 0, b1w, b1h);
479 0 : setblurshader(i%2, 1, bloomblur, blurweights.data(), bluroffsets.data(), GL_TEXTURE_RECTANGLE);
480 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
481 0 : screenquad(b0w, b0h);
482 0 : std::swap(b0w, b1w);
483 0 : std::swap(b0h, b1h);
484 0 : std::swap(b0tex, b1tex);
485 0 : std::swap(b0fbo, b1fbo);
486 : }
487 : }
488 :
489 0 : if(aa >= AA_Split)
490 : {
491 0 : glBindFramebuffer(GL_FRAMEBUFFER, outfbo);
492 0 : glViewport(0, 0, vieww, viewh);
493 0 : glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
494 0 : glActiveTexture(GL_TEXTURE1);
495 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
496 0 : glActiveTexture(GL_TEXTURE0);
497 0 : switch(aa)
498 : {
499 0 : case AA_SplitLuma:
500 : {
501 0 : SETSHADER(msaatonemapsplitluma);
502 0 : break;
503 : }
504 0 : case AA_SplitMasked:
505 : {
506 0 : SETSHADER(msaatonemapsplitmasked);
507 0 : setaavelocityparams(GL_TEXTURE3);
508 0 : break;
509 : }
510 0 : default:
511 : {
512 0 : SETSHADER(msaatonemapsplit);
513 0 : break;
514 : }
515 : }
516 0 : screenquad(vieww, viewh, b0w, b0h);
517 : }
518 0 : else if(msaalight <= 1 || !msaatonemap)
519 : {
520 0 : glBindFramebuffer(GL_FRAMEBUFFER, outfbo);
521 0 : glViewport(0, 0, vieww, viewh);
522 0 : glBindTexture(GL_TEXTURE_RECTANGLE, hdrtex);
523 0 : glActiveTexture(GL_TEXTURE1);
524 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
525 0 : glActiveTexture(GL_TEXTURE0);
526 0 : switch(aa)
527 : {
528 0 : case AA_Luma:
529 : {
530 0 : SETSHADER(hdrtonemapluma);
531 0 : break;
532 : }
533 0 : case AA_Masked:
534 : {
535 0 : if(!msaasamples && ghasstencil)
536 : {
537 0 : glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
538 0 : glStencilFunc(GL_EQUAL, 0, 0x80);
539 0 : glEnable(GL_STENCIL_TEST);
540 0 : SETSHADER(hdrtonemap);
541 0 : screenquad(vieww, viewh, b0w, b0h);
542 :
543 0 : glStencilFunc(GL_EQUAL, 0x80, 0x80);
544 0 : SETSHADER(hdrtonemapstencil);
545 0 : screenquad(vieww, viewh, b0w, b0h);
546 0 : glDisable(GL_STENCIL_TEST);
547 0 : goto done; //see bottom of fxn
548 : }
549 0 : SETSHADER(hdrtonemapmasked);
550 0 : setaavelocityparams(GL_TEXTURE3);
551 0 : break;
552 : }
553 0 : default:
554 : {
555 0 : SETSHADER(hdrtonemap);
556 0 : break;
557 : }
558 : }
559 0 : screenquad(vieww, viewh, b0w, b0h);
560 0 : }
561 : else
562 : {
563 0 : bool blit = msaalight > 2 && msaatonemapblit && (!aa || !outfbo);
564 :
565 0 : glBindFramebuffer(GL_FRAMEBUFFER, blit ? msrefractfbo : outfbo);
566 0 : glViewport(0, 0, vieww, viewh);
567 0 : glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mshdrtex);
568 0 : glActiveTexture(GL_TEXTURE1);
569 0 : glBindTexture(GL_TEXTURE_RECTANGLE, b0tex);
570 0 : glActiveTexture(GL_TEXTURE0);
571 :
572 0 : if(blit)
573 : {
574 0 : SETSHADER(msaatonemapsample);
575 : }
576 : else
577 : {
578 0 : switch(aa)
579 : {
580 0 : case AA_Luma:
581 : {
582 0 : SETSHADER(msaatonemapluma);
583 0 : break;
584 : }
585 0 : case AA_Masked:
586 : {
587 0 : SETSHADER(msaatonemapmasked);
588 0 : setaavelocityparams(GL_TEXTURE3);
589 0 : break;
590 : }
591 0 : default:
592 : {
593 0 : SETSHADER(msaatonemap);
594 0 : break;
595 : }
596 : }
597 : }
598 0 : screenquad(vieww, viewh, b0w, b0h);
599 :
600 0 : if(blit)
601 : {
602 0 : glBindFramebuffer(GL_READ_FRAMEBUFFER, msrefractfbo);
603 0 : glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa || !outfbo ? refractfbo : outfbo);
604 0 : glBlitFramebuffer(0, 0, vieww, viewh, 0, 0, vieww, viewh, GL_COLOR_BUFFER_BIT, GL_NEAREST);
605 :
606 0 : if(!outfbo)
607 : {
608 0 : glBindFramebuffer(GL_FRAMEBUFFER, outfbo);
609 0 : glViewport(0, 0, vieww, viewh);
610 0 : if(!blit)
611 : {
612 0 : SETSHADER(hdrnop);
613 : }
614 : else
615 : {
616 0 : switch(aa)
617 : {
618 0 : case AA_Luma:
619 : {
620 0 : SETSHADER(hdrnopluma);
621 0 : break;
622 : }
623 0 : case AA_Masked:
624 : {
625 0 : SETSHADER(hdrnopmasked);
626 0 : setaavelocityparams(GL_TEXTURE3);
627 0 : break;
628 : }
629 0 : default:
630 : {
631 0 : SETSHADER(hdrnop);
632 0 : break;
633 : }
634 : }
635 : }
636 0 : glBindTexture(GL_TEXTURE_RECTANGLE, refracttex);
637 0 : screenquad(vieww, viewh);
638 : }
639 : }
640 : }
641 :
642 0 : done:
643 0 : if(bloompbo)
644 : {
645 0 : gle::disablecolor();
646 : }
647 :
648 0 : endtimer(hdrtimer);
649 0 : }
|