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

Revision 3326, 42.0 KB checked in by mattausch, 15 years ago (diff)

strange texture error!!

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