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

Revision 3038, 26.1 KB checked in by mattausch, 16 years ago (diff)

unified shader stuff, but phreetham sky not working anymore for forward rendering

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"
[3038]11#include "ResourceManager.h"
[2858]12
[3038]13
[3003]14#include <IL/il.h>
15#include <assert.h>
[2859]16
[3003]17
[3021]18#ifdef _CRT_SET
19        #define _CRTDBG_MAP_ALLOC
20        #include <stdlib.h>
21        #include <crtdbg.h>
22
23        // redefine new operator
24        #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
25        #define new DEBUG_NEW
26#endif
27
28
[2858]29using namespace std;
30
31
[3003]32static void startil()
33{
34        ilInit();
35        assert(ilGetError() == IL_NO_ERROR);
36}
37
38
39static void stopil()
40{
41        ilShutDown();
42        assert(ilGetError() == IL_NO_ERROR);
43}
44
[2858]45namespace CHCDemoEngine
46{
47
[3026]48static ShaderProgram *sCgSsaoProgram = NULL;
49static ShaderProgram *sCgGiProgram = NULL;
[2873]50
[3026]51static ShaderProgram *sCgDeferredProgram = NULL;
52static ShaderProgram *sCgAntiAliasingProgram = NULL;
53static ShaderProgram *sCgDeferredShadowProgram = NULL;
[2859]54
[3026]55static ShaderProgram *sCgCombineSsaoProgram = NULL;
56static ShaderProgram *sCgCombineIllumProgram = NULL;
57static ShaderProgram *sCgLogLumProgram = NULL;
58static ShaderProgram *sCgToneProgram = NULL;
59static ShaderProgram *sCgDownSampleProgram = NULL;
[2869]60
[3019]61ShaderContainer DeferredRenderer::sShaders;
[2992]62
[2879]63static GLuint noiseTex = 0;
[2865]64
[2859]65// ssao random spherical samples
[2903]66static Sample2 samples2[NUM_SAMPLES];
[2966]67// number of pcf tabs
68Sample2 pcfSamples[NUM_PCF_TABS];
69
[3026]70
[2976]71int DeferredRenderer::colorBufferIdx = 0;
[2859]72
[2992]73
[3025]74
75static float GaussianDistribution(float x, float y, float rho)
76{
77    float g = 1.0f / sqrtf(2.0f * M_PI * rho * rho);
78    g *= expf( -(x*x + y*y) / (2.0f * rho * rho));
79
80    return g;
81}
82
83
[2859]84static void PrintGLerror(char *msg)
85{
86        GLenum errCode;
87        const GLubyte *errStr;
88       
89        if ((errCode = glGetError()) != GL_NO_ERROR)
90        {
91                errStr = gluErrorString(errCode);
92                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
93        }
94}
95
[3017]96static void ComputeSampleOffsets(float *sampleOffsets, int w, int h)
97{
98        /*
99        const float xoffs = 0.5f / w;
100        const float yoffs = 0.5f / h;
[2859]101
[3017]102        sampleOffsets[0] =  xoffs; sampleOffsets[1] =  yoffs;
103        sampleOffsets[2] =  xoffs; sampleOffsets[3] = -yoffs;
104        sampleOffsets[4] = -xoffs; sampleOffsets[5] = -yoffs;
105        sampleOffsets[6] = -xoffs; sampleOffsets[7] =  yoffs;
106        */
107        //const float xoffs = .5f / w;
108        //const float yoffs = .5f / h;
109       
110        const float xoffs = 1.0f / w;
111        const float yoffs = 1.0f / h;
[2976]112
[3017]113        int idx  = 0;
114
115        for (int x = -1; x <= 1; ++ x)
116        {
117                for (int y = -1; y <= 1; ++ y)
118                {
119                        sampleOffsets[idx + 0] = x * xoffs;
120                        sampleOffsets[idx + 1] = y * yoffs;
121
122                        idx += 2;
123                }
124        }
125}
126
[3026]127
128void DeferredRenderer::DrawQuad(ShaderProgram *p)
129{
130        Vector3 tl, tr, bl, br;
131        ComputeViewVectors(tl, tr, bl, br);
132
133        p->Bind();
134
135        // note: slightly larger texture could hide ambient occlusion error on border but costs resolution
136        const float offs = 0.5f;
137       
138        glBegin(GL_QUADS);
139
140        glTexCoord2f(0, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, bl.x, bl.y, bl.z); glVertex3f(-offs, -offs, -0.5f);
141        glTexCoord2f(1, 0); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, br.x, br.y, br.z); glVertex3f( offs, -offs, -0.5f);
142        glTexCoord2f(1, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tr.x, tr.y, tr.z); glVertex3f( offs,  offs, -0.5f);
143        glTexCoord2f(0, 1); glMultiTexCoord3fARB(GL_TEXTURE1_ARB, tl.x, tl.y, tl.z); glVertex3f(-offs,  offs, -0.5f);
144
145        glEnd();
146}
147
148
[2859]149/** Generate poisson disc distributed sample points on the unit disc
150*/
[2887]151static void GenerateSamples(int sampling)
[2859]152{
[2887]153        switch (sampling)
154        {
[2930]155        case DeferredRenderer::SAMPLING_POISSON:
[2887]156                {
[2930]157                        PoissonDiscSampleGenerator2 poisson(NUM_SAMPLES, 1.0f);
[2900]158                        poisson.Generate((float *)samples2);
[2887]159                }
160                break;
[2930]161        case DeferredRenderer::SAMPLING_QUADRATIC:
[2887]162                {
[2930]163                        QuadraticDiscSampleGenerator2 g(NUM_SAMPLES, 1.0f);
164                        g.Generate((float *)samples2);
[2887]165                }
166                break;
[2930]167        default: // SAMPLING_DEFAULT
[3026]168                {
169                        RandomSampleGenerator2 g(NUM_SAMPLES, 1.0f);
170                        g.Generate((float *)samples2);
171                }
[2903]172        }
[2859]173}
174
175
[2879]176static void CreateNoiseTex2D(int w, int h)
177{
178        //GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
179        float *randomNormals = new float[w * h * 3];
180
[2900]181        static HaltonSequence halton;
182        float r[2];
183
[2879]184        for (int i = 0; i < w * h * 3; i += 3)
185        {
[2903]186                // create random samples on a circle
187                r[0] = RandomValue(0, 1);
188                //halton.GetNext(1, r);
189
190                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
191               
192                randomNormals[i + 0] = cos(theta);
193                randomNormals[i + 1] = sin(theta);
194                randomNormals[i + 2] = 0;
[2879]195        }
196
197        glEnable(GL_TEXTURE_2D);
198        glGenTextures(1, &noiseTex);
199        glBindTexture(GL_TEXTURE_2D, noiseTex);
200               
201        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
202        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
203        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
204        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
205
206        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGB, GL_FLOAT, randomNormals);
207
208        glBindTexture(GL_TEXTURE_2D, 0);
209        glDisable(GL_TEXTURE_2D);
210
211        delete [] randomNormals;
212
213        cout << "created noise texture" << endl;
214
215        PrintGLerror("noisetexture");
216}
217
218
[3019]219static void InitBuffer(FrameBufferObject *fbo, int index)
220{
221        // read the second buffer, write to the first buffer
222        fbo->Bind();
223        glDrawBuffers(1, mrt + index);
224
225        //glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
226        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
227
228        glEnd();
229
230        FrameBufferObject::Release();
231}
232
233
[2896]234DeferredRenderer::DeferredRenderer(int w, int h, Camera *cam, float scaleFactor):
[2860]235mWidth(w), mHeight(h),
236mCamera(cam),
[2875]237mUseTemporalCoherence(true),
[2895]238mRegenerateSamples(true),
[2930]239mSamplingMethod(SAMPLING_POISSON),
[2895]240mShadingMethod(DEFAULT),
[3019]241mIllumFboIndex(0)
[2861]242{
[2879]243        // create noise texture for ssao
244        CreateNoiseTex2D(w, h);
245
[2965]246
[2861]247        ///////////
248        //-- the flip-flop fbos
[2859]249
[3019]250        mIllumFbo = new FrameBufferObject(w / 2, h / 2, FrameBufferObject::DEPTH_NONE);
251        mFBOs.push_back(mIllumFbo);
[2891]252
[3019]253        for (int i = 0; i < 4; ++ i)
254        {
255                mIllumFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
256                InitBuffer(mIllumFbo, i);
257        }
[3002]258
259        mDownSampleFbo = new FrameBufferObject(w / 2, h / 2, FrameBufferObject::DEPTH_NONE);
260        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGBA_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3017]261        mDownSampleFbo->AddColorBuffer(ColorBufferObject::RGB_FLOAT_16, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR);
[3019]262
263        mFBOs.push_back(mDownSampleFbo);
[3038]264
265        InitCg();
[2861]266}
267
268
[2896]269DeferredRenderer::~DeferredRenderer()
[2861]270{
[3019]271        CLEAR_CONTAINER(mFBOs);
[2861]272        glDeleteTextures(1, &noiseTex);
273}
274
275
[2896]276void DeferredRenderer::SetUseTemporalCoherence(bool temporal)
[2875]277{
278        mUseTemporalCoherence = temporal;
279}
280
281
[3021]282
[3038]283void DeferredRenderer::InitCg()
[3026]284{       
[3038]285        ResourceManager *rm = ResourceManager::GetSingleton();
[2873]286
[3038]287        sCgDeferredProgram = rm->CreateFragmentProgram("deferred", "main");
288        sCgDeferredShadowProgram = rm->CreateFragmentProgram("deferred", "main_shadow");
289        sCgSsaoProgram = rm->CreateFragmentProgram("ssao", "main");
290        sCgGiProgram = rm->CreateFragmentProgram("globillum", "main");
291        sCgCombineIllumProgram = rm->CreateFragmentProgram("globillum", "combine");
292        sCgCombineSsaoProgram = rm->CreateFragmentProgram("ssao", "combine");
293        sCgAntiAliasingProgram = rm->CreateFragmentProgram("antialiasing", "main");
294        sCgToneProgram = rm->CreateFragmentProgram("tonemap", "ToneMap");
295        sCgDownSampleProgram = rm->CreateFragmentProgram("tonemap", "DownSample");
296        sCgToneProgram = rm->CreateFragmentProgram("tonemap", "ToneMap");
297        sCgLogLumProgram = rm->CreateFragmentProgram("tonemap", "CalcAvgLogLum");
298
[3034]299        int i;
300
301        i = 0;
302
303        sCgSsaoProgram->AddParameter("colors", i ++);
[3035]304        sCgSsaoProgram->AddParameter("normals", i ++);
[3034]305        sCgSsaoProgram->AddParameter("oldTex", i ++);
306        sCgSsaoProgram->AddParameter("noise", i ++);
307        sCgSsaoProgram->AddParameter("eyePos", i ++);
308        sCgSsaoProgram->AddParameter("temporalCoherence", i ++);
309        sCgSsaoProgram->AddParameter("samples", i ++);
310        sCgSsaoProgram->AddParameter("bl", i ++);
311        sCgSsaoProgram->AddParameter("br", i ++);
312        sCgSsaoProgram->AddParameter("tl", i ++);
313        sCgSsaoProgram->AddParameter("tr", i ++);
[3035]314        sCgSsaoProgram->AddParameter("modelViewProj", i ++);
315        sCgSsaoProgram->AddParameter("oldModelViewProj", i ++);
[3034]316
317        i = 0;
318
319        sCgGiProgram->AddParameter("colors", i ++);
[3035]320        sCgGiProgram->AddParameter("normals", i ++);
[3034]321        sCgGiProgram->AddParameter("noise", i ++);
322        sCgGiProgram->AddParameter("oldSsaoTex", i ++);
323        sCgGiProgram->AddParameter("oldIllumTex", i ++);
324        sCgGiProgram->AddParameter("eyePos", i ++);
325        sCgGiProgram->AddParameter("temporalCoherence", i ++);
326        sCgGiProgram->AddParameter("samples", i ++);
327        sCgGiProgram->AddParameter("bl", i ++);
328        sCgGiProgram->AddParameter("br", i ++);
329        sCgGiProgram->AddParameter("tl", i ++);
330        sCgGiProgram->AddParameter("tr", i ++);
[3035]331        sCgGiProgram->AddParameter("oldModelViewProj", i ++);
332        sCgGiProgram->AddParameter("modelViewProj", i ++);
[3034]333
334        sCgAntiAliasingProgram->AddParameter("colors", 0);
335        sCgAntiAliasingProgram->AddParameter("normals", 1);
336
337        sCgDeferredProgram->AddParameter("colors", 0);
338        sCgDeferredProgram->AddParameter("normals", 1);
339        sCgDeferredProgram->AddParameter("lightDir", 2);
340
[3035]341        sCgLogLumProgram->AddParameter("colors", 0);
342       
343        sCgToneProgram->AddParameter("colors", 0);
344        sCgToneProgram->AddParameter("imageKey", 1);
345        sCgToneProgram->AddParameter("whiteLum", 2);
346        sCgToneProgram->AddParameter("middleGrey", 3);
[3034]347
[3035]348        sCgDownSampleProgram->AddParameter("colors", 0);
349        sCgDownSampleProgram->AddParameter("downSampleOffs", 1);
350
351        sCgDeferredShadowProgram->AddParameter("colors", 0);
352        sCgDeferredShadowProgram->AddParameter("normals", 1);
353        sCgDeferredShadowProgram->AddParameter("shadowMap", 2);
354        sCgDeferredShadowProgram->AddParameter("noise", 3);
355        sCgDeferredShadowProgram->AddParameter("shadowMatrix", 4);
356        sCgDeferredShadowProgram->AddParameter("sampleWidth", 5);
357        sCgDeferredShadowProgram->AddParameter("lightDir", 6);
358        sCgDeferredShadowProgram->AddParameter("eyePos", 7);
359        sCgDeferredShadowProgram->AddParameter("samples", 8);
360        sCgDeferredShadowProgram->AddParameter("weights", 9);
361
[3036]362        sCgCombineIllumProgram->AddParameter("colors", 0);
363        sCgCombineIllumProgram->AddParameter("ssaoTex", 1);
364        sCgCombineIllumProgram->AddParameter("illumTex", 2);
[3035]365
[3036]366        sCgCombineSsaoProgram->AddParameter("colors", 0);
367        sCgCombineSsaoProgram->AddParameter("ssaoTex", 1);
368        sCgCombineSsaoProgram->AddParameter("filterOffs", 2);
369        sCgCombineSsaoProgram->AddParameter("filterWeights", 3);
370
371
[3026]372        float filterWeights[NUM_PCF_TABS];
373        PoissonDiscSampleGenerator2 poisson(NUM_PCF_TABS, 1.0f);
374        poisson.Generate((float *)pcfSamples);
[2990]375
[3026]376        for (int i = 0; i < NUM_PCF_TABS; ++ i)
[2880]377        {
[3026]378                filterWeights[i] = GaussianDistribution(pcfSamples[i].x, pcfSamples[i].y, 1.0f);
[2880]379        }
380
[3035]381        sCgDeferredShadowProgram->SetArray2f(8, (float *)pcfSamples, NUM_PCF_TABS);
382        sCgDeferredShadowProgram->SetArray1f(9, (float *)filterWeights, NUM_PCF_TABS);
[2880]383
[2859]384        PrintGLerror("init");
385}
386
387
[2896]388void DeferredRenderer::Render(FrameBufferObject *fbo,
[2897]389                                                          const Matrix4x4 &oldProjViewMatrix,
[2900]390                                                          const Matrix4x4 &projViewMatrix,
[2901]391                                                          float tempCohFactor,
[2952]392                                                          DirectionalLight *light,
[2991]393                                                          bool useToneMapping,
394                                                          ShadowMap *shadowMap
395                                                          )
[2859]396{
[2868]397        // switch roles of old and new fbo
398        // the algorihm uses two input fbos, where the one
399        // contais the color buffer from the last frame,
400        // the other one will be written
[2897]401
[3019]402        mIllumFboIndex = 2 - mIllumFboIndex;
[2976]403       
[3006]404
[3038]405        ResourceManager::GetSingleton()->EnableFragmentProfile();
[2867]406
407        glDisable(GL_ALPHA_TEST);
408        glDisable(GL_TEXTURE_2D);
409        glDisable(GL_LIGHTING);
[3007]410        glDisable(GL_BLEND);
[3008]411        glDisable(GL_DEPTH_TEST);
[2867]412
[2880]413        glPushAttrib(GL_VIEWPORT_BIT);
414        glViewport(0, 0, mWidth, mHeight);
415
[2867]416        glMatrixMode(GL_PROJECTION);
417        glPushMatrix();
418        glLoadIdentity();
419
[2897]420        const float offs = 0.5f;
421        glOrtho(-offs, offs, -offs, offs, 0, 1);
422
[2867]423        glMatrixMode(GL_MODELVIEW);
424        glPushMatrix();
425        glLoadIdentity();
426
[2944]427        if (shadowMap)
[2952]428                FirstPassShadow(fbo, light, shadowMap);
[2895]429        else
[2952]430                FirstPass(fbo, light);
[2944]431
432        switch (mShadingMethod)
[2880]433        {
[2944]434        case SSAO:
[3009]435                // downsample fbo buffers for colors, normals
[3006]436                DownSample(fbo, colorBufferIdx, mDownSampleFbo, 0);
437                DownSample(fbo, 1, mDownSampleFbo, 1);
438
[3027]439                ComputeSsao(fbo, tempCohFactor, projViewMatrix, oldProjViewMatrix);
[2944]440                CombineSsao(fbo);
441                break;
442        case GI:
[3009]443                // downsample fbo buffers for colors, normals
[3006]444                DownSample(fbo, colorBufferIdx, mDownSampleFbo, 0);
[3009]445                DownSample(fbo, 1, mDownSampleFbo, 1);
446
[3006]447                ComputeGlobIllum(fbo, tempCohFactor, projViewMatrix, oldProjViewMatrix);
[2944]448                CombineIllum(fbo);
449                break;
450        default: // DEFAULT
451                // do nothing: standard deferred shading
452                break;
453        }
[2884]454
[2991]455        if (useToneMapping)
456        {
457                float imageKey, whiteLum, middleGrey;
458
459                ComputeToneParameters(fbo, light, imageKey, whiteLum, middleGrey);
[3007]460                ToneMap(fbo, imageKey, whiteLum, middleGrey);
[2991]461        }
462
[2970]463        AntiAliasing(fbo, light);
[2867]464
465        glEnable(GL_LIGHTING);
466        glDisable(GL_TEXTURE_2D);
467
468        glMatrixMode(GL_PROJECTION);
469        glPopMatrix();
470
471        glMatrixMode(GL_MODELVIEW);
472        glPopMatrix();
473
474        glPopAttrib();
475
[3007]476        FrameBufferObject::Release();
[3038]477        ResourceManager::GetSingleton()->DisableFragmentProfile();
[2859]478}
479
480
[2896]481void DeferredRenderer::ComputeSsao(FrameBufferObject *fbo,
[2901]482                                                                   float tempCohFactor,
[3027]483                                                                   const Matrix4x4 &projViewMatrix,
484                                                                   const Matrix4x4 &oldProjViewMatrix
[2900]485                                                                   )
[2859]486{
[3016]487#if 0
[3015]488        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
489        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
490#else
[3006]491        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
[3009]492        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
[3015]493#endif
494
[3019]495        GLuint oldTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
[2993]496
[3006]497        glPushAttrib(GL_VIEWPORT_BIT);
[3019]498        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
[3006]499
[2861]500        // read the second buffer, write to the first buffer
[3019]501        mIllumFbo->Bind();
502        glDrawBuffers(1, mrt + mIllumFboIndex);
[2868]503
[3034]504        sCgSsaoProgram->SetTexture(0, colorsTex);
505        sCgSsaoProgram->SetTexture(1, normalsTex);
506        sCgSsaoProgram->SetTexture(2, oldTex);
507        sCgSsaoProgram->SetTexture(3, noiseTex);
508
[3027]509        const Vector3 pos = mCamera->GetPosition();
[3034]510        sCgSsaoProgram->SetValue3f(4, pos.x, pos.y, pos.z);
[3027]511
[3034]512        sCgSsaoProgram->SetValue1f(5, (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
[3035]513       
[2895]514        if (mUseTemporalCoherence || mRegenerateSamples)
[2875]515        {
[2895]516                mRegenerateSamples = false;
[2859]517
[2875]518                // q: should we generate new samples or only rotate the old ones?
519                // in the first case, the sample patterns look nicer, but the kernel
520                // needs longer to converge
[2895]521                GenerateSamples(mSamplingMethod);
[3035]522                sCgSsaoProgram->SetArray2f(6, (float *)samples2, NUM_SAMPLES);
[2875]523        }
[2859]524
525        Vector3 tl, tr, bl, br;
526        ComputeViewVectors(tl, tr, bl, br);
527
[3035]528        sCgSsaoProgram->SetValue3f(7, bl.x, bl.y, bl.z);
529        sCgSsaoProgram->SetValue3f(8, br.x, br.y, br.z);
530        sCgSsaoProgram->SetValue3f(9, tl.x, tl.y, tl.z);
531        sCgSsaoProgram->SetValue3f(10, tr.x, tr.y, tr.z);
[2987]532
[3035]533        sCgSsaoProgram->SetMatrix(11, projViewMatrix);
534        sCgSsaoProgram->SetMatrix(12, oldProjViewMatrix);
535
536
[3026]537        DrawQuad(sCgSsaoProgram);
[2987]538
[3006]539        glPopAttrib();
[2859]540
541        PrintGLerror("ssao first pass");
542}
543
544
[2896]545void DeferredRenderer::ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br)
[2860]546{
547        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
[2859]548
[2860]549        mCamera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
550
[2888]551        bl = Normalize(nbl - fbl);
552        br = Normalize(nbr - fbr);
553        tl = Normalize(ntl - ftl);
554        tr = Normalize(ntr - ftr);
[2860]555}
556
557
[2865]558static void SetVertex(float x, float y, float x_offs, float y_offs)
559{
560        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
561        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
562        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
563        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
564        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
565
566        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
567        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
568
569        glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
570}
571
572
[2970]573void DeferredRenderer::AntiAliasing(FrameBufferObject *fbo, DirectionalLight *light)
[2865]574{
[3007]575        FrameBufferObject::Release();
576
[2968]577        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2967]578
[2968]579        GLuint colorsTex = colorBuffer->GetTexture();
[2865]580        GLuint normalsTex = fbo->GetColorBuffer(2)->GetTexture();
[3007]581
[3034]582        sCgAntiAliasingProgram->SetTexture(0, colorsTex);
583        sCgAntiAliasingProgram->SetTexture(1, normalsTex);
[2865]584
[3026]585        sCgAntiAliasingProgram->Bind();
[2868]586
[2865]587        glColor3f(1.0f, 1.0f, 1.0f);
588
589        glBegin(GL_QUADS);
590
591        // the neighbouring texels
592        float x_offs = 1.0f / mWidth;
593        float y_offs = 1.0f / mHeight;
594
595        SetVertex(0, 0, x_offs, y_offs);
596        SetVertex(1, 0, x_offs, y_offs);
597        SetVertex(1, 1, x_offs, y_offs);
598        SetVertex(0, 1, x_offs, y_offs);
599
600        glEnd();
601
[2867]602        PrintGLerror("antialiasing");
[2865]603}
604
605
[2952]606void DeferredRenderer::FirstPass(FrameBufferObject *fbo, DirectionalLight *light)
[2868]607{
[2973]608        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]609        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
610        GLuint positionsTex = fbo->GetColorBuffer(2)->GetTexture();
[2868]611
[2879]612        fbo->Bind();
[2868]613
[2973]614        colorBufferIdx = 3 - colorBufferIdx;
[2899]615        glDrawBuffers(1, mrt + colorBufferIdx);
[2868]616
[3026]617        const Vector3 lightDir = -light->GetDirection();
[2868]618
[3034]619        sCgDeferredProgram->SetTexture(0, colorsTex);
620        sCgDeferredProgram->SetTexture(1, normalsTex);
621        sCgDeferredProgram->SetValue3f(2, lightDir.x, lightDir.y, lightDir.z);
[2868]622       
[3026]623        DrawQuad(sCgDeferredProgram);
[2952]624
[2868]625        PrintGLerror("deferred shading");
626}
627
[2869]628
[2896]629void DeferredRenderer::ComputeGlobIllum(FrameBufferObject *fbo,
[2901]630                                                                                float tempCohFactor,
[3006]631                                                                                const Matrix4x4 &projViewMatrix,
[2901]632                                                                                const Matrix4x4 &oldProjViewMatrix)
[2869]633{
[3016]634#if 0
635        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
636        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
637#else
[3003]638        GLuint colorsTex = mDownSampleFbo->GetColorBuffer(0)->GetTexture();
[3009]639        GLuint normalsTex = mDownSampleFbo->GetColorBuffer(1)->GetTexture();
[3016]640#endif
[2869]641
[3006]642        glPushAttrib(GL_VIEWPORT_BIT);
[3019]643        glViewport(0, 0, mIllumFbo->GetWidth(), mIllumFbo->GetHeight());
[2869]644
[2873]645        // read the second buffer, write to the first buffer
[3019]646        mIllumFbo->Bind();
[2873]647
[3019]648        glDrawBuffers(2, mrt + mIllumFboIndex);
[2873]649
[3019]650        GLuint oldSsaoTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex)->GetTexture();
651        GLuint oldIllumTex = mIllumFbo->GetColorBuffer(2 - mIllumFboIndex + 1)->GetTexture();
[3006]652       
[2869]653
[3034]654        sCgGiProgram->SetTexture(0, colorsTex);
655        sCgGiProgram->SetTexture(1, normalsTex);
656        sCgGiProgram->SetTexture(2, noiseTex);
657        sCgGiProgram->SetTexture(3, oldSsaoTex);
658        sCgGiProgram->SetTexture(4, oldIllumTex);
[2869]659
[3034]660        const Vector3 pos = mCamera->GetPosition();
661        sCgGiProgram->SetValue3f(5, pos.x, pos.y, pos.z);
662
663
664        sCgGiProgram->SetValue1f(6,
[3026]665                (mUseTemporalCoherence && !mRegenerateSamples) ? tempCohFactor : 0);
[2869]666
[2895]667        if (mUseTemporalCoherence || mRegenerateSamples)
[2875]668        {
[2895]669                mRegenerateSamples = false;
[2873]670
[2875]671                // q: should we generate new samples or only rotate the old ones?
672                // in the first case, the sample patterns look nicer, but the kernel
673                // needs longer to converge
[2895]674                GenerateSamples(mSamplingMethod);
[2903]675
[3034]676                sCgGiProgram->SetArray2f(7, (float *)samples2, NUM_SAMPLES);
[2875]677        }
678
[2895]679
[2873]680        Vector3 tl, tr, bl, br;
681        ComputeViewVectors(tl, tr, bl, br);
[2990]682       
[3034]683        sCgGiProgram->SetValue3f(8, bl.x, bl.y, bl.z);
684        sCgGiProgram->SetValue3f(9, br.x, br.y, br.z);
685        sCgGiProgram->SetValue3f(10, tl.x, tl.y, tl.z);
686        sCgGiProgram->SetValue3f(11, tr.x, tr.y, tr.z);
[2873]687
[3035]688        sCgGiProgram->SetMatrix(12, oldProjViewMatrix);
689        sCgGiProgram->SetMatrix(13, projViewMatrix);
690
691
[3026]692        DrawQuad(sCgGiProgram);
[2990]693
[3006]694        glPopAttrib();
695
[2873]696        PrintGLerror("globillum first pass");
[2869]697}
698
699
[2896]700void DeferredRenderer::CombineIllum(FrameBufferObject *fbo)
[2880]701{
[2973]702        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[2884]703
[3019]704        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
705        GLuint illumTex = mIllumFbo->GetColorBuffer(mIllumFboIndex + 1)->GetTexture();
[2880]706
[2891]707
[2880]708        fbo->Bind();
709
[2884]710        // overwrite old color texture
[2973]711        colorBufferIdx = 3 - colorBufferIdx;
712
[2899]713        glDrawBuffers(1, mrt + colorBufferIdx);
[2880]714
[3036]715        sCgCombineIllumProgram->SetTexture(0, colorsTex);
716        sCgCombineIllumProgram->SetTexture(1, ssaoTex);
717        sCgCombineIllumProgram->SetTexture(2, illumTex);
[2880]718       
[3026]719        DrawQuad(sCgCombineIllumProgram);
[2880]720
721        PrintGLerror("combine");
722}
723
724
[2896]725void DeferredRenderer::CombineSsao(FrameBufferObject *fbo)
[2880]726{
[2973]727        fbo->Bind();
728
729        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]730        GLuint positionsTex = fbo->GetColorBuffer(2)->GetTexture();
731       
[3019]732        GLuint ssaoTex = mIllumFbo->GetColorBuffer(mIllumFboIndex)->GetTexture();
[2880]733
[2895]734        // overwrite old color texture
[2973]735        colorBufferIdx = 3 - colorBufferIdx;
[2899]736        glDrawBuffers(1, mrt + colorBufferIdx);
[2880]737
[3017]738        float filterOffsets[NUM_DOWNSAMPLES * 2];
739        float filterWeights[NUM_DOWNSAMPLES];
740
741        PoissonDiscSampleGenerator2 poisson(NUM_DOWNSAMPLES, 1.0f);
742        poisson.Generate((float *)filterOffsets);
743
744        const float xoffs = 2.0f / fbo->GetWidth();
745        const float yoffs = 2.0f / fbo->GetHeight();
746
747        for (int i = 0; i < NUM_DOWNSAMPLES; ++ i)
748        {
749                float x = filterOffsets[2 * i + 0];
750                float y = filterOffsets[2 * i + 1];
751
752                filterOffsets[2 * i + 0] *= xoffs;
753                filterOffsets[2 * i + 1] *= yoffs;
754
755                filterWeights[i] = GaussianDistribution(x, y, 1.0f);
756        }
757
[3036]758       
759        sCgCombineSsaoProgram->SetTexture(0, colorsTex);
760        sCgCombineSsaoProgram->SetTexture(1, ssaoTex);
[3017]761
[3036]762        sCgCombineSsaoProgram->SetArray2f(2, (float *)filterOffsets, NUM_DOWNSAMPLES);
763        sCgCombineSsaoProgram->SetArray1f(3, (float *)filterWeights, NUM_DOWNSAMPLES);
[2880]764       
[3026]765        DrawQuad(sCgCombineSsaoProgram);
[2974]766       
[2880]767        PrintGLerror("combine ssao");
768}
769
770
[2952]771void DeferredRenderer::FirstPassShadow(FrameBufferObject *fbo,
772                                                                           DirectionalLight *light,
773                                                                           ShadowMap *shadowMap)
[2895]774{
[2973]775        fbo->Bind();
[2880]776
[2973]777        GLuint colorsTex = fbo->GetColorBuffer(colorBufferIdx)->GetTexture();
[3009]778        GLuint normalsTex = fbo->GetColorBuffer(1)->GetTexture();
779        GLuint positionsTex = fbo->GetColorBuffer(2)->GetTexture();
[2973]780
[2928]781        GLuint shadowTex = shadowMap->GetDepthTexture();
[2895]782
783        Matrix4x4 shadowMatrix;
784        shadowMap->GetTextureMatrix(shadowMatrix);
785
[2973]786        colorBufferIdx = 3 - colorBufferIdx;
[2899]787        glDrawBuffers(1, mrt + colorBufferIdx);
[2895]788
[3035]789        sCgDeferredShadowProgram->SetTexture(0, colorsTex);
790        sCgDeferredShadowProgram->SetTexture(1, normalsTex);
791        sCgDeferredShadowProgram->SetTexture(2, shadowTex);
792        sCgDeferredShadowProgram->SetTexture(3, noiseTex);
[2895]793
[3035]794        sCgDeferredShadowProgram->SetMatrix(4, shadowMatrix);
[3027]795
[3035]796        sCgDeferredShadowProgram->SetValue1f(5, 2.0f / shadowMap->GetSize());
[3027]797
[3026]798        const Vector3 lightDir = -light->GetDirection();
[3035]799        sCgDeferredShadowProgram->SetValue3f(6, lightDir.x, lightDir.y, lightDir.z);
[2895]800
[3016]801        const Vector3 pos = mCamera->GetPosition();
[3035]802        sCgDeferredShadowProgram->SetValue3f(7, pos.x, pos.y, pos.z);
[2952]803
[3026]804        DrawQuad(sCgDeferredShadowProgram);
[2895]805
806        PrintGLerror("deferred shading + shadows");
807}
808
809
[2896]810void DeferredRenderer::SetSamplingMethod(SAMPLING_METHOD s)
[2895]811{
812        if (s != mSamplingMethod)
813        {
814                mSamplingMethod = s;
815                mRegenerateSamples = true;
816        }
817}
818
[2897]819
820void DeferredRenderer::SetShadingMethod(SHADING_METHOD s)
821{
822        if (s != mShadingMethod)
823        {
824                mShadingMethod = s;
825                mRegenerateSamples = true;
826        }
827}
828
[2965]829
[2973]830void DeferredRenderer::ComputeToneParameters(FrameBufferObject *fbo,
831                                                                                         DirectionalLight *light,
832                                                                                         float &imageKey,
833                                                                                         float &whiteLum,
834                                                                                         float &middleGrey)
[2972]835{
[2975]836        // hack: estimate value where sky burns out
[3010]837        whiteLum = log(WHITE_LUMINANCE);
[2973]838       
[2975]839        ////////////////////
840        //-- linear interpolate brightness key depending on the current sun position
[2973]841
842        const float minKey = 0.09f;
[3020]843        const float maxKey = 0.36f;
[2973]844
845        const float lightIntensity = DotProd(-light->GetDirection(), Vector3::UNIT_Z());
846        middleGrey = lightIntensity * maxKey + (1.0f - lightIntensity) * minKey;
[2991]847
[2993]848
[2991]849        //////////
850        //-- compute avg loglum
851
852        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2992]853        GLuint colorsTex = colorBuffer->GetTexture();
[2991]854
855        fbo->Bind();
856
857        colorBufferIdx = 3 - colorBufferIdx;
858        glDrawBuffers(1, mrt + colorBufferIdx);
859       
[3035]860        sCgLogLumProgram->SetTexture(0, colorsTex);
[3026]861        DrawQuad(sCgLogLumProgram);
[2991]862       
863        PrintGLerror("ToneMapParams");
864
865
866        ///////////////////
867        //-- compute avg loglum in scene using mipmapping
868
[3008]869        glBindTexture(GL_TEXTURE_2D, fbo->GetColorBuffer(colorBufferIdx)->GetTexture());
870        glGenerateMipmapEXT(GL_TEXTURE_2D);
[2972]871}
872
873
[3003]874static void ExportData(float *data, int w, int h)
875{
876        startil();
877
878        cout << "w: " << w << " h: " << h << endl;
879        ILstring filename = ILstring("downsample2.jpg");
880        ilRegisterType(IL_FLOAT);
881
882        const int depth = 1;
883        const int bpp = 4;
884
885        if (!ilTexImage(w, h, depth, bpp, IL_RGBA, IL_FLOAT, data))
886        {
887                cerr << "IL error " << ilGetError() << endl;
888                stopil();
889                return;
890        }
891
892        if (!ilSaveImage(filename))
893        {
894                cerr << "TGA write error " << ilGetError() << endl;
895        }
896
897        stopil();
898}
899
900
[3006]901void DeferredRenderer::DownSample(FrameBufferObject *fbo, int bufferIdx,
902                                                                  FrameBufferObject *downSampleFbo,
903                                                                  int downSampleBufferIdx)
[2972]904{
[3006]905        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(bufferIdx);
[2994]906        GLuint colorsTex = colorBuffer->GetTexture();
[3006]907
908        glPushAttrib(GL_VIEWPORT_BIT);
909        glViewport(0, 0, downSampleFbo->GetWidth(), downSampleFbo->GetHeight());
[2972]910       
[3035]911        sCgDownSampleProgram->SetTexture(0, colorsTex);
[2994]912
[3017]913        float downSampleOffsets[NUM_DOWNSAMPLES * 2];
914        ComputeSampleOffsets(downSampleOffsets, fbo->GetWidth(), fbo->GetHeight());
915
[3035]916        sCgDownSampleProgram->SetArray2f(1, (float *)downSampleOffsets, NUM_DOWNSAMPLES);
[3010]917
[2994]918        mDownSampleFbo->Bind();
[3006]919        glDrawBuffers(1, mrt + downSampleBufferIdx);
[2994]920
[3026]921        DrawQuad(sCgDownSampleProgram);
[3005]922       
[3006]923        glPopAttrib();
924       
[3005]925        PrintGLerror("downsample");
[2972]926}
927
928
[2973]929void DeferredRenderer::ToneMap(FrameBufferObject *fbo,
930                                                           float imageKey,
931                                                           float whiteLum,
932                                                           float middleGrey)
[2972]933{
934        ColorBufferObject *colorBuffer = fbo->GetColorBuffer(colorBufferIdx);
[2994]935        GLuint colorsTex = colorBuffer->GetTexture();
[2972]936
[2973]937        fbo->Bind();
[3025]938       
[2973]939        colorBufferIdx = 3 - colorBufferIdx;
940        glDrawBuffers(1, mrt + colorBufferIdx);
[3007]941
[3035]942        sCgToneProgram->SetTexture(0, colorsTex);
943        sCgToneProgram->SetValue1f(1, imageKey);
944        sCgToneProgram->SetValue1f(2, whiteLum);
945        sCgToneProgram->SetValue1f(3, middleGrey);
[3007]946
[3026]947        DrawQuad(sCgToneProgram);
[2972]948
[2973]949        PrintGLerror("ToneMap");
[2972]950}
951
952
[2858]953} // namespace
Note: See TracBrowser for help on using the repository browser.