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

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