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

Revision 3105, 27.5 KB checked in by mattausch, 16 years ago (diff)

now strafing up not working anymore!!!!

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