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

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