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

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