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

Revision 3301, 41.9 KB checked in by mattausch, 15 years ago (diff)

working on separable filter but not working yet

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