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

Revision 3371, 43.3 KB checked in by mattausch, 15 years ago (diff)

fehler tritt nicht auf!!

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