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

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