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

Revision 3028, 24.3 KB checked in by mattausch, 16 years ago (diff)

debug version: what to do with shader programs??

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