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

Revision 3231, 37.3 KB checked in by mattausch, 16 years ago (diff)

worked on sampling pattern

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