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

Revision 3205, 32.5 KB checked in by mattausch, 16 years ago (diff)

as good as i cab do it right now but flickering when dynamic object enters + if dynamic object stops

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