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

Revision 3341, 42.3 KB checked in by mattausch, 15 years ago (diff)

nix geht

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"
[3213]12#include "Texture.h"
13
[3198]14#include <math.h>
[2858]15
[3003]16#include <IL/il.h>
17#include <assert.h>
[2859]18
[3003]19
[3021]20#ifdef _CRT_SET
21        #define _CRTDBG_MAP_ALLOC
22        #include <stdlib.h>
23        #include <crtdbg.h>
24
25        // redefine new operator
26        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
27        #define new DEBUG_NEW
28#endif
29
30
[2858]31using namespace std;
32
33
[3003]34static void startil()
35{
36        ilInit();
37        assert(ilGetError() == IL_NO_ERROR);
38}
39
40
41static void stopil()
42{
43        ilShutDown();
44        assert(ilGetError() == IL_NO_ERROR);
45}
46
[3198]47
[2858]48namespace CHCDemoEngine
49{
50
[3026]51static ShaderProgram *sCgSsaoProgram = NULL;
52static ShaderProgram *sCgGiProgram = NULL;
[2873]53
[3026]54static ShaderProgram *sCgDeferredProgram = NULL;
55static ShaderProgram *sCgAntiAliasingProgram = NULL;
56static ShaderProgram *sCgDeferredShadowProgram = NULL;
[2859]57
[3026]58static ShaderProgram *sCgCombineSsaoProgram = NULL;
[3301]59static ShaderProgram *sCgFilterSsaoProgram = NULL;
[3026]60static ShaderProgram *sCgCombineIllumProgram = NULL;
61static ShaderProgram *sCgLogLumProgram = NULL;
62static ShaderProgram *sCgToneProgram = NULL;
63static ShaderProgram *sCgDownSampleProgram = NULL;
[3137]64static ShaderProgram *sCgScaleDepthProgram = NULL;
[3155]65static ShaderProgram *sCgPrepareSsaoProgram = NULL;
[3213]66static ShaderProgram *sCgLenseFlareProgram = NULL;
[2869]67
[3232]68static ShaderProgram *sCgDOFProgram = NULL;
[2992]69
[3232]70
[3129]71static GLuint noiseTex2D = 0;
72static GLuint noiseTex1D = 0;
[3324]73static GLuint sampleTex2D = 0;
[2865]74
[3128]75
[3324]76static Sample2 samples2[NUM_PRECOMPUTED_SAMPLES];
[2859]77// ssao random spherical samples
[3324]78//static Sample2 samples2[NUM_SAMPLES];
79
[3232]80// pcf samples
[3103]81static Sample2 pcfSamples[NUM_PCF_TABS];
[3232]82// dof samples
83static Sample2 dofSamples[NUM_DOF_TABS];
[2966]84
[3214]85static Texture *sHaloTex[5];
[3103]86
[3118]87int DeferredRenderer::colorBufferIdx = 0;
[2859]88
[2992]89
[3212]90
91
[3085]92/** Helper method that computes the view vectors in the corners of the current view frustum.
93*/
[3316]94static void ComputeViewVectors(PerspectiveCamera *cam,
95                                                           Vector3 &bl,
96                                                           Vector3 &br,
97                                                           Vector3 &tl,
98                                                           Vector3 &tr)
[3085]99{
100        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
101        cam->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
102
103        bl = Normalize(nbl - fbl);
104        br = Normalize(nbr - fbr);
105        tl = Normalize(ntl - ftl);
106        tr = Normalize(ntr - ftr);
107}
108
109
[3025]110static float GaussianDistribution(float x, float y, float rho)
111{
[3110]112        float g = 1.0f / sqrtf(2.0f * M_PI * rho * rho);
[3133]113    g *= expf( -(x * x + y * y) / (2.0f * rho * rho));
[3025]114
115    return g;
116}
117
118
[2859]119static void PrintGLerror(char *msg)
120{
121        GLenum errCode;
122        const GLubyte *errStr;
123       
124        if ((errCode = glGetError()) != GL_NO_ERROR)
125        {
126                errStr = gluErrorString(errCode);
127                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
128        }
129}
130
131
[3206]132static Sample2 UnitTest(float x, float y, int wi, int he)
[3198]133{
134        Sample2 s;
135
136        s.x = float(floor(x * (float)wi - 0.5f) + 1.0f) / (float)wi;
137        s.y = float(floor(y * (float)he - 0.5f) + 1.0f) / (float)he;
138
139        return s;
140}
141
142
[3134]143static void ComputeSampleOffsets(float *sampleOffsets,
144                                                                 int imageW, int imageH,
145                                                                 float width,
146                                                                 int samples)
147{
148        const float xoffs = width / (float)imageW;
149        const float yoffs = width / (float)imageH;
[3017]150       
[3134]151        const int numSamples = (int)sqrt((float)samples);
152        const int startSamples = -numSamples / 2;
153        const int endSamples = numSamples + startSamples - 1;
154        //cout << startSamples << " " << endSamples << endl;
[2976]155
[3134]156        int idx = 0;
[3017]157
[3134]158        for (int x = startSamples; x <= endSamples; ++ x)
[3017]159        {
[3134]160                for (int y = startSamples; y <= endSamples; ++ y)
[3017]161                {
[3134]162                        sampleOffsets[idx + 0] = (float)x * xoffs;
163                        sampleOffsets[idx + 1] = (float)y * yoffs;
[3017]164                        idx += 2;
165                }
166        }
167}
168
[3026]169
[3327]170static float *GrabTexture(GLuint tex, int w, int h)
171{
172        glBindTexture(GL_TEXTURE_2D, tex);
173
174        float *data = new float[w * h * 3];
175
176        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, data);
177
178        glBindTexture(GL_TEXTURE_2D, 0);
179        glDisable(GL_TEXTURE_2D);
180
181        return data;
182}
183
184
[3132]185void DeferredRenderer::FlipFbos(FrameBufferObject *fbo)
186{
187        fbo->Bind();
188        colorBufferIdx = 3 - colorBufferIdx;
189        glDrawBuffers(1, mrt + colorBufferIdx);
190}
191
192
[3026]193void DeferredRenderer::DrawQuad(ShaderProgram *p)
194{
[3132]195        if (p) p->Bind();
[3026]196
[3089]197        // interpolate the view vector
[3085]198        Vector3 bl = mCornersView[0];
199        Vector3 br = mCornersView[1];
200        Vector3 tl = mCornersView[2];
201        Vector3 tr = mCornersView[3];
202
[3026]203        // note: slightly larger texture could hide ambient occlusion error on border but costs resolution
204        glBegin(GL_QUADS);
205
[3093]206        glTexCoord2f(0, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, bl.x, bl.y, bl.z); glVertex2f( .0f,  .0f);
207        glTexCoord2f(1, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, br.x, br.y, br.z); glVertex2f(1.0f,  .0f);
208        glTexCoord2f(1, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tr.x, tr.y, tr.z); glVertex2f(1.0f, 1.0f);
209        glTexCoord2f(0, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tl.x, tl.y, tl.z); glVertex2f( .0f, 1.0f);
[3026]210
211        glEnd();
212}
213
[2859]214/** Generate poisson disc distributed sample points on the unit disc
215*/
[2887]216static void GenerateSamples(int sampling)
[2859]217{
[2887]218        switch (sampling)
219        {
[2930]220        case DeferredRenderer::SAMPLING_POISSON:
[2887]221                {
[3338]222                        PoissonDiscSampleGenerator2D poisson(NUM_PRECOMPUTED_SAMPLES, 1.0f);
[2900]223                        poisson.Generate((float *)samples2);
[2887]224                }
225                break;
[2930]226        case DeferredRenderer::SAMPLING_QUADRATIC:
[2887]227                {
[3338]228                        //PoissonDiscSampleGenerator2D poisson(NUM_PRECOMPUTED_SAMPLES, 1.0f);
229                        //poisson.Generate((float *)samples2);
[3324]230                        QuadraticDiscSampleGenerator2D g(NUM_PRECOMPUTED_SAMPLES, 1.0f);
[2930]231                        g.Generate((float *)samples2);
[2887]232                }
233                break;
[2930]234        default: // SAMPLING_DEFAULT
[3026]235                {
[3338]236                        RandomSampleGenerator2D g(NUM_SAMPLES, 1.0f);
[3026]237                        g.Generate((float *)samples2);
238                }
[2903]239        }
[2859]240}
241
242
[2879]243static void CreateNoiseTex2D(int w, int h)
244{
245        //GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
[3227]246        Vector3 *randomNormals = new Vector3[w * h];
[2879]247
[3227]248        for (int i = 0; i < w * h; ++ i)
[2879]249        {
[2903]250                // create random samples on a circle
[3227]251                const float r = RandomValue(0, 1);
[2903]252
[3227]253                const float theta = 2.0f * acos(sqrt(1.0f - r));
254                //randomNormals[i] = Vector3(cos(theta), sin(theta), 0);
255                randomNormals[i] = Vector3(RandomValue(-M_PI, M_PI), 0, 0);
256                //Normalize(randomNormals[i]);
[2879]257        }
258
[3227]259
[2879]260        glEnable(GL_TEXTURE_2D);
[3129]261        glGenTextures(1, &noiseTex2D);
262        glBindTexture(GL_TEXTURE_2D, noiseTex2D);
[2879]263               
[3227]264        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
265        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
266        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
267        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
[2879]268        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
269        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
270
[3227]271        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGB, GL_FLOAT, (float *)randomNormals);
[2879]272
273        glBindTexture(GL_TEXTURE_2D, 0);
274        glDisable(GL_TEXTURE_2D);
275
276        delete [] randomNormals;
277
278        cout << "created noise texture" << endl;
279
280        PrintGLerror("noisetexture");
281}
282
283
[3326]284static void UpdateSampleTex(Sample2 *samples, int numSamples)
285{
[3332]286        PrintGLerror("here4");
[3326]287        glEnable(GL_TEXTURE_2D);
288        glBindTexture(GL_TEXTURE_2D, sampleTex2D);
289               
290        const int w = numSamples; const int h = 1;
291
292        float *tempBuffer = new float[numSamples * 3];
293
294        for (int i = 0; i < numSamples; ++ i)
295        {
296                tempBuffer[i * 3 + 0] = samples[i].x;
297                tempBuffer[i * 3 + 1] = samples[i].y;
298                tempBuffer[i * 3 + 2] = 0;
299        }
300
301        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGB, GL_FLOAT, (float *)tempBuffer);
302
[3333]303        glBindTexture(GL_TEXTURE_2D, 0);
[3326]304        glDisable(GL_TEXTURE_2D);
305
306        cout << "updated sample texture" << endl;
307
308        delete [] tempBuffer;
309
[3332]310        PrintGLerror("update sample tex");
[3326]311}
312
313
[3324]314static void CreateSampleTex(Sample2 *samples, int numSamples)
315{
316        glEnable(GL_TEXTURE_2D);
317        glGenTextures(1, &sampleTex2D);
318        glBindTexture(GL_TEXTURE_2D, sampleTex2D);
319               
320        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
321        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
322        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
323        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
324
[3326]325        const int w = numSamples; const int h = 1;
[3324]326
327        float *tempBuffer = new float[numSamples * 3];
328
329        for (int i = 0; i < numSamples; ++ i)
330        {
331                tempBuffer[i * 3 + 0] = samples[i].x;
332                tempBuffer[i * 3 + 1] = samples[i].y;
333                tempBuffer[i * 3 + 2] = 0;
334        }
335
336        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, w, h, 0, GL_RGB, GL_FLOAT, (float *)tempBuffer);
337
338        glBindTexture(GL_TEXTURE_2D, 0);
339        glDisable(GL_TEXTURE_2D);
340
341        cout << "created sample texture" << endl;
342
343        delete [] tempBuffer;
344
[3332]345        PrintGLerror("create sample tex");
[3324]346}
347
348
[3213]349static void PrepareLenseFlare()
350{
[3214]351        string textures[] = {"flare4.tga", "lens2.jpg", "lens3.jpg", "lens4.jpg", "lens1.jpg"};
[3213]352
[3270]353        // todo: delete halo textures
[3214]354        for (int i = 0; i < 5; ++ i)
[3213]355        {
356                sHaloTex[i] = new Texture(model_path + textures[i]);
357
[3214]358                sHaloTex[i]->SetBoundaryModeS(Texture::BORDER);
359                sHaloTex[i]->SetBoundaryModeT(Texture::BORDER);
[3213]360
361                sHaloTex[i]->Create();
362        }
363
364        cout << "prepared lense flare textures" << endl;
365
366        PrintGLerror("prepare lense flare");
367}
368
369
[3216]370DeferredRenderer::DeferredRenderer(int w, int h,
371                                                                   PerspectiveCamera *cam,
372                                                                   bool ssaoUseFullResolution):
[2860]373mWidth(w), mHeight(h),
374mCamera(cam),
[2875]375mUseTemporalCoherence(true),
[2895]376mRegenerateSamples(true),
[2930]377mSamplingMethod(SAMPLING_POISSON),
[2895]378mShadingMethod(DEFAULT),
[3189]379mIllumFboIndex(0),
[3212]380mSortSamples(true),
381mKernelRadius(1e-8f),
[3215]382mSampleIntensity(0.2f),
[3219]383mSunVisiblePixels(0),
[3220]384mSavedFrameNumber(-1),
[3235]385mSavedFrameSuffix(""),
[3242]386mMaxDistance(1e6f),
387mTempCohFactor(.0f),
388mUseToneMapping(false),
389mUseAntiAliasing(false),
[3305]390mUseDepthOfField(false),
[3316]391mSsaoUseFullResolution(ssaoUseFullResolution),
[3319]392mMaxConvergence(2000.0f),
393mSpatialWeight(.0f)
[2861]394{
395        ///////////
396        //-- the flip-flop fbos
[2859]397
[3216]398        int downSampledWidth, downSampledHeight;
399
[3305]400        if (mSsaoUseFullResolution)
[3216]401        {
402                downSampledWidth = w; downSampledHeight = h;
403                cout << "using full resolution ssao" << endl;
404        }
405        else
406        {
407                downSampledWidth = w / 2; downSampledHeight = h / 2;
408                cout << "using half resolution ssao" << endl;
409        }
410
[3305]411
412        /////////
[3301]413        //-- the illumination fbo is either half size or full size
414
[3216]415        mIllumFbo = new FrameBufferObject(downSampledWidth, downSampledHeight, FrameBufferObject::DEPTH_NONE);
[3019]416        mFBOs.push_back(mIllumFbo);
[2891]417
[3019]418        for (int i = 0; i < 4; ++ i)
419        {
[3332]420                mIllumFbo->AddColorBuffer(ColorBufferObject::R_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3117]421                FrameBufferObject::InitBuffer(mIllumFbo, i);
[3019]422        }
[3002]423
[3117]424
425        ///////////////
[3212]426        //-- the downsampled ssao + color bleeding textures:
[3305]427        //-- as GI is mostly low frequency, we can use lower resolution to improve performance
[3117]428
[3222]429        mDownSampleFbo = new FrameBufferObject(downSampledWidth, downSampledHeight, FrameBufferObject::DEPTH_NONE);
[3204]430        // the downsampled color + depth buffer
[3002]431        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3204]432        // downsample buffer for the normal texture
[3212]433        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3019]434
[3199]435        for (int i = 0; i < 2; ++ i)
436        {
437                FrameBufferObject::InitBuffer(mDownSampleFbo, i);
438        }
[3117]439
[3019]440        mFBOs.push_back(mDownSampleFbo);
[3038]441
[3305]442
443        /////////
444        //-- temporal buffer
445
446        mTempFbo = new FrameBufferObject(mWidth, mHeight, FrameBufferObject::DEPTH_NONE);
447        mFBOs.push_back(mTempFbo);
448
449        mTempFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
450        FrameBufferObject::InitBuffer(mTempFbo, 0);
451       
452
[3084]453        // create noise texture for ssao
[3150]454        // for performance reasons we use a smaller texture and repeat it over the screen
455        CreateNoiseTex2D(mIllumFbo->GetWidth() / 4, mIllumFbo->GetWidth() / 4);
[3301]456               
[3085]457        mProjViewMatrix = IdentityMatrix();
458        mOldProjViewMatrix = IdentityMatrix();
459
460        for (int i = 0; i < 4; ++ i)
461        {
462                mCornersView[i] = mOldCornersView[i] = Vector3::UNIT_X();
463        }
464
465        mEyePos = mOldEyePos = Vector3::ZERO();
466
[3213]467        PrepareLenseFlare();
468
[3038]469        InitCg();
[2861]470}
471
472
[2896]473DeferredRenderer::~DeferredRenderer()
[2861]474{
[3019]475        CLEAR_CONTAINER(mFBOs);
[3206]476
[3129]477        glDeleteTextures(1, &noiseTex2D);
478        glDeleteTextures(1, &noiseTex1D);
[2861]479}
480
481
[3038]482void DeferredRenderer::InitCg()
[3026]483{       
[3057]484        ShaderManager *sm = ShaderManager::GetSingleton();
[2873]485
[3216]486        sCgDeferredProgram = sm->CreateFragmentProgram("deferred", "main", "DeferredFrag");
487        sCgDeferredShadowProgram = sm->CreateFragmentProgram("deferred", "main_shadow", "DeferredFragShadow");
488        sCgSsaoProgram = sm->CreateFragmentProgram("ssao", "main", "SsaoFrag");
489        sCgGiProgram = sm->CreateFragmentProgram("globillum", "main", "GiFrag");
490        sCgCombineIllumProgram = sm->CreateFragmentProgram("globillum", "combine", "CombineGi");
[3305]491
492        if (mSsaoUseFullResolution)
493        {
494                sCgFilterSsaoProgram = sm->CreateFragmentProgram("combineSsaoSep", "FilterSsaoFullRes", "FilterSsao");
495        }
496        else
497        {
498                sCgFilterSsaoProgram = sm->CreateFragmentProgram("combineSsaoSep", "FilterSsaoHalfRes", "FilterSsao");
499        }
500       
501        sCgCombineSsaoProgram = sm->CreateFragmentProgram("combineSsaoSep", "CombineSsao", "CombineSsao");
[3216]502        sCgAntiAliasingProgram = sm->CreateFragmentProgram("antialiasing", "main", "AntiAliasing");
503        sCgToneProgram = sm->CreateFragmentProgram("tonemap", "ToneMap", "ToneMap");
[3137]504        sCgDownSampleProgram = sm->CreateFragmentProgram("deferred", "Output", "Output");
505        sCgScaleDepthProgram = sm->CreateFragmentProgram("deferred", "ScaleDepth", "ScaleDepth");
[3216]506        sCgLogLumProgram = sm->CreateFragmentProgram("tonemap", "CalcAvgLogLum", "AvgLogLum");
[3155]507        sCgPrepareSsaoProgram = sm->CreateFragmentProgram("deferred", "PrepareSsao", "PrepareSsao");
[3213]508        sCgLenseFlareProgram = sm->CreateFragmentProgram("lenseFlare", "LenseFlare", "LenseFlare");
[3232]509        sCgDOFProgram = sm->CreateFragmentProgram("depthOfField", "DepthOfField", "DepthOfField");
[3038]510
[3034]511
[3104]512        ///////////////////
513        //-- initialize program parameters
[3034]514
[3104]515        string ssaoParams[] =
[3313]516                {"colors", "normals", "oldTex", "noiseTex", "temporalCoherence",
[3111]517                 "samples", "bl", "br", "tl", "tr",
518                 "modelViewProj", "oldModelViewProj", "oldEyePos", "oldbl", "oldbr",
[3212]519                 "oldtl", "oldtr", "attribsTex", "kernelRadius", "sampleIntensity"};
[3324]520       
[3212]521        sCgSsaoProgram->AddParameters(ssaoParams, 0, 20);
[3085]522       
[3104]523        string giParams[] =
524                {"colors", "normals", "noiseTex", "oldSsaoTex", "oldIllumTex",
[3111]525                 "temporalCoherence", "samples", "bl", "br", "tl",
526                 "tr", "oldModelViewProj", "modelViewProj"};
[3232]527
[3104]528        sCgGiProgram->AddParameters(giParams, 0, 13);
[3034]529
[3104]530        string toneParams[] = {"colors", "imageKey", "whiteLum", "middleGrey"};
531        sCgToneProgram->AddParameters(toneParams, 0, 4);
[3034]532
533
[3104]534        ////////////////
535
536        string deferredShadowParams[] =
537                {"colors", "normals", "shadowMap", "noiseTex", "shadowMatrix",
538                 "sampleWidth", "lightDir", "eyePos", "samples", "weights"};
[3035]539       
[3104]540        sCgDeferredShadowProgram->AddParameters(deferredShadowParams, 0, 10);
541       
542        ////////////////
[3034]543
[3104]544        string combineIllumParams[] = {"colorsTex", "ssaoTex", "illumTex"};
545        sCgCombineIllumProgram->AddParameters(combineIllumParams, 0, 3);
[3035]546
[3104]547        ////////////////
[3035]548
[3299]549        string combineSsaoParams[] =
[3319]550                {"colorsTex", "ssaoTex", "bl", "br", "tl", "tr", "res", "maxConvergence", "spatialWeight"};
[3232]551
[3319]552        sCgCombineSsaoProgram->AddParameters(combineSsaoParams, 0, 9);
[3035]553
[3301]554       
555        ////////////////
[3299]556
[3301]557        string filterSsaoParams[] =
[3319]558                {"colorsTex", "ssaoTex", "bl", "br", "tl", "tr", "res", "maxConvergence", "spatialWeight"};
559        sCgFilterSsaoProgram->AddParameters(filterSsaoParams, 0, 9);
[3301]560
561
[3104]562        //////////////
[3036]563
[3104]564        string deferredParams[] = {"colors", "normals", "lightDir"};
565        sCgDeferredProgram->AddParameters(deferredParams, 0, 3);
566
567        ///////////////////
568
[3136]569        string aaParams[] = {"colors", "normals", "offsets"};
570        sCgAntiAliasingProgram->AddParameters(aaParams, 0, 3);
[3104]571
572        /////////////////////
573
[3137]574        string downSampleParams[] = {"colors"};
575        sCgDownSampleProgram->AddParameters(downSampleParams, 0, 1);
[3104]576
[3137]577        /////////////////////
578
579        string scaleDepthParams[] = {"colors"};
580        sCgScaleDepthProgram->AddParameters(scaleDepthParams, 0, 1);
581
[3104]582        ////////////
583
584        sCgLogLumProgram->AddParameter("colors", 0);
[3128]585
586        ////////////////
587
[3155]588       
589        string prepareSsaoParams[] =
[3326]590                {"colorsTex", "normalsTex", "diffVals", "oldTex",
[3167]591                 "oldEyePos", "modelViewProj", "oldModelViewProj",
[3326]592                 "oldbl", "oldbr", "oldtl", "oldtr", "myTex"};
[3325]593        sCgPrepareSsaoProgram->AddParameters(prepareSsaoParams, 0, 12);
[3155]594
595
596        ////////////////
[3213]597       
598        string lenseFlareParams[] =
599                {"colorsTex", "flareTex1", "flareTex2", "flareTex3", "flareTex4",
[3215]600                 "flareTex5", "vectorToLight", "distanceToLight", "sunVisiblePixels"};
[3213]601
[3215]602        sCgLenseFlareProgram->AddParameters(lenseFlareParams, 0, 9);
[3213]603
[3232]604       
605        ////////////////
606       
[3235]607        string dofParams[] = {"colorsTex", "filterOffs", "sceneRange", "zFocus"};
[3213]608
[3235]609        sCgDOFProgram->AddParameters(dofParams, 0, 4);
[3232]610
611
[3144]612        /////////
[3133]613        //-- pcf tabs for shadowing
614
[3026]615        float filterWeights[NUM_PCF_TABS];
[3227]616        PoissonDiscSampleGenerator2D poisson2(NUM_PCF_TABS, 1.0f);
[3103]617        poisson2.Generate((float *)pcfSamples);
[2990]618
[3026]619        for (int i = 0; i < NUM_PCF_TABS; ++ i)
[2880]620        {
[3026]621                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
[2880]622        }
623
[3035]624        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
625        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
[2880]626
[3232]627
628        /////////
629        //-- pcf tabs for depth of field
630
631        // todo matt: it is stupid to put num samples and width of kernel into constructor => change this!!!
632        PoissonDiscSampleGenerator2D poisson3(NUM_DOF_TABS, 1.0f);
[3235]633        poisson3.Generate((float *)dofSamples);
[3232]634
[3235]635        for (int i = 0; i < NUM_DOF_TABS; ++ i)
636        {
637                dofSamples[i].x *= 1.0f / mWidth;
638                dofSamples[i].y *= 1.0f / mHeight;
639        }
640
[3232]641        //float dofWeights[NUM_PCF_TABS];
642        //sCgDOFProgram->SetArray1f(2, (float *)dofWeights, NUM_DOF_TABS);
643
[2859]644        PrintGLerror("init");
645}
646
647
[2896]648void DeferredRenderer::Render(FrameBufferObject *fbo,
[2952]649                                                          DirectionalLight *light,
[2991]650                                                          ShadowMap *shadowMap
651                                                          )
[2859]652{
[3085]653        InitFrame();
654
[2944]655        if (shadowMap)
[2952]656                FirstPassShadow(fbo, light, shadowMap);
[2895]657        else
[2952]658                FirstPass(fbo, light);
[2944]659
[3103]660        if (mShadingMethod != 0)
[2880]661        {
[3332]662                PrepareSsao(fbo); // downsample fbo buffers
[3103]663        }
[3006]664
[3213]665        // q: use antialiasing before or after ssao?
[3193]666        //if (useAntiAliasing) AntiAliasing(fbo, light);
[3132]667
[3103]668        switch (mShadingMethod)
669        {
670        case SSAO:
[3242]671                ComputeSsao(fbo, mTempCohFactor);
[3301]672                FilterSsao(fbo);
[2944]673                CombineSsao(fbo);
674                break;
675        case GI:
[3242]676                ComputeGlobIllum(fbo, mTempCohFactor);
[2944]677                CombineIllum(fbo);
678                break;
[3214]679        default:
[2944]680                // do nothing: standard deferred shading
681                break;
682        }
[2884]683
[3242]684        /// depth of field
685        if (mUseDepthOfField)
686        {
687                DepthOfField(fbo);
688        }
[3235]689
[3242]690        if (mUseToneMapping)
[2991]691        {
692                float imageKey, whiteLum, middleGrey;
693
694                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
[3007]695                ToneMap(fbo, imageKey, whiteLum, middleGrey);
[2991]696        }
697
[3215]698        /// compute lense flare
699        LenseFlare(fbo, light);
[3213]700
[3219]701        const bool saveFrame = (mSavedFrameNumber != -1);
702        const bool displayAfterAA = !saveFrame;
703
[3175]704        // multisampling is difficult / costly with deferred shading
705        // at least do some edge blurring
[3242]706        if (mUseAntiAliasing) AntiAliasing(fbo, light, displayAfterAA);
[3219]707       
708        /// store the current frame
709        if (saveFrame) SaveFrame(fbo);
[3135]710
[3219]711        // if it hasn't been done yet => just output the latest buffer
[3242]712        if (!mUseAntiAliasing || !displayAfterAA)
[3326]713        {
[3219]714                Output(fbo);
[3326]715        }
[3219]716
[2867]717        glEnable(GL_LIGHTING);
718        glDisable(GL_TEXTURE_2D);
719
720        glMatrixMode(GL_PROJECTION);
721        glPopMatrix();
722
723        glMatrixMode(GL_MODELVIEW);
724        glPopMatrix();
725
[3089]726        // viewport
[2867]727        glPopAttrib();
728
[3007]729        FrameBufferObject::Release();
[3057]730        ShaderManager::GetSingleton()->DisableFragmentProfile();
[2859]731}
732
733
[3167]734static inline float SqrMag(const Sample2 &s)
735{
736        return (s.x * s.x + s.y * s.y);
737}
738
739
740static inline float SqrDist(const Sample2 &a, const Sample2 &b)
741{
742        float x = a.x - b.x;
743        float y = a.y - b.y;
744       
745        return x * x + y * y;
746}
747
748
749static inline bool lt(const Sample2 &a, const Sample2 &b)
750{
751        return SqrMag(a) < SqrMag(b);
752}
753
754
755void DeferredRenderer::SortSamples()
756{
757        static Sample2 tempSamples[NUM_SAMPLES];
758        static bool checked[NUM_SAMPLES];
759
760        for (int i = 0; i < NUM_SAMPLES; ++ i)
761                checked[i] = false;
762
763        Sample2 currentSample;
764        currentSample.x = 0; currentSample.y = 0;
765        int ns = 0; // the next sample index
766
767        for (int i = 0; i < NUM_SAMPLES; ++ i)
768        {
769                float minLen = 1e20f;
770
771                for (int j = 0; j < NUM_SAMPLES; ++ j)
772                {
773                        if (checked[j]) continue;
774
775                        Sample2 s = samples2[j];
776                        const float len = SqrDist(s, currentSample);
777
778                        if (len < minLen)
779                        {
780                                minLen = len;
781                                ns = j;
782                        }
783                }
784
785                tempSamples[i] = samples2[ns];
786                currentSample = samples2[ns];
[3327]787
[3167]788                checked[ns] = true;
789        }
790
791        for (int i = 0; i < NUM_SAMPLES; ++ i)
792                samples2[i] = tempSamples[i];
793}
794
795
[3199]796void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo, float tempCohFactor)
[2859]797{
[3117]798        GLuint colorsTex, normalsTex, attribsTex;
[3015]799
[3133]800        if (0)
[3199]801        {
[3117]802                colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3199]803                normalsTex = fbo->GetColorBuffer(1)->GetTexture();
804        }
[3117]805        else
[3199]806        {
807                normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
[3117]808                colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
[3199]809        }
810
[3198]811        attribsTex = fbo->GetColorBuffer(2)->GetTexture();
[3117]812
[3341]813
[3325]814        /////////
815        //-- flip flop between illumination buffers
816
817        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
818
[3006]819        glPushAttrib(GL_VIEWPORT_BIT);
[3019]820        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
[3006]821
[2861]822        // read the second buffer, write to the first buffer
[3019]823        mIllumFbo->Bind();
[3325]824        glDrawBuffers(2, mrt + mIllumFboIndex);
[2868]825
[3095]826        int i = 0;
[3034]827
[3095]828        sCgSsaoProgram->SetTexture(i ++, colorsTex);
829        sCgSsaoProgram->SetTexture(i ++, normalsTex);
[3325]830        sCgSsaoProgram->SetTexture(i ++, oldSsaoTex);
[3129]831        sCgSsaoProgram->SetTexture(i ++, noiseTex2D);
[3095]832
[3313]833        sCgSsaoProgram->SetValue1f(i ++, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
[3035]834       
[3325]835
[3324]836        if (/*mUseTemporalCoherence || */mRegenerateSamples)
[2875]837        {
[2895]838                mRegenerateSamples = false;
[2859]839
[2875]840                // q: should we generate new samples or only rotate the old ones?
841                // in the first case, the sample patterns look nicer, but the kernel
842                // needs longer to converge
[3324]843                GenerateSamples(mSamplingMethod);
[3326]844
845                if (!sampleTex2D)
846                {
847                        CreateSampleTex(samples2, NUM_PRECOMPUTED_SAMPLES);
[3341]848                        cout<<"here34"<<endl;
[3326]849                }
850                else
851                {
852                        UpdateSampleTex(samples2, NUM_PRECOMPUTED_SAMPLES);
853                }
854
[3327]855
[3192]856                //if (mSortSamples) { SortSamples(); }
[3324]857                //sCgSsaoProgram->SetArray2f(i, (float *)samples2, NUM_SAMPLES);
858                //sCgSsaoProgram->SetArray2f(i, (float *)samples2, NUM_PRECOMPUTED_SAMPLES);
[2875]859        }
[3327]860
861        sCgSsaoProgram->SetTexture(i, sampleTex2D);
862
[3095]863        ++ i;
[2859]864
[3095]865        for (int j = 0; j < 4; ++ j, ++ i)
[3324]866        {
[3095]867                sCgSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
[3324]868        }
[2987]869
[3095]870        sCgSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
871        sCgSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
[3062]872
[3105]873        Vector3 de;
874        de.x = mOldEyePos.x - mEyePos.x;
875        de.y = mOldEyePos.y - mEyePos.y;
876        de.z = mOldEyePos.z - mEyePos.z;
[3035]877
[3095]878        sCgSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
[3093]879
[3095]880        for (int j = 0; j < 4; ++ j, ++ i)
[3212]881        {
[3095]882                sCgSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
[3212]883        }
[3085]884
[3110]885        sCgSsaoProgram->SetTexture(i ++, attribsTex);
[3212]886        sCgSsaoProgram->SetValue1f(i ++, mKernelRadius);
[3227]887        sCgSsaoProgram->SetValue1f(i ++, mSampleIntensity * mKernelRadius);
[3110]888
[3026]889        DrawQuad(sCgSsaoProgram);
[3006]890        glPopAttrib();
[2859]891
892        PrintGLerror("ssao first pass");
893}
894
895
[2865]896static void SetVertex(float x, float y, float x_offs, float y_offs)
897{
898        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
899        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
900        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
901        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
902        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
903
904        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
905        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
906
[3089]907        //glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
908        glVertex2f(x, y);
[2865]909}
910
911
[3219]912void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo,
913                                                                        DirectionalLight *light,
914                                                                        bool displayFrame)
[2865]915{
[2968]916        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
917        GLuint colorsTex = colorBuffer->GetTexture();
[3136]918        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[3007]919
[3132]920        // read the second buffer, write to the first buffer
[3219]921        if (!displayFrame)
[3327]922        {
[3219]923                FlipFbos(fbo);
[3327]924        }
[3219]925        else
[3327]926        {
[3219]927                // end of the pipeline => just draw image to screen
928                FrameBufferObject::Release();
[3327]929        }
[3132]930
[3136]931        // the neighbouring texels
932        float xOffs = 1.0f / fbo->GetWidth();
933        float yOffs = 1.0f / fbo->GetHeight();
934
[3034]935        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
936        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
[2865]937
[3136]938        float offsets[16];
939        int i = 0;
[2868]940
[3136]941        offsets[i] = -xOffs; offsets[i + 1] =  yOffs; i += 2; // left top
942        offsets[i] =  xOffs; offsets[i + 1] = -yOffs; i += 2; // right bottom
943        offsets[i] =  xOffs; offsets[i + 1] =  yOffs; i += 2; // right top
944        offsets[i] = -xOffs; offsets[i + 1] = -yOffs; i += 2; // left bottom
945        offsets[i] = -xOffs; offsets[i + 1] =    .0f; i += 2; // left
946        offsets[i] =  xOffs; offsets[i + 1] =    .0f; i += 2; // right
947        offsets[i] =    .0f; offsets[i + 1] =  yOffs; i += 2; // top
948        offsets[i] =    .0f; offsets[i + 1] = -yOffs; i += 2; // bottom
[2865]949
[3136]950        sCgAntiAliasingProgram->SetArray2f(2, offsets, 8);
[2865]951
[3136]952        DrawQuad(sCgAntiAliasingProgram);
[2865]953
[2867]954        PrintGLerror("antialiasing");
[2865]955}
956
957
[2952]958void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
[2868]959{
[2973]960        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]961        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[2868]962
[3132]963        FlipFbos(fbo);
[2868]964
[3026]965        const Vector3 lightDir = -light->GetDirection();
[2868]966
[3034]967        sCgDeferredProgram->SetTexture(0, colorsTex);
968        sCgDeferredProgram->SetTexture(1, normalsTex);
969        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
[2868]970       
[3026]971        DrawQuad(sCgDeferredProgram);
[2952]972
[2868]973        PrintGLerror("deferred shading");
974}
975
[2869]976
[2896]977void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
[3085]978                                                                                float tempCohFactor)
[2869]979{
[3016]980#if 0
981        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
982        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
983#else
[3003]984        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
[3009]985        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
[3016]986#endif
[2869]987
[3006]988        glPushAttrib(GL_VIEWPORT_BIT);
[3019]989        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
[2869]990
[2873]991        // read the second buffer, write to the first buffer
[3019]992        mIllumFbo->Bind();
993        glDrawBuffers(2, mrt + mIllumFboIndex);
[2873]994
[3326]995        // bind the old buffers for temporal coherence
[3019]996        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
997        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
[2869]998
[3160]999        int i = 0;
[2869]1000
[3160]1001        sCgGiProgram->SetTexture(i ++, colorsTex);
1002        sCgGiProgram->SetTexture(i ++, normalsTex);
1003        sCgGiProgram->SetTexture(i ++, noiseTex2D);
1004        sCgGiProgram->SetTexture(i ++, oldSsaoTex);
1005        sCgGiProgram->SetTexture(i ++, oldIllumTex);
1006
1007        sCgGiProgram->SetValue1f(i ++,
[3026]1008                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
[2869]1009
[2895]1010        if (mUseTemporalCoherence || mRegenerateSamples)
[2875]1011        {
[2895]1012                mRegenerateSamples = false;
[2873]1013
[2875]1014                // q: should we generate new samples or only rotate the old ones?
1015                // in the first case, the sample patterns look nicer, but the kernel
1016                // needs longer to converge
[2895]1017                GenerateSamples(mSamplingMethod);
[2903]1018
[3160]1019                sCgGiProgram->SetArray2f(i ++, (float *)samples2, NUM_SAMPLES);
[2875]1020        }
1021
[3085]1022        Vector3 bl = mCornersView[0];
1023        Vector3 br = mCornersView[1];
1024        Vector3 tl = mCornersView[2];
1025        Vector3 tr = mCornersView[3];
[2895]1026
[3160]1027        sCgGiProgram->SetValue3f(i ++, bl.x, bl.y, bl.z);
1028        sCgGiProgram->SetValue3f(i ++, br.x, br.y, br.z);
1029        sCgGiProgram->SetValue3f(i ++, tl.x, tl.y, tl.z);
1030        sCgGiProgram->SetValue3f(i ++, tr.x, tr.y, tr.z);
[2873]1031
[3160]1032        sCgGiProgram->SetMatrix(i ++, mOldProjViewMatrix);
1033        sCgGiProgram->SetMatrix(i ++, mProjViewMatrix);
[3035]1034
1035
[3026]1036        DrawQuad(sCgGiProgram);
[2990]1037
[3006]1038        glPopAttrib();
1039
[2873]1040        PrintGLerror("globillum first pass");
[2869]1041}
1042
1043
[2896]1044void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
[2880]1045{
[2973]1046        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[2884]1047
[3019]1048        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
1049        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
[2880]1050
[3132]1051        FlipFbos(fbo);
[2891]1052
[3036]1053        sCgCombineIllumProgram->SetTexture(0, colorsTex);
1054        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
1055        sCgCombineIllumProgram->SetTexture(2, illumTex);
[2880]1056       
[3026]1057        DrawQuad(sCgCombineIllumProgram);
[2880]1058
1059        PrintGLerror("combine");
1060}
1061
1062
[3301]1063void DeferredRenderer::FilterSsao(FrameBufferObject *fbo)
[2880]1064{
[2973]1065        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3103]1066        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[3144]1067        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
[3132]1068       
[3305]1069        mTempFbo->Bind();
1070        glDrawBuffers(1, mrt);
[3301]1071       
[3104]1072        int i = 0;
[3148]1073
[3301]1074        sCgFilterSsaoProgram->SetTexture(i ++, colorsTex);
1075        sCgFilterSsaoProgram->SetTexture(i ++, ssaoTex);
[3017]1076
[3163]1077        for (int j = 0; j < 4; ++ j, ++ i)
[3296]1078        {
[3301]1079                sCgFilterSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
[3296]1080        }
[3134]1081
[3305]1082        sCgFilterSsaoProgram->SetValue2f(i ++, (float)mWidth, (float)mHeight);
[3319]1083        sCgFilterSsaoProgram->SetValue1f(i ++, mMaxConvergence);
1084        sCgFilterSsaoProgram->SetValue1f(i ++, mSpatialWeight);
[3300]1085
[3301]1086        DrawQuad(sCgFilterSsaoProgram);
[3340]1087        PrintGLerror("filter ssao");
[2880]1088}
1089
1090
[3301]1091void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
[3296]1092{
1093        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
1094        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[3305]1095        GLuint ssaoTex = mTempFbo->GetColorBuffer(0)->GetTexture();
[3296]1096       
1097        FlipFbos(fbo);
1098
1099        int i = 0;
1100
1101        sCgCombineSsaoProgram->SetTexture(i ++, colorsTex);
1102        sCgCombineSsaoProgram->SetTexture(i ++, ssaoTex);
1103
1104        for (int j = 0; j < 4; ++ j, ++ i)
1105        {
1106                sCgCombineSsaoProgram->SetValue3f(i, mCornersView[j].x, mCornersView[j].y, mCornersView[j].z);
1107        }
1108
[3305]1109        sCgCombineSsaoProgram->SetValue2f(i ++, mWidth, mHeight);
[3319]1110        sCgCombineSsaoProgram->SetValue1f(i ++, mMaxConvergence);
1111        sCgCombineSsaoProgram->SetValue1f(i ++, mSpatialWeight);
[3296]1112
1113        DrawQuad(sCgCombineSsaoProgram);
1114       
1115        PrintGLerror("combine ssao");
1116}
1117
1118
[2952]1119void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
1120                                                                           DirectionalLight *light,
1121                                                                           ShadowMap *shadowMap)
[2895]1122{
[2973]1123        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]1124        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[2973]1125
[2928]1126        GLuint shadowTex = shadowMap->GetDepthTexture();
[2895]1127
1128        Matrix4x4 shadowMatrix;
1129        shadowMap->GetTextureMatrix(shadowMatrix);
1130
1131
[3132]1132        FlipFbos(fbo);
1133
[3035]1134        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
1135        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
1136        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
[3129]1137        sCgDeferredShadowProgram->SetTexture(3, noiseTex2D);
[3035]1138        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
1139        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
[3027]1140
[3026]1141        const Vector3 lightDir = -light->GetDirection();
[3035]1142        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
[3085]1143        sCgDeferredShadowProgram->SetValue3f(7, mEyePos.x, mEyePos.y, mEyePos.z);
[2952]1144
[3026]1145        DrawQuad(sCgDeferredShadowProgram);
[2895]1146
1147        PrintGLerror("deferred shading + shadows");
1148}
1149
1150
[2973]1151void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
1152                                                                                         DirectionalLight *light,
1153                                                                                         float &imageKey,
1154                                                                                         float &whiteLum,
1155                                                                                         float &middleGrey)
[2972]1156{
[2975]1157        // hack: estimate value where sky burns out
[3010]1158        whiteLum = log(WHITE_LUMINANCE);
[2973]1159       
[2975]1160        ////////////////////
1161        //-- linear interpolate brightness key depending on the current sun position
[2973]1162
1163        const float minKey = 0.09f;
[3020]1164        const float maxKey = 0.36f;
[2973]1165
1166        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
1167        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
[2991]1168
[2993]1169
[2991]1170        //////////
1171        //-- compute avg loglum
1172
1173        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2992]1174        GLuint colorsTex = colorBuffer->GetTexture();
[2991]1175
[3132]1176        FlipFbos(fbo);
[2991]1177       
[3035]1178        sCgLogLumProgram->SetTexture(0, colorsTex);
[3026]1179        DrawQuad(sCgLogLumProgram);
[2991]1180       
1181        PrintGLerror("ToneMapParams");
1182
1183
1184        ///////////////////
1185        //-- compute avg loglum in scene using mipmapping
1186
[3008]1187        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
1188        glGenerateMipmapEXT(GL_TEXTURE_2D);
[2972]1189}
1190
1191
[3003]1192static void ExportData(float *data, int w, int h)
1193{
1194        startil();
1195
1196        cout << "w: " << w << " h: " << h << endl;
1197        ILstring filename = ILstring("downsample2.jpg");
1198        ilRegisterType(IL_FLOAT);
1199
1200        const int depth = 1;
1201        const int bpp = 4;
1202
1203        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
1204        {
1205                cerr << "IL error " << ilGetError() << endl;
1206                stopil();
1207                return;
1208        }
1209
1210        if (!ilSaveImage(filename))
1211        {
1212                cerr << "TGA write error " << ilGetError() << endl;
1213        }
1214
1215        stopil();
1216}
1217
1218
[3155]1219void DeferredRenderer::PrepareSsao(FrameBufferObject *fbo)
1220{
[3198]1221        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3199]1222        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
[3198]1223        GLuint diffVals = fbo->GetColorBuffer(2)->GetTexture();
[3325]1224
[3155]1225        // flip flop between illumination buffers
[3198]1226        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
[3326]1227        GLuint myTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
[3155]1228
1229        int i = 0;
1230
1231        sCgPrepareSsaoProgram->SetTexture(i ++, colorsTex);
[3199]1232        sCgPrepareSsaoProgram->SetTexture(i ++, normalsTex);
[3167]1233        sCgPrepareSsaoProgram->SetTexture(i ++, diffVals);
[3155]1234        sCgPrepareSsaoProgram->SetTexture(i ++, oldTex);
1235
1236        Vector3 de;
1237        de.x = mOldEyePos.x - mEyePos.x;
1238        de.y = mOldEyePos.y - mEyePos.y;
1239        de.z = mOldEyePos.z - mEyePos.z;
1240
1241        sCgPrepareSsaoProgram->SetValue3f(i ++, de.x, de.y, de.z);
1242
[3156]1243        sCgPrepareSsaoProgram->SetMatrix(i ++, mProjViewMatrix);
1244        sCgPrepareSsaoProgram->SetMatrix(i ++, mOldProjViewMatrix);
1245
[3326]1246
[3156]1247        for (int j = 0; j < 4; ++ j, ++ i)
[3325]1248        {
[3156]1249                sCgPrepareSsaoProgram->SetValue3f(i, mOldCornersView[j].x, mOldCornersView[j].y, mOldCornersView[j].z);
[3325]1250        }
[3156]1251
[3326]1252        sCgPrepareSsaoProgram->SetTexture(i ++, myTex);
1253
[3155]1254        glPushAttrib(GL_VIEWPORT_BIT);
1255        glViewport(0, 0, mDownSampleFbo->GetWidth(), mDownSampleFbo->GetHeight());
1256       
1257        mDownSampleFbo->Bind();
1258
[3212]1259        // prepare downsampled depth and normal texture for ssao
[3199]1260        glDrawBuffers(2, mrt);
[3155]1261
1262        DrawQuad(sCgPrepareSsaoProgram);
1263       
1264        glPopAttrib();
1265        PrintGLerror("prepareSsao");
1266}
1267
1268
[3103]1269void DeferredRenderer::DownSample(FrameBufferObject *fbo,
1270                                                                  int bufferIdx,
[3006]1271                                                                  FrameBufferObject *downSampleFbo,
[3137]1272                                                                  int downSampleBufferIdx,
1273                                                                  ShaderProgram *program)
[2972]1274{
[3137]1275        ColorBufferObject *buffer = fbo->GetColorBuffer(bufferIdx);
1276        GLuint tex = buffer->GetTexture();
[3006]1277
1278        glPushAttrib(GL_VIEWPORT_BIT);
1279        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
[2972]1280       
[3137]1281        downSampleFbo->Bind();
[2994]1282
[3137]1283        program->SetTexture(0, tex);
[3006]1284        glDrawBuffers(1, mrt + downSampleBufferIdx);
[2994]1285
[3137]1286        DrawQuad(program);
[3005]1287       
[3006]1288        glPopAttrib();
[3005]1289        PrintGLerror("downsample");
[2972]1290}
1291
1292
[2973]1293void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
1294                                                           float imageKey,
1295                                                           float whiteLum,
1296                                                           float middleGrey)
[2972]1297{
1298        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2994]1299        GLuint colorsTex = colorBuffer->GetTexture();
[3326]1300       
[2972]1301
[3132]1302        FlipFbos(fbo);
[3007]1303
[3035]1304        sCgToneProgram->SetTexture(0, colorsTex);
1305        sCgToneProgram->SetValue1f(1, imageKey);
1306        sCgToneProgram->SetValue1f(2, whiteLum);
1307        sCgToneProgram->SetValue1f(3, middleGrey);
[3007]1308
[3026]1309        DrawQuad(sCgToneProgram);
[2972]1310
[2973]1311        PrintGLerror("ToneMap");
[2972]1312}
1313
1314
[3132]1315void DeferredRenderer::Output(FrameBufferObject *fbo)
1316{
1317        glPushAttrib(GL_VIEWPORT_BIT);
1318        glViewport(0, 0, fbo->GetWidth(), fbo->GetHeight());
1319       
1320        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1321        GLuint colorsTex = colorBuffer->GetTexture();
1322
1323        sCgDownSampleProgram->SetTexture(0, colorsTex);
1324
1325        FrameBufferObject::Release();
1326        DrawQuad(sCgDownSampleProgram);
1327
[3326]1328        PrintGLerror("Output");
[3132]1329}
1330
1331
[3085]1332void DeferredRenderer::InitFrame()
1333{
[3095]1334        for (int i = 0; i < 4; ++ i)
[3326]1335        {
[3095]1336                mOldCornersView[i] = mCornersView[i];
[3326]1337        }
[3095]1338
[3085]1339        mOldProjViewMatrix = mProjViewMatrix;
[3095]1340        mOldEyePos = mEyePos;
[3106]1341        mEyePos = mCamera->GetPosition();
[3081]1342
[3104]1343        // hack: temporarily change far to improve precision
1344        const float oldFar = mCamera->GetFar();
[3106]1345        const float oldNear = mCamera->GetNear();
[3132]1346       
[3104]1347
[3106]1348        Matrix4x4 matViewing, matProjection;
[3104]1349
[3106]1350
1351        ///////////////////
1352
[3213]1353        // use view orientation as we assume that the eye point is always in the center
1354        // of our coordinate system, this way we have the highest precision near the eye point
[3093]1355        mCamera->GetViewOrientationMatrix(matViewing);
[3085]1356        mCamera->GetProjectionMatrix(matProjection);
1357
1358        mProjViewMatrix = matViewing * matProjection;
[3095]1359        ComputeViewVectors(mCamera, mCornersView[0], mCornersView[1], mCornersView[2], mCornersView[3]);
[3106]1360       
[3085]1361
[3095]1362        // switch roles of old and new fbo
1363        // the algorihm uses two input fbos, where the one
1364        // contais the color buffer from the last frame,
1365        // the other one will be written
[3085]1366
[3095]1367        mIllumFboIndex = 2 - mIllumFboIndex;
1368       
1369        // enable fragment shading
1370        ShaderManager::GetSingleton()->EnableFragmentProfile();
1371
1372        glDisable(GL_ALPHA_TEST);
1373        glDisable(GL_TEXTURE_2D);
1374        glDisable(GL_LIGHTING);
1375        glDisable(GL_BLEND);
1376        glDisable(GL_DEPTH_TEST);
1377
1378        glPolygonMode(GL_FRONT, GL_FILL);
1379
1380        glMatrixMode(GL_PROJECTION);
1381        glPushMatrix();
1382        glLoadIdentity();
1383
1384        gluOrtho2D(0, 1, 0, 1);
1385
1386
1387        glMatrixMode(GL_MODELVIEW);
1388        glPushMatrix();
1389        glLoadIdentity();
1390
1391       
1392        glPushAttrib(GL_VIEWPORT_BIT);
1393        glViewport(0, 0, mWidth, mHeight);
[3128]1394
1395        // revert to old far and near plane
[3104]1396        mCamera->SetFar(oldFar);
[3106]1397        mCamera->SetNear(oldNear);
[3085]1398}
1399
[3212]1400
[3213]1401void DeferredRenderer::LenseFlare(FrameBufferObject *fbo,
[3215]1402                                                                  DirectionalLight *light                                                       
[3213]1403                                                                  )
[3212]1404{
[3242]1405        // light source visible?
[3215]1406        if (!mSunVisiblePixels) return;
1407
[3213]1408        // the sun is a large distance in the reverse light direction
1409        // => extrapolate light pos
1410        const Vector3 lightPos = light->GetDirection() * -1e3f;
1411
[3214]1412        float w;
1413        Vector3 projLightPos = mProjViewMatrix.Transform(w, lightPos, 1.0f);
1414        projLightPos /= w;
1415        projLightPos = projLightPos * 0.5f + Vector3(0.5f);
[3213]1416
1417        // vector to light from screen center in texture space
1418        Vector3 vectorToLight = projLightPos - Vector3(0.5f);
1419        vectorToLight.z = .0f;
1420
1421        const float distanceToLight = Magnitude(vectorToLight);
1422        vectorToLight /= distanceToLight;
[3214]1423        //cout << "dist " << distanceToLight << " v " << vectorToLight << endl;
[3213]1424
1425
[3212]1426        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[3213]1427        GLuint colorsTex = colorBuffer->GetTexture();
1428       
[3212]1429        FlipFbos(fbo);
1430
[3213]1431        int i = 0;
[3212]1432
[3213]1433        sCgLenseFlareProgram->SetTexture(i ++, colorsTex);
1434        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[0]->GetId());
1435        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[1]->GetId());
1436        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[2]->GetId());
1437        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[3]->GetId());
[3214]1438        sCgLenseFlareProgram->SetTexture(i ++, sHaloTex[4]->GetId());
[3213]1439        sCgLenseFlareProgram->SetValue2f(i ++, vectorToLight.x, vectorToLight.y);
1440        sCgLenseFlareProgram->SetValue1f(i ++, distanceToLight);
[3215]1441        sCgLenseFlareProgram->SetValue1f(i ++, (float)mSunVisiblePixels);
[3213]1442
[3212]1443        DrawQuad(sCgLenseFlareProgram);
1444
1445        PrintGLerror("LenseFlare");
1446}
1447
1448
[3232]1449void DeferredRenderer::DepthOfField(FrameBufferObject *fbo)
1450{
1451        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1452        GLuint colorsTex = colorBuffer->GetTexture();
1453       
1454        FlipFbos(fbo);
1455
1456        int i = 0;
1457
[3235]1458        const float zFocus = 7.0f;
1459
[3232]1460        sCgDOFProgram->SetTexture(i ++, colorsTex);
1461        sCgDOFProgram->SetArray2f(i ++, (float *)dofSamples, NUM_DOF_TABS);
[3235]1462        sCgDOFProgram->SetValue1f(i ++, min(mCamera->GetFar(), mMaxDistance) - mCamera->GetNear());
1463        sCgDOFProgram->SetValue1f(i ++, zFocus);
[3232]1464
1465        DrawQuad(sCgDOFProgram);
1466
1467        PrintGLerror("LenseFlare");
1468}
1469
1470
[3219]1471void DeferredRenderer::SaveFrame(FrameBufferObject *fbo)
1472{
1473        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
1474        GLuint colorsTex = colorBuffer->GetTexture();
[3215]1475
[3219]1476        GLubyte *data = new GLubyte[mWidth * mHeight * 4];
1477
1478        // grab texture data
1479        glEnable(GL_TEXTURE_2D);
1480        glBindTexture(GL_TEXTURE_2D, colorsTex);
1481        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
1482
1483        glBindTexture(GL_TEXTURE_2D, 0);
1484        glDisable(GL_TEXTURE_2D);
1485
1486        /////////////////
1487
1488        startil();
1489
1490        static char imageName[200];
[3287]1491        sprintf(imageName, "%s_%05d.tga", mSavedFrameSuffix.c_str(), mSavedFrameNumber);
[3219]1492
1493        ILstring fileName = ILstring(imageName);
1494        ilRegisterType(IL_FLOAT);
1495
1496        const int depth = 1;
1497        const int bpp = 4;
1498
1499        if (!ilTexImage(mWidth, mHeight, depth, bpp, IL_RGBA, IL_UNSIGNED_BYTE, data))
1500        {
1501                cerr << "IL error " << ilGetError() << endl;
1502                stopil();
1503                return;
1504        }
1505
1506        ilEnable(IL_FILE_OVERWRITE);
1507
1508        if (!ilSaveImage(fileName))
1509        {
1510                cerr << "TGA write error " << ilGetError() << endl;
1511        }
1512
1513        delete [] data;
1514        stopil();
1515
1516        PrintGLerror("Store frame");
1517}
1518
1519
[3215]1520void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
1521{
1522        mUseTemporalCoherence = temporal;
1523}
1524
1525
1526void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
1527{
1528        if (s != mSamplingMethod)
1529        {
1530                mSamplingMethod = s;
1531                mRegenerateSamples = true;
1532        }
1533}
1534
1535
1536void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
1537{
1538        if (s != mShadingMethod)
1539        {
1540                mShadingMethod = s;
1541                mRegenerateSamples = true;
1542        }
1543}
1544
1545
1546#if TODO
1547
1548void DeferredRenderer::SetNumSamples(int numSamples)
1549{
1550        mNumSamples = numSamples;
1551}
1552
1553#endif
1554
1555
1556void DeferredRenderer::SetSampleIntensity(float sampleIntensity)
1557{
1558        mSampleIntensity = sampleIntensity;
[3247]1559        mRegenerateSamples = true;
[3215]1560}
1561
1562
1563void DeferredRenderer::SetKernelRadius(float kernelRadius)
1564{
1565        mKernelRadius = kernelRadius;
[3247]1566        mRegenerateSamples = true;
[3215]1567}
1568
1569
[3242]1570/*void DeferredRenderer::SetSortSamples(bool sortSamples)
[3215]1571{
1572        mSortSamples = sortSamples;
[3242]1573}*/
[3215]1574
1575
1576void DeferredRenderer::SetSunVisiblePixels(int pixels)
1577{
1578        mSunVisiblePixels = pixels;
1579}
1580
1581
[3235]1582void DeferredRenderer::SetMaxDistance(float maxDist)
1583{
1584        mMaxDistance = maxDist;
1585}
1586
1587
[3242]1588void DeferredRenderer::SetUseToneMapping(bool toneMapping)
1589{
1590        mUseToneMapping = toneMapping;
1591}
1592       
1593
1594void DeferredRenderer::SetUseAntiAliasing(bool antiAliasing)
1595{
1596        mUseAntiAliasing = antiAliasing;
1597}
1598
1599
1600void DeferredRenderer::SetUseDepthOfField(bool dof)
1601{
1602        mUseDepthOfField = dof;
1603}
1604
1605
1606void DeferredRenderer::SetTemporalCoherenceFactorForSsao(float factor)
1607{
1608        mTempCohFactor = factor;
1609}
1610
1611
[3220]1612void DeferredRenderer::SetSaveFrame(const string &suffix, int frameNumber)
[3219]1613{
[3220]1614        mSavedFrameSuffix = suffix;
[3219]1615        mSavedFrameNumber = frameNumber;
1616}
[3215]1617
[3219]1618
[3316]1619void DeferredRenderer::SetMaxConvergence(float c)
1620{
1621        mMaxConvergence = c;
1622}
1623
1624
[3319]1625void DeferredRenderer::SetSpatialWeight(float w)
1626{
1627        mSpatialWeight = w;
1628}
1629
1630
[2858]1631} // namespace
Note: See TracBrowser for help on using the repository browser.