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

Revision 3372, 43.2 KB checked in by mattausch, 16 years ago (diff)

reverted but now a good version

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