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

Revision 3189, 32.2 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
13#include <IL/il.h>
14#include <assert.h>
15
16
17#ifdef _CRT_SET
18        #define _CRTDBG_MAP_ALLOC
19        #include <stdlib.h>
20        #include <crtdbg.h>
21
22        // redefine new operator
23        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
24        #define new DEBUG_NEW
25#endif
26
27
28using namespace std;
29
30
31static void startil()
32{
33        ilInit();
34        assert(ilGetError() == IL_NO_ERROR);
35}
36
37
38static void stopil()
39{
40        ilShutDown();
41        assert(ilGetError() == IL_NO_ERROR);
42}
43
44namespace CHCDemoEngine
45{
46
47static ShaderProgram *sCgSsaoProgram = NULL;
48static ShaderProgram *sCgGiProgram = NULL;
49
50static ShaderProgram *sCgDeferredProgram = NULL;
51static ShaderProgram *sCgAntiAliasingProgram = NULL;
52static ShaderProgram *sCgDeferredShadowProgram = NULL;
53
54static ShaderProgram *sCgCombineSsaoProgram = NULL;
55static ShaderProgram *sCgCombineIllumProgram = NULL;
56static ShaderProgram *sCgLogLumProgram = NULL;
57static ShaderProgram *sCgToneProgram = NULL;
58static ShaderProgram *sCgDownSampleProgram = NULL;
59static ShaderProgram *sCgScaleDepthProgram = NULL;
60static ShaderProgram *sCgPrepareSsaoProgram = NULL;
61
62
63static GLuint noiseTex2D = 0;
64static GLuint noiseTex1D = 0;
65
66
67// ssao random spherical samples
68static Sample2 samples2[NUM_SAMPLES];
69// number of pcf tabs
70static Sample2 pcfSamples[NUM_PCF_TABS];
71
72
73static float ssaoFilterOffsets[NUM_SSAO_FILTER_SAMPLES * 2];
74static float ssaoFilterWeights[NUM_SSAO_FILTER_SAMPLES];
75
76
77int DeferredRenderer::colorBufferIdx = 0;
78
79
80/** Helper method that computes the view vectors in the corners of the current view frustum.
81*/
82static void ComputeViewVectors(PerspectiveCamera *cam, Vector3 &bl, Vector3 &br, Vector3 &tl, Vector3 &tr)
83{
84        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
85        cam->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
86
87        bl = Normalize(nbl - fbl);
88        br = Normalize(nbr - fbr);
89        tl = Normalize(ntl - ftl);
90        tr = Normalize(ntr - ftr);
91}
92
93
94static float GaussianDistribution(float x, float y, float rho)
95{
96        float g = 1.0f / sqrtf(2.0f * M_PI * rho * rho);
97    g *= expf( -(x * x + y * y) / (2.0f * rho * rho));
98
99    return g;
100}
101
102
103static void PrintGLerror(char *msg)
104{
105        GLenum errCode;
106        const GLubyte *errStr;
107       
108        if ((errCode = glGetError()) != GL_NO_ERROR)
109        {
110                errStr = gluErrorString(errCode);
111                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
112        }
113}
114
115
116static void ComputeSampleOffsets(float *sampleOffsets,
117                                                                 int imageW, int imageH,
118                                                                 float width,
119                                                                 int samples)
120{
121        const float xoffs = width / (float)imageW;
122        const float yoffs = width / (float)imageH;
123       
124        const int numSamples = (int)sqrt((float)samples);
125        const int startSamples = -numSamples / 2;
126        const int endSamples = numSamples + startSamples - 1;
127        //cout << startSamples << " " << endSamples << endl;
128
129        int idx = 0;
130
131        for (int x = startSamples; x <= endSamples; ++ x)
132        {
133                for (int y = startSamples; y <= endSamples; ++ y)
134                {
135                        sampleOffsets[idx + 0] = (float)x * xoffs;
136                        sampleOffsets[idx + 1] = (float)y * yoffs;
137                        idx += 2;
138                }
139        }
140}
141
142
143void DeferredRenderer::FlipFbos(FrameBufferObject *fbo)
144{
145        fbo->Bind();
146        colorBufferIdx = 3 - colorBufferIdx;
147        glDrawBuffers(1, mrt + colorBufferIdx);
148}
149
150
151void DeferredRenderer::DrawQuad(ShaderProgram *p)
152{
153        if (p) p->Bind();
154
155        // interpolate the view vector
156        Vector3 bl = mCornersView[0];
157        Vector3 br = mCornersView[1];
158        Vector3 tl = mCornersView[2];
159        Vector3 tr = mCornersView[3];
160
161        // note: slightly larger texture could hide ambient occlusion error on border but costs resolution
162        glBegin(GL_QUADS);
163
164        glTexCoord2f(0, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, bl.x, bl.y, bl.z); glVertex2f( .0f,  .0f);
165        glTexCoord2f(1, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, br.x, br.y, br.z); glVertex2f(1.0f,  .0f);
166        glTexCoord2f(1, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tr.x, tr.y, tr.z); glVertex2f(1.0f, 1.0f);
167        glTexCoord2f(0, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tl.x, tl.y, tl.z); glVertex2f( .0f, 1.0f);
168
169        glEnd();
170}
171
172
173/** Generate poisson disc distributed sample points on the unit disc
174*/
175static void GenerateSamples(int sampling)
176{
177        switch (sampling)
178        {
179        case DeferredRenderer::SAMPLING_POISSON:
180                {
181                        PoissonDiscSampleGenerator2 poisson(NUM_SAMPLES, 1.0f);
182                        poisson.Generate((float *)samples2);
183                }
184                break;
185        case DeferredRenderer::SAMPLING_QUADRATIC:
186                {
187                        QuadraticDiscSampleGenerator2 g(NUM_SAMPLES, 1.0f);
188                        g.Generate((float *)samples2);
189                }
190                break;
191        default: // SAMPLING_DEFAULT
192                {
193                        RandomSampleGenerator2 g(NUM_SAMPLES, 1.0f);
194                        g.Generate((float *)samples2);
195                }
196        }
197}
198
199
200static void CreateNoiseTex2D(int w, int h)
201{
202        //GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
203        float *randomNormals = new float[w * h * 3];
204
205        static HaltonSequence halton;
206        float r[2];
207
208        for (int i = 0; i < w * h * 3; i += 3)
209        {
210                // create random samples on a circle
211                r[0] = RandomValue(0, 1);
212                //halton.GetNext(1, r);
213
214                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
215               
216                randomNormals[i + 0] = cos(theta);
217                randomNormals[i + 1] = sin(theta);
218                randomNormals[i + 2] = 0;
219        }
220
221        glEnable(GL_TEXTURE_2D);
222        glGenTextures(1, &noiseTex2D);
223        glBindTexture(GL_TEXTURE_2D, noiseTex2D);
224               
225        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
226        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
227        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
228        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
229
230        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGB, GL_FLOAT, randomNormals);
231
232        glBindTexture(GL_TEXTURE_2D, 0);
233        glDisable(GL_TEXTURE_2D);
234
235        delete [] randomNormals;
236
237        cout << "created noise texture" << endl;
238
239        PrintGLerror("noisetexture");
240}
241
242
243static void CreateNoiseTex1D(int w)
244{
245        float *randomValues = new float[w * 3];
246
247        static HaltonSequence halton;
248       
249        randomValues[0] = randomValues[1] = randomValues[2] = 0;
250
251        for (int i = 3; i < w * 3; i += 3)
252        {
253                // create random samples on a circle
254                randomValues[i + 0] = 20.0f * RandomValue(0, 1) / 512.0f;
255                randomValues[i + 1] = 20.0f * RandomValue(0, 1) / 384.0f;
256                randomValues[i + 2] = 0;
257        }
258
259        glEnable(GL_TEXTURE_2D);
260        glGenTextures(1, &noiseTex1D);
261        glBindTexture(GL_TEXTURE_2D, noiseTex1D);
262               
263        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
264        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
265        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
266        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
267
268        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, 1, 0, GL_RGB, GL_FLOAT, randomValues);
269
270        glBindTexture(GL_TEXTURE_2D, 0);
271        glDisable(GL_TEXTURE_2D);
272
273        delete [] randomValues;
274
275        cout << "created noise texture 1D" << endl;
276
277        PrintGLerror("noisetexture 1D");
278}
279
280
281
282DeferredRenderer::DeferredRenderer(int w, int h, PerspectiveCamera *cam):
283mWidth(w), mHeight(h),
284mCamera(cam),
285mUseTemporalCoherence(true),
286mRegenerateSamples(true),
287mSamplingMethod(SAMPLING_POISSON),
288mShadingMethod(DEFAULT),
289mIllumFboIndex(0),
290mSortSamples(true)
291{
292        ///////////
293        //-- the flip-flop fbos
294
295        //const int dsw = w / 2; const int dsh = h / 2;
296        const int dsw = w; const int dsh = h;
297
298        mIllumFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
299        //mIllumFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
300
301        mFBOs.push_back(mIllumFbo);
302
303        for (int i = 0; i < 4; ++ i)
304        {
305                mIllumFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
306                FrameBufferObject::InitBuffer(mIllumFbo, i);
307        }
308
309
310        ///////////////
311        //-- the downsampled ssao + color bleeding textures: as gi is inherently low frequency, we can use these to improve performance
312
313        mDownSampleFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
314        //mDownSampleFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
315        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
316        // downsample buffer for the normal texture
317        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
318        // downsample buffer for the offset texture
319        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
320
321        for (int i = 0; i < 3; ++ i)
322        {
323                FrameBufferObject::InitBuffer(mDownSampleFbo, i);
324        }
325
326        mFBOs.push_back(mDownSampleFbo);
327
328        // create noise texture for ssao
329        // for performance reasons we use a smaller texture and repeat it over the screen
330        CreateNoiseTex2D(mIllumFbo->GetWidth() / 4, mIllumFbo->GetWidth() / 4);
331        //CreateNoiseTex1D(mIllumFbo->GetWidth() / 4);
332
333        mProjViewMatrix = IdentityMatrix();
334        mOldProjViewMatrix = IdentityMatrix();
335
336        for (int i = 0; i < 4; ++ i)
337        {
338                mCornersView[i] = mOldCornersView[i] = Vector3::UNIT_X();
339        }
340
341        mEyePos = mOldEyePos = Vector3::ZERO();
342
343        InitCg();
344}
345
346
347DeferredRenderer::~DeferredRenderer()
348{
349        CLEAR_CONTAINER(mFBOs);
350        glDeleteTextures(1, &noiseTex2D);
351        glDeleteTextures(1, &noiseTex1D);
352}
353
354
355void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
356{
357        mUseTemporalCoherence = temporal;
358}
359
360
361
362void DeferredRenderer::InitCg()
363{       
364        ShaderManager *sm = ShaderManager::GetSingleton();
365
366        sCgDeferredProgram = sm->CreateFragmentProgram("deferred", "main", "deferredFrag");
367        sCgDeferredShadowProgram = sm->CreateFragmentProgram("deferred", "main_shadow", "deferredFragShader");
368        sCgSsaoProgram = sm->CreateFragmentProgram("ssao", "main", "ssaoFrag");
369        sCgGiProgram = sm->CreateFragmentProgram("globillum", "main", "giFrag");
370        sCgCombineIllumProgram = sm->CreateFragmentProgram("globillum", "combine", "combineGi");
371        sCgCombineSsaoProgram = sm->CreateFragmentProgram("combineSsao", "combine", "combineSsao");
372        sCgAntiAliasingProgram = sm->CreateFragmentProgram("antialiasing", "main", "antiAliasing");
373        sCgToneProgram = sm->CreateFragmentProgram("tonemap", "ToneMap", "toneMap");
374        sCgDownSampleProgram = sm->CreateFragmentProgram("deferred", "Output", "Output");
375        sCgScaleDepthProgram = sm->CreateFragmentProgram("deferred", "ScaleDepth", "ScaleDepth");
376        sCgLogLumProgram = sm->CreateFragmentProgram("tonemap", "CalcAvgLogLum", "avgLogLum");
377        sCgPrepareSsaoProgram = sm->CreateFragmentProgram("deferred", "PrepareSsao", "PrepareSsao");
378
379
380        ///////////////////
381        //-- initialize program parameters
382
383        string ssaoParams[] =
384                {"colors", "normals", "oldTex", "noiseTex", "temporalCoherence",
385                 "samples", "bl", "br", "tl", "tr",
386                 "modelViewProj", "oldModelViewProj", "oldEyePos", "oldbl", "oldbr",
387                 "oldtl", "oldtr", "attribsTex"};
388        sCgSsaoProgram->AddParameters(ssaoParams, 0, 18);
389       
390        string giParams[] =
391                {"colors", "normals", "noiseTex", "oldSsaoTex", "oldIllumTex",
392                 "temporalCoherence", "samples", "bl", "br", "tl",
393                 "tr", "oldModelViewProj", "modelViewProj"};
394        sCgGiProgram->AddParameters(giParams, 0, 13);
395
396        string toneParams[] = {"colors", "imageKey", "whiteLum", "middleGrey"};
397        sCgToneProgram->AddParameters(toneParams, 0, 4);
398
399
400        ////////////////
401
402        string deferredShadowParams[] =
403                {"colors", "normals", "shadowMap", "noiseTex", "shadowMatrix",
404                 "sampleWidth", "lightDir", "eyePos", "samples", "weights"};
405       
406        sCgDeferredShadowProgram->AddParameters(deferredShadowParams, 0, 10);
407       
408        ////////////////
409
410        string combineIllumParams[] = {"colorsTex", "ssaoTex", "illumTex"};
411        sCgCombineIllumProgram->AddParameters(combineIllumParams, 0, 3);
412
413        ////////////////
414
415        string combineSsaoParams[] =
416                {"colorsTex", "normalsTex", "ssaoTex", "filterOffs",
417                 "filterWeights", "modelViewProj", "bl", "br", "tl", "tr"};
418        sCgCombineSsaoProgram->AddParameters(combineSsaoParams, 0, 10);
419
420        //////////////
421
422        string deferredParams[] = {"colors", "normals", "lightDir"};
423        sCgDeferredProgram->AddParameters(deferredParams, 0, 3);
424
425        ///////////////////
426
427        string aaParams[] = {"colors", "normals", "offsets"};
428        sCgAntiAliasingProgram->AddParameters(aaParams, 0, 3);
429
430        /////////////////////
431
432        string downSampleParams[] = {"colors"};
433        sCgDownSampleProgram->AddParameters(downSampleParams, 0, 1);
434
435        /////////////////////
436
437        string scaleDepthParams[] = {"colors"};
438        sCgScaleDepthProgram->AddParameters(scaleDepthParams, 0, 1);
439
440        ////////////
441
442        sCgLogLumProgram->AddParameter("colors", 0);
443
444        ////////////////
445
446       
447        string prepareSsaoParams[] =
448                {"colorsTex", "normalsTex", "diffVals", "oldTex",
449                 "oldEyePos", "modelViewProj", "oldModelViewProj",
450                 "oldbl", "oldbr", "oldtl", "oldtr"};
451
452        sCgPrepareSsaoProgram->AddParameters(prepareSsaoParams, 0, 11);
453
454
455        ////////////////
456
457        const float filterWidth = 1.0f;
458
459        PoissonDiscSampleGenerator2 poisson(NUM_SSAO_FILTER_SAMPLES, 1.0f);
460        poisson.Generate((float *)ssaoFilterOffsets);
461
462        const float xoffs = (float)filterWidth / mWidth;
463        const float yoffs = (float)filterWidth / mHeight;
464
465        for (int i = 0; i < NUM_SSAO_FILTER_SAMPLES; ++ i)
466        {
467                float x = ssaoFilterOffsets[2 * i + 0];
468                float y = ssaoFilterOffsets[2 * i + 1];
469
470                ssaoFilterWeights[i] = GaussianDistribution(x, y, 1.0f);
471                //ssaoFilterWeights[i] = 1.0f;
472
473                ssaoFilterOffsets[2 * i + 0] *= xoffs;
474                ssaoFilterOffsets[2 * i + 1] *= yoffs;
475        }
476
477
478        /////////
479        //-- pcf tabs for shadowing
480
481        float filterWeights[NUM_PCF_TABS];
482        PoissonDiscSampleGenerator2 poisson2(NUM_PCF_TABS, 1.0f);
483        poisson2.Generate((float *)pcfSamples);
484
485        for (int i = 0; i < NUM_PCF_TABS; ++ i)
486        {
487                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
488        }
489
490        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
491        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
492
493        PrintGLerror("init");
494}
495
496
497void DeferredRenderer::Render(FrameBufferObject *fbo,
498                                                          float tempCohFactor,
499                                                          DirectionalLight *light,
500                                                          bool useToneMapping,
501                                                          bool useAntiAliasing,
502                                                          ShadowMap *shadowMap
503                                                          )
504{
505        InitFrame();
506
507        if (shadowMap)
508                FirstPassShadow(fbo, light, shadowMap);
509        else
510                FirstPass(fbo, light);
511
512        if (mShadingMethod != 0)
513        {
514                // downsample fbo buffers
515                PrepareSsao(fbo);
516        }
517
518        // multisampling is difficult / costly with deferred shading
519        // at least do some edge blurring
520        if (useAntiAliasing) AntiAliasing(fbo, light);
521
522        switch (mShadingMethod)
523        {
524        case SSAO:
525                ComputeSsao(fbo, tempCohFactor);
526                CombineSsao(fbo);
527                break;
528        case GI:
529                ComputeGlobIllum(fbo, tempCohFactor);
530                CombineIllum(fbo);
531                break;
532        default: // DEFAULT
533                // do nothing: standard deferred shading
534                break;
535        }
536
537        if (useToneMapping)
538        {
539                float imageKey, whiteLum, middleGrey;
540
541                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
542                ToneMap(fbo, imageKey, whiteLum, middleGrey);
543        }
544
545        // multisampling is difficult / costly with deferred shading
546        // at least do some edge blurring
547        //if (useAntiAliasing) AntiAliasing(fbo, light); else
548        Output(fbo); // just output the latest buffer
549
550        glEnable(GL_LIGHTING);
551        glDisable(GL_TEXTURE_2D);
552
553        glMatrixMode(GL_PROJECTION);
554        glPopMatrix();
555
556        glMatrixMode(GL_MODELVIEW);
557        glPopMatrix();
558
559        // viewport
560        glPopAttrib();
561
562        FrameBufferObject::Release();
563        ShaderManager::GetSingleton()->DisableFragmentProfile();
564}
565
566
567
568static inline float SqrMag(const Sample2 &s)
569{
570        return (s.x * s.x + s.y * s.y);
571}
572
573
574static inline float SqrDist(const Sample2 &a, const Sample2 &b)
575{
576        float x = a.x - b.x;
577        float y = a.y - b.y;
578       
579        return x * x + y * y;
580}
581
582
583static inline bool lt(const Sample2 &a, const Sample2 &b)
584{
585        return SqrMag(a) < SqrMag(b);
586}
587
588
589void DeferredRenderer::SortSamples()
590{
591        static Sample2 tempSamples[NUM_SAMPLES];
592        static bool checked[NUM_SAMPLES];
593
594        for (int i = 0; i < NUM_SAMPLES; ++ i)
595                checked[i] = false;
596
597        Sample2 currentSample;
598        currentSample.x = 0; currentSample.y = 0;
599        int ns = 0; // the next sample index
600
601        for (int i = 0; i < NUM_SAMPLES; ++ i)
602        {
603                float minLen = 1e20f;
604
605                for (int j = 0; j < NUM_SAMPLES; ++ j)
606                {
607                        if (checked[j]) continue;
608
609                        Sample2 s = samples2[j];
610                        const float len = SqrDist(s, currentSample);
611
612                        if (len < minLen)
613                        {
614                                minLen = len;
615                                ns = j;
616                        }
617                }
618
619                tempSamples[i] = samples2[ns];
620                currentSample = samples2[ns];
621                checked[ns] = true;
622        }
623
624        for (int i = 0; i < NUM_SAMPLES; ++ i)
625                samples2[i] = tempSamples[i];
626}
627
628
629void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo,
630                                                                   float tempCohFactor)
631{
632        GLuint colorsTex, normalsTex, attribsTex;
633
634        if (0)
635        {
636                colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
637                normalsTex = fbo->GetColorBuffer(1)->GetTexture();
638                attribsTex = fbo->GetColorBuffer(2)->GetTexture();
639        }
640        else
641        {
642                colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
643                normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
644                attribsTex = mDownSampleFbo->GetColorBuffer(2)->GetTexture();
645                //attribsTex = fbo->GetColorBuffer(2)->GetTexture();
646        }
647
648        // flip flop between illumination buffers
649        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
650
651        glPushAttrib(GL_VIEWPORT_BIT);
652        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
653
654        // read the second buffer, write to the first buffer
655        mIllumFbo->Bind();
656        glDrawBuffers(1, mrt + mIllumFboIndex);
657
658        int i = 0;
659
660        sCgSsaoProgram->SetTexture(i ++, colorsTex);
661        sCgSsaoProgram->SetTexture(i ++, normalsTex);
662        sCgSsaoProgram->SetTexture(i ++, oldTex);
663        sCgSsaoProgram->SetTexture(i ++, noiseTex2D);
664
665        sCgSsaoProgram->SetValue1f(i ++, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
666       
667        if (mUseTemporalCoherence || mRegenerateSamples)
668        {
669                mRegenerateSamples = false;
670
671                // q: should we generate new samples or only rotate the old ones?
672                // in the first case, the sample patterns look nicer, but the kernel
673                // needs longer to converge
674                GenerateSamples(mSamplingMethod);
675
676                if (mSortSamples) { SortSamples(); }
677                sCgSsaoProgram->SetArray2f(i, (float *)samples2, NUM_SAMPLES);
678        }
679       
680        ++ i;
681
682        for (int j = 0; j < 4; ++ j, ++ i)
683                sCgSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
684
685        sCgSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
686        sCgSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
687
688        Vector3 de;
689        de.x = mOldEyePos.x - mEyePos.x;
690        de.y = mOldEyePos.y - mEyePos.y;
691        de.z = mOldEyePos.z - mEyePos.z;
692
693        sCgSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
694
695        for (int j = 0; j < 4; ++ j, ++ i)
696                sCgSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
697
698        sCgSsaoProgram->SetTexture(i ++, attribsTex);
699
700
701        DrawQuad(sCgSsaoProgram);
702
703        glPopAttrib();
704
705        PrintGLerror("ssao first pass");
706}
707
708
709static void SetVertex(float x, float y, float x_offs, float y_offs)
710{
711        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
712        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
713        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
714        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
715        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
716
717        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
718        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
719
720        //glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
721        glVertex2f(x, y);
722}
723
724
725void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo, DirectionalLight *light)
726{
727        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
728        GLuint colorsTex = colorBuffer->GetTexture();
729        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
730
731        // read the second buffer, write to the first buffer
732        FlipFbos(fbo);
733        // end of the pipeline => just draw image to screen
734        //FrameBufferObject::Release();
735
736        // the neighbouring texels
737        float xOffs = 1.0f / fbo->GetWidth();
738        float yOffs = 1.0f / fbo->GetHeight();
739
740        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
741        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
742
743        float offsets[16];
744        int i = 0;
745
746        offsets[i] = -xOffs; offsets[i + 1] =  yOffs; i += 2; // left top
747        offsets[i] =  xOffs; offsets[i + 1] = -yOffs; i += 2; // right bottom
748        offsets[i] =  xOffs; offsets[i + 1] =  yOffs; i += 2; // right top
749        offsets[i] = -xOffs; offsets[i + 1] = -yOffs; i += 2; // left bottom
750        offsets[i] = -xOffs; offsets[i + 1] =    .0f; i += 2; // left
751        offsets[i] =  xOffs; offsets[i + 1] =    .0f; i += 2; // right
752        offsets[i] =    .0f; offsets[i + 1] =  yOffs; i += 2; // top
753        offsets[i] =    .0f; offsets[i + 1] = -yOffs; i += 2; // bottom
754
755        sCgAntiAliasingProgram->SetArray2f(2, offsets, 8);
756
757        DrawQuad(sCgAntiAliasingProgram);
758
759        PrintGLerror("antialiasing");
760}
761
762
763void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
764{
765        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
766        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
767
768        FlipFbos(fbo);
769
770        const Vector3 lightDir = -light->GetDirection();
771
772        sCgDeferredProgram->SetTexture(0, colorsTex);
773        sCgDeferredProgram->SetTexture(1, normalsTex);
774        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
775       
776        DrawQuad(sCgDeferredProgram);
777
778        PrintGLerror("deferred shading");
779}
780
781
782void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
783                                                                                float tempCohFactor)
784{
785#if 0
786        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
787        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
788#else
789        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
790        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
791#endif
792
793        glPushAttrib(GL_VIEWPORT_BIT);
794        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
795
796        // read the second buffer, write to the first buffer
797        mIllumFbo->Bind();
798
799        glDrawBuffers(2, mrt + mIllumFboIndex);
800
801        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
802        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
803
804        int i = 0;
805
806        sCgGiProgram->SetTexture(i ++, colorsTex);
807        sCgGiProgram->SetTexture(i ++, normalsTex);
808        sCgGiProgram->SetTexture(i ++, noiseTex2D);
809        sCgGiProgram->SetTexture(i ++, oldSsaoTex);
810        sCgGiProgram->SetTexture(i ++, oldIllumTex);
811
812        sCgGiProgram->SetValue1f(i ++,
813                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
814
815        if (mUseTemporalCoherence || mRegenerateSamples)
816        {
817                mRegenerateSamples = false;
818
819                // q: should we generate new samples or only rotate the old ones?
820                // in the first case, the sample patterns look nicer, but the kernel
821                // needs longer to converge
822                GenerateSamples(mSamplingMethod);
823
824                sCgGiProgram->SetArray2f(i ++, (float *)samples2, NUM_SAMPLES);
825        }
826
827        Vector3 bl = mCornersView[0];
828        Vector3 br = mCornersView[1];
829        Vector3 tl = mCornersView[2];
830        Vector3 tr = mCornersView[3];
831
832        sCgGiProgram->SetValue3f(i ++, bl.x, bl.y, bl.z);
833        sCgGiProgram->SetValue3f(i ++, br.x, br.y, br.z);
834        sCgGiProgram->SetValue3f(i ++, tl.x, tl.y, tl.z);
835        sCgGiProgram->SetValue3f(i ++, tr.x, tr.y, tr.z);
836
837        sCgGiProgram->SetMatrix(i ++, mOldProjViewMatrix);
838        sCgGiProgram->SetMatrix(i ++, mProjViewMatrix);
839
840
841        DrawQuad(sCgGiProgram);
842
843        glPopAttrib();
844
845        PrintGLerror("globillum first pass");
846}
847
848
849void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
850{
851        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
852
853        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
854        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
855
856        FlipFbos(fbo);
857
858        sCgCombineIllumProgram->SetTexture(0, colorsTex);
859        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
860        sCgCombineIllumProgram->SetTexture(2, illumTex);
861       
862        DrawQuad(sCgCombineIllumProgram);
863
864        PrintGLerror("combine");
865}
866
867
868void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
869{
870        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
871        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
872        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
873       
874        FlipFbos(fbo);
875
876        int i = 0;
877
878        sCgCombineSsaoProgram->SetTexture(i ++, colorsTex);
879        sCgCombineSsaoProgram->SetTexture(i ++, normalsTex);
880        sCgCombineSsaoProgram->SetTexture(i ++, ssaoTex);
881
882        sCgCombineSsaoProgram->SetArray2f(i ++, (float *)ssaoFilterOffsets, NUM_SSAO_FILTER_SAMPLES);
883        sCgCombineSsaoProgram->SetArray1f(i ++, (float *)ssaoFilterWeights, NUM_SSAO_FILTER_SAMPLES);
884       
885        sCgCombineSsaoProgram->SetMatrix(i++, mProjViewMatrix);
886
887        for (int j = 0; j < 4; ++ j, ++ i)
888                sCgCombineSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
889
890        DrawQuad(sCgCombineSsaoProgram);
891       
892        PrintGLerror("combine ssao");
893}
894
895
896void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
897                                                                           DirectionalLight *light,
898                                                                           ShadowMap *shadowMap)
899{
900        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
901        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
902
903        GLuint shadowTex = shadowMap->GetDepthTexture();
904
905        Matrix4x4 shadowMatrix;
906        shadowMap->GetTextureMatrix(shadowMatrix);
907
908
909        FlipFbos(fbo);
910
911        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
912        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
913        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
914        sCgDeferredShadowProgram->SetTexture(3, noiseTex2D);
915        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
916        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
917
918        const Vector3 lightDir = -light->GetDirection();
919        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
920        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
921
922        DrawQuad(sCgDeferredShadowProgram);
923
924        PrintGLerror("deferred shading + shadows");
925}
926
927
928void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
929{
930        if (s != mSamplingMethod)
931        {
932                mSamplingMethod = s;
933                mRegenerateSamples = true;
934        }
935}
936
937
938void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
939{
940        if (s != mShadingMethod)
941        {
942                mShadingMethod = s;
943                mRegenerateSamples = true;
944        }
945}
946
947
948void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
949                                                                                         DirectionalLight *light,
950                                                                                         float &imageKey,
951                                                                                         float &whiteLum,
952                                                                                         float &middleGrey)
953{
954        // hack: estimate value where sky burns out
955        whiteLum = log(WHITE_LUMINANCE);
956       
957        ////////////////////
958        //-- linear interpolate brightness key depending on the current sun position
959
960        const float minKey = 0.09f;
961        const float maxKey = 0.36f;
962
963        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
964        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
965
966
967        //////////
968        //-- compute avg loglum
969
970        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
971        GLuint colorsTex = colorBuffer->GetTexture();
972
973        FlipFbos(fbo);
974       
975        sCgLogLumProgram->SetTexture(0, colorsTex);
976        DrawQuad(sCgLogLumProgram);
977       
978        PrintGLerror("ToneMapParams");
979
980
981        ///////////////////
982        //-- compute avg loglum in scene using mipmapping
983
984        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
985        glGenerateMipmapEXT(GL_TEXTURE_2D);
986}
987
988
989static void ExportData(float *data, int w, int h)
990{
991        startil();
992
993        cout << "w: " << w << " h: " << h << endl;
994        ILstring filename = ILstring("downsample2.jpg");
995        ilRegisterType(IL_FLOAT);
996
997        const int depth = 1;
998        const int bpp = 4;
999
1000        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
1001        {
1002                cerr << "IL error " << ilGetError() << endl;
1003                stopil();
1004                return;
1005        }
1006
1007        if (!ilSaveImage(filename))
1008        {
1009                cerr << "TGA write error " << ilGetError() << endl;
1010        }
1011
1012        stopil();
1013}
1014
1015
1016void DeferredRenderer::PrepareSsao(FrameBufferObject *fbo)
1017{
1018        GLuint colorsTex, normalsTex, diffVals, oldTex;
1019
1020        colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1021        normalsTex = fbo->GetColorBuffer(1)->GetTexture();
1022        diffVals = fbo->GetColorBuffer(2)->GetTexture();
1023        //diffVals = mDownSampleFbo->GetColorBuffer(2)->GetTexture();
1024
1025        // flip flop between illumination buffers
1026        oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
1027
1028        int i = 0;
1029
1030        sCgPrepareSsaoProgram->SetTexture(i ++, colorsTex);
1031        sCgPrepareSsaoProgram->SetTexture(i ++, normalsTex);
1032        sCgPrepareSsaoProgram->SetTexture(i ++, diffVals);
1033        sCgPrepareSsaoProgram->SetTexture(i ++, oldTex);
1034
1035        Vector3 de;
1036        de.x = mOldEyePos.x - mEyePos.x;
1037        de.y = mOldEyePos.y - mEyePos.y;
1038        de.z = mOldEyePos.z - mEyePos.z;
1039
1040        sCgPrepareSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
1041
1042        sCgPrepareSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
1043        sCgPrepareSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
1044
1045        for (int j = 0; j < 4; ++ j, ++ i)
1046                sCgPrepareSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
1047
1048        glPushAttrib(GL_VIEWPORT_BIT);
1049        glViewport(0, 0, mDownSampleFbo->GetWidth(), mDownSampleFbo->GetHeight());
1050       
1051        mDownSampleFbo->Bind();
1052
1053        glDrawBuffers(3, mrt + 0);
1054
1055        DrawQuad(sCgPrepareSsaoProgram);
1056       
1057        glPopAttrib();
1058        PrintGLerror("prepareSsao");
1059}
1060
1061
1062
1063void DeferredRenderer::DownSample(FrameBufferObject *fbo,
1064                                                                  int bufferIdx,
1065                                                                  FrameBufferObject *downSampleFbo,
1066                                                                  int downSampleBufferIdx,
1067                                                                  ShaderProgram *program)
1068{
1069        ColorBufferObject *buffer = fbo->GetColorBuffer(bufferIdx);
1070        GLuint tex = buffer->GetTexture();
1071
1072        glPushAttrib(GL_VIEWPORT_BIT);
1073        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
1074       
1075        downSampleFbo->Bind();
1076
1077        program->SetTexture(0, tex);
1078        glDrawBuffers(1, mrt + downSampleBufferIdx);
1079
1080        DrawQuad(program);
1081       
1082        glPopAttrib();
1083        PrintGLerror("downsample");
1084}
1085
1086
1087void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
1088                                                           float imageKey,
1089                                                           float whiteLum,
1090                                                           float middleGrey)
1091{
1092        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1093        GLuint colorsTex = colorBuffer->GetTexture();
1094        //FrameBufferObject::Release();
1095
1096        FlipFbos(fbo);
1097
1098        sCgToneProgram->SetTexture(0, colorsTex);
1099        sCgToneProgram->SetValue1f(1, imageKey);
1100        sCgToneProgram->SetValue1f(2, whiteLum);
1101        sCgToneProgram->SetValue1f(3, middleGrey);
1102
1103        DrawQuad(sCgToneProgram);
1104
1105        PrintGLerror("ToneMap");
1106}
1107
1108
1109void DeferredRenderer::Output(FrameBufferObject *fbo)
1110{
1111        glPushAttrib(GL_VIEWPORT_BIT);
1112        glViewport(0, 0, fbo->GetWidth(), fbo->GetHeight());
1113       
1114        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1115        GLuint colorsTex = colorBuffer->GetTexture();
1116
1117        sCgDownSampleProgram->SetTexture(0, colorsTex);
1118
1119        FrameBufferObject::Release();
1120        DrawQuad(sCgDownSampleProgram);
1121
1122        PrintGLerror("output");
1123}
1124
1125
1126void DeferredRenderer::InitFrame()
1127{
1128        for (int i = 0; i < 4; ++ i)
1129                mOldCornersView[i] = mCornersView[i];
1130
1131        mOldProjViewMatrix = mProjViewMatrix;
1132        mOldEyePos = mEyePos;
1133        mEyePos = mCamera->GetPosition();
1134
1135        // hack: temporarily change far to improve precision
1136        const float oldFar = mCamera->GetFar();
1137        const float oldNear = mCamera->GetNear();
1138       
1139
1140        Matrix4x4 matViewing, matProjection;
1141
1142
1143        ///////////////////
1144
1145
1146        mCamera->GetViewOrientationMatrix(matViewing);
1147        mCamera->GetProjectionMatrix(matProjection);
1148
1149        mProjViewMatrix = matViewing * matProjection;
1150        ComputeViewVectors(mCamera, mCornersView[0], mCornersView[1], mCornersView[2], mCornersView[3]);
1151       
1152
1153        // switch roles of old and new fbo
1154        // the algorihm uses two input fbos, where the one
1155        // contais the color buffer from the last frame,
1156        // the other one will be written
1157
1158        mIllumFboIndex = 2 - mIllumFboIndex;
1159       
1160        // enable fragment shading
1161        ShaderManager::GetSingleton()->EnableFragmentProfile();
1162
1163        glDisable(GL_ALPHA_TEST);
1164        glDisable(GL_TEXTURE_2D);
1165        glDisable(GL_LIGHTING);
1166        glDisable(GL_BLEND);
1167        glDisable(GL_DEPTH_TEST);
1168
1169        glPolygonMode(GL_FRONT, GL_FILL);
1170
1171        glMatrixMode(GL_PROJECTION);
1172        glPushMatrix();
1173        glLoadIdentity();
1174
1175        gluOrtho2D(0, 1, 0, 1);
1176
1177
1178        glMatrixMode(GL_MODELVIEW);
1179        glPushMatrix();
1180        glLoadIdentity();
1181
1182       
1183        glPushAttrib(GL_VIEWPORT_BIT);
1184        glViewport(0, 0, mWidth, mHeight);
1185
1186        // revert to old far and near plane
1187        mCamera->SetFar(oldFar);
1188        mCamera->SetNear(oldNear);
1189}
1190
1191
1192} // namespace
Note: See TracBrowser for help on using the repository browser.