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

Revision 3319, 40.3 KB checked in by mattausch, 15 years ago (diff)
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 "Texture.h"
13
14#include <math.h>
15
16#include <IL/il.h>
17#include <assert.h>
18
19
20#ifdef _CRT_SET
21        #define _CRTDBG_MAP_ALLOC
22        #include <stdlib.h>
23        #include <crtdbg.h>
24
25        // redefine new operator
26        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
27        #define new DEBUG_NEW
28#endif
29
30
31using namespace std;
32
33
34static void startil()
35{
36        ilInit();
37        assert(ilGetError() == IL_NO_ERROR);
38}
39
40
41static void stopil()
42{
43        ilShutDown();
44        assert(ilGetError() == IL_NO_ERROR);
45}
46
47
48namespace CHCDemoEngine
49{
50
51static ShaderProgram *sCgSsaoProgram = NULL;
52static ShaderProgram *sCgGiProgram = NULL;
53
54static ShaderProgram *sCgDeferredProgram = NULL;
55static ShaderProgram *sCgAntiAliasingProgram = NULL;
56static ShaderProgram *sCgDeferredShadowProgram = NULL;
57
58static ShaderProgram *sCgCombineSsaoProgram = NULL;
59static ShaderProgram *sCgFilterSsaoProgram = NULL;
60static ShaderProgram *sCgCombineIllumProgram = NULL;
61static ShaderProgram *sCgLogLumProgram = NULL;
62static ShaderProgram *sCgToneProgram = NULL;
63static ShaderProgram *sCgDownSampleProgram = NULL;
64static ShaderProgram *sCgScaleDepthProgram = NULL;
65static ShaderProgram *sCgPrepareSsaoProgram = NULL;
66static ShaderProgram *sCgLenseFlareProgram = NULL;
67
68static ShaderProgram *sCgDOFProgram = NULL;
69
70
71static GLuint noiseTex2D = 0;
72static GLuint noiseTex1D = 0;
73
74
75// ssao random spherical samples
76static Sample2 samples2[NUM_SAMPLES];
77//#define NUM_PRECOMPUTED_SAMPLES 240
78//static Sample2 samples2[NUM_PRECOMPUTED_SAMPLES];
79// pcf samples
80static Sample2 pcfSamples[NUM_PCF_TABS];
81// dof samples
82static Sample2 dofSamples[NUM_DOF_TABS];
83
84static Texture *sHaloTex[5];
85
86int DeferredRenderer::colorBufferIdx = 0;
87
88
89
90
91/** Helper method that computes the view vectors in the corners of the current view frustum.
92*/
93static void ComputeViewVectors(PerspectiveCamera *cam,
94                                                           Vector3 &bl,
95                                                           Vector3 &br,
96                                                           Vector3 &tl,
97                                                           Vector3 &tr)
98{
99        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
100        cam->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
101
102        bl = Normalize(nbl - fbl);
103        br = Normalize(nbr - fbr);
104        tl = Normalize(ntl - ftl);
105        tr = Normalize(ntr - ftr);
106}
107
108
109static float GaussianDistribution(float x, float y, float rho)
110{
111        float g = 1.0f / sqrtf(2.0f * M_PI * rho * rho);
112    g *= expf( -(x * x + y * y) / (2.0f * rho * rho));
113
114    return g;
115}
116
117
118static void PrintGLerror(char *msg)
119{
120        GLenum errCode;
121        const GLubyte *errStr;
122       
123        if ((errCode = glGetError()) != GL_NO_ERROR)
124        {
125                errStr = gluErrorString(errCode);
126                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
127        }
128}
129
130
131static Sample2 UnitTest(float x, float y, int wi, int he)
132{
133        Sample2 s;
134
135        s.x = float(floor(x * (float)wi - 0.5f) + 1.0f) / (float)wi;
136        s.y = float(floor(y * (float)he - 0.5f) + 1.0f) / (float)he;
137
138        return s;
139}
140
141
142static void ComputeSampleOffsets(float *sampleOffsets,
143                                                                 int imageW, int imageH,
144                                                                 float width,
145                                                                 int samples)
146{
147        const float xoffs = width / (float)imageW;
148        const float yoffs = width / (float)imageH;
149       
150        const int numSamples = (int)sqrt((float)samples);
151        const int startSamples = -numSamples / 2;
152        const int endSamples = numSamples + startSamples - 1;
153        //cout << startSamples << " " << endSamples << endl;
154
155        int idx = 0;
156
157        for (int x = startSamples; x <= endSamples; ++ x)
158        {
159                for (int y = startSamples; y <= endSamples; ++ y)
160                {
161                        sampleOffsets[idx + 0] = (float)x * xoffs;
162                        sampleOffsets[idx + 1] = (float)y * yoffs;
163                        idx += 2;
164                }
165        }
166}
167
168
169void DeferredRenderer::FlipFbos(FrameBufferObject *fbo)
170{
171        fbo->Bind();
172        colorBufferIdx = 3 - colorBufferIdx;
173        glDrawBuffers(1, mrt + colorBufferIdx);
174}
175
176
177void DeferredRenderer::DrawQuad(ShaderProgram *p)
178{
179        if (p) p->Bind();
180
181        // interpolate the view vector
182        Vector3 bl = mCornersView[0];
183        Vector3 br = mCornersView[1];
184        Vector3 tl = mCornersView[2];
185        Vector3 tr = mCornersView[3];
186
187        // note: slightly larger texture could hide ambient occlusion error on border but costs resolution
188        glBegin(GL_QUADS);
189
190        glTexCoord2f(0, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, bl.x, bl.y, bl.z); glVertex2f( .0f,  .0f);
191        glTexCoord2f(1, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, br.x, br.y, br.z); glVertex2f(1.0f,  .0f);
192        glTexCoord2f(1, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tr.x, tr.y, tr.z); glVertex2f(1.0f, 1.0f);
193        glTexCoord2f(0, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tl.x, tl.y, tl.z); glVertex2f( .0f, 1.0f);
194
195        glEnd();
196}
197
198
199/** Generate poisson disc distributed sample points on the unit disc
200*/
201static void GenerateSamples(int sampling)
202{
203        switch (sampling)
204        {
205        case DeferredRenderer::SAMPLING_POISSON:
206                {
207                        static PoissonDiscSampleGenerator2D poisson(NUM_SAMPLES, 1.0f);
208                        poisson.Generate((float *)samples2);
209                }
210                break;
211        case DeferredRenderer::SAMPLING_QUADRATIC:
212                {
213                        //static QuadraticDiscSampleGenerator2D g(NUM_PRECOMPUTED_SAMPLES, 1.0f);
214                        static QuadraticDiscSampleGenerator2D g(NUM_SAMPLES, 1.0f);
215                        g.Generate((float *)samples2);
216                }
217                break;
218        default: // SAMPLING_DEFAULT
219                {
220                        static RandomSampleGenerator2D g(NUM_SAMPLES, 1.0f);
221                        g.Generate((float *)samples2);
222                }
223        }
224}
225
226
227static void CreateNoiseTex2D(int w, int h)
228{
229        //GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
230        Vector3 *randomNormals = new Vector3[w * h];
231
232        for (int i = 0; i < w * h; ++ i)
233        {
234                // create random samples on a circle
235                const float r = RandomValue(0, 1);
236
237                const float theta = 2.0f * acos(sqrt(1.0f - r));
238                //randomNormals[i] = Vector3(cos(theta), sin(theta), 0);
239                randomNormals[i] = Vector3(RandomValue(-M_PI, M_PI), 0, 0);
240                //Normalize(randomNormals[i]);
241        }
242
243
244        glEnable(GL_TEXTURE_2D);
245        glGenTextures(1, &noiseTex2D);
246        glBindTexture(GL_TEXTURE_2D, noiseTex2D);
247               
248        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
249        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
250        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
251        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
252        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
253        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
254
255        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGB, GL_FLOAT, (float *)randomNormals);
256
257        glBindTexture(GL_TEXTURE_2D, 0);
258        glDisable(GL_TEXTURE_2D);
259
260        delete [] randomNormals;
261
262        cout << "created noise texture" << endl;
263
264        PrintGLerror("noisetexture");
265}
266
267
268static void PrepareLenseFlare()
269{
270        string textures[] = {"flare4.tga", "lens2.jpg", "lens3.jpg", "lens4.jpg", "lens1.jpg"};
271
272        // todo: delete halo textures
273        for (int i = 0; i < 5; ++ i)
274        {
275                sHaloTex[i] = new Texture(model_path + textures[i]);
276
277                sHaloTex[i]->SetBoundaryModeS(Texture::BORDER);
278                sHaloTex[i]->SetBoundaryModeT(Texture::BORDER);
279
280                sHaloTex[i]->Create();
281        }
282
283        cout << "prepared lense flare textures" << endl;
284
285        PrintGLerror("prepare lense flare");
286}
287
288
289DeferredRenderer::DeferredRenderer(int w, int h,
290                                                                   PerspectiveCamera *cam,
291                                                                   bool ssaoUseFullResolution):
292mWidth(w), mHeight(h),
293mCamera(cam),
294mUseTemporalCoherence(true),
295mRegenerateSamples(true),
296mSamplingMethod(SAMPLING_POISSON),
297mShadingMethod(DEFAULT),
298mIllumFboIndex(0),
299mSortSamples(true),
300mKernelRadius(1e-8f),
301mSampleIntensity(0.2f),
302mSunVisiblePixels(0),
303mSavedFrameNumber(-1),
304mSavedFrameSuffix(""),
305mMaxDistance(1e6f),
306mTempCohFactor(.0f),
307mUseToneMapping(false),
308mUseAntiAliasing(false),
309mUseDepthOfField(false),
310mSsaoUseFullResolution(ssaoUseFullResolution),
311mMaxConvergence(2000.0f),
312mSpatialWeight(.0f)
313{
314        ///////////
315        //-- the flip-flop fbos
316
317        int downSampledWidth, downSampledHeight;
318
319        if (mSsaoUseFullResolution)
320        {
321                downSampledWidth = w; downSampledHeight = h;
322                cout << "using full resolution ssao" << endl;
323        }
324        else
325        {
326                downSampledWidth = w / 2; downSampledHeight = h / 2;
327                cout << "using half resolution ssao" << endl;
328        }
329
330
331        /////////
332        //-- the illumination fbo is either half size or full size
333
334        mIllumFbo = new FrameBufferObject(downSampledWidth, downSampledHeight, FrameBufferObject::DEPTH_NONE);
335        mFBOs.push_back(mIllumFbo);
336
337        for (int i = 0; i < 4; ++ i)
338        {
339                mIllumFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
340                FrameBufferObject::InitBuffer(mIllumFbo, i);
341        }
342
343
344        ///////////////
345        //-- the downsampled ssao + color bleeding textures:
346        //-- as GI is mostly low frequency, we can use lower resolution to improve performance
347
348        mDownSampleFbo = new FrameBufferObject(downSampledWidth, downSampledHeight, FrameBufferObject::DEPTH_NONE);
349        // the downsampled color + depth buffer
350        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
351        // downsample buffer for the normal texture
352        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
353
354        for (int i = 0; i < 2; ++ i)
355        {
356                FrameBufferObject::InitBuffer(mDownSampleFbo, i);
357        }
358
359        mFBOs.push_back(mDownSampleFbo);
360
361
362        /////////
363        //-- temporal buffer
364
365        mTempFbo = new FrameBufferObject(mWidth, mHeight, FrameBufferObject::DEPTH_NONE);
366        mFBOs.push_back(mTempFbo);
367
368        mTempFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
369        FrameBufferObject::InitBuffer(mTempFbo, 0);
370       
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        PrepareLenseFlare();
387
388        InitCg();
389}
390
391
392DeferredRenderer::~DeferredRenderer()
393{
394        CLEAR_CONTAINER(mFBOs);
395
396        glDeleteTextures(1, &noiseTex2D);
397        glDeleteTextures(1, &noiseTex1D);
398}
399
400
401void DeferredRenderer::InitCg()
402{       
403        ShaderManager *sm = ShaderManager::GetSingleton();
404
405        sCgDeferredProgram = sm->CreateFragmentProgram("deferred", "main", "DeferredFrag");
406        sCgDeferredShadowProgram = sm->CreateFragmentProgram("deferred", "main_shadow", "DeferredFragShadow");
407        sCgSsaoProgram = sm->CreateFragmentProgram("ssao", "main", "SsaoFrag");
408        sCgGiProgram = sm->CreateFragmentProgram("globillum", "main", "GiFrag");
409        sCgCombineIllumProgram = sm->CreateFragmentProgram("globillum", "combine", "CombineGi");
410
411        if (mSsaoUseFullResolution)
412        {
413                sCgFilterSsaoProgram = sm->CreateFragmentProgram("combineSsaoSep", "FilterSsaoFullRes", "FilterSsao");
414        }
415        else
416        {
417                sCgFilterSsaoProgram = sm->CreateFragmentProgram("combineSsaoSep", "FilterSsaoHalfRes", "FilterSsao");
418        }
419       
420        sCgCombineSsaoProgram = sm->CreateFragmentProgram("combineSsaoSep", "CombineSsao", "CombineSsao");
421        sCgAntiAliasingProgram = sm->CreateFragmentProgram("antialiasing", "main", "AntiAliasing");
422        sCgToneProgram = sm->CreateFragmentProgram("tonemap", "ToneMap", "ToneMap");
423        sCgDownSampleProgram = sm->CreateFragmentProgram("deferred", "Output", "Output");
424        sCgScaleDepthProgram = sm->CreateFragmentProgram("deferred", "ScaleDepth", "ScaleDepth");
425        sCgLogLumProgram = sm->CreateFragmentProgram("tonemap", "CalcAvgLogLum", "AvgLogLum");
426        sCgPrepareSsaoProgram = sm->CreateFragmentProgram("deferred", "PrepareSsao", "PrepareSsao");
427        sCgLenseFlareProgram = sm->CreateFragmentProgram("lenseFlare", "LenseFlare", "LenseFlare");
428        sCgDOFProgram = sm->CreateFragmentProgram("depthOfField", "DepthOfField", "DepthOfField");
429
430
431        ///////////////////
432        //-- initialize program parameters
433
434        string ssaoParams[] =
435                {"colors", "normals", "oldTex", "noiseTex", "temporalCoherence",
436                 "samples", "bl", "br", "tl", "tr",
437                 "modelViewProj", "oldModelViewProj", "oldEyePos", "oldbl", "oldbr",
438                 "oldtl", "oldtr", "attribsTex", "kernelRadius", "sampleIntensity"};
439        sCgSsaoProgram->AddParameters(ssaoParams, 0, 20);
440       
441        string giParams[] =
442                {"colors", "normals", "noiseTex", "oldSsaoTex", "oldIllumTex",
443                 "temporalCoherence", "samples", "bl", "br", "tl",
444                 "tr", "oldModelViewProj", "modelViewProj"};
445
446        sCgGiProgram->AddParameters(giParams, 0, 13);
447
448        string toneParams[] = {"colors", "imageKey", "whiteLum", "middleGrey"};
449        sCgToneProgram->AddParameters(toneParams, 0, 4);
450
451
452        ////////////////
453
454        string deferredShadowParams[] =
455                {"colors", "normals", "shadowMap", "noiseTex", "shadowMatrix",
456                 "sampleWidth", "lightDir", "eyePos", "samples", "weights"};
457       
458        sCgDeferredShadowProgram->AddParameters(deferredShadowParams, 0, 10);
459       
460        ////////////////
461
462        string combineIllumParams[] = {"colorsTex", "ssaoTex", "illumTex"};
463        sCgCombineIllumProgram->AddParameters(combineIllumParams, 0, 3);
464
465        ////////////////
466
467        string combineSsaoParams[] =
468                //{"colorsTex", "ssaoTex", "bl", "br", "tl", "tr", "res", "maxConvergence"};
469                {"colorsTex", "ssaoTex", "bl", "br", "tl", "tr", "res", "maxConvergence", "spatialWeight"};
470
471        //sCgCombineSsaoProgram->AddParameters(combineSsaoParams, 0, 13);
472        sCgCombineSsaoProgram->AddParameters(combineSsaoParams, 0, 9);
473
474       
475        ////////////////
476
477        string filterSsaoParams[] =
478                {"colorsTex", "ssaoTex", "bl", "br", "tl", "tr", "res", "maxConvergence", "spatialWeight"};
479
480        sCgFilterSsaoProgram->AddParameters(filterSsaoParams, 0, 9);
481
482
483        //////////////
484
485        string deferredParams[] = {"colors", "normals", "lightDir"};
486        sCgDeferredProgram->AddParameters(deferredParams, 0, 3);
487
488        ///////////////////
489
490        string aaParams[] = {"colors", "normals", "offsets"};
491        sCgAntiAliasingProgram->AddParameters(aaParams, 0, 3);
492
493        /////////////////////
494
495        string downSampleParams[] = {"colors"};
496        sCgDownSampleProgram->AddParameters(downSampleParams, 0, 1);
497
498        /////////////////////
499
500        string scaleDepthParams[] = {"colors"};
501        sCgScaleDepthProgram->AddParameters(scaleDepthParams, 0, 1);
502
503        ////////////
504
505        sCgLogLumProgram->AddParameter("colors", 0);
506
507        ////////////////
508
509       
510        string prepareSsaoParams[] =
511                {"colorsTex", "normalsTex", "diffVals", "oldTex",
512                 "oldEyePos", "modelViewProj", "oldModelViewProj",
513                 "oldbl", "oldbr", "oldtl", "oldtr"};
514
515        sCgPrepareSsaoProgram->AddParameters(prepareSsaoParams, 0, 11);
516
517
518        ////////////////
519       
520        string lenseFlareParams[] =
521                {"colorsTex", "flareTex1", "flareTex2", "flareTex3", "flareTex4",
522                 "flareTex5", "vectorToLight", "distanceToLight", "sunVisiblePixels"};
523
524        sCgLenseFlareProgram->AddParameters(lenseFlareParams, 0, 9);
525
526       
527        ////////////////
528       
529        string dofParams[] = {"colorsTex", "filterOffs", "sceneRange", "zFocus"};
530
531        sCgDOFProgram->AddParameters(dofParams, 0, 4);
532
533
534        /////////
535        //-- pcf tabs for shadowing
536
537        float filterWeights[NUM_PCF_TABS];
538        PoissonDiscSampleGenerator2D poisson2(NUM_PCF_TABS, 1.0f);
539        poisson2.Generate((float *)pcfSamples);
540
541        for (int i = 0; i < NUM_PCF_TABS; ++ i)
542        {
543                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
544        }
545
546        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
547        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
548
549
550        /////////
551        //-- pcf tabs for depth of field
552
553        // todo matt: it is stupid to put num samples and width of kernel into constructor => change this!!!
554        PoissonDiscSampleGenerator2D poisson3(NUM_DOF_TABS, 1.0f);
555        poisson3.Generate((float *)dofSamples);
556
557        for (int i = 0; i < NUM_DOF_TABS; ++ i)
558        {
559                dofSamples[i].x *= 1.0f / mWidth;
560                dofSamples[i].y *= 1.0f / mHeight;
561        }
562
563        //float dofWeights[NUM_PCF_TABS];
564        //sCgDOFProgram->SetArray1f(2, (float *)dofWeights, NUM_DOF_TABS);
565
566        PrintGLerror("init");
567}
568
569
570void DeferredRenderer::Render(FrameBufferObject *fbo,
571                                                          DirectionalLight *light,
572                                                          ShadowMap *shadowMap
573                                                          )
574{
575        InitFrame();
576
577        if (shadowMap)
578                FirstPassShadow(fbo, light, shadowMap);
579        else
580                FirstPass(fbo, light);
581
582        if (mShadingMethod != 0)
583        {
584                PrepareSsao(fbo); // downsample fbo buffers
585        }
586
587        // q: use antialiasing before or after ssao?
588        //if (useAntiAliasing) AntiAliasing(fbo, light);
589
590        switch (mShadingMethod)
591        {
592        case SSAO:
593                ComputeSsao(fbo, mTempCohFactor);
594                FilterSsao(fbo);
595                CombineSsao(fbo);
596                break;
597        case GI:
598                ComputeGlobIllum(fbo, mTempCohFactor);
599                CombineIllum(fbo);
600                break;
601        default:
602                // do nothing: standard deferred shading
603                break;
604        }
605
606        /// depth of field
607        if (mUseDepthOfField)
608        {
609                DepthOfField(fbo);
610        }
611
612        if (mUseToneMapping)
613        {
614                float imageKey, whiteLum, middleGrey;
615
616                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
617                ToneMap(fbo, imageKey, whiteLum, middleGrey);
618        }
619
620        /// compute lense flare
621        LenseFlare(fbo, light);
622
623        const bool saveFrame = (mSavedFrameNumber != -1);
624        const bool displayAfterAA = !saveFrame;
625
626        // multisampling is difficult / costly with deferred shading
627        // at least do some edge blurring
628        if (mUseAntiAliasing) AntiAliasing(fbo, light, displayAfterAA);
629       
630        /// store the current frame
631        if (saveFrame) SaveFrame(fbo);
632
633        // if it hasn't been done yet => just output the latest buffer
634        if (!mUseAntiAliasing || !displayAfterAA)
635                Output(fbo);
636
637        glEnable(GL_LIGHTING);
638        glDisable(GL_TEXTURE_2D);
639
640        glMatrixMode(GL_PROJECTION);
641        glPopMatrix();
642
643        glMatrixMode(GL_MODELVIEW);
644        glPopMatrix();
645
646        // viewport
647        glPopAttrib();
648
649        FrameBufferObject::Release();
650        ShaderManager::GetSingleton()->DisableFragmentProfile();
651}
652
653
654static inline float SqrMag(const Sample2 &s)
655{
656        return (s.x * s.x + s.y * s.y);
657}
658
659
660static inline float SqrDist(const Sample2 &a, const Sample2 &b)
661{
662        float x = a.x - b.x;
663        float y = a.y - b.y;
664       
665        return x * x + y * y;
666}
667
668
669static inline bool lt(const Sample2 &a, const Sample2 &b)
670{
671        return SqrMag(a) < SqrMag(b);
672}
673
674
675void DeferredRenderer::SortSamples()
676{
677        static Sample2 tempSamples[NUM_SAMPLES];
678        static bool checked[NUM_SAMPLES];
679
680        for (int i = 0; i < NUM_SAMPLES; ++ i)
681                checked[i] = false;
682
683        Sample2 currentSample;
684        currentSample.x = 0; currentSample.y = 0;
685        int ns = 0; // the next sample index
686
687        for (int i = 0; i < NUM_SAMPLES; ++ i)
688        {
689                float minLen = 1e20f;
690
691                for (int j = 0; j < NUM_SAMPLES; ++ j)
692                {
693                        if (checked[j]) continue;
694
695                        Sample2 s = samples2[j];
696                        const float len = SqrDist(s, currentSample);
697
698                        if (len < minLen)
699                        {
700                                minLen = len;
701                                ns = j;
702                        }
703                }
704
705                tempSamples[i] = samples2[ns];
706                currentSample = samples2[ns];
707                checked[ns] = true;
708        }
709
710        for (int i = 0; i < NUM_SAMPLES; ++ i)
711                samples2[i] = tempSamples[i];
712}
713
714
715void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo, float tempCohFactor)
716{
717        GLuint colorsTex, normalsTex, attribsTex;
718
719        if (0)
720        {
721                colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
722                normalsTex = fbo->GetColorBuffer(1)->GetTexture();
723        }
724        else
725        {
726                normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
727                colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
728        }
729
730        attribsTex = fbo->GetColorBuffer(2)->GetTexture();
731
732        // flip flop between illumination buffers
733        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
734
735        glPushAttrib(GL_VIEWPORT_BIT);
736        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
737
738        // read the second buffer, write to the first buffer
739        mIllumFbo->Bind();
740        glDrawBuffers(1, mrt + mIllumFboIndex);
741
742        int i = 0;
743
744        sCgSsaoProgram->SetTexture(i ++, colorsTex);
745        sCgSsaoProgram->SetTexture(i ++, normalsTex);
746        sCgSsaoProgram->SetTexture(i ++, oldTex);
747        sCgSsaoProgram->SetTexture(i ++, noiseTex2D);
748
749        sCgSsaoProgram->SetValue1f(i ++, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
750       
751        static int currentPos = 0;
752
753        if (mUseTemporalCoherence || mRegenerateSamples)
754        {
755                mRegenerateSamples = false;
756
757                // q: should we generate new samples or only rotate the old ones?
758                // in the first case, the sample patterns look nicer, but the kernel
759                // needs longer to converge
760                //if (currentPos + NUM_SAMPLES >= NUM_PRECOMPUTED_SAMPLES)      {
761                        currentPos = 0;
762                        GenerateSamples(mSamplingMethod);
763                //}
764
765                //if (mSortSamples) { SortSamples(); }
766                sCgSsaoProgram->SetArray2f(i, (float *)samples2 + currentPos, NUM_SAMPLES);
767
768                currentPos += NUM_SAMPLES;
769        }
770       
771        ++ i;
772
773        for (int j = 0; j < 4; ++ j, ++ i)
774                sCgSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
775
776        sCgSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
777        sCgSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
778
779        Vector3 de;
780        de.x = mOldEyePos.x - mEyePos.x;
781        de.y = mOldEyePos.y - mEyePos.y;
782        de.z = mOldEyePos.z - mEyePos.z;
783
784        sCgSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
785
786        for (int j = 0; j < 4; ++ j, ++ i)
787        {
788                sCgSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
789        }
790
791        sCgSsaoProgram->SetTexture(i ++, attribsTex);
792        sCgSsaoProgram->SetValue1f(i ++, mKernelRadius);
793        sCgSsaoProgram->SetValue1f(i ++, mSampleIntensity * mKernelRadius);
794
795
796        DrawQuad(sCgSsaoProgram);
797
798        glPopAttrib();
799
800        PrintGLerror("ssao first pass");
801}
802
803
804static void SetVertex(float x, float y, float x_offs, float y_offs)
805{
806        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
807        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
808        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
809        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
810        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
811
812        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
813        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
814
815        //glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
816        glVertex2f(x, y);
817}
818
819
820void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo,
821                                                                        DirectionalLight *light,
822                                                                        bool displayFrame)
823{
824        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
825        GLuint colorsTex = colorBuffer->GetTexture();
826        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
827
828        // read the second buffer, write to the first buffer
829        if (!displayFrame)
830                FlipFbos(fbo);
831        else
832                // end of the pipeline => just draw image to screen
833                FrameBufferObject::Release();
834
835        // the neighbouring texels
836        float xOffs = 1.0f / fbo->GetWidth();
837        float yOffs = 1.0f / fbo->GetHeight();
838
839        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
840        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
841
842        float offsets[16];
843        int i = 0;
844
845        offsets[i] = -xOffs; offsets[i + 1] =  yOffs; i += 2; // left top
846        offsets[i] =  xOffs; offsets[i + 1] = -yOffs; i += 2; // right bottom
847        offsets[i] =  xOffs; offsets[i + 1] =  yOffs; i += 2; // right top
848        offsets[i] = -xOffs; offsets[i + 1] = -yOffs; i += 2; // left bottom
849        offsets[i] = -xOffs; offsets[i + 1] =    .0f; i += 2; // left
850        offsets[i] =  xOffs; offsets[i + 1] =    .0f; i += 2; // right
851        offsets[i] =    .0f; offsets[i + 1] =  yOffs; i += 2; // top
852        offsets[i] =    .0f; offsets[i + 1] = -yOffs; i += 2; // bottom
853
854        sCgAntiAliasingProgram->SetArray2f(2, offsets, 8);
855
856        DrawQuad(sCgAntiAliasingProgram);
857
858        PrintGLerror("antialiasing");
859}
860
861
862void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
863{
864        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
865        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
866
867        FlipFbos(fbo);
868
869        const Vector3 lightDir = -light->GetDirection();
870
871        sCgDeferredProgram->SetTexture(0, colorsTex);
872        sCgDeferredProgram->SetTexture(1, normalsTex);
873        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
874       
875        DrawQuad(sCgDeferredProgram);
876
877        PrintGLerror("deferred shading");
878}
879
880
881void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
882                                                                                float tempCohFactor)
883{
884#if 0
885        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
886        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
887#else
888        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
889        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
890#endif
891
892        glPushAttrib(GL_VIEWPORT_BIT);
893        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
894
895        // read the second buffer, write to the first buffer
896        mIllumFbo->Bind();
897
898        glDrawBuffers(2, mrt + mIllumFboIndex);
899
900        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
901        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
902
903        int i = 0;
904
905        sCgGiProgram->SetTexture(i ++, colorsTex);
906        sCgGiProgram->SetTexture(i ++, normalsTex);
907        sCgGiProgram->SetTexture(i ++, noiseTex2D);
908        sCgGiProgram->SetTexture(i ++, oldSsaoTex);
909        sCgGiProgram->SetTexture(i ++, oldIllumTex);
910
911        sCgGiProgram->SetValue1f(i ++,
912                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
913
914        if (mUseTemporalCoherence || mRegenerateSamples)
915        {
916                mRegenerateSamples = false;
917
918                // q: should we generate new samples or only rotate the old ones?
919                // in the first case, the sample patterns look nicer, but the kernel
920                // needs longer to converge
921                GenerateSamples(mSamplingMethod);
922
923                sCgGiProgram->SetArray2f(i ++, (float *)samples2, NUM_SAMPLES);
924        }
925
926        Vector3 bl = mCornersView[0];
927        Vector3 br = mCornersView[1];
928        Vector3 tl = mCornersView[2];
929        Vector3 tr = mCornersView[3];
930
931        sCgGiProgram->SetValue3f(i ++, bl.x, bl.y, bl.z);
932        sCgGiProgram->SetValue3f(i ++, br.x, br.y, br.z);
933        sCgGiProgram->SetValue3f(i ++, tl.x, tl.y, tl.z);
934        sCgGiProgram->SetValue3f(i ++, tr.x, tr.y, tr.z);
935
936        sCgGiProgram->SetMatrix(i ++, mOldProjViewMatrix);
937        sCgGiProgram->SetMatrix(i ++, mProjViewMatrix);
938
939
940        DrawQuad(sCgGiProgram);
941
942        glPopAttrib();
943
944        PrintGLerror("globillum first pass");
945}
946
947
948void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
949{
950        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
951
952        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
953        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
954
955        FlipFbos(fbo);
956
957        sCgCombineIllumProgram->SetTexture(0, colorsTex);
958        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
959        sCgCombineIllumProgram->SetTexture(2, illumTex);
960       
961        DrawQuad(sCgCombineIllumProgram);
962
963        PrintGLerror("combine");
964}
965
966
967void DeferredRenderer::FilterSsao(FrameBufferObject *fbo)
968{
969        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
970        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
971        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
972       
973        //mIllumFbo->Bind();
974        //glDrawBuffers(1, mrt + mIllumFboIndex + 1);
975        mTempFbo->Bind();
976        glDrawBuffers(1, mrt);
977       
978        int i = 0;
979
980        sCgFilterSsaoProgram->SetTexture(i ++, colorsTex);
981        sCgFilterSsaoProgram->SetTexture(i ++, ssaoTex);
982
983        for (int j = 0; j < 4; ++ j, ++ i)
984        {
985                sCgFilterSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
986        }
987
988        sCgFilterSsaoProgram->SetValue2f(i ++, (float)mWidth, (float)mHeight);
989        sCgFilterSsaoProgram->SetValue1f(i ++, mMaxConvergence);
990        sCgFilterSsaoProgram->SetValue1f(i ++, mSpatialWeight);
991
992        DrawQuad(sCgFilterSsaoProgram);
993        PrintGLerror("combine ssao");
994}
995
996
997void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
998{
999        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1000        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
1001        //GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
1002        GLuint ssaoTex = mTempFbo->GetColorBuffer(0)->GetTexture();
1003       
1004        FlipFbos(fbo);
1005
1006        int i = 0;
1007
1008        sCgCombineSsaoProgram->SetTexture(i ++, colorsTex);
1009        sCgCombineSsaoProgram->SetTexture(i ++, ssaoTex);
1010
1011        for (int j = 0; j < 4; ++ j, ++ i)
1012        {
1013                sCgCombineSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
1014        }
1015
1016        sCgCombineSsaoProgram->SetValue2f(i ++, mWidth, mHeight);
1017        sCgCombineSsaoProgram->SetValue1f(i ++, mMaxConvergence);
1018        sCgCombineSsaoProgram->SetValue1f(i ++, mSpatialWeight);
1019
1020        DrawQuad(sCgCombineSsaoProgram);
1021       
1022        PrintGLerror("combine ssao");
1023}
1024
1025
1026void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
1027                                                                           DirectionalLight *light,
1028                                                                           ShadowMap *shadowMap)
1029{
1030        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1031        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
1032
1033        GLuint shadowTex = shadowMap->GetDepthTexture();
1034
1035        Matrix4x4 shadowMatrix;
1036        shadowMap->GetTextureMatrix(shadowMatrix);
1037
1038
1039        FlipFbos(fbo);
1040
1041        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
1042        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
1043        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
1044        sCgDeferredShadowProgram->SetTexture(3, noiseTex2D);
1045        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
1046        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
1047
1048        const Vector3 lightDir = -light->GetDirection();
1049        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
1050        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
1051
1052        DrawQuad(sCgDeferredShadowProgram);
1053
1054        PrintGLerror("deferred shading + shadows");
1055}
1056
1057
1058void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
1059                                                                                         DirectionalLight *light,
1060                                                                                         float &imageKey,
1061                                                                                         float &whiteLum,
1062                                                                                         float &middleGrey)
1063{
1064        // hack: estimate value where sky burns out
1065        whiteLum = log(WHITE_LUMINANCE);
1066       
1067        ////////////////////
1068        //-- linear interpolate brightness key depending on the current sun position
1069
1070        const float minKey = 0.09f;
1071        const float maxKey = 0.36f;
1072
1073        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
1074        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
1075
1076
1077        //////////
1078        //-- compute avg loglum
1079
1080        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1081        GLuint colorsTex = colorBuffer->GetTexture();
1082
1083        FlipFbos(fbo);
1084       
1085        sCgLogLumProgram->SetTexture(0, colorsTex);
1086        DrawQuad(sCgLogLumProgram);
1087       
1088        PrintGLerror("ToneMapParams");
1089
1090
1091        ///////////////////
1092        //-- compute avg loglum in scene using mipmapping
1093
1094        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
1095        glGenerateMipmapEXT(GL_TEXTURE_2D);
1096}
1097
1098
1099static void ExportData(float *data, int w, int h)
1100{
1101        startil();
1102
1103        cout << "w: " << w << " h: " << h << endl;
1104        ILstring filename = ILstring("downsample2.jpg");
1105        ilRegisterType(IL_FLOAT);
1106
1107        const int depth = 1;
1108        const int bpp = 4;
1109
1110        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
1111        {
1112                cerr << "IL error " << ilGetError() << endl;
1113                stopil();
1114                return;
1115        }
1116
1117        if (!ilSaveImage(filename))
1118        {
1119                cerr << "TGA write error " << ilGetError() << endl;
1120        }
1121
1122        stopil();
1123}
1124
1125
1126void DeferredRenderer::PrepareSsao(FrameBufferObject *fbo)
1127{
1128        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1129        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
1130        GLuint diffVals = fbo->GetColorBuffer(2)->GetTexture();
1131        // flip flop between illumination buffers
1132        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
1133
1134        int i = 0;
1135
1136        sCgPrepareSsaoProgram->SetTexture(i ++, colorsTex);
1137        sCgPrepareSsaoProgram->SetTexture(i ++, normalsTex);
1138        sCgPrepareSsaoProgram->SetTexture(i ++, diffVals);
1139        sCgPrepareSsaoProgram->SetTexture(i ++, oldTex);
1140
1141        Vector3 de;
1142        de.x = mOldEyePos.x - mEyePos.x;
1143        de.y = mOldEyePos.y - mEyePos.y;
1144        de.z = mOldEyePos.z - mEyePos.z;
1145
1146        sCgPrepareSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
1147
1148        sCgPrepareSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
1149        sCgPrepareSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
1150
1151        for (int j = 0; j < 4; ++ j, ++ i)
1152                sCgPrepareSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
1153
1154        glPushAttrib(GL_VIEWPORT_BIT);
1155        glViewport(0, 0, mDownSampleFbo->GetWidth(), mDownSampleFbo->GetHeight());
1156       
1157        mDownSampleFbo->Bind();
1158
1159        // prepare downsampled depth and normal texture for ssao
1160        glDrawBuffers(2, mrt);
1161
1162        DrawQuad(sCgPrepareSsaoProgram);
1163       
1164        glPopAttrib();
1165        PrintGLerror("prepareSsao");
1166}
1167
1168
1169void DeferredRenderer::DownSample(FrameBufferObject *fbo,
1170                                                                  int bufferIdx,
1171                                                                  FrameBufferObject *downSampleFbo,
1172                                                                  int downSampleBufferIdx,
1173                                                                  ShaderProgram *program)
1174{
1175        ColorBufferObject *buffer = fbo->GetColorBuffer(bufferIdx);
1176        GLuint tex = buffer->GetTexture();
1177
1178        glPushAttrib(GL_VIEWPORT_BIT);
1179        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
1180       
1181        downSampleFbo->Bind();
1182
1183        program->SetTexture(0, tex);
1184        glDrawBuffers(1, mrt + downSampleBufferIdx);
1185
1186        DrawQuad(program);
1187       
1188        glPopAttrib();
1189        PrintGLerror("downsample");
1190}
1191
1192
1193void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
1194                                                           float imageKey,
1195                                                           float whiteLum,
1196                                                           float middleGrey)
1197{
1198        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1199        GLuint colorsTex = colorBuffer->GetTexture();
1200        //FrameBufferObject::Release();
1201
1202        FlipFbos(fbo);
1203
1204        sCgToneProgram->SetTexture(0, colorsTex);
1205        sCgToneProgram->SetValue1f(1, imageKey);
1206        sCgToneProgram->SetValue1f(2, whiteLum);
1207        sCgToneProgram->SetValue1f(3, middleGrey);
1208
1209        DrawQuad(sCgToneProgram);
1210
1211        PrintGLerror("ToneMap");
1212}
1213
1214
1215void DeferredRenderer::Output(FrameBufferObject *fbo)
1216{
1217        glPushAttrib(GL_VIEWPORT_BIT);
1218        glViewport(0, 0, fbo->GetWidth(), fbo->GetHeight());
1219       
1220        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1221        GLuint colorsTex = colorBuffer->GetTexture();
1222
1223        sCgDownSampleProgram->SetTexture(0, colorsTex);
1224
1225        FrameBufferObject::Release();
1226        DrawQuad(sCgDownSampleProgram);
1227
1228        PrintGLerror("output");
1229}
1230
1231
1232void DeferredRenderer::InitFrame()
1233{
1234        for (int i = 0; i < 4; ++ i)
1235                mOldCornersView[i] = mCornersView[i];
1236
1237        mOldProjViewMatrix = mProjViewMatrix;
1238        mOldEyePos = mEyePos;
1239        mEyePos = mCamera->GetPosition();
1240
1241        // hack: temporarily change far to improve precision
1242        const float oldFar = mCamera->GetFar();
1243        const float oldNear = mCamera->GetNear();
1244       
1245
1246        Matrix4x4 matViewing, matProjection;
1247
1248
1249        ///////////////////
1250
1251        // use view orientation as we assume that the eye point is always in the center
1252        // of our coordinate system, this way we have the highest precision near the eye point
1253        mCamera->GetViewOrientationMatrix(matViewing);
1254        mCamera->GetProjectionMatrix(matProjection);
1255
1256        mProjViewMatrix = matViewing * matProjection;
1257        ComputeViewVectors(mCamera, mCornersView[0], mCornersView[1], mCornersView[2], mCornersView[3]);
1258       
1259
1260        // switch roles of old and new fbo
1261        // the algorihm uses two input fbos, where the one
1262        // contais the color buffer from the last frame,
1263        // the other one will be written
1264
1265        mIllumFboIndex = 2 - mIllumFboIndex;
1266       
1267        // enable fragment shading
1268        ShaderManager::GetSingleton()->EnableFragmentProfile();
1269
1270        glDisable(GL_ALPHA_TEST);
1271        glDisable(GL_TEXTURE_2D);
1272        glDisable(GL_LIGHTING);
1273        glDisable(GL_BLEND);
1274        glDisable(GL_DEPTH_TEST);
1275
1276        glPolygonMode(GL_FRONT, GL_FILL);
1277
1278        glMatrixMode(GL_PROJECTION);
1279        glPushMatrix();
1280        glLoadIdentity();
1281
1282        gluOrtho2D(0, 1, 0, 1);
1283
1284
1285        glMatrixMode(GL_MODELVIEW);
1286        glPushMatrix();
1287        glLoadIdentity();
1288
1289       
1290        glPushAttrib(GL_VIEWPORT_BIT);
1291        glViewport(0, 0, mWidth, mHeight);
1292
1293        // revert to old far and near plane
1294        mCamera->SetFar(oldFar);
1295        mCamera->SetNear(oldNear);
1296}
1297
1298
1299void DeferredRenderer::LenseFlare(FrameBufferObject *fbo,
1300                                                                  DirectionalLight *light                                                       
1301                                                                  )
1302{
1303        // light source visible?
1304        if (!mSunVisiblePixels) return;
1305
1306        // the sun is a large distance in the reverse light direction
1307        // => extrapolate light pos
1308        const Vector3 lightPos = light->GetDirection() * -1e3f;
1309
1310        float w;
1311        Vector3 projLightPos = mProjViewMatrix.Transform(w, lightPos, 1.0f);
1312        projLightPos /= w;
1313        projLightPos = projLightPos * 0.5f + Vector3(0.5f);
1314
1315        // vector to light from screen center in texture space
1316        Vector3 vectorToLight = projLightPos - Vector3(0.5f);
1317        vectorToLight.z = .0f;
1318
1319        const float distanceToLight = Magnitude(vectorToLight);
1320        vectorToLight /= distanceToLight;
1321
1322        //cout << "dist " << distanceToLight << " v " << vectorToLight << endl;
1323
1324
1325        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1326        GLuint colorsTex = colorBuffer->GetTexture();
1327       
1328        FlipFbos(fbo);
1329
1330        int i = 0;
1331
1332        sCgLenseFlareProgram->SetTexture(i ++, colorsTex);
1333        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[0]->GetId());
1334        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[1]->GetId());
1335        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[2]->GetId());
1336        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[3]->GetId());
1337        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[4]->GetId());
1338        sCgLenseFlareProgram->SetValue2f(i ++, vectorToLight.x, vectorToLight.y);
1339        sCgLenseFlareProgram->SetValue1f(i ++, distanceToLight);
1340        sCgLenseFlareProgram->SetValue1f(i ++, (float)mSunVisiblePixels);
1341
1342        DrawQuad(sCgLenseFlareProgram);
1343
1344        PrintGLerror("LenseFlare");
1345}
1346
1347
1348void DeferredRenderer::DepthOfField(FrameBufferObject *fbo)
1349{
1350        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1351        GLuint colorsTex = colorBuffer->GetTexture();
1352       
1353        FlipFbos(fbo);
1354
1355        int i = 0;
1356
1357        const float zFocus = 7.0f;
1358
1359        sCgDOFProgram->SetTexture(i ++, colorsTex);
1360        sCgDOFProgram->SetArray2f(i ++, (float *)dofSamples, NUM_DOF_TABS);
1361        sCgDOFProgram->SetValue1f(i ++, min(mCamera->GetFar(), mMaxDistance) - mCamera->GetNear());
1362        sCgDOFProgram->SetValue1f(i ++, zFocus);
1363
1364        DrawQuad(sCgDOFProgram);
1365
1366        PrintGLerror("LenseFlare");
1367}
1368
1369
1370void DeferredRenderer::SaveFrame(FrameBufferObject *fbo)
1371{
1372        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1373        GLuint colorsTex = colorBuffer->GetTexture();
1374
1375        GLubyte *data = new GLubyte[mWidth * mHeight * 4];
1376
1377        // grab texture data
1378        glEnable(GL_TEXTURE_2D);
1379        glBindTexture(GL_TEXTURE_2D, colorsTex);
1380        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
1381
1382        glBindTexture(GL_TEXTURE_2D, 0);
1383        glDisable(GL_TEXTURE_2D);
1384
1385        /////////////////
1386
1387        startil();
1388
1389        static char imageName[200];
1390        sprintf(imageName, "%s_%05d.tga", mSavedFrameSuffix.c_str(), mSavedFrameNumber);
1391
1392        ILstring fileName = ILstring(imageName);
1393        ilRegisterType(IL_FLOAT);
1394
1395        const int depth = 1;
1396        const int bpp = 4;
1397
1398        if (!ilTexImage(mWidth, mHeight, depth, bpp, IL_RGBA, IL_UNSIGNED_BYTE, data))
1399        {
1400                cerr << "IL error " << ilGetError() << endl;
1401                stopil();
1402                return;
1403        }
1404
1405        ilEnable(IL_FILE_OVERWRITE);
1406
1407        if (!ilSaveImage(fileName))
1408        {
1409                cerr << "TGA write error " << ilGetError() << endl;
1410        }
1411
1412        delete [] data;
1413
1414        stopil();
1415
1416        PrintGLerror("Store frame");
1417}
1418
1419
1420void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
1421{
1422        mUseTemporalCoherence = temporal;
1423}
1424
1425
1426void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
1427{
1428        if (s != mSamplingMethod)
1429        {
1430                mSamplingMethod = s;
1431                mRegenerateSamples = true;
1432        }
1433}
1434
1435
1436void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
1437{
1438        if (s != mShadingMethod)
1439        {
1440                mShadingMethod = s;
1441                mRegenerateSamples = true;
1442        }
1443}
1444
1445
1446#if TODO
1447
1448void DeferredRenderer::SetNumSamples(int numSamples)
1449{
1450        mNumSamples = numSamples;
1451}
1452
1453#endif
1454
1455
1456void DeferredRenderer::SetSampleIntensity(float sampleIntensity)
1457{
1458        mSampleIntensity = sampleIntensity;
1459        mRegenerateSamples = true;
1460}
1461
1462
1463void DeferredRenderer::SetKernelRadius(float kernelRadius)
1464{
1465        mKernelRadius = kernelRadius;
1466        mRegenerateSamples = true;
1467}
1468
1469
1470/*void DeferredRenderer::SetSortSamples(bool sortSamples)
1471{
1472        mSortSamples = sortSamples;
1473}*/
1474
1475
1476void DeferredRenderer::SetSunVisiblePixels(int pixels)
1477{
1478        mSunVisiblePixels = pixels;
1479}
1480
1481
1482void DeferredRenderer::SetMaxDistance(float maxDist)
1483{
1484        mMaxDistance = maxDist;
1485}
1486
1487
1488void DeferredRenderer::SetUseToneMapping(bool toneMapping)
1489{
1490        mUseToneMapping = toneMapping;
1491}
1492       
1493
1494void DeferredRenderer::SetUseAntiAliasing(bool antiAliasing)
1495{
1496        mUseAntiAliasing = antiAliasing;
1497}
1498
1499
1500void DeferredRenderer::SetUseDepthOfField(bool dof)
1501{
1502        mUseDepthOfField = dof;
1503}
1504
1505
1506void DeferredRenderer::SetTemporalCoherenceFactorForSsao(float factor)
1507{
1508        mTempCohFactor = factor;
1509}
1510
1511
1512void DeferredRenderer::SetSaveFrame(const string &suffix, int frameNumber)
1513{
1514        mSavedFrameSuffix = suffix;
1515        mSavedFrameNumber = frameNumber;
1516}
1517
1518
1519void DeferredRenderer::SetMaxConvergence(float c)
1520{
1521        mMaxConvergence = c;
1522}
1523
1524
1525void DeferredRenderer::SetSpatialWeight(float w)
1526{
1527        mSpatialWeight = w;
1528}
1529
1530
1531} // namespace
Note: See TracBrowser for help on using the repository browser.