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

Revision 3350, 42.7 KB checked in by mattausch, 15 years ago (diff)

implemented ssao for diffuse illumination

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