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

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