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

Revision 3132, 30.6 KB checked in by mattausch, 16 years ago (diff)

reordered functions: antialiasing comes after initial shading pass and before ssao.cgadded final output pass which does nothing but stream everything out

now ssao much nicer but slower!!

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