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

Revision 3095, 28.0 KB checked in by mattausch, 16 years ago (diff)

probably improved temporal coherence but strange ssao

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