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

Revision 3306, 39.6 KB checked in by mattausch, 15 years ago (diff)

found error with border

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