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

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