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

Revision 3327, 42.6 KB checked in by mattausch, 15 years ago (diff)

probably found error with texture

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