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

Revision 3085, 28.3 KB checked in by mattausch, 16 years ago (diff)
RevLine 
[2896]1#include "DeferredRenderer.h"
[2859]2#include "FrameBufferObject.h"
3#include "RenderState.h"
4#include "SampleGenerator.h"
[2860]5#include "Vector3.h"
6#include "Camera.h"
[2884]7#include "shaderenv.h"
[2886]8#include "Halton.h"
[2895]9#include "ShadowMapping.h"
[2952]10#include "Light.h"
[3057]11#include "ShaderManager.h"
[2858]12
[3003]13#include <IL/il.h>
14#include <assert.h>
[2859]15
[3003]16
[3021]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
[2858]28using namespace std;
29
30
[3003]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
[2858]44namespace CHCDemoEngine
45{
46
[3026]47static ShaderProgram *sCgSsaoProgram = NULL;
48static ShaderProgram *sCgGiProgram = NULL;
[2873]49
[3026]50static ShaderProgram *sCgDeferredProgram = NULL;
51static ShaderProgram *sCgAntiAliasingProgram = NULL;
52static ShaderProgram *sCgDeferredShadowProgram = NULL;
[2859]53
[3026]54static ShaderProgram *sCgCombineSsaoProgram = NULL;
55static ShaderProgram *sCgCombineIllumProgram = NULL;
56static ShaderProgram *sCgLogLumProgram = NULL;
57static ShaderProgram *sCgToneProgram = NULL;
58static ShaderProgram *sCgDownSampleProgram = NULL;
[2869]59
[3019]60ShaderContainer DeferredRenderer::sShaders;
[2992]61
[2879]62static GLuint noiseTex = 0;
[2865]63
[2859]64// ssao random spherical samples
[2903]65static Sample2 samples2[NUM_SAMPLES];
[2966]66// number of pcf tabs
67Sample2 pcfSamples[NUM_PCF_TABS];
68
[3026]69
[2976]70int DeferredRenderer::colorBufferIdx = 0;
[2859]71
[2992]72
[3085]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;
[3025]78
[3085]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
[3025]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
[2859]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
[3017]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;
[2859]114
[3017]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;
[2976]125
[3017]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
[3026]140
141void DeferredRenderer::DrawQuad(ShaderProgram *p)
142{
143        p->Bind();
144
[3085]145        Vector3 bl = mCornersView[0];
146        Vector3 br = mCornersView[1];
147        Vector3 tl = mCornersView[2];
148        Vector3 tr = mCornersView[3];
149
[3026]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
[2859]164/** Generate poisson disc distributed sample points on the unit disc
165*/
[2887]166static void GenerateSamples(int sampling)
[2859]167{
[2887]168        switch (sampling)
169        {
[2930]170        case DeferredRenderer::SAMPLING_POISSON:
[2887]171                {
[2930]172                        PoissonDiscSampleGenerator2 poisson(NUM_SAMPLES, 1.0f);
[2900]173                        poisson.Generate((float *)samples2);
[2887]174                }
175                break;
[2930]176        case DeferredRenderer::SAMPLING_QUADRATIC:
[2887]177                {
[2930]178                        QuadraticDiscSampleGenerator2 g(NUM_SAMPLES, 1.0f);
179                        g.Generate((float *)samples2);
[2887]180                }
181                break;
[2930]182        default: // SAMPLING_DEFAULT
[3026]183                {
184                        RandomSampleGenerator2 g(NUM_SAMPLES, 1.0f);
185                        g.Generate((float *)samples2);
186                }
[2903]187        }
[2859]188}
189
190
[2879]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
[2900]196        static HaltonSequence halton;
197        float r[2];
198
[2879]199        for (int i = 0; i < w * h * 3; i += 3)
200        {
[2903]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;
[2879]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
[3019]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
[3068]246DeferredRenderer::DeferredRenderer(int w, int h, PerspectiveCamera *cam):
[2860]247mWidth(w), mHeight(h),
248mCamera(cam),
[2875]249mUseTemporalCoherence(true),
[2895]250mRegenerateSamples(true),
[2930]251mSamplingMethod(SAMPLING_POISSON),
[2895]252mShadingMethod(DEFAULT),
[3019]253mIllumFboIndex(0)
[2861]254{
255        ///////////
256        //-- the flip-flop fbos
[2859]257
[3019]258        mIllumFbo = new FrameBufferObject(w / 2, h / 2, FrameBufferObject::DEPTH_NONE);
259        mFBOs.push_back(mIllumFbo);
[2891]260
[3019]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        }
[3002]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);
[3017]269        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3019]270
271        mFBOs.push_back(mDownSampleFbo);
[3038]272
[3084]273        // create noise texture for ssao
274        CreateNoiseTex2D(mDownSampleFbo->GetWidth(), mDownSampleFbo->GetHeight());
275
[3085]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
[3038]286        InitCg();
[2861]287}
288
289
[2896]290DeferredRenderer::~DeferredRenderer()
[2861]291{
[3019]292        CLEAR_CONTAINER(mFBOs);
[2861]293        glDeleteTextures(1, &noiseTex);
294}
295
296
[2896]297void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
[2875]298{
299        mUseTemporalCoherence = temporal;
300}
301
302
[3021]303
[3038]304void DeferredRenderer::InitCg()
[3026]305{       
[3057]306        ShaderManager *sm = ShaderManager::GetSingleton();
[2873]307
[3057]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");
[3038]318
[3034]319        int i;
320
321        i = 0;
322        sCgSsaoProgram->AddParameter("colors", i ++);
[3035]323        sCgSsaoProgram->AddParameter("normals", i ++);
[3034]324        sCgSsaoProgram->AddParameter("oldTex", i ++);
[3084]325        sCgSsaoProgram->AddParameter("noiseTex", i ++);
[3034]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 ++);
[3035]333        sCgSsaoProgram->AddParameter("modelViewProj", i ++);
334        sCgSsaoProgram->AddParameter("oldModelViewProj", i ++);
[3034]335
[3085]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       
[3034]342        i = 0;
343        sCgGiProgram->AddParameter("colors", i ++);
[3035]344        sCgGiProgram->AddParameter("normals", i ++);
[3084]345        sCgGiProgram->AddParameter("noiseTex", i ++);
[3034]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 ++);
[3035]355        sCgGiProgram->AddParameter("oldModelViewProj", i ++);
356        sCgGiProgram->AddParameter("modelViewProj", i ++);
[3034]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
[3035]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);
[3034]371
[3035]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
[3036]386        sCgCombineIllumProgram->AddParameter("colors", 0);
387        sCgCombineIllumProgram->AddParameter("ssaoTex", 1);
388        sCgCombineIllumProgram->AddParameter("illumTex", 2);
[3035]389
[3036]390        sCgCombineSsaoProgram->AddParameter("colors", 0);
391        sCgCombineSsaoProgram->AddParameter("ssaoTex", 1);
392        sCgCombineSsaoProgram->AddParameter("filterOffs", 2);
393        sCgCombineSsaoProgram->AddParameter("filterWeights", 3);
394
395
[3026]396        float filterWeights[NUM_PCF_TABS];
397        PoissonDiscSampleGenerator2 poisson(NUM_PCF_TABS, 1.0f);
398        poisson.Generate((float *)pcfSamples);
[2990]399
[3026]400        for (int i = 0; i < NUM_PCF_TABS; ++ i)
[2880]401        {
[3026]402                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
[2880]403        }
404
[3035]405        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
406        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
[2880]407
[2859]408        PrintGLerror("init");
409}
410
411
[2896]412void DeferredRenderer::Render(FrameBufferObject *fbo,
[2901]413                                                          float tempCohFactor,
[2952]414                                                          DirectionalLight *light,
[2991]415                                                          bool useToneMapping,
416                                                          ShadowMap *shadowMap
417                                                          )
[2859]418{
[3085]419        InitFrame();
420
[2868]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
[2897]425
[3019]426        mIllumFboIndex = 2 - mIllumFboIndex;
[2976]427       
[3006]428
[3057]429        ShaderManager::GetSingleton()->EnableFragmentProfile();
[2867]430
431        glDisable(GL_ALPHA_TEST);
432        glDisable(GL_TEXTURE_2D);
433        glDisable(GL_LIGHTING);
[3007]434        glDisable(GL_BLEND);
[3008]435        glDisable(GL_DEPTH_TEST);
[2867]436
[2880]437        glPushAttrib(GL_VIEWPORT_BIT);
438        glViewport(0, 0, mWidth, mHeight);
439
[2867]440        glMatrixMode(GL_PROJECTION);
441        glPushMatrix();
442        glLoadIdentity();
443
[2897]444        const float offs = 0.5f;
445        glOrtho(-offs, offs, -offs, offs, 0, 1);
446
[2867]447        glMatrixMode(GL_MODELVIEW);
448        glPushMatrix();
449        glLoadIdentity();
450
[2944]451        if (shadowMap)
[2952]452                FirstPassShadow(fbo, light, shadowMap);
[2895]453        else
[2952]454                FirstPass(fbo, light);
[2944]455
456        switch (mShadingMethod)
[2880]457        {
[2944]458        case SSAO:
[3009]459                // downsample fbo buffers for colors, normals
[3006]460                DownSample(fbo, colorBufferIdx, mDownSampleFbo, 0);
461                DownSample(fbo, 1, mDownSampleFbo, 1);
462
[3085]463                ComputeSsao(fbo, tempCohFactor);
[2944]464                CombineSsao(fbo);
465                break;
466        case GI:
[3009]467                // downsample fbo buffers for colors, normals
[3006]468                DownSample(fbo, colorBufferIdx, mDownSampleFbo, 0);
[3009]469                DownSample(fbo, 1, mDownSampleFbo, 1);
470
[3085]471                ComputeGlobIllum(fbo, tempCohFactor);
[2944]472                CombineIllum(fbo);
473                break;
474        default: // DEFAULT
475                // do nothing: standard deferred shading
476                break;
477        }
[2884]478
[2991]479        if (useToneMapping)
480        {
481                float imageKey, whiteLum, middleGrey;
482
483                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
[3007]484                ToneMap(fbo, imageKey, whiteLum, middleGrey);
[2991]485        }
486
[2970]487        AntiAliasing(fbo, light);
[2867]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
[3007]500        FrameBufferObject::Release();
[3057]501        ShaderManager::GetSingleton()->DisableFragmentProfile();
[2859]502}
503
504
[2896]505void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo,
[3085]506                                                                   float tempCohFactor
507                                                                   
[2900]508                                                                   )
[2859]509{
[3016]510#if 0
[3015]511        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
512        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
513#else
[3006]514        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
[3009]515        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
[3015]516#endif
517
[3019]518        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
[2993]519
[3006]520        glPushAttrib(GL_VIEWPORT_BIT);
[3019]521        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
[3006]522
[2861]523        // read the second buffer, write to the first buffer
[3019]524        mIllumFbo->Bind();
525        glDrawBuffers(1, mrt + mIllumFboIndex);
[2868]526
[3034]527        sCgSsaoProgram->SetTexture(0, colorsTex);
528        sCgSsaoProgram->SetTexture(1, normalsTex);
529        sCgSsaoProgram->SetTexture(2, oldTex);
530        sCgSsaoProgram->SetTexture(3, noiseTex);
531
[3085]532        sCgSsaoProgram->SetValue3f(4, mEyePos.x, mEyePos.y, mEyePos.z);
[3027]533
[3034]534        sCgSsaoProgram->SetValue1f(5, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
[3035]535       
[2895]536        if (mUseTemporalCoherence || mRegenerateSamples)
[2875]537        {
[2895]538                mRegenerateSamples = false;
[2859]539
[2875]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
[2895]543                GenerateSamples(mSamplingMethod);
[3035]544                sCgSsaoProgram->SetArray2f(6, (float *)samples2, NUM_SAMPLES);
[2875]545        }
[3085]546       
547        Vector3 bl = mCornersView[0];
548        Vector3 br = mCornersView[1];
549        Vector3 tl = mCornersView[2];
550        Vector3 tr = mCornersView[3];
[2859]551
[3035]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);
[2987]556
[3063]557        //cout << "new projview:\n" << projViewMatrix << endl;
558        //cout << "old projview:\n" << oldProjViewMatrix << endl;
[3062]559
[3085]560        sCgSsaoProgram->SetMatrix(11, mProjViewMatrix);
561        sCgSsaoProgram->SetMatrix(12, mOldProjViewMatrix);
[3035]562
[3085]563        bl = mOldCornersView[0];
564        br = mOldCornersView[1];
565        tl = mOldCornersView[2];
566        tr = mOldCornersView[3];
[3035]567
[3085]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
[3026]575        DrawQuad(sCgSsaoProgram);
[2987]576
[3006]577        glPopAttrib();
[2859]578
579        PrintGLerror("ssao first pass");
580}
581
582
[2865]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
[2970]598void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo, DirectionalLight *light)
[2865]599{
[3007]600        FrameBufferObject::Release();
601
[2968]602        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2967]603
[2968]604        GLuint colorsTex = colorBuffer->GetTexture();
[2865]605        GLuint normalsTex = fbo->GetColorBuffer(2)->GetTexture();
[3007]606
[3034]607        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
608        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
[2865]609
[3026]610        sCgAntiAliasingProgram->Bind();
[2868]611
[2865]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
[2867]627        PrintGLerror("antialiasing");
[2865]628}
629
630
[2952]631void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
[2868]632{
[2973]633        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]634        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[2868]635
[2879]636        fbo->Bind();
[2868]637
[2973]638        colorBufferIdx = 3 - colorBufferIdx;
[2899]639        glDrawBuffers(1, mrt + colorBufferIdx);
[2868]640
[3026]641        const Vector3 lightDir = -light->GetDirection();
[2868]642
[3034]643        sCgDeferredProgram->SetTexture(0, colorsTex);
644        sCgDeferredProgram->SetTexture(1, normalsTex);
645        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
[2868]646       
[3026]647        DrawQuad(sCgDeferredProgram);
[2952]648
[2868]649        PrintGLerror("deferred shading");
650}
651
[2869]652
[2896]653void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
[3085]654                                                                                float tempCohFactor)
[2869]655{
[3016]656#if 0
657        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
658        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
659#else
[3003]660        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
[3009]661        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
[3016]662#endif
[2869]663
[3006]664        glPushAttrib(GL_VIEWPORT_BIT);
[3019]665        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
[2869]666
[2873]667        // read the second buffer, write to the first buffer
[3019]668        mIllumFbo->Bind();
[2873]669
[3019]670        glDrawBuffers(2, mrt + mIllumFboIndex);
[2873]671
[3019]672        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
673        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
[3006]674       
[2869]675
[3034]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);
[2869]681
[3085]682        sCgGiProgram->SetValue3f(5, mEyePos.x, mEyePos.y, mEyePos.z);
[3034]683
684
685        sCgGiProgram->SetValue1f(6,
[3026]686                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
[2869]687
[2895]688        if (mUseTemporalCoherence || mRegenerateSamples)
[2875]689        {
[2895]690                mRegenerateSamples = false;
[2873]691
[2875]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
[2895]695                GenerateSamples(mSamplingMethod);
[2903]696
[3034]697                sCgGiProgram->SetArray2f(7, (float *)samples2, NUM_SAMPLES);
[2875]698        }
699
[3085]700        Vector3 bl = mCornersView[0];
701        Vector3 br = mCornersView[1];
702        Vector3 tl = mCornersView[2];
703        Vector3 tr = mCornersView[3];
[2895]704
[3034]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);
[2873]709
[3085]710        sCgGiProgram->SetMatrix(12, mOldProjViewMatrix);
711        sCgGiProgram->SetMatrix(13, mProjViewMatrix);
[3035]712
713
[3026]714        DrawQuad(sCgGiProgram);
[2990]715
[3006]716        glPopAttrib();
717
[2873]718        PrintGLerror("globillum first pass");
[2869]719}
720
721
[2896]722void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
[2880]723{
[2973]724        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[2884]725
[3019]726        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
727        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
[2880]728
[2891]729
[2880]730        fbo->Bind();
731
[2884]732        // overwrite old color texture
[2973]733        colorBufferIdx = 3 - colorBufferIdx;
734
[2899]735        glDrawBuffers(1, mrt + colorBufferIdx);
[2880]736
[3036]737        sCgCombineIllumProgram->SetTexture(0, colorsTex);
738        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
739        sCgCombineIllumProgram->SetTexture(2, illumTex);
[2880]740       
[3026]741        DrawQuad(sCgCombineIllumProgram);
[2880]742
743        PrintGLerror("combine");
744}
745
746
[2896]747void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
[2880]748{
[2973]749        fbo->Bind();
750
751        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]752       
[3019]753        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
[2880]754
[2895]755        // overwrite old color texture
[2973]756        colorBufferIdx = 3 - colorBufferIdx;
[2899]757        glDrawBuffers(1, mrt + colorBufferIdx);
[2880]758
[3079]759        float filterOffsets[NUM_SSAO_FILTERSAMPLES * 2];
760        float filterWeights[NUM_SSAO_FILTERSAMPLES];
[3017]761
[3079]762        PoissonDiscSampleGenerator2 poisson(NUM_SSAO_FILTERSAMPLES, 1.0f);
[3017]763        poisson.Generate((float *)filterOffsets);
764
[3079]765        const float filterWidth = 10.0f;
766        const float xoffs = filterWidth / fbo->GetWidth();
767        const float yoffs = filterWidth / fbo->GetHeight();
[3017]768
[3079]769        for (int i = 0; i < NUM_SSAO_FILTERSAMPLES; ++ i)
[3017]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
[3036]780       
781        sCgCombineSsaoProgram->SetTexture(0, colorsTex);
782        sCgCombineSsaoProgram->SetTexture(1, ssaoTex);
[3017]783
[3079]784        sCgCombineSsaoProgram->SetArray2f(2, (float *)filterOffsets, NUM_SSAO_FILTERSAMPLES);
785        sCgCombineSsaoProgram->SetArray1f(3, (float *)filterWeights, NUM_SSAO_FILTERSAMPLES);
[2880]786       
[3026]787        DrawQuad(sCgCombineSsaoProgram);
[2974]788       
[2880]789        PrintGLerror("combine ssao");
790}
791
792
[2952]793void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
794                                                                           DirectionalLight *light,
795                                                                           ShadowMap *shadowMap)
[2895]796{
[2973]797        fbo->Bind();
[2880]798
[2973]799        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]800        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[2973]801
[2928]802        GLuint shadowTex = shadowMap->GetDepthTexture();
[2895]803
804        Matrix4x4 shadowMatrix;
805        shadowMap->GetTextureMatrix(shadowMatrix);
806
[2973]807        colorBufferIdx = 3 - colorBufferIdx;
[2899]808        glDrawBuffers(1, mrt + colorBufferIdx);
[2895]809
[3035]810        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
811        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
812        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
813        sCgDeferredShadowProgram->SetTexture(3, noiseTex);
[2895]814
[3035]815        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
[3027]816
[3035]817        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
[3027]818
[3026]819        const Vector3 lightDir = -light->GetDirection();
[3035]820        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
[2895]821
[3085]822        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
[2952]823
[3026]824        DrawQuad(sCgDeferredShadowProgram);
[2895]825
826        PrintGLerror("deferred shading + shadows");
827}
828
829
[2896]830void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
[2895]831{
832        if (s != mSamplingMethod)
833        {
834                mSamplingMethod = s;
835                mRegenerateSamples = true;
836        }
837}
838
[2897]839
840void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
841{
842        if (s != mShadingMethod)
843        {
844                mShadingMethod = s;
845                mRegenerateSamples = true;
846        }
847}
848
[2965]849
[2973]850void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
851                                                                                         DirectionalLight *light,
852                                                                                         float &imageKey,
853                                                                                         float &whiteLum,
854                                                                                         float &middleGrey)
[2972]855{
[2975]856        // hack: estimate value where sky burns out
[3010]857        whiteLum = log(WHITE_LUMINANCE);
[2973]858       
[2975]859        ////////////////////
860        //-- linear interpolate brightness key depending on the current sun position
[2973]861
862        const float minKey = 0.09f;
[3020]863        const float maxKey = 0.36f;
[2973]864
865        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
866        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
[2991]867
[2993]868
[2991]869        //////////
870        //-- compute avg loglum
871
872        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2992]873        GLuint colorsTex = colorBuffer->GetTexture();
[2991]874
875        fbo->Bind();
876
877        colorBufferIdx = 3 - colorBufferIdx;
878        glDrawBuffers(1, mrt + colorBufferIdx);
879       
[3035]880        sCgLogLumProgram->SetTexture(0, colorsTex);
[3026]881        DrawQuad(sCgLogLumProgram);
[2991]882       
883        PrintGLerror("ToneMapParams");
884
885
886        ///////////////////
887        //-- compute avg loglum in scene using mipmapping
888
[3008]889        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
890        glGenerateMipmapEXT(GL_TEXTURE_2D);
[2972]891}
892
893
[3003]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
[3006]921void DeferredRenderer::DownSample(FrameBufferObject *fbo, int bufferIdx,
922                                                                  FrameBufferObject *downSampleFbo,
923                                                                  int downSampleBufferIdx)
[2972]924{
[3006]925        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(bufferIdx);
[2994]926        GLuint colorsTex = colorBuffer->GetTexture();
[3006]927
928        glPushAttrib(GL_VIEWPORT_BIT);
929        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
[2972]930       
[3035]931        sCgDownSampleProgram->SetTexture(0, colorsTex);
[2994]932
[3017]933        float downSampleOffsets[NUM_DOWNSAMPLES * 2];
934        ComputeSampleOffsets(downSampleOffsets, fbo->GetWidth(), fbo->GetHeight());
935
[3035]936        sCgDownSampleProgram->SetArray2f(1, (float *)downSampleOffsets, NUM_DOWNSAMPLES);
[3010]937
[2994]938        mDownSampleFbo->Bind();
[3006]939        glDrawBuffers(1, mrt + downSampleBufferIdx);
[2994]940
[3026]941        DrawQuad(sCgDownSampleProgram);
[3005]942       
[3006]943        glPopAttrib();
944       
[3005]945        PrintGLerror("downsample");
[2972]946}
947
948
[2973]949void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
950                                                           float imageKey,
951                                                           float whiteLum,
952                                                           float middleGrey)
[2972]953{
954        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2994]955        GLuint colorsTex = colorBuffer->GetTexture();
[2972]956
[2973]957        fbo->Bind();
[3025]958       
[2973]959        colorBufferIdx = 3 - colorBufferIdx;
960        glDrawBuffers(1, mrt + colorBufferIdx);
[3007]961
[3035]962        sCgToneProgram->SetTexture(0, colorsTex);
963        sCgToneProgram->SetValue1f(1, imageKey);
964        sCgToneProgram->SetValue1f(2, whiteLum);
965        sCgToneProgram->SetValue1f(3, middleGrey);
[3007]966
[3026]967        DrawQuad(sCgToneProgram);
[2972]968
[2973]969        PrintGLerror("ToneMap");
[2972]970}
971
972
[3081]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
[3085]1001void DeferredRenderer::InitFrame()
1002{
1003        mOldProjViewMatrix = mProjViewMatrix;
[3081]1004
[3085]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
[2858]1024} // namespace
Note: See TracBrowser for help on using the repository browser.