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

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