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

Revision 3324, 41.3 KB checked in by mattausch, 15 years ago (diff)

indexing working not so bad

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