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

Revision 3332, 42.4 KB checked in by mattausch, 15 years ago (diff)

debug / performance stuff

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