source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/DeferredRenderer.cpp @ 3212

Revision 3212, 34.1 KB checked in by mattausch, 16 years ago (diff)

made ssao parameters more flexible
started to implement lense flare

Line 
1#include "DeferredRenderer.h"
2#include "FrameBufferObject.h"
3#include "RenderState.h"
4#include "SampleGenerator.h"
5#include "Vector3.h"
6#include "Camera.h"
7#include "shaderenv.h"
8#include "Halton.h"
9#include "ShadowMapping.h"
10#include "Light.h"
11#include "ShaderManager.h"
12#include <math.h>
13
14#include <IL/il.h>
15#include <assert.h>
16
17
18#ifdef _CRT_SET
19        #define _CRTDBG_MAP_ALLOC
20        #include <stdlib.h>
21        #include <crtdbg.h>
22
23        // redefine new operator
24        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
25        #define new DEBUG_NEW
26#endif
27
28
29using namespace std;
30
31
32static void startil()
33{
34        ilInit();
35        assert(ilGetError() == IL_NO_ERROR);
36}
37
38
39static void stopil()
40{
41        ilShutDown();
42        assert(ilGetError() == IL_NO_ERROR);
43}
44
45
46namespace CHCDemoEngine
47{
48
49static ShaderProgram *sCgSsaoProgram = NULL;
50static ShaderProgram *sCgGiProgram = NULL;
51
52static ShaderProgram *sCgDeferredProgram = NULL;
53static ShaderProgram *sCgAntiAliasingProgram = NULL;
54static ShaderProgram *sCgDeferredShadowProgram = NULL;
55
56static ShaderProgram *sCgCombineSsaoProgram = NULL;
57static ShaderProgram *sCgCombineIllumProgram = NULL;
58static ShaderProgram *sCgLogLumProgram = NULL;
59static ShaderProgram *sCgToneProgram = NULL;
60static ShaderProgram *sCgDownSampleProgram = NULL;
61static ShaderProgram *sCgScaleDepthProgram = NULL;
62static ShaderProgram *sCgPrepareSsaoProgram = NULL;
63
64
65static GLuint noiseTex2D = 0;
66static GLuint noiseTex1D = 0;
67
68
69// ssao random spherical samples
70static Sample2 samples2[NUM_SAMPLES];
71// number of pcf tabs
72static Sample2 pcfSamples[NUM_PCF_TABS];
73
74
75static float ssaoFilterOffsets[NUM_SSAO_FILTER_SAMPLES * 2];
76static float ssaoFilterWeights[NUM_SSAO_FILTER_SAMPLES];
77
78static GLuint sBurstTex;
79static GLuint sHaloTex[4];
80
81int DeferredRenderer::colorBufferIdx = 0;
82
83
84static void PrepareLenseFlare()
85{
86        sBurstTex = new Texture("burst.jpg");
87
88        Texture(const std::string &filename);
89
90        glEnable(GL_TEXTURE_2D);
91        glGenTextures(1, &sBurstTex);
92        glBindTexture(GL_TEXTURE_2D, sBurstTex);
93               
94        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
95        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
96        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
97        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
98
99        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, randomNormals);
100
101        glBindTexture(GL_TEXTURE_2D, 0);
102        glDisable(GL_TEXTURE_2D);
103
104        delete [] randomNormals;
105
106        cout << "prepared lense flare textures" << endl;
107
108        PrintGLerror("prepare lense flare");
109}
110
111
112/** Helper method that computes the view vectors in the corners of the current view frustum.
113*/
114static void ComputeViewVectors(PerspectiveCamera *cam, Vector3 &bl, Vector3 &br, Vector3 &tl, Vector3 &tr)
115{
116        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
117        cam->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
118
119        bl = Normalize(nbl - fbl);
120        br = Normalize(nbr - fbr);
121        tl = Normalize(ntl - ftl);
122        tr = Normalize(ntr - ftr);
123}
124
125
126static float GaussianDistribution(float x, float y, float rho)
127{
128        float g = 1.0f / sqrtf(2.0f * M_PI * rho * rho);
129    g *= expf( -(x * x + y * y) / (2.0f * rho * rho));
130
131    return g;
132}
133
134
135static void PrintGLerror(char *msg)
136{
137        GLenum errCode;
138        const GLubyte *errStr;
139       
140        if ((errCode = glGetError()) != GL_NO_ERROR)
141        {
142                errStr = gluErrorString(errCode);
143                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
144        }
145}
146
147
148static Sample2 UnitTest(float x, float y, int wi, int he)
149{
150        Sample2 s;
151
152        s.x = float(floor(x * (float)wi - 0.5f) + 1.0f) / (float)wi;
153        s.y = float(floor(y * (float)he - 0.5f) + 1.0f) / (float)he;
154
155        return s;
156}
157
158
159static void ComputeSampleOffsets(float *sampleOffsets,
160                                                                 int imageW, int imageH,
161                                                                 float width,
162                                                                 int samples)
163{
164        const float xoffs = width / (float)imageW;
165        const float yoffs = width / (float)imageH;
166       
167        const int numSamples = (int)sqrt((float)samples);
168        const int startSamples = -numSamples / 2;
169        const int endSamples = numSamples + startSamples - 1;
170        //cout << startSamples << " " << endSamples << endl;
171
172        int idx = 0;
173
174        for (int x = startSamples; x <= endSamples; ++ x)
175        {
176                for (int y = startSamples; y <= endSamples; ++ y)
177                {
178                        sampleOffsets[idx + 0] = (float)x * xoffs;
179                        sampleOffsets[idx + 1] = (float)y * yoffs;
180                        idx += 2;
181                }
182        }
183}
184
185
186void DeferredRenderer::FlipFbos(FrameBufferObject *fbo)
187{
188        fbo->Bind();
189        colorBufferIdx = 3 - colorBufferIdx;
190        glDrawBuffers(1, mrt + colorBufferIdx);
191}
192
193
194void DeferredRenderer::DrawQuad(ShaderProgram *p)
195{
196        if (p) p->Bind();
197
198        // interpolate the view vector
199        Vector3 bl = mCornersView[0];
200        Vector3 br = mCornersView[1];
201        Vector3 tl = mCornersView[2];
202        Vector3 tr = mCornersView[3];
203
204        // note: slightly larger texture could hide ambient occlusion error on border but costs resolution
205        glBegin(GL_QUADS);
206
207        glTexCoord2f(0, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, bl.x, bl.y, bl.z); glVertex2f( .0f,  .0f);
208        glTexCoord2f(1, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, br.x, br.y, br.z); glVertex2f(1.0f,  .0f);
209        glTexCoord2f(1, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tr.x, tr.y, tr.z); glVertex2f(1.0f, 1.0f);
210        glTexCoord2f(0, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tl.x, tl.y, tl.z); glVertex2f( .0f, 1.0f);
211
212        glEnd();
213}
214
215
216/** Generate poisson disc distributed sample points on the unit disc
217*/
218static void GenerateSamples(int sampling)
219{
220        switch (sampling)
221        {
222        case DeferredRenderer::SAMPLING_POISSON:
223                {
224                        PoissonDiscSampleGenerator2 poisson(NUM_SAMPLES, 1.0f);
225                        poisson.Generate((float *)samples2);
226                }
227                break;
228        case DeferredRenderer::SAMPLING_QUADRATIC:
229                {
230                        QuadraticDiscSampleGenerator2 g(NUM_SAMPLES, 1.0f);
231                        g.Generate((float *)samples2);
232                }
233                break;
234        default: // SAMPLING_DEFAULT
235                {
236                        RandomSampleGenerator2 g(NUM_SAMPLES, 1.0f);
237                        g.Generate((float *)samples2);
238                }
239        }
240}
241
242
243static void CreateNoiseTex2D(int w, int h)
244{
245        //GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
246        float *randomNormals = new float[w * h * 3];
247
248        static HaltonSequence halton;
249        float r[2];
250
251        for (int i = 0; i < w * h * 3; i += 3)
252        {
253                // create random samples on a circle
254                r[0] = RandomValue(0, 1);
255                //halton.GetNext(1, r);
256
257                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
258               
259                randomNormals[i + 0] = cos(theta);
260                randomNormals[i + 1] = sin(theta);
261                randomNormals[i + 2] = 0;
262        }
263
264        glEnable(GL_TEXTURE_2D);
265        glGenTextures(1, &noiseTex2D);
266        glBindTexture(GL_TEXTURE_2D, noiseTex2D);
267               
268        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
269        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
270        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
271        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
272
273        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGB, GL_FLOAT, randomNormals);
274
275        glBindTexture(GL_TEXTURE_2D, 0);
276        glDisable(GL_TEXTURE_2D);
277
278        delete [] randomNormals;
279
280        cout << "created noise texture" << endl;
281
282        PrintGLerror("noisetexture");
283}
284
285
286static void CreateNoiseTex1D(int w)
287{
288        float *randomValues = new float[w * 3];
289
290        static HaltonSequence halton;
291       
292        randomValues[0] = randomValues[1] = randomValues[2] = 0;
293
294        for (int i = 3; i < w * 3; i += 3)
295        {
296                // create random samples on a circle
297                randomValues[i + 0] = 20.0f * RandomValue(0, 1) / 512.0f;
298                randomValues[i + 1] = 20.0f * RandomValue(0, 1) / 384.0f;
299                randomValues[i + 2] = 0;
300        }
301
302        glEnable(GL_TEXTURE_2D);
303        glGenTextures(1, &noiseTex1D);
304        glBindTexture(GL_TEXTURE_2D, noiseTex1D);
305               
306        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
307        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
308        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
309        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
310
311        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, 1, 0, GL_RGB, GL_FLOAT, randomValues);
312
313        glBindTexture(GL_TEXTURE_2D, 0);
314        glDisable(GL_TEXTURE_2D);
315
316        delete [] randomValues;
317
318        cout << "created noise texture 1D" << endl;
319
320        PrintGLerror("noisetexture 1D");
321}
322
323
324DeferredRenderer::DeferredRenderer(int w, int h, PerspectiveCamera *cam):
325mWidth(w), mHeight(h),
326mCamera(cam),
327mUseTemporalCoherence(true),
328mRegenerateSamples(true),
329mSamplingMethod(SAMPLING_POISSON),
330mShadingMethod(DEFAULT),
331mIllumFboIndex(0),
332mSortSamples(true),
333mKernelRadius(1e-8f),
334mSampleIntensity(0.2f)
335{
336        ///////////
337        //-- the flip-flop fbos
338
339        //const int dsw = w / 2; const int dsh = h / 2;
340        const int dsw = w; const int dsh = h;
341
342        mIllumFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
343        //mIllumFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
344
345        mFBOs.push_back(mIllumFbo);
346
347        for (int i = 0; i < 4; ++ i)
348        {
349                mIllumFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
350                FrameBufferObject::InitBuffer(mIllumFbo, i);
351        }
352
353
354        ///////////////
355        //-- the downsampled ssao + color bleeding textures:
356        //-- as GI is mostly low frequency, we can use lower resolution toimprove performance
357
358        mDownSampleFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
359        // the downsampled color + depth buffer
360        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
361        // downsample buffer for the normal texture
362        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
363
364
365        for (int i = 0; i < 2; ++ i)
366        {
367                FrameBufferObject::InitBuffer(mDownSampleFbo, i);
368        }
369
370        mFBOs.push_back(mDownSampleFbo);
371
372        // create noise texture for ssao
373        // for performance reasons we use a smaller texture and repeat it over the screen
374        CreateNoiseTex2D(mIllumFbo->GetWidth() / 4, mIllumFbo->GetWidth() / 4);
375       
376        mProjViewMatrix = IdentityMatrix();
377        mOldProjViewMatrix = IdentityMatrix();
378
379        for (int i = 0; i < 4; ++ i)
380        {
381                mCornersView[i] = mOldCornersView[i] = Vector3::UNIT_X();
382        }
383
384        mEyePos = mOldEyePos = Vector3::ZERO();
385
386        InitCg();
387}
388
389
390DeferredRenderer::~DeferredRenderer()
391{
392        CLEAR_CONTAINER(mFBOs);
393
394        glDeleteTextures(1, &noiseTex2D);
395        glDeleteTextures(1, &noiseTex1D);
396}
397
398
399void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
400{
401        mUseTemporalCoherence = temporal;
402}
403
404
405
406void DeferredRenderer::InitCg()
407{       
408        ShaderManager *sm = ShaderManager::GetSingleton();
409
410        sCgDeferredProgram = sm->CreateFragmentProgram("deferred", "main", "deferredFrag");
411        sCgDeferredShadowProgram = sm->CreateFragmentProgram("deferred", "main_shadow", "deferredFragShader");
412        sCgSsaoProgram = sm->CreateFragmentProgram("ssao", "main", "ssaoFrag");
413        sCgGiProgram = sm->CreateFragmentProgram("globillum", "main", "giFrag");
414        sCgCombineIllumProgram = sm->CreateFragmentProgram("globillum", "combine", "combineGi");
415        sCgCombineSsaoProgram = sm->CreateFragmentProgram("combineSsao", "combine", "combineSsao");
416        sCgAntiAliasingProgram = sm->CreateFragmentProgram("antialiasing", "main", "antiAliasing");
417        sCgToneProgram = sm->CreateFragmentProgram("tonemap", "ToneMap", "toneMap");
418        sCgDownSampleProgram = sm->CreateFragmentProgram("deferred", "Output", "Output");
419        sCgScaleDepthProgram = sm->CreateFragmentProgram("deferred", "ScaleDepth", "ScaleDepth");
420        sCgLogLumProgram = sm->CreateFragmentProgram("tonemap", "CalcAvgLogLum", "avgLogLum");
421        sCgPrepareSsaoProgram = sm->CreateFragmentProgram("deferred", "PrepareSsao", "PrepareSsao");
422
423
424        ///////////////////
425        //-- initialize program parameters
426
427        string ssaoParams[] =
428                {"colors", "normals", "oldTex", "noiseTex", "temporalCoherence",
429                 "samples", "bl", "br", "tl", "tr",
430                 "modelViewProj", "oldModelViewProj", "oldEyePos", "oldbl", "oldbr",
431                 "oldtl", "oldtr", "attribsTex", "kernelRadius", "sampleIntensity"};
432        sCgSsaoProgram->AddParameters(ssaoParams, 0, 20);
433       
434        string giParams[] =
435                {"colors", "normals", "noiseTex", "oldSsaoTex", "oldIllumTex",
436                 "temporalCoherence", "samples", "bl", "br", "tl",
437                 "tr", "oldModelViewProj", "modelViewProj"};
438        sCgGiProgram->AddParameters(giParams, 0, 13);
439
440        string toneParams[] = {"colors", "imageKey", "whiteLum", "middleGrey"};
441        sCgToneProgram->AddParameters(toneParams, 0, 4);
442
443
444        ////////////////
445
446        string deferredShadowParams[] =
447                {"colors", "normals", "shadowMap", "noiseTex", "shadowMatrix",
448                 "sampleWidth", "lightDir", "eyePos", "samples", "weights"};
449       
450        sCgDeferredShadowProgram->AddParameters(deferredShadowParams, 0, 10);
451       
452        ////////////////
453
454        string combineIllumParams[] = {"colorsTex", "ssaoTex", "illumTex"};
455        sCgCombineIllumProgram->AddParameters(combineIllumParams, 0, 3);
456
457        ////////////////
458
459        string combineSsaoParams[] =
460                {"colorsTex", "normalsTex", "ssaoTex", "filterOffs",
461                 "filterWeights", "modelViewProj", "bl", "br", "tl", "tr", "w", "h"};
462        sCgCombineSsaoProgram->AddParameters(combineSsaoParams, 0, 12);
463
464        //////////////
465
466        string deferredParams[] = {"colors", "normals", "lightDir"};
467        sCgDeferredProgram->AddParameters(deferredParams, 0, 3);
468
469        ///////////////////
470
471        string aaParams[] = {"colors", "normals", "offsets"};
472        sCgAntiAliasingProgram->AddParameters(aaParams, 0, 3);
473
474        /////////////////////
475
476        string downSampleParams[] = {"colors"};
477        sCgDownSampleProgram->AddParameters(downSampleParams, 0, 1);
478
479        /////////////////////
480
481        string scaleDepthParams[] = {"colors"};
482        sCgScaleDepthProgram->AddParameters(scaleDepthParams, 0, 1);
483
484        ////////////
485
486        sCgLogLumProgram->AddParameter("colors", 0);
487
488        ////////////////
489
490       
491        string prepareSsaoParams[] =
492                {"colorsTex", "normalsTex", "diffVals", "oldTex",
493                 "oldEyePos", "modelViewProj", "oldModelViewProj",
494                 "oldbl", "oldbr", "oldtl", "oldtr"};
495
496        sCgPrepareSsaoProgram->AddParameters(prepareSsaoParams, 0, 11);
497
498
499        ////////////////
500
501        const float filterWidth = 1.0f;
502
503        PoissonDiscSampleGenerator2 poisson(NUM_SSAO_FILTER_SAMPLES, 1.0f);
504        poisson.Generate((float *)ssaoFilterOffsets);
505
506        const float xoffs = (float)filterWidth / mWidth;
507        const float yoffs = (float)filterWidth / mHeight;
508
509        for (int i = 0; i < NUM_SSAO_FILTER_SAMPLES; ++ i)
510        {
511                float x = ssaoFilterOffsets[2 * i + 0];
512                float y = ssaoFilterOffsets[2 * i + 1];
513
514                ssaoFilterWeights[i] = GaussianDistribution(x, y, 1.0f);
515                //ssaoFilterWeights[i] = 1.0f;
516
517                ssaoFilterOffsets[2 * i + 0] *= xoffs;
518                ssaoFilterOffsets[2 * i + 1] *= yoffs;
519        }
520
521
522        /////////
523        //-- pcf tabs for shadowing
524
525        float filterWeights[NUM_PCF_TABS];
526        PoissonDiscSampleGenerator2 poisson2(NUM_PCF_TABS, 1.0f);
527        poisson2.Generate((float *)pcfSamples);
528
529        for (int i = 0; i < NUM_PCF_TABS; ++ i)
530        {
531                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
532        }
533
534        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
535        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
536
537        PrintGLerror("init");
538}
539
540
541void DeferredRenderer::Render(FrameBufferObject *fbo,
542                                                          float tempCohFactor,
543                                                          DirectionalLight *light,
544                                                          bool useToneMapping,
545                                                          bool useAntiAliasing,
546                                                          ShadowMap *shadowMap
547                                                          )
548{
549        InitFrame();
550
551        if (shadowMap)
552                FirstPassShadow(fbo, light, shadowMap);
553        else
554                FirstPass(fbo, light);
555
556        if (mShadingMethod != 0)
557        {
558                // downsample fbo buffers
559                PrepareSsao(fbo);
560        }
561
562        // multisampling is difficult / costly with deferred shading
563        // at least do some edge blurring
564        //if (useAntiAliasing) AntiAliasing(fbo, light);
565
566        switch (mShadingMethod)
567        {
568        case SSAO:
569                ComputeSsao(fbo, tempCohFactor);
570                CombineSsao(fbo);
571                break;
572        case GI:
573                ComputeGlobIllum(fbo, tempCohFactor);
574                CombineIllum(fbo);
575                break;
576        default: // DEFAULT
577                // do nothing: standard deferred shading
578                break;
579        }
580
581        if (useToneMapping)
582        {
583                float imageKey, whiteLum, middleGrey;
584
585                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
586                ToneMap(fbo, imageKey, whiteLum, middleGrey);
587        }
588
589        // multisampling is difficult / costly with deferred shading
590        // at least do some edge blurring
591        if (useAntiAliasing) AntiAliasing(fbo, light); else
592        Output(fbo); // just output the latest buffer
593
594        glEnable(GL_LIGHTING);
595        glDisable(GL_TEXTURE_2D);
596
597        glMatrixMode(GL_PROJECTION);
598        glPopMatrix();
599
600        glMatrixMode(GL_MODELVIEW);
601        glPopMatrix();
602
603        // viewport
604        glPopAttrib();
605
606        FrameBufferObject::Release();
607        ShaderManager::GetSingleton()->DisableFragmentProfile();
608}
609
610
611
612static inline float SqrMag(const Sample2 &s)
613{
614        return (s.x * s.x + s.y * s.y);
615}
616
617
618static inline float SqrDist(const Sample2 &a, const Sample2 &b)
619{
620        float x = a.x - b.x;
621        float y = a.y - b.y;
622       
623        return x * x + y * y;
624}
625
626
627static inline bool lt(const Sample2 &a, const Sample2 &b)
628{
629        return SqrMag(a) < SqrMag(b);
630}
631
632
633void DeferredRenderer::SortSamples()
634{
635        static Sample2 tempSamples[NUM_SAMPLES];
636        static bool checked[NUM_SAMPLES];
637
638        for (int i = 0; i < NUM_SAMPLES; ++ i)
639                checked[i] = false;
640
641        Sample2 currentSample;
642        currentSample.x = 0; currentSample.y = 0;
643        int ns = 0; // the next sample index
644
645        for (int i = 0; i < NUM_SAMPLES; ++ i)
646        {
647                float minLen = 1e20f;
648
649                for (int j = 0; j < NUM_SAMPLES; ++ j)
650                {
651                        if (checked[j]) continue;
652
653                        Sample2 s = samples2[j];
654                        const float len = SqrDist(s, currentSample);
655
656                        if (len < minLen)
657                        {
658                                minLen = len;
659                                ns = j;
660                        }
661                }
662
663                tempSamples[i] = samples2[ns];
664                currentSample = samples2[ns];
665                checked[ns] = true;
666        }
667
668        for (int i = 0; i < NUM_SAMPLES; ++ i)
669                samples2[i] = tempSamples[i];
670}
671
672
673void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo, float tempCohFactor)
674{
675        GLuint colorsTex, normalsTex, attribsTex;
676
677        if (0)
678        {
679                colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
680                normalsTex = fbo->GetColorBuffer(1)->GetTexture();
681        }
682        else
683        {
684                normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
685                colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
686        }
687
688        attribsTex = fbo->GetColorBuffer(2)->GetTexture();
689
690        // flip flop between illumination buffers
691        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
692
693        glPushAttrib(GL_VIEWPORT_BIT);
694        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
695
696        // read the second buffer, write to the first buffer
697        mIllumFbo->Bind();
698        glDrawBuffers(1, mrt + mIllumFboIndex);
699
700        int i = 0;
701
702        sCgSsaoProgram->SetTexture(i ++, colorsTex);
703        sCgSsaoProgram->SetTexture(i ++, normalsTex);
704        sCgSsaoProgram->SetTexture(i ++, oldTex);
705        sCgSsaoProgram->SetTexture(i ++, noiseTex2D);
706
707        sCgSsaoProgram->SetValue1f(i ++, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
708       
709        if (mUseTemporalCoherence || mRegenerateSamples)
710        {
711                mRegenerateSamples = false;
712
713                // q: should we generate new samples or only rotate the old ones?
714                // in the first case, the sample patterns look nicer, but the kernel
715                // needs longer to converge
716                GenerateSamples(mSamplingMethod);
717
718                //if (mSortSamples) { SortSamples(); }
719                sCgSsaoProgram->SetArray2f(i, (float *)samples2, NUM_SAMPLES);
720        }
721       
722        ++ i;
723
724        for (int j = 0; j < 4; ++ j, ++ i)
725                sCgSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
726
727        sCgSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
728        sCgSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
729
730        Vector3 de;
731        de.x = mOldEyePos.x - mEyePos.x;
732        de.y = mOldEyePos.y - mEyePos.y;
733        de.z = mOldEyePos.z - mEyePos.z;
734
735        sCgSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
736
737        for (int j = 0; j < 4; ++ j, ++ i)
738        {
739                sCgSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
740        }
741
742        sCgSsaoProgram->SetTexture(i ++, attribsTex);
743        sCgSsaoProgram->SetValue1f(i ++, mKernelRadius);
744        sCgSsaoProgram->SetValue1f(i ++, mSampleIntensity);
745
746
747        DrawQuad(sCgSsaoProgram);
748
749        glPopAttrib();
750
751        PrintGLerror("ssao first pass");
752}
753
754
755static void SetVertex(float x, float y, float x_offs, float y_offs)
756{
757        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
758        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
759        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
760        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
761        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
762
763        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
764        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
765
766        //glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
767        glVertex2f(x, y);
768}
769
770
771void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo, DirectionalLight *light)
772{
773        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
774        GLuint colorsTex = colorBuffer->GetTexture();
775        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
776
777        // read the second buffer, write to the first buffer
778        //FlipFbos(fbo);
779        // end of the pipeline => just draw image to screen
780        FrameBufferObject::Release();
781
782        // the neighbouring texels
783        float xOffs = 1.0f / fbo->GetWidth();
784        float yOffs = 1.0f / fbo->GetHeight();
785
786        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
787        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
788
789        float offsets[16];
790        int i = 0;
791
792        offsets[i] = -xOffs; offsets[i + 1] =  yOffs; i += 2; // left top
793        offsets[i] =  xOffs; offsets[i + 1] = -yOffs; i += 2; // right bottom
794        offsets[i] =  xOffs; offsets[i + 1] =  yOffs; i += 2; // right top
795        offsets[i] = -xOffs; offsets[i + 1] = -yOffs; i += 2; // left bottom
796        offsets[i] = -xOffs; offsets[i + 1] =    .0f; i += 2; // left
797        offsets[i] =  xOffs; offsets[i + 1] =    .0f; i += 2; // right
798        offsets[i] =    .0f; offsets[i + 1] =  yOffs; i += 2; // top
799        offsets[i] =    .0f; offsets[i + 1] = -yOffs; i += 2; // bottom
800
801        sCgAntiAliasingProgram->SetArray2f(2, offsets, 8);
802
803        DrawQuad(sCgAntiAliasingProgram);
804
805        PrintGLerror("antialiasing");
806}
807
808
809void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
810{
811        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
812        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
813
814        FlipFbos(fbo);
815
816        const Vector3 lightDir = -light->GetDirection();
817
818        sCgDeferredProgram->SetTexture(0, colorsTex);
819        sCgDeferredProgram->SetTexture(1, normalsTex);
820        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
821       
822        DrawQuad(sCgDeferredProgram);
823
824        PrintGLerror("deferred shading");
825}
826
827
828void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
829                                                                                float tempCohFactor)
830{
831#if 0
832        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
833        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
834#else
835        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
836        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
837#endif
838
839        glPushAttrib(GL_VIEWPORT_BIT);
840        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
841
842        // read the second buffer, write to the first buffer
843        mIllumFbo->Bind();
844
845        glDrawBuffers(2, mrt + mIllumFboIndex);
846
847        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
848        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
849
850        int i = 0;
851
852        sCgGiProgram->SetTexture(i ++, colorsTex);
853        sCgGiProgram->SetTexture(i ++, normalsTex);
854        sCgGiProgram->SetTexture(i ++, noiseTex2D);
855        sCgGiProgram->SetTexture(i ++, oldSsaoTex);
856        sCgGiProgram->SetTexture(i ++, oldIllumTex);
857
858        sCgGiProgram->SetValue1f(i ++,
859                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
860
861        if (mUseTemporalCoherence || mRegenerateSamples)
862        {
863                mRegenerateSamples = false;
864
865                // q: should we generate new samples or only rotate the old ones?
866                // in the first case, the sample patterns look nicer, but the kernel
867                // needs longer to converge
868                GenerateSamples(mSamplingMethod);
869
870                sCgGiProgram->SetArray2f(i ++, (float *)samples2, NUM_SAMPLES);
871        }
872
873        Vector3 bl = mCornersView[0];
874        Vector3 br = mCornersView[1];
875        Vector3 tl = mCornersView[2];
876        Vector3 tr = mCornersView[3];
877
878        sCgGiProgram->SetValue3f(i ++, bl.x, bl.y, bl.z);
879        sCgGiProgram->SetValue3f(i ++, br.x, br.y, br.z);
880        sCgGiProgram->SetValue3f(i ++, tl.x, tl.y, tl.z);
881        sCgGiProgram->SetValue3f(i ++, tr.x, tr.y, tr.z);
882
883        sCgGiProgram->SetMatrix(i ++, mOldProjViewMatrix);
884        sCgGiProgram->SetMatrix(i ++, mProjViewMatrix);
885
886
887        DrawQuad(sCgGiProgram);
888
889        glPopAttrib();
890
891        PrintGLerror("globillum first pass");
892}
893
894
895void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
896{
897        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
898
899        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
900        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
901
902        FlipFbos(fbo);
903
904        sCgCombineIllumProgram->SetTexture(0, colorsTex);
905        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
906        sCgCombineIllumProgram->SetTexture(2, illumTex);
907       
908        DrawQuad(sCgCombineIllumProgram);
909
910        PrintGLerror("combine");
911}
912
913
914void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
915{
916        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
917        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
918        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
919       
920        FlipFbos(fbo);
921
922        int i = 0;
923
924        sCgCombineSsaoProgram->SetTexture(i ++, colorsTex);
925        sCgCombineSsaoProgram->SetTexture(i ++, normalsTex);
926        sCgCombineSsaoProgram->SetTexture(i ++, ssaoTex);
927
928        sCgCombineSsaoProgram->SetArray2f(i ++, (float *)ssaoFilterOffsets, NUM_SSAO_FILTER_SAMPLES);
929        sCgCombineSsaoProgram->SetArray1f(i ++, (float *)ssaoFilterWeights, NUM_SSAO_FILTER_SAMPLES);
930       
931        sCgCombineSsaoProgram->SetMatrix(i++, mProjViewMatrix);
932
933        for (int j = 0; j < 4; ++ j, ++ i)
934                sCgCombineSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
935
936        sCgCombineSsaoProgram->SetValue1f(i ++, mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetWidth());
937        sCgCombineSsaoProgram->SetValue1f(i ++, mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetHeight());
938
939        DrawQuad(sCgCombineSsaoProgram);
940       
941        PrintGLerror("combine ssao");
942}
943
944
945void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
946                                                                           DirectionalLight *light,
947                                                                           ShadowMap *shadowMap)
948{
949        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
950        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
951
952        GLuint shadowTex = shadowMap->GetDepthTexture();
953
954        Matrix4x4 shadowMatrix;
955        shadowMap->GetTextureMatrix(shadowMatrix);
956
957
958        FlipFbos(fbo);
959
960        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
961        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
962        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
963        sCgDeferredShadowProgram->SetTexture(3, noiseTex2D);
964        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
965        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
966
967        const Vector3 lightDir = -light->GetDirection();
968        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
969        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
970
971        DrawQuad(sCgDeferredShadowProgram);
972
973        PrintGLerror("deferred shading + shadows");
974}
975
976
977void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
978{
979        if (s != mSamplingMethod)
980        {
981                mSamplingMethod = s;
982                mRegenerateSamples = true;
983        }
984}
985
986
987void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
988{
989        if (s != mShadingMethod)
990        {
991                mShadingMethod = s;
992                mRegenerateSamples = true;
993        }
994}
995
996
997#if TODO
998
999void DeferredRenderer::SetNumSamples(int numSamples)
1000{
1001        mNumSamples = numSamples;
1002}
1003
1004#endif
1005
1006
1007void DeferredRenderer::SetSampleIntensity(float sampleIntensity)
1008{
1009        mSampleIntensity = sampleIntensity;
1010}
1011
1012
1013void DeferredRenderer::SetKernelRadius(float kernelRadius)
1014{
1015        mKernelRadius = kernelRadius;
1016}
1017
1018
1019void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
1020                                                                                         DirectionalLight *light,
1021                                                                                         float &imageKey,
1022                                                                                         float &whiteLum,
1023                                                                                         float &middleGrey)
1024{
1025        // hack: estimate value where sky burns out
1026        whiteLum = log(WHITE_LUMINANCE);
1027       
1028        ////////////////////
1029        //-- linear interpolate brightness key depending on the current sun position
1030
1031        const float minKey = 0.09f;
1032        const float maxKey = 0.36f;
1033
1034        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
1035        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
1036
1037
1038        //////////
1039        //-- compute avg loglum
1040
1041        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1042        GLuint colorsTex = colorBuffer->GetTexture();
1043
1044        FlipFbos(fbo);
1045       
1046        sCgLogLumProgram->SetTexture(0, colorsTex);
1047        DrawQuad(sCgLogLumProgram);
1048       
1049        PrintGLerror("ToneMapParams");
1050
1051
1052        ///////////////////
1053        //-- compute avg loglum in scene using mipmapping
1054
1055        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
1056        glGenerateMipmapEXT(GL_TEXTURE_2D);
1057}
1058
1059
1060static void ExportData(float *data, int w, int h)
1061{
1062        startil();
1063
1064        cout << "w: " << w << " h: " << h << endl;
1065        ILstring filename = ILstring("downsample2.jpg");
1066        ilRegisterType(IL_FLOAT);
1067
1068        const int depth = 1;
1069        const int bpp = 4;
1070
1071        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
1072        {
1073                cerr << "IL error " << ilGetError() << endl;
1074                stopil();
1075                return;
1076        }
1077
1078        if (!ilSaveImage(filename))
1079        {
1080                cerr << "TGA write error " << ilGetError() << endl;
1081        }
1082
1083        stopil();
1084}
1085
1086
1087void DeferredRenderer::PrepareSsao(FrameBufferObject *fbo)
1088{
1089        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1090        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
1091        GLuint diffVals = fbo->GetColorBuffer(2)->GetTexture();
1092        // flip flop between illumination buffers
1093        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
1094
1095        int i = 0;
1096
1097        sCgPrepareSsaoProgram->SetTexture(i ++, colorsTex);
1098        sCgPrepareSsaoProgram->SetTexture(i ++, normalsTex);
1099        sCgPrepareSsaoProgram->SetTexture(i ++, diffVals);
1100        sCgPrepareSsaoProgram->SetTexture(i ++, oldTex);
1101
1102        Vector3 de;
1103        de.x = mOldEyePos.x - mEyePos.x;
1104        de.y = mOldEyePos.y - mEyePos.y;
1105        de.z = mOldEyePos.z - mEyePos.z;
1106
1107        sCgPrepareSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
1108
1109        sCgPrepareSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
1110        sCgPrepareSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
1111
1112        for (int j = 0; j < 4; ++ j, ++ i)
1113                sCgPrepareSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
1114
1115        glPushAttrib(GL_VIEWPORT_BIT);
1116        glViewport(0, 0, mDownSampleFbo->GetWidth(), mDownSampleFbo->GetHeight());
1117       
1118        mDownSampleFbo->Bind();
1119
1120        // prepare downsampled depth and normal texture for ssao
1121        glDrawBuffers(2, mrt);
1122
1123        DrawQuad(sCgPrepareSsaoProgram);
1124       
1125        glPopAttrib();
1126        PrintGLerror("prepareSsao");
1127}
1128
1129
1130void DeferredRenderer::DownSample(FrameBufferObject *fbo,
1131                                                                  int bufferIdx,
1132                                                                  FrameBufferObject *downSampleFbo,
1133                                                                  int downSampleBufferIdx,
1134                                                                  ShaderProgram *program)
1135{
1136        ColorBufferObject *buffer = fbo->GetColorBuffer(bufferIdx);
1137        GLuint tex = buffer->GetTexture();
1138
1139        glPushAttrib(GL_VIEWPORT_BIT);
1140        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
1141       
1142        downSampleFbo->Bind();
1143
1144        program->SetTexture(0, tex);
1145        glDrawBuffers(1, mrt + downSampleBufferIdx);
1146
1147        DrawQuad(program);
1148       
1149        glPopAttrib();
1150        PrintGLerror("downsample");
1151}
1152
1153
1154void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
1155                                                           float imageKey,
1156                                                           float whiteLum,
1157                                                           float middleGrey)
1158{
1159        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1160        GLuint colorsTex = colorBuffer->GetTexture();
1161        //FrameBufferObject::Release();
1162
1163        FlipFbos(fbo);
1164
1165        sCgToneProgram->SetTexture(0, colorsTex);
1166        sCgToneProgram->SetValue1f(1, imageKey);
1167        sCgToneProgram->SetValue1f(2, whiteLum);
1168        sCgToneProgram->SetValue1f(3, middleGrey);
1169
1170        DrawQuad(sCgToneProgram);
1171
1172        PrintGLerror("ToneMap");
1173}
1174
1175
1176void DeferredRenderer::Output(FrameBufferObject *fbo)
1177{
1178        glPushAttrib(GL_VIEWPORT_BIT);
1179        glViewport(0, 0, fbo->GetWidth(), fbo->GetHeight());
1180       
1181        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1182        GLuint colorsTex = colorBuffer->GetTexture();
1183
1184        sCgDownSampleProgram->SetTexture(0, colorsTex);
1185
1186        FrameBufferObject::Release();
1187        DrawQuad(sCgDownSampleProgram);
1188
1189        PrintGLerror("output");
1190}
1191
1192
1193void DeferredRenderer::InitFrame()
1194{
1195        for (int i = 0; i < 4; ++ i)
1196                mOldCornersView[i] = mCornersView[i];
1197
1198        mOldProjViewMatrix = mProjViewMatrix;
1199        mOldEyePos = mEyePos;
1200        mEyePos = mCamera->GetPosition();
1201
1202        // hack: temporarily change far to improve precision
1203        const float oldFar = mCamera->GetFar();
1204        const float oldNear = mCamera->GetNear();
1205       
1206
1207        Matrix4x4 matViewing, matProjection;
1208
1209
1210        ///////////////////
1211
1212
1213        mCamera->GetViewOrientationMatrix(matViewing);
1214        mCamera->GetProjectionMatrix(matProjection);
1215
1216        mProjViewMatrix = matViewing * matProjection;
1217        ComputeViewVectors(mCamera, mCornersView[0], mCornersView[1], mCornersView[2], mCornersView[3]);
1218       
1219
1220        // switch roles of old and new fbo
1221        // the algorihm uses two input fbos, where the one
1222        // contais the color buffer from the last frame,
1223        // the other one will be written
1224
1225        mIllumFboIndex = 2 - mIllumFboIndex;
1226       
1227        // enable fragment shading
1228        ShaderManager::GetSingleton()->EnableFragmentProfile();
1229
1230        glDisable(GL_ALPHA_TEST);
1231        glDisable(GL_TEXTURE_2D);
1232        glDisable(GL_LIGHTING);
1233        glDisable(GL_BLEND);
1234        glDisable(GL_DEPTH_TEST);
1235
1236        glPolygonMode(GL_FRONT, GL_FILL);
1237
1238        glMatrixMode(GL_PROJECTION);
1239        glPushMatrix();
1240        glLoadIdentity();
1241
1242        gluOrtho2D(0, 1, 0, 1);
1243
1244
1245        glMatrixMode(GL_MODELVIEW);
1246        glPushMatrix();
1247        glLoadIdentity();
1248
1249       
1250        glPushAttrib(GL_VIEWPORT_BIT);
1251        glViewport(0, 0, mWidth, mHeight);
1252
1253        // revert to old far and near plane
1254        mCamera->SetFar(oldFar);
1255        mCamera->SetNear(oldNear);
1256}
1257
1258
1259void DeferredRenderer::LenseFlare(FrameBufferObject *fbo)
1260{
1261        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1262
1263        FlipFbos(fbo);
1264
1265        sCgLenseFlareProgram->SetTexture(0, colorsTex);
1266        sCgLenseFlareProgram->SetTexture(1, sBurstTex);
1267        sCgLenseFlareProgram->SetTexture(2, sHaloTex[0]);
1268        sCgLenseFlareProgram->SetTexture(3, sHaloTex[1]);
1269        sCgLenseFlareProgram->SetValue1f(4, sHaloTex[2]);
1270        sCgLenseFlareProgram->SetValue1f(5, sHaloTex[3]);
1271
1272        DrawQuad(sCgLenseFlareProgram);
1273
1274        PrintGLerror("LenseFlare");
1275}
1276
1277
1278} // namespace
Note: See TracBrowser for help on using the repository browser.