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

Revision 3143, 31.9 KB checked in by mattausch, 16 years ago (diff)

managed to remove halo by modifying depth / normal discontinuity filter

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 *sCgSmoothSsaoProgram = NULL;
60static ShaderProgram *sCgScaleDepthProgram = 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_FILTERSAMPLES * 2];
74static float ssaoFilterWeights[NUM_SSAO_FILTERSAMPLES];
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)
290{
291        ///////////
292        //-- the flip-flop fbos
293
294        const int dsw = w / 2; const int dsh = h / 2;
295        //const int dsw = w; const int dsh = h;
296
297        mIllumFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
298        //mIllumFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
299
300        mFBOs.push_back(mIllumFbo);
301
302        for (int i = 0; i < 4; ++ i)
303        {
304                mIllumFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
305                FrameBufferObject::InitBuffer(mIllumFbo, i);
306        }
307
308
309        ///////////////
310        //-- the downsampled ssao + color bleeding textures: as gi is inherently low frequency, we can use these to improve performance
311
312        mDownSampleFbo = new FrameBufferObject(dsw, dsh, FrameBufferObject::DEPTH_NONE);
313        //mDownSampleFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
314        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
315        // downsample buffer for the normal texture
316        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
317        // downsample buffer for the offset texture
318        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
319
320        for (int i = 0; i < 3; ++ i)
321        {
322                FrameBufferObject::InitBuffer(mDownSampleFbo, i);
323        }
324
325        mFBOs.push_back(mDownSampleFbo);
326
327        // create noise texture for ssao
328        CreateNoiseTex2D(mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
329        //CreateNoiseTex2D(mIllumFbo->GetWidth() / 4, mIllumFbo->GetWidth() / 4);
330        CreateNoiseTex1D(mWidth / 8);
331
332        mProjViewMatrix = IdentityMatrix();
333        mOldProjViewMatrix = IdentityMatrix();
334
335        for (int i = 0; i < 4; ++ i)
336        {
337                mCornersView[i] = mOldCornersView[i] = Vector3::UNIT_X();
338        }
339
340        mEyePos = mOldEyePos = Vector3::ZERO();
341
342        InitCg();
343}
344
345
346DeferredRenderer::~DeferredRenderer()
347{
348        CLEAR_CONTAINER(mFBOs);
349        glDeleteTextures(1, &noiseTex2D);
350        glDeleteTextures(1, &noiseTex1D);
351}
352
353
354void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
355{
356        mUseTemporalCoherence = temporal;
357}
358
359
360
361void DeferredRenderer::InitCg()
362{       
363        ShaderManager *sm = ShaderManager::GetSingleton();
364
365        sCgDeferredProgram = sm->CreateFragmentProgram("deferred", "main", "deferredFrag");
366        sCgDeferredShadowProgram = sm->CreateFragmentProgram("deferred", "main_shadow", "deferredFragShader");
367        sCgSsaoProgram = sm->CreateFragmentProgram("ssao", "main", "ssaoFrag");
368        sCgGiProgram = sm->CreateFragmentProgram("globillum", "main", "giFrag");
369        sCgCombineIllumProgram = sm->CreateFragmentProgram("globillum", "combine", "combineGi");
370        sCgCombineSsaoProgram = sm->CreateFragmentProgram("combineSsao", "combine", "combineSsao");
371        sCgAntiAliasingProgram = sm->CreateFragmentProgram("antialiasing", "main", "antiAliasing");
372        sCgToneProgram = sm->CreateFragmentProgram("tonemap", "ToneMap", "toneMap");
373        sCgDownSampleProgram = sm->CreateFragmentProgram("deferred", "Output", "Output");
374        sCgScaleDepthProgram = sm->CreateFragmentProgram("deferred", "ScaleDepth", "ScaleDepth");
375        sCgLogLumProgram = sm->CreateFragmentProgram("tonemap", "CalcAvgLogLum", "avgLogLum");
376        sCgSmoothSsaoProgram = sm->CreateFragmentProgram("combineSsao", "smoothSsao", "smoothSsao");
377
378
379        ///////////////////
380        //-- initialize program parameters
381
382        string ssaoParams[] =
383                {"colors", "normals", "oldTex", "noiseTex", "temporalCoherence",
384                 "samples", "bl", "br", "tl", "tr",
385                 "modelViewProj", "oldModelViewProj", "oldEyePos", "oldbl", "oldbr",
386                 "oldtl", "oldtr", "attribsTex", "noiseTex1D"};
387        sCgSsaoProgram->AddParameters(ssaoParams, 0, 19);
388       
389        string giParams[] =
390                {"colors", "normals", "noiseTex", "oldSsaoTex", "oldIllumTex",
391                 "temporalCoherence", "samples", "bl", "br", "tl",
392                 "tr", "oldModelViewProj", "modelViewProj"};
393        sCgGiProgram->AddParameters(giParams, 0, 13);
394
395        string toneParams[] = {"colors", "imageKey", "whiteLum", "middleGrey"};
396        sCgToneProgram->AddParameters(toneParams, 0, 4);
397
398
399        ////////////////
400
401        string deferredShadowParams[] =
402                {"colors", "normals", "shadowMap", "noiseTex", "shadowMatrix",
403                 "sampleWidth", "lightDir", "eyePos", "samples", "weights"};
404       
405        sCgDeferredShadowProgram->AddParameters(deferredShadowParams, 0, 10);
406       
407        ////////////////
408
409        string combineIllumParams[] = {"colorsTex", "ssaoTex", "illumTex"};
410        sCgCombineIllumProgram->AddParameters(combineIllumParams, 0, 3);
411
412        ////////////////
413
414        string combineSsaoParams[] = {"colorsTex", "normalsTex", "ssaoTex", "filterOffs", "filterWeights", "bl", "br", "tl", "tr"};
415        sCgCombineSsaoProgram->AddParameters(combineSsaoParams, 0, 9);
416
417        //////////////
418
419        string deferredParams[] = {"colors", "normals", "lightDir"};
420        sCgDeferredProgram->AddParameters(deferredParams, 0, 3);
421
422        ///////////////////
423
424        string aaParams[] = {"colors", "normals", "offsets"};
425        sCgAntiAliasingProgram->AddParameters(aaParams, 0, 3);
426
427        /////////////////////
428
429        string downSampleParams[] = {"colors"};
430        sCgDownSampleProgram->AddParameters(downSampleParams, 0, 1);
431
432        /////////////////////
433
434        string scaleDepthParams[] = {"colors"};
435        sCgScaleDepthProgram->AddParameters(scaleDepthParams, 0, 1);
436
437        ////////////
438
439        sCgLogLumProgram->AddParameter("colors", 0);
440
441        ////////////////
442
443        string smoothSsaoParams[] = {"normalsTex", "ssaoTex", "filterOffs", "filterWeights"};
444        sCgSmoothSsaoProgram->AddParameters(smoothSsaoParams, 0, 4);
445       
446       
447        ///////////
448
449        const float filterWidth = 100.0f;
450        //const float filterWidth = 1000.0f;
451
452#if 1
453        PoissonDiscSampleGenerator2 poisson(NUM_SSAO_FILTERSAMPLES, 1.0f);
454        poisson.Generate((float *)ssaoFilterOffsets);
455
456        const float xoffs = (float)filterWidth / mWidth;
457        const float yoffs = (float)filterWidth / mHeight;
458
459        for (int i = 0; i < NUM_SSAO_FILTERSAMPLES; ++ i)
460        {
461                float x = ssaoFilterOffsets[2 * i + 0];
462                float y = ssaoFilterOffsets[2 * i + 1];
463
464                ssaoFilterWeights[i] = GaussianDistribution(x, y, 1.0f);
465                //ssaoFilterWeights[i] = 1.0f;
466
467                ssaoFilterOffsets[2 * i + 0] *= xoffs;
468                ssaoFilterOffsets[2 * i + 1] *= yoffs;
469        }
470#else
471        //ComputeSampleOffsets(ssaoFilterOffsets, mWidth, mHeight, sqrt(NUM_SSAO_FILTERSAMPLES), NUM_SSAO_FILTERSAMPLES);
472        ComputeSampleOffsets(ssaoFilterOffsets, mWidth, mHeight, filterWidth, NUM_SSAO_FILTERSAMPLES);
473        //cout<<"ssao filter size: " << NUM_SSAO_FILTERSAMPLES << endl;
474        for (int i = 0; i < NUM_SSAO_FILTERSAMPLES; ++ i)
475                ssaoFilterWeights[i] = 1.0f;
476
477#endif
478
479        ///////
480        //-- pcf tabs for shadowing
481
482        float filterWeights[NUM_PCF_TABS];
483        PoissonDiscSampleGenerator2 poisson2(NUM_PCF_TABS, 1.0f);
484        poisson2.Generate((float *)pcfSamples);
485
486        for (int i = 0; i < NUM_PCF_TABS; ++ i)
487        {
488                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
489        }
490
491        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
492        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
493
494        PrintGLerror("init");
495}
496
497
498void DeferredRenderer::Render(FrameBufferObject *fbo,
499                                                          float tempCohFactor,
500                                                          DirectionalLight *light,
501                                                          bool useToneMapping,
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                // colors
516                DownSample(fbo, colorBufferIdx, mDownSampleFbo, 0, sCgScaleDepthProgram);
517                DownSample(fbo, 1, mDownSampleFbo, 1, sCgDownSampleProgram); // normals
518                DownSample(fbo, 2, mDownSampleFbo, 2, sCgDownSampleProgram); // offsets
519        }
520
521        // antialiasing of the color buffer
522        //AntiAliasing(fbo, light);
523
524        switch (mShadingMethod)
525        {
526        case SSAO:
527                ComputeSsao(fbo, tempCohFactor);
528                SmoothSsao(fbo);
529                CombineSsao(fbo);
530                break;
531        case GI:
532                ComputeGlobIllum(fbo, tempCohFactor);
533                CombineIllum(fbo);
534                break;
535        default: // DEFAULT
536                // do nothing: standard deferred shading
537                break;
538        }
539
540        if (useToneMapping)
541        {
542                float imageKey, whiteLum, middleGrey;
543
544                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
545                ToneMap(fbo, imageKey, whiteLum, middleGrey);
546        }
547
548        // as multisampling is difficult / costly with deferred shading,
549        // at least do some antialiasing
550        AntiAliasing(fbo, light);
551
552        // just output the latest buffer
553        //Output(fbo);
554
555        glEnable(GL_LIGHTING);
556        glDisable(GL_TEXTURE_2D);
557
558        glMatrixMode(GL_PROJECTION);
559        glPopMatrix();
560
561        glMatrixMode(GL_MODELVIEW);
562        glPopMatrix();
563
564        // viewport
565        glPopAttrib();
566
567        FrameBufferObject::Release();
568        ShaderManager::GetSingleton()->DisableFragmentProfile();
569}
570
571
572void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo,
573                                                                   float tempCohFactor)
574{
575        GLuint colorsTex, normalsTex, attribsTex;
576
577        if (0)
578        {
579                colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
580                normalsTex = fbo->GetColorBuffer(1)->GetTexture();
581                attribsTex = fbo->GetColorBuffer(2)->GetTexture();
582        }
583        else
584        {
585                colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
586                normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
587                attribsTex = mDownSampleFbo->GetColorBuffer(2)->GetTexture();
588                //attribsTex = fbo->GetColorBuffer(2)->GetTexture();
589        }
590
591        // flip flop between illumination buffers
592        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
593
594        glPushAttrib(GL_VIEWPORT_BIT);
595        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
596
597        // read the second buffer, write to the first buffer
598        mIllumFbo->Bind();
599        glDrawBuffers(1, mrt + mIllumFboIndex);
600
601        int i = 0;
602
603        sCgSsaoProgram->SetTexture(i ++, colorsTex);
604        sCgSsaoProgram->SetTexture(i ++, normalsTex);
605        sCgSsaoProgram->SetTexture(i ++, oldTex);
606        sCgSsaoProgram->SetTexture(i ++, noiseTex2D);
607
608        sCgSsaoProgram->SetValue1f(i ++, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
609       
610        if (mUseTemporalCoherence || mRegenerateSamples)
611        //if (mRegenerateSamples)
612        {
613                mRegenerateSamples = false;
614
615                // q: should we generate new samples or only rotate the old ones?
616                // in the first case, the sample patterns look nicer, but the kernel
617                // needs longer to converge
618                GenerateSamples(mSamplingMethod);
619                sCgSsaoProgram->SetArray2f(i, (float *)samples2, NUM_SAMPLES);
620        }
621       
622        ++ i;
623
624        for (int j = 0; j < 4; ++ j, ++ i)
625                sCgSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
626
627        sCgSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
628        sCgSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
629
630        Vector3 de;
631        de.x = mOldEyePos.x - mEyePos.x;
632        de.y = mOldEyePos.y - mEyePos.y;
633        de.z = mOldEyePos.z - mEyePos.z;
634
635        sCgSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
636
637        for (int j = 0; j < 4; ++ j, ++ i)
638                sCgSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
639
640        sCgSsaoProgram->SetTexture(i ++, attribsTex);
641
642        sCgSsaoProgram->SetTexture(i ++, noiseTex1D);
643
644        DrawQuad(sCgSsaoProgram);
645
646        glPopAttrib();
647
648        PrintGLerror("ssao first pass");
649}
650
651
652static void SetVertex(float x, float y, float x_offs, float y_offs)
653{
654        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
655        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
656        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
657        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
658        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
659
660        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
661        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
662
663        //glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
664        glVertex2f(x, y);
665}
666
667
668void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo, DirectionalLight *light)
669{
670        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
671        GLuint colorsTex = colorBuffer->GetTexture();
672        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
673
674        FrameBufferObject::Release();
675        // read the second buffer, write to the first buffer
676        //FlipFbos(fbo);
677
678        // the neighbouring texels
679        float xOffs = 1.0f / fbo->GetWidth();
680        float yOffs = 1.0f / fbo->GetHeight();
681
682        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
683        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
684
685        float offsets[16];
686        int i = 0;
687
688        offsets[i] = -xOffs; offsets[i + 1] =  yOffs; i += 2; // left top
689        offsets[i] =  xOffs; offsets[i + 1] = -yOffs; i += 2; // right bottom
690        offsets[i] =  xOffs; offsets[i + 1] =  yOffs; i += 2; // right top
691        offsets[i] = -xOffs; offsets[i + 1] = -yOffs; i += 2; // left bottom
692        offsets[i] = -xOffs; offsets[i + 1] =    .0f; i += 2; // left
693        offsets[i] =  xOffs; offsets[i + 1] =    .0f; i += 2; // right
694        offsets[i] =    .0f; offsets[i + 1] =  yOffs; i += 2; // top
695        offsets[i] =    .0f; offsets[i + 1] = -yOffs; i += 2; // bottom
696
697        sCgAntiAliasingProgram->SetArray2f(2, offsets, 8);
698
699        DrawQuad(sCgAntiAliasingProgram);
700
701        PrintGLerror("antialiasing");
702}
703
704
705void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
706{
707        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
708        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
709
710        FlipFbos(fbo);
711
712        const Vector3 lightDir = -light->GetDirection();
713
714        sCgDeferredProgram->SetTexture(0, colorsTex);
715        sCgDeferredProgram->SetTexture(1, normalsTex);
716        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
717       
718        DrawQuad(sCgDeferredProgram);
719
720        PrintGLerror("deferred shading");
721}
722
723
724void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
725                                                                                float tempCohFactor)
726{
727#if 0
728        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
729        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
730#else
731        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
732        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
733#endif
734
735        glPushAttrib(GL_VIEWPORT_BIT);
736        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
737
738        // read the second buffer, write to the first buffer
739        mIllumFbo->Bind();
740
741        glDrawBuffers(2, mrt + mIllumFboIndex);
742
743        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
744        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
745
746        sCgGiProgram->SetTexture(0, colorsTex);
747        sCgGiProgram->SetTexture(1, normalsTex);
748        sCgGiProgram->SetTexture(2, noiseTex2D);
749        sCgGiProgram->SetTexture(3, oldSsaoTex);
750        sCgGiProgram->SetTexture(4, oldIllumTex);
751
752        sCgGiProgram->SetValue1f(5,
753                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
754
755        if (mUseTemporalCoherence || mRegenerateSamples)
756        {
757                mRegenerateSamples = false;
758
759                // q: should we generate new samples or only rotate the old ones?
760                // in the first case, the sample patterns look nicer, but the kernel
761                // needs longer to converge
762                GenerateSamples(mSamplingMethod);
763
764                sCgGiProgram->SetArray2f(6, (float *)samples2, NUM_SAMPLES);
765        }
766
767        Vector3 bl = mCornersView[0];
768        Vector3 br = mCornersView[1];
769        Vector3 tl = mCornersView[2];
770        Vector3 tr = mCornersView[3];
771
772        sCgGiProgram->SetValue3f(7, bl.x, bl.y, bl.z);
773        sCgGiProgram->SetValue3f(8, br.x, br.y, br.z);
774        sCgGiProgram->SetValue3f(9, tl.x, tl.y, tl.z);
775        sCgGiProgram->SetValue3f(10, tr.x, tr.y, tr.z);
776
777        sCgGiProgram->SetMatrix(11, mOldProjViewMatrix);
778        sCgGiProgram->SetMatrix(12, mProjViewMatrix);
779
780
781        DrawQuad(sCgGiProgram);
782
783        glPopAttrib();
784
785        PrintGLerror("globillum first pass");
786}
787
788
789void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
790{
791        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
792
793        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
794        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
795
796        FlipFbos(fbo);
797
798        sCgCombineIllumProgram->SetTexture(0, colorsTex);
799        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
800        sCgCombineIllumProgram->SetTexture(2, illumTex);
801       
802        DrawQuad(sCgCombineIllumProgram);
803
804        PrintGLerror("combine");
805}
806
807
808void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
809{
810        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
811        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
812        GLuint ssaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
813        //GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
814       
815        FlipFbos(fbo);
816
817        int i = 0;
818        sCgCombineSsaoProgram->SetTexture(i ++, colorsTex);
819        sCgCombineSsaoProgram->SetTexture(i ++, normalsTex);
820        sCgCombineSsaoProgram->SetTexture(i ++, ssaoTex);
821
822        sCgCombineSsaoProgram->SetArray2f(i ++, (float *)ssaoFilterOffsets, NUM_SSAO_FILTERSAMPLES);
823        sCgCombineSsaoProgram->SetArray1f(i ++, (float *)ssaoFilterWeights, NUM_SSAO_FILTERSAMPLES);
824       
825        Vector3 bl = mCornersView[0];
826        Vector3 br = mCornersView[1];
827        Vector3 tl = mCornersView[2];
828        Vector3 tr = mCornersView[3];
829
830        sCgCombineSsaoProgram->SetValue3f(i ++, bl.x, bl.y, bl.z);
831        sCgCombineSsaoProgram->SetValue3f(i ++, br.x, br.y, br.z);
832        sCgCombineSsaoProgram->SetValue3f(i ++, tl.x, tl.y, tl.z);
833        sCgCombineSsaoProgram->SetValue3f(i ++, tr.x, tr.y, tr.z);
834
835
836        DrawQuad(sCgCombineSsaoProgram);
837       
838        PrintGLerror("combine ssao");
839}
840
841
842void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
843                                                                           DirectionalLight *light,
844                                                                           ShadowMap *shadowMap)
845{
846        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
847        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
848
849        GLuint shadowTex = shadowMap->GetDepthTexture();
850
851        Matrix4x4 shadowMatrix;
852        shadowMap->GetTextureMatrix(shadowMatrix);
853
854
855        FlipFbos(fbo);
856
857        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
858        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
859        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
860        sCgDeferredShadowProgram->SetTexture(3, noiseTex2D);
861        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
862        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
863
864        const Vector3 lightDir = -light->GetDirection();
865        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
866        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
867
868        DrawQuad(sCgDeferredShadowProgram);
869
870        PrintGLerror("deferred shading + shadows");
871}
872
873
874void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
875{
876        if (s != mSamplingMethod)
877        {
878                mSamplingMethod = s;
879                mRegenerateSamples = true;
880        }
881}
882
883
884void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
885{
886        if (s != mShadingMethod)
887        {
888                mShadingMethod = s;
889                mRegenerateSamples = true;
890        }
891}
892
893
894void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
895                                                                                         DirectionalLight *light,
896                                                                                         float &imageKey,
897                                                                                         float &whiteLum,
898                                                                                         float &middleGrey)
899{
900        // hack: estimate value where sky burns out
901        whiteLum = log(WHITE_LUMINANCE);
902       
903        ////////////////////
904        //-- linear interpolate brightness key depending on the current sun position
905
906        const float minKey = 0.09f;
907        const float maxKey = 0.36f;
908
909        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
910        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
911
912
913        //////////
914        //-- compute avg loglum
915
916        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
917        GLuint colorsTex = colorBuffer->GetTexture();
918
919        FlipFbos(fbo);
920       
921        sCgLogLumProgram->SetTexture(0, colorsTex);
922        DrawQuad(sCgLogLumProgram);
923       
924        PrintGLerror("ToneMapParams");
925
926
927        ///////////////////
928        //-- compute avg loglum in scene using mipmapping
929
930        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
931        glGenerateMipmapEXT(GL_TEXTURE_2D);
932}
933
934
935static void ExportData(float *data, int w, int h)
936{
937        startil();
938
939        cout << "w: " << w << " h: " << h << endl;
940        ILstring filename = ILstring("downsample2.jpg");
941        ilRegisterType(IL_FLOAT);
942
943        const int depth = 1;
944        const int bpp = 4;
945
946        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
947        {
948                cerr << "IL error " << ilGetError() << endl;
949                stopil();
950                return;
951        }
952
953        if (!ilSaveImage(filename))
954        {
955                cerr << "TGA write error " << ilGetError() << endl;
956        }
957
958        stopil();
959}
960
961
962void DeferredRenderer::DownSample(FrameBufferObject *fbo,
963                                                                  int bufferIdx,
964                                                                  FrameBufferObject *downSampleFbo,
965                                                                  int downSampleBufferIdx,
966                                                                  ShaderProgram *program)
967{
968        ColorBufferObject *buffer = fbo->GetColorBuffer(bufferIdx);
969        GLuint tex = buffer->GetTexture();
970
971        glPushAttrib(GL_VIEWPORT_BIT);
972        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
973       
974        downSampleFbo->Bind();
975
976        program->SetTexture(0, tex);
977        glDrawBuffers(1, mrt + downSampleBufferIdx);
978
979        DrawQuad(program);
980       
981        glPopAttrib();
982        PrintGLerror("downsample");
983}
984
985
986void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
987                                                           float imageKey,
988                                                           float whiteLum,
989                                                           float middleGrey)
990{
991        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
992        GLuint colorsTex = colorBuffer->GetTexture();
993        //FrameBufferObject::Release();
994
995        FlipFbos(fbo);
996
997        sCgToneProgram->SetTexture(0, colorsTex);
998        sCgToneProgram->SetValue1f(1, imageKey);
999        sCgToneProgram->SetValue1f(2, whiteLum);
1000        sCgToneProgram->SetValue1f(3, middleGrey);
1001
1002        DrawQuad(sCgToneProgram);
1003
1004        PrintGLerror("ToneMap");
1005}
1006
1007
1008void DeferredRenderer::Output(FrameBufferObject *fbo)
1009{
1010        glPushAttrib(GL_VIEWPORT_BIT);
1011        glViewport(0, 0, fbo->GetWidth(), fbo->GetHeight());
1012       
1013        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1014        GLuint colorsTex = colorBuffer->GetTexture();
1015
1016        sCgDownSampleProgram->SetTexture(0, colorsTex);
1017
1018        FrameBufferObject::Release();
1019        DrawQuad(sCgDownSampleProgram);
1020
1021        PrintGLerror("output");
1022}
1023
1024
1025/*
1026void DeferredRenderer::BackProject(FrameBufferObject *fbo)
1027{
1028        // back project new frame into old one and check
1029        // if pixel still valid. store this property with ssao texture or even
1030        // betteer with color / depth texture. This way
1031        // we can sample this property together with the color / depth
1032        // values and we do not require additional texture lookups
1033        fbo->Bind();
1034
1035        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1036        //GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
1037
1038        // overwrite old color texture
1039        //colorBufferIdx = 3 - colorBufferIdx;
1040        //glDrawBuffers(1, mrt + colorBufferIdx);
1041        //glDrawBuffers(1, mrt + colorBufferIdx);
1042
1043        sCgCombineSsaoProgram->SetTexture(0, colorsTex);
1044        //sCgCombineSsaoProgram->SetTexture(1, ssaoTex);
1045
1046        DrawQuad(sCgBackProjectProgram);
1047       
1048        PrintGLerror("combine ssao");
1049}
1050*/
1051
1052
1053void DeferredRenderer::InitFrame()
1054{
1055        for (int i = 0; i < 4; ++ i)
1056                mOldCornersView[i] = mCornersView[i];
1057
1058        mOldProjViewMatrix = mProjViewMatrix;
1059        mOldEyePos = mEyePos;
1060        mEyePos = mCamera->GetPosition();
1061
1062        // hack: temporarily change far to improve precision
1063        const float oldFar = mCamera->GetFar();
1064        const float oldNear = mCamera->GetNear();
1065       
1066
1067        Matrix4x4 matViewing, matProjection;
1068
1069
1070        ///////////////////
1071
1072
1073        mCamera->GetViewOrientationMatrix(matViewing);
1074        mCamera->GetProjectionMatrix(matProjection);
1075
1076        mProjViewMatrix = matViewing * matProjection;
1077        ComputeViewVectors(mCamera, mCornersView[0], mCornersView[1], mCornersView[2], mCornersView[3]);
1078       
1079
1080        // switch roles of old and new fbo
1081        // the algorihm uses two input fbos, where the one
1082        // contais the color buffer from the last frame,
1083        // the other one will be written
1084
1085        mIllumFboIndex = 2 - mIllumFboIndex;
1086       
1087        // enable fragment shading
1088        ShaderManager::GetSingleton()->EnableFragmentProfile();
1089
1090        glDisable(GL_ALPHA_TEST);
1091        glDisable(GL_TEXTURE_2D);
1092        glDisable(GL_LIGHTING);
1093        glDisable(GL_BLEND);
1094        glDisable(GL_DEPTH_TEST);
1095
1096        glPolygonMode(GL_FRONT, GL_FILL);
1097
1098        glMatrixMode(GL_PROJECTION);
1099        glPushMatrix();
1100        glLoadIdentity();
1101
1102        gluOrtho2D(0, 1, 0, 1);
1103
1104
1105        glMatrixMode(GL_MODELVIEW);
1106        glPushMatrix();
1107        glLoadIdentity();
1108
1109       
1110        glPushAttrib(GL_VIEWPORT_BIT);
1111        glViewport(0, 0, mWidth, mHeight);
1112
1113        // revert to old far and near plane
1114        mCamera->SetFar(oldFar);
1115        mCamera->SetNear(oldNear);
1116}
1117
1118
1119void DeferredRenderer::SmoothSsao(FrameBufferObject *fbo)
1120{
1121        mIllumFbo->Bind();
1122
1123        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
1124        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
1125
1126        // overwrite old ssao texture
1127        glDrawBuffers(1, mrt + 2 - mIllumFboIndex);
1128
1129        glPushAttrib(GL_VIEWPORT_BIT);
1130        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
1131
1132        int i = 0;
1133        sCgSmoothSsaoProgram->SetTexture(i ++, normalsTex);
1134        sCgSmoothSsaoProgram->SetTexture(i ++, ssaoTex);
1135
1136        sCgSmoothSsaoProgram->SetArray2f(i ++, (float *)ssaoFilterOffsets, NUM_SSAO_FILTERSAMPLES);
1137        sCgSmoothSsaoProgram->SetArray1f(i ++, (float *)ssaoFilterWeights, NUM_SSAO_FILTERSAMPLES);
1138       
1139        DrawQuad(sCgSmoothSsaoProgram);
1140
1141        glPopAttrib();
1142
1143        PrintGLerror("combine ssao");
1144}
1145
1146
1147} // namespace
Note: See TracBrowser for help on using the repository browser.