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

Revision 3305, 39.7 KB checked in by mattausch, 15 years ago (diff)

removed filter radius

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