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

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