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

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