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

Revision 3103, 28.3 KB checked in by mattausch, 16 years ago (diff)

still some error with ssao on edges
bilateral filter slow

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        sCgAntiAliasingProgram = sm->CreateFragmentProgram("antialiasing", "main", "antiAliasing");
325        sCgToneProgram = sm->CreateFragmentProgram("tonemap", "ToneMap", "toneMap");
326        sCgDownSampleProgram = sm->CreateFragmentProgram("tonemap", "DownSample", "downSample");
327        sCgLogLumProgram = sm->CreateFragmentProgram("tonemap", "CalcAvgLogLum", "avgLogLum");
328
329        int i;
330
331        i = 0;
332        sCgSsaoProgram->AddParameter("colors", i ++);
333        sCgSsaoProgram->AddParameter("normals", i ++);
334        sCgSsaoProgram->AddParameter("oldTex", i ++);
335        sCgSsaoProgram->AddParameter("noiseTex", i ++);
336        sCgSsaoProgram->AddParameter("temporalCoherence", i ++);
337        sCgSsaoProgram->AddParameter("samples", i ++);
338        sCgSsaoProgram->AddParameter("bl", i ++);
339        sCgSsaoProgram->AddParameter("br", i ++);
340        sCgSsaoProgram->AddParameter("tl", i ++);
341        sCgSsaoProgram->AddParameter("tr", i ++);
342        sCgSsaoProgram->AddParameter("modelViewProj", i ++);
343        sCgSsaoProgram->AddParameter("oldModelViewProj", i ++);
344
345        sCgSsaoProgram->AddParameter("oldEyePos", i ++);
346        sCgSsaoProgram->AddParameter("oldbl", i ++);
347        sCgSsaoProgram->AddParameter("oldbr", i ++);
348        sCgSsaoProgram->AddParameter("oldtl", i ++);
349        sCgSsaoProgram->AddParameter("oldtr", i ++);
350       
351        i = 0;
352        sCgGiProgram->AddParameter("colors", i ++);
353        sCgGiProgram->AddParameter("normals", i ++);
354        sCgGiProgram->AddParameter("noiseTex", i ++);
355        sCgGiProgram->AddParameter("oldSsaoTex", i ++);
356        sCgGiProgram->AddParameter("oldIllumTex", i ++);
357        sCgGiProgram->AddParameter("temporalCoherence", i ++);
358        sCgGiProgram->AddParameter("samples", i ++);
359        sCgGiProgram->AddParameter("bl", i ++);
360        sCgGiProgram->AddParameter("br", i ++);
361        sCgGiProgram->AddParameter("tl", i ++);
362        sCgGiProgram->AddParameter("tr", i ++);
363        sCgGiProgram->AddParameter("oldModelViewProj", i ++);
364        sCgGiProgram->AddParameter("modelViewProj", i ++);
365
366        sCgAntiAliasingProgram->AddParameter("colors", 0);
367        sCgAntiAliasingProgram->AddParameter("normals", 1);
368
369        sCgDeferredProgram->AddParameter("colors", 0);
370        sCgDeferredProgram->AddParameter("normals", 1);
371        sCgDeferredProgram->AddParameter("lightDir", 2);
372
373        sCgLogLumProgram->AddParameter("colors", 0);
374       
375        sCgToneProgram->AddParameter("colors", 0);
376        sCgToneProgram->AddParameter("imageKey", 1);
377        sCgToneProgram->AddParameter("whiteLum", 2);
378        sCgToneProgram->AddParameter("middleGrey", 3);
379
380        sCgDownSampleProgram->AddParameter("colors", 0);
381        sCgDownSampleProgram->AddParameter("downSampleOffs", 1);
382
383        sCgDeferredShadowProgram->AddParameter("colors", 0);
384        sCgDeferredShadowProgram->AddParameter("normals", 1);
385        sCgDeferredShadowProgram->AddParameter("shadowMap", 2);
386        sCgDeferredShadowProgram->AddParameter("noise", 3);
387        sCgDeferredShadowProgram->AddParameter("shadowMatrix", 4);
388        sCgDeferredShadowProgram->AddParameter("sampleWidth", 5);
389        sCgDeferredShadowProgram->AddParameter("lightDir", 6);
390        sCgDeferredShadowProgram->AddParameter("eyePos", 7);
391        sCgDeferredShadowProgram->AddParameter("samples", 8);
392        sCgDeferredShadowProgram->AddParameter("weights", 9);
393
394        sCgCombineIllumProgram->AddParameter("colors", 0);
395        sCgCombineIllumProgram->AddParameter("ssaoTex", 1);
396        sCgCombineIllumProgram->AddParameter("illumTex", 2);
397
398        sCgCombineSsaoProgram->AddParameter("colorsTex", 0);
399        sCgCombineSsaoProgram->AddParameter("normalsTex", 1);
400        sCgCombineSsaoProgram->AddParameter("ssaoTex", 2);
401        sCgCombineSsaoProgram->AddParameter("filterOffs", 3);
402        sCgCombineSsaoProgram->AddParameter("filterWeights", 4);
403
404        PoissonDiscSampleGenerator2 poisson(NUM_SSAO_FILTERSAMPLES, 1.0f);
405        poisson.Generate((float *)ssaoFilterOffsets);
406
407        //const float filterWidth = 10.0f;
408        const float filterWidth = 5.0f;
409
410        //const float xoffs = filterWidth / mDownSampleFbo->GetWidth();
411        //const float yoffs = filterWidth / mDownSampleFbo->GetHeight();
412        const float xoffs = (float)filterWidth / 1024.0f;
413        const float yoffs = (float)filterWidth / 768.0f;
414
415        for (int i = 0; i < NUM_SSAO_FILTERSAMPLES; ++ i)
416        {
417                float x = ssaoFilterOffsets[2 * i + 0];
418                float y = ssaoFilterOffsets[2 * i + 1];
419
420                ssaoFilterOffsets[2 * i + 0] *= xoffs;
421                ssaoFilterOffsets[2 * i + 1] *= yoffs;
422
423                ssaoFilterWeights[i] = GaussianDistribution(x, y, 1.0f);
424        }
425
426
427        float filterWeights[NUM_PCF_TABS];
428        PoissonDiscSampleGenerator2 poisson2(NUM_PCF_TABS, 1.0f);
429        poisson2.Generate((float *)pcfSamples);
430
431        for (int i = 0; i < NUM_PCF_TABS; ++ i)
432        {
433                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
434        }
435
436        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
437        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
438
439        PrintGLerror("init");
440}
441
442
443void DeferredRenderer::Render(FrameBufferObject *fbo,
444                                                          float tempCohFactor,
445                                                          DirectionalLight *light,
446                                                          bool useToneMapping,
447                                                          ShadowMap *shadowMap
448                                                          )
449{
450        InitFrame();
451
452        if (shadowMap)
453                FirstPassShadow(fbo, light, shadowMap);
454        else
455                FirstPass(fbo, light);
456
457
458        if (mShadingMethod != 0)
459        {
460                // downsample fbo buffers for colors
461                DownSample(fbo, colorBufferIdx, mDownSampleFbo, 0);
462                // normals
463                DownSample(fbo, 1, mDownSampleFbo, 1);
464        }
465
466        switch (mShadingMethod)
467        {
468        case SSAO:
469
470                ComputeSsao(fbo, tempCohFactor);
471                CombineSsao(fbo);
472                break;
473        case GI:
474                ComputeGlobIllum(fbo, tempCohFactor);
475                CombineIllum(fbo);
476                break;
477        default: // DEFAULT
478                // do nothing: standard deferred shading
479                break;
480        }
481
482        if (useToneMapping)
483        {
484                float imageKey, whiteLum, middleGrey;
485
486                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
487                ToneMap(fbo, imageKey, whiteLum, middleGrey);
488        }
489
490        AntiAliasing(fbo, light);
491
492        glEnable(GL_LIGHTING);
493        glDisable(GL_TEXTURE_2D);
494
495        glMatrixMode(GL_PROJECTION);
496        glPopMatrix();
497
498        glMatrixMode(GL_MODELVIEW);
499        glPopMatrix();
500
501        // viewport
502        glPopAttrib();
503
504        FrameBufferObject::Release();
505        ShaderManager::GetSingleton()->DisableFragmentProfile();
506}
507
508
509void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo,
510                                                                   float tempCohFactor)
511{
512#if 0
513        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
514        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
515#else
516        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
517        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
518#endif
519
520        // flip flop between illumination buffers
521        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
522
523        glPushAttrib(GL_VIEWPORT_BIT);
524        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
525
526        // read the second buffer, write to the first buffer
527        mIllumFbo->Bind();
528        glDrawBuffers(1, mrt + mIllumFboIndex);
529
530        int i = 0;
531
532        sCgSsaoProgram->SetTexture(i ++, colorsTex);
533        sCgSsaoProgram->SetTexture(i ++, normalsTex);
534        sCgSsaoProgram->SetTexture(i ++, oldTex);
535        sCgSsaoProgram->SetTexture(i ++, noiseTex);
536
537        sCgSsaoProgram->SetValue1f(i ++, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
538       
539        if (mUseTemporalCoherence || mRegenerateSamples)
540        {
541                mRegenerateSamples = false;
542
543                // q: should we generate new samples or only rotate the old ones?
544                // in the first case, the sample patterns look nicer, but the kernel
545                // needs longer to converge
546                GenerateSamples(mSamplingMethod);
547                sCgSsaoProgram->SetArray2f(i, (float *)samples2, NUM_SAMPLES);
548        }
549       
550        ++ i;
551
552        for (int j = 0; j < 4; ++ j, ++ i)
553                sCgSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
554
555        sCgSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
556        sCgSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
557
558        Vector3 de = mOldEyePos - mEyePos;
559        //Vector3 de = mEyePos - mOldEyePos;
560
561        sCgSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
562
563        for (int j = 0; j < 4; ++ j, ++ i)
564                sCgSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
565
566        DrawQuad(sCgSsaoProgram);
567
568        glPopAttrib();
569
570        PrintGLerror("ssao first pass");
571}
572
573
574static void SetVertex(float x, float y, float x_offs, float y_offs)
575{
576        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
577        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
578        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
579        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
580        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
581
582        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
583        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
584
585        //glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
586        glVertex2f(x, y);
587}
588
589
590void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo, DirectionalLight *light)
591{
592        FrameBufferObject::Release();
593
594        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
595
596        GLuint colorsTex = colorBuffer->GetTexture();
597        GLuint normalsTex = fbo->GetColorBuffer(2)->GetTexture();
598
599        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
600        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
601
602        sCgAntiAliasingProgram->Bind();
603
604        glBegin(GL_QUADS);
605
606        // the neighbouring texels
607        float x_offs = 1.0f / mWidth;
608        float y_offs = 1.0f / mHeight;
609
610        SetVertex(0, 0, x_offs, y_offs);
611        SetVertex(1, 0, x_offs, y_offs);
612        SetVertex(1, 1, x_offs, y_offs);
613        SetVertex(0, 1, x_offs, y_offs);
614
615        glEnd();
616
617        PrintGLerror("antialiasing");
618}
619
620
621void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
622{
623        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
624        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
625
626        fbo->Bind();
627
628        colorBufferIdx = 3 - colorBufferIdx;
629        glDrawBuffers(1, mrt + colorBufferIdx);
630
631        const Vector3 lightDir = -light->GetDirection();
632
633        sCgDeferredProgram->SetTexture(0, colorsTex);
634        sCgDeferredProgram->SetTexture(1, normalsTex);
635        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
636       
637        DrawQuad(sCgDeferredProgram);
638
639        PrintGLerror("deferred shading");
640}
641
642
643void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
644                                                                                float tempCohFactor)
645{
646#if 0
647        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
648        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
649#else
650        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
651        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
652#endif
653
654        glPushAttrib(GL_VIEWPORT_BIT);
655        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
656
657        // read the second buffer, write to the first buffer
658        mIllumFbo->Bind();
659
660        glDrawBuffers(2, mrt + mIllumFboIndex);
661
662        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
663        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
664       
665
666        sCgGiProgram->SetTexture(0, colorsTex);
667        sCgGiProgram->SetTexture(1, normalsTex);
668        sCgGiProgram->SetTexture(2, noiseTex);
669        sCgGiProgram->SetTexture(3, oldSsaoTex);
670        sCgGiProgram->SetTexture(4, oldIllumTex);
671
672        sCgGiProgram->SetValue1f(5,
673                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
674
675        if (mUseTemporalCoherence || mRegenerateSamples)
676        {
677                mRegenerateSamples = false;
678
679                // q: should we generate new samples or only rotate the old ones?
680                // in the first case, the sample patterns look nicer, but the kernel
681                // needs longer to converge
682                GenerateSamples(mSamplingMethod);
683
684                sCgGiProgram->SetArray2f(6, (float *)samples2, NUM_SAMPLES);
685        }
686
687        Vector3 bl = mCornersView[0];
688        Vector3 br = mCornersView[1];
689        Vector3 tl = mCornersView[2];
690        Vector3 tr = mCornersView[3];
691
692        sCgGiProgram->SetValue3f(7, bl.x, bl.y, bl.z);
693        sCgGiProgram->SetValue3f(8, br.x, br.y, br.z);
694        sCgGiProgram->SetValue3f(9, tl.x, tl.y, tl.z);
695        sCgGiProgram->SetValue3f(10, tr.x, tr.y, tr.z);
696
697        sCgGiProgram->SetMatrix(11, mOldProjViewMatrix);
698        sCgGiProgram->SetMatrix(12, mProjViewMatrix);
699
700
701        DrawQuad(sCgGiProgram);
702
703        glPopAttrib();
704
705        PrintGLerror("globillum first pass");
706}
707
708
709void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
710{
711        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
712
713        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
714        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
715
716
717        fbo->Bind();
718
719        // overwrite old color texture
720        colorBufferIdx = 3 - colorBufferIdx;
721
722        glDrawBuffers(1, mrt + colorBufferIdx);
723
724        sCgCombineIllumProgram->SetTexture(0, colorsTex);
725        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
726        sCgCombineIllumProgram->SetTexture(2, illumTex);
727       
728        DrawQuad(sCgCombineIllumProgram);
729
730        PrintGLerror("combine");
731}
732
733
734void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
735{
736        fbo->Bind();
737
738        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
739        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
740        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
741
742        // overwrite old color texture
743        colorBufferIdx = 3 - colorBufferIdx;
744        glDrawBuffers(1, mrt + colorBufferIdx);
745
746        sCgCombineSsaoProgram->SetTexture(0, colorsTex);
747        sCgCombineSsaoProgram->SetTexture(1, normalsTex);
748        sCgCombineSsaoProgram->SetTexture(2, ssaoTex);
749
750        sCgCombineSsaoProgram->SetArray2f(3, (float *)ssaoFilterOffsets, NUM_SSAO_FILTERSAMPLES);
751        sCgCombineSsaoProgram->SetArray1f(4, (float *)ssaoFilterWeights, NUM_SSAO_FILTERSAMPLES);
752       
753        DrawQuad(sCgCombineSsaoProgram);
754       
755        PrintGLerror("combine ssao");
756}
757
758
759void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
760                                                                           DirectionalLight *light,
761                                                                           ShadowMap *shadowMap)
762{
763        fbo->Bind();
764
765        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
766        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
767
768        GLuint shadowTex = shadowMap->GetDepthTexture();
769
770        Matrix4x4 shadowMatrix;
771        shadowMap->GetTextureMatrix(shadowMatrix);
772
773        colorBufferIdx = 3 - colorBufferIdx;
774        glDrawBuffers(1, mrt + colorBufferIdx);
775
776        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
777        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
778        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
779        sCgDeferredShadowProgram->SetTexture(3, noiseTex);
780        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
781        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
782
783        const Vector3 lightDir = -light->GetDirection();
784        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
785        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
786
787        DrawQuad(sCgDeferredShadowProgram);
788
789        PrintGLerror("deferred shading + shadows");
790}
791
792
793void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
794{
795        if (s != mSamplingMethod)
796        {
797                mSamplingMethod = s;
798                mRegenerateSamples = true;
799        }
800}
801
802
803void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
804{
805        if (s != mShadingMethod)
806        {
807                mShadingMethod = s;
808                mRegenerateSamples = true;
809        }
810}
811
812
813void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
814                                                                                         DirectionalLight *light,
815                                                                                         float &imageKey,
816                                                                                         float &whiteLum,
817                                                                                         float &middleGrey)
818{
819        // hack: estimate value where sky burns out
820        whiteLum = log(WHITE_LUMINANCE);
821       
822        ////////////////////
823        //-- linear interpolate brightness key depending on the current sun position
824
825        const float minKey = 0.09f;
826        const float maxKey = 0.36f;
827
828        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
829        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
830
831
832        //////////
833        //-- compute avg loglum
834
835        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
836        GLuint colorsTex = colorBuffer->GetTexture();
837
838        fbo->Bind();
839
840        colorBufferIdx = 3 - colorBufferIdx;
841        glDrawBuffers(1, mrt + colorBufferIdx);
842       
843        sCgLogLumProgram->SetTexture(0, colorsTex);
844        DrawQuad(sCgLogLumProgram);
845       
846        PrintGLerror("ToneMapParams");
847
848
849        ///////////////////
850        //-- compute avg loglum in scene using mipmapping
851
852        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
853        glGenerateMipmapEXT(GL_TEXTURE_2D);
854}
855
856
857static void ExportData(float *data, int w, int h)
858{
859        startil();
860
861        cout << "w: " << w << " h: " << h << endl;
862        ILstring filename = ILstring("downsample2.jpg");
863        ilRegisterType(IL_FLOAT);
864
865        const int depth = 1;
866        const int bpp = 4;
867
868        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
869        {
870                cerr << "IL error " << ilGetError() << endl;
871                stopil();
872                return;
873        }
874
875        if (!ilSaveImage(filename))
876        {
877                cerr << "TGA write error " << ilGetError() << endl;
878        }
879
880        stopil();
881}
882
883
884void DeferredRenderer::DownSample(FrameBufferObject *fbo,
885                                                                  int bufferIdx,
886                                                                  FrameBufferObject *downSampleFbo,
887                                                                  int downSampleBufferIdx)
888{
889        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(bufferIdx);
890        GLuint colorsTex = colorBuffer->GetTexture();
891
892        glPushAttrib(GL_VIEWPORT_BIT);
893        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
894       
895        sCgDownSampleProgram->SetTexture(0, colorsTex);
896
897        float downSampleOffsets[NUM_DOWNSAMPLES * 2];
898        ComputeSampleOffsets(downSampleOffsets, fbo->GetWidth(), fbo->GetHeight());
899
900        sCgDownSampleProgram->SetArray2f(1, (float *)downSampleOffsets, NUM_DOWNSAMPLES);
901
902        mDownSampleFbo->Bind();
903        glDrawBuffers(1, mrt + downSampleBufferIdx);
904
905        DrawQuad(sCgDownSampleProgram);
906       
907        glPopAttrib();
908       
909        PrintGLerror("downsample");
910}
911
912
913void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
914                                                           float imageKey,
915                                                           float whiteLum,
916                                                           float middleGrey)
917{
918        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
919        GLuint colorsTex = colorBuffer->GetTexture();
920
921        fbo->Bind();
922       
923        colorBufferIdx = 3 - colorBufferIdx;
924        glDrawBuffers(1, mrt + colorBufferIdx);
925
926        sCgToneProgram->SetTexture(0, colorsTex);
927        sCgToneProgram->SetValue1f(1, imageKey);
928        sCgToneProgram->SetValue1f(2, whiteLum);
929        sCgToneProgram->SetValue1f(3, middleGrey);
930
931        DrawQuad(sCgToneProgram);
932
933        PrintGLerror("ToneMap");
934}
935
936
937/*
938void DeferredRenderer::BackProject(FrameBufferObject *fbo)
939{
940        // back project new frame into old one and check
941        // if pixel still valid. store this property with ssao texture or even
942        // betteer with color / depth texture. This way
943        // we can sample this property together with the color / depth
944        // values and we do not require additional texture lookups
945        fbo->Bind();
946
947        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
948        //GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
949
950        // overwrite old color texture
951        //colorBufferIdx = 3 - colorBufferIdx;
952        //glDrawBuffers(1, mrt + colorBufferIdx);
953        //glDrawBuffers(1, mrt + colorBufferIdx);
954
955        sCgCombineSsaoProgram->SetTexture(0, colorsTex);
956        //sCgCombineSsaoProgram->SetTexture(1, ssaoTex);
957
958        DrawQuad(sCgBackProjectProgram);
959       
960        PrintGLerror("combine ssao");
961}
962*/
963
964
965void DeferredRenderer::InitFrame()
966{
967        for (int i = 0; i < 4; ++ i)
968                mOldCornersView[i] = mCornersView[i];
969
970        mOldProjViewMatrix = mProjViewMatrix;
971        mOldEyePos = mEyePos;
972
973
974        ///////////////////
975
976        Matrix4x4 matViewing, matProjection;
977
978        //mCamera->GetModelViewMatrix(matViewing);
979        mCamera->GetViewOrientationMatrix(matViewing);
980        mCamera->GetProjectionMatrix(matProjection);
981
982        mProjViewMatrix = matViewing * matProjection;
983        ComputeViewVectors(mCamera, mCornersView[0], mCornersView[1], mCornersView[2], mCornersView[3]);
984        mEyePos = mCamera->GetPosition();
985
986
987        // switch roles of old and new fbo
988        // the algorihm uses two input fbos, where the one
989        // contais the color buffer from the last frame,
990        // the other one will be written
991
992        mIllumFboIndex = 2 - mIllumFboIndex;
993       
994        // enable fragment shading
995        ShaderManager::GetSingleton()->EnableFragmentProfile();
996
997        glDisable(GL_ALPHA_TEST);
998        glDisable(GL_TEXTURE_2D);
999        glDisable(GL_LIGHTING);
1000        glDisable(GL_BLEND);
1001        glDisable(GL_DEPTH_TEST);
1002
1003        glPolygonMode(GL_FRONT, GL_FILL);
1004
1005        glMatrixMode(GL_PROJECTION);
1006        glPushMatrix();
1007        glLoadIdentity();
1008
1009        gluOrtho2D(0, 1, 0, 1);
1010
1011
1012        glMatrixMode(GL_MODELVIEW);
1013        glPushMatrix();
1014        glLoadIdentity();
1015
1016       
1017        glPushAttrib(GL_VIEWPORT_BIT);
1018        glViewport(0, 0, mWidth, mHeight);
1019}
1020
1021
1022} // namespace
Note: See TracBrowser for help on using the repository browser.