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

Revision 3222, 37.9 KB checked in by mattausch, 16 years ago (diff)

found error that made it slower

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