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

Revision 3227, 37.0 KB checked in by mattausch, 16 years ago (diff)

worked on sampling / convergence

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