source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SsaoShader.cpp @ 2869

Revision 2869, 16.3 KB checked in by mattausch, 16 years ago (diff)

computing ao in nice function ... but slow!!

Line 
1#include "SsaoShader.h"
2#include "FrameBufferObject.h"
3#include "RenderState.h"
4#include "SampleGenerator.h"
5#include "Vector3.h"
6#include "Camera.h"
7
8
9using namespace std;
10
11static GLenum mymrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};
12
13namespace CHCDemoEngine
14{
15
16// number of ssao samples
17#define NUM_SAMPLES 16
18
19
20static CGprogram sCgSsaoProgram = NULL;
21static CGprogram sCgDeferredProgram2 = NULL;
22static CGprogram sCgAntiAliasingProgram = NULL;
23static CGprogram sCgCombineProgram = NULL;
24
25static CGparameter sColorsTexCombineParam;
26static CGparameter sSsaoTexCombineParam;
27
28static CGparameter sColorsTexDeferredParam;
29static CGparameter sPositionsTexDeferredParam;
30static CGparameter sNormalsTexDeferredParam;
31
32static CGparameter sColorsTexParam;
33static CGparameter sPositionsTexParam;
34static CGparameter sNormalsTexParam;
35
36
37static CGparameter sOldModelViewProjMatrixParam;
38static CGparameter sMaxDepthParam;
39static CGparameter sSamplesParam;
40static CGparameter sOldTexParam;
41static CGparameter sNoiseTexParam;
42static CGparameter sNoiseMultiplierParam;
43static CGparameter sExpFactorParam;
44
45static CGparameter sColorsTexAntiAliasingParam;
46static CGparameter sNormalsTexAntiAliasingParam;
47
48
49static GLuint noiseTex;
50
51// ssao random spherical samples
52static Sample2 samples[NUM_SAMPLES];
53
54
55static void PrintGLerror(char *msg)
56{
57        GLenum errCode;
58        const GLubyte *errStr;
59       
60        if ((errCode = glGetError()) != GL_NO_ERROR)
61        {
62                errStr = gluErrorString(errCode);
63                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
64        }
65}
66
67
68/** Generate poisson disc distributed sample points on the unit disc
69*/
70static void GenerateSamples()
71{
72        static PoissonDiscSampleGenerator poisson(NUM_SAMPLES, 1.0f);
73        poisson.Generate((Sample2 *)samples);
74}
75
76
77SsaoShader::SsaoShader(int w, int h, Camera *cam, float scaleFactor):
78mWidth(w), mHeight(h),
79mCamera(cam),
80mScaleFactor(scaleFactor)
81{
82       
83        ///////////
84        //-- the flip-flop fbos
85
86        mNewFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
87        // the diffuse color buffer
88        mNewFbo->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, false);
89       
90        mOldFbo = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
91        // the diffuse color buffer
92        mOldFbo->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, false);
93       
94        mFbo3 = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
95        // the diffuse color buffer
96        mFbo3->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, false);
97               
98        mFbo4 = new FrameBufferObject(w, h, FrameBufferObject::DEPTH_NONE);
99        // the diffuse color buffer
100        mFbo4->AddColorBuffer(ColorBufferObject::BUFFER_FLOAT_32, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, false);
101
102        // create noise texture for ssao
103        CreateNoiseTex2D();
104}
105
106
107SsaoShader::~SsaoShader()
108{
109        if (sCgSsaoProgram)
110                cgDestroyProgram(sCgSsaoProgram);
111
112        DEL_PTR(mNewFbo);
113        DEL_PTR(mOldFbo);
114
115        glDeleteTextures(1, &noiseTex);
116}
117
118
119void SsaoShader::Init(CGcontext context)
120{       
121        sCgDeferredProgram2 =
122                cgCreateProgramFromFile(context,
123                                                                CG_SOURCE,
124                                                                "src/shaders/deferred.cg",
125                                                                RenderState::sCgFragmentProfile,
126                                                                "main2",
127                                                                NULL);
128
129        if (sCgDeferredProgram2 != NULL)
130        {
131                cgGLLoadProgram(sCgDeferredProgram2);
132
133                // we need size of texture for scaling
134                sPositionsTexDeferredParam = cgGetNamedParameter(sCgDeferredProgram2, "positions"); 
135                sColorsTexDeferredParam = cgGetNamedParameter(sCgDeferredProgram2, "colors"); 
136                sNormalsTexDeferredParam = cgGetNamedParameter(sCgDeferredProgram2, "normals");
137        }
138        else
139                cerr << "deferred program failed to load" << endl;
140
141
142        sCgCombineProgram =
143                cgCreateProgramFromFile(context,
144                                                                CG_SOURCE,
145                                                                "src/shaders/ssao.cg",
146                                                                RenderState::sCgFragmentProfile,
147                                                                "combined",
148                                                                NULL);
149
150        if (sCgCombineProgram != NULL)
151        {
152                cgGLLoadProgram(sCgCombineProgram);
153
154                // we need size of texture for scaling
155                sColorsTexCombineParam = cgGetNamedParameter(sCgCombineProgram, "colors"); 
156                sSsaoTexCombineParam = cgGetNamedParameter(sCgCombineProgram, "ssaoTex");
157        }
158        else
159                cerr << "combined program failed to load" << endl;
160
161
162        ///////////////
163
164        sCgSsaoProgram =
165                cgCreateProgramFromFile(context,
166                                                                CG_SOURCE,
167                                                                "src/shaders/ssao.cg",
168                                                                RenderState::sCgFragmentProfile,
169                                                                "main",
170                                                                NULL);
171
172        if (sCgSsaoProgram != NULL)
173        {
174                cgGLLoadProgram(sCgSsaoProgram);
175
176                // we need size of texture for scaling
177                sPositionsTexParam = cgGetNamedParameter(sCgSsaoProgram, "positions"); 
178                sColorsTexParam = cgGetNamedParameter(sCgSsaoProgram, "colors"); 
179                sNormalsTexParam = cgGetNamedParameter(sCgSsaoProgram, "normals"); 
180                sNoiseTexParam = cgGetNamedParameter(sCgSsaoProgram, "noiseTexture");
181                sNoiseMultiplierParam = cgGetNamedParameter(sCgSsaoProgram, "noiseMultiplier");
182               
183                sOldModelViewProjMatrixParam = cgGetNamedParameter(sCgSsaoProgram, "oldModelViewProj");
184                sMaxDepthParam = cgGetNamedParameter(sCgSsaoProgram, "maxDepth");
185                sExpFactorParam = cgGetNamedParameter(sCgSsaoProgram, "expFactor");
186
187                sSamplesParam = cgGetNamedParameter(sCgSsaoProgram, "samples");
188                sOldTexParam = cgGetNamedParameter(sCgSsaoProgram, "oldTex"); 
189
190                // generate samples for ssao kernel
191                GenerateSamples();
192                cgGLSetParameterArray2f(sSamplesParam, 0, NUM_SAMPLES, (const float *)samples);
193        }
194        else
195                cerr << "ssao program failed to load" << endl;
196
197        sCgAntiAliasingProgram =
198                cgCreateProgramFromFile(context,
199                                                                CG_SOURCE,
200                                                                "src/shaders/antialiasing.cg",
201                                                                RenderState::sCgFragmentProfile,
202                                                                "main",
203                                                                NULL);
204
205        if (sCgAntiAliasingProgram != NULL)
206        {
207                cgGLLoadProgram(sCgAntiAliasingProgram);
208
209                sColorsTexAntiAliasingParam = cgGetNamedParameter(sCgAntiAliasingProgram, "colors"); 
210                sNormalsTexAntiAliasingParam = cgGetNamedParameter(sCgAntiAliasingProgram, "normals");
211        }
212        else
213                cerr << "antialiasing program failed to load" << endl;
214
215
216        PrintGLerror("init");
217}
218
219
220void SsaoShader::Render(FrameBufferObject *fbo,
221                                                const Matrix4x4 &oldProjViewMatrix,
222                                                float expFactor)
223{
224       
225        // switch roles of old and new fbo
226        // the algorihm uses two input fbos, where the one
227        // contais the color buffer from the last frame,
228        // the other one will be written
229        swap(mNewFbo, mOldFbo);
230
231        cgGLSetMatrixParameterfc(sOldModelViewProjMatrixParam, (const float *)oldProjViewMatrix.x);
232
233        glPushAttrib(GL_VIEWPORT_BIT);
234        glViewport(0, 0, mWidth, mHeight);
235
236        FrameBufferObject::Release();
237
238        glDrawBuffers(1, mymrt);
239
240        cgGLEnableProfile(RenderState::sCgFragmentProfile);
241
242        glDisable(GL_ALPHA_TEST);
243        glDisable(GL_TEXTURE_2D);
244        glDisable(GL_LIGHTING);
245
246        glMatrixMode(GL_PROJECTION);
247        glPushMatrix();
248        glLoadIdentity();
249
250        glMatrixMode(GL_MODELVIEW);
251        glPushMatrix();
252        glLoadIdentity();
253
254        const float offs = 0.5f;
255        glOrtho(-offs, offs, -offs, offs, 0, 1);
256
257        FirstPass(fbo);
258        ComputeSsao(fbo, expFactor);
259        Combine(fbo);
260        AntiAliasing(fbo);
261
262        glEnable(GL_LIGHTING);
263        glDisable(GL_TEXTURE_2D);
264
265        glMatrixMode(GL_PROJECTION);
266        glPopMatrix();
267
268        glMatrixMode(GL_MODELVIEW);
269        glPopMatrix();
270
271        glPopAttrib();
272
273        cgGLDisableProfile(RenderState::sCgFragmentProfile);
274}
275
276
277void SsaoShader::ComputeSsao(FrameBufferObject *fbo, float expFactor)
278{
279        GLuint colorsTex = mFbo3->GetColorBuffer(0)->GetTexture();
280        GLuint positionsTex = fbo->GetColorBuffer(1)->GetTexture();
281        GLuint normalsTex = fbo->GetColorBuffer(2)->GetTexture();
282
283        if (1)
284        {
285                // generate mip map levels for position texture
286                glBindTexture(GL_TEXTURE_2D, positionsTex);
287                glGenerateMipmapEXT(GL_TEXTURE_2D);
288        }
289
290
291        // read the second buffer, write to the first buffer
292        mNewFbo->Bind();
293        glDrawBuffers(1, mymrt);
294
295        GLuint oldTex = mOldFbo->GetColorBuffer(0)->GetTexture();
296
297        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
298
299        cgGLEnableProfile(RenderState::sCgFragmentProfile);
300        cgGLBindProgram(sCgSsaoProgram);
301
302        cgGLSetTextureParameter(sPositionsTexParam, positionsTex);
303        cgGLEnableTextureParameter(sPositionsTexParam);
304
305        cgGLSetTextureParameter(sColorsTexParam, colorsTex);
306        cgGLEnableTextureParameter(sColorsTexParam);
307
308        cgGLSetTextureParameter(sNormalsTexParam, normalsTex);
309        cgGLEnableTextureParameter(sNormalsTexParam);
310
311        cgGLSetTextureParameter(sNoiseTexParam, noiseTex);
312        cgGLEnableTextureParameter(sNoiseTexParam);
313
314        cgGLSetTextureParameter(sOldTexParam, oldTex);
315        cgGLEnableTextureParameter(sOldTexParam);
316
317        cgGLSetParameter1f(sNoiseMultiplierParam, RandomValue(3.0f, 17.0f));
318       
319        cgGLSetParameter1f(sMaxDepthParam, mScaleFactor);
320        cgGLSetParameter1f(sExpFactorParam, expFactor);
321
322
323        //GenerateSamples();
324        cgGLSetParameterArray2f(sSamplesParam, 0, NUM_SAMPLES, (const float *)samples);
325
326        Vector3 tl, tr, bl, br;
327        ComputeViewVectors(tl, tr, bl, br);
328
329        glColor3f(1.0f, 1.0f, 1.0f);
330
331        glBegin(GL_QUADS);
332
333        // note: slightly larger texture hides ambient occlusion error on border but costs resolution
334        //const float new_offs = 0.55f;
335        const float new_offs = 0.5f;
336       
337        glColor3f(bl.x, bl.y, bl.z); glTexCoord2f(0, 0); glVertex3f(-new_offs, -new_offs, -0.5f);
338        glColor3f(br.x, br.y, br.z); glTexCoord2f(1, 0); glVertex3f( new_offs, -new_offs, -0.5f);
339        glColor3f(tr.x, tr.y, tr.z); glTexCoord2f(1, 1); glVertex3f( new_offs,  new_offs, -0.5f);
340        glColor3f(tl.x, tl.y, tl.z); glTexCoord2f(0, 1); glVertex3f(-new_offs,  new_offs, -0.5f);
341
342        glEnd();
343
344        cgGLDisableTextureParameter(sColorsTexParam);
345        cgGLDisableTextureParameter(sPositionsTexParam);
346        cgGLDisableTextureParameter(sNormalsTexParam);
347        cgGLDisableTextureParameter(sNoiseTexParam);
348        cgGLDisableTextureParameter(sOldTexParam);
349
350        FrameBufferObject::Release();
351
352        PrintGLerror("ssao first pass");
353}
354
355
356void SsaoShader::ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br)
357{
358        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
359
360        mCamera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
361
362#if 1 // matT: debug this!!
363       
364        bl = -Normalize(nbl - fbl);
365        br = -Normalize(nbr - fbr);
366        tl = -Normalize(ntl - ftl);
367        tr = -Normalize(ntr - ftr);
368
369#else // just take camera direction
370       
371        bl = -Normalize(mCamera->GetDirection());
372        br = -Normalize(mCamera->GetDirection());
373        tl = -Normalize(mCamera->GetDirection());
374        tr = -Normalize(mCamera->GetDirection());
375
376#endif
377
378        // normalize to 0 .. 1
379        bl = bl * 0.5f + 0.5f;
380        br = br * 0.5f + 0.5f;
381        tl = tl * 0.5f + 0.5f;
382        tr = tr * 0.5f + 0.5f;
383}
384
385
386void SsaoShader::CreateNoiseTex2D()
387{
388        //GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
389        float *randomNormals = new float[mWidth * mHeight * 3];
390
391        for (int i = 0; i < mWidth * mHeight * 3; i += 3)
392        {
393                // create random samples on a circle
394                const float rx = RandomValue(0, 1);
395                const float theta = 2.0f * acos(sqrt(1.0f - rx));
396
397                //randomNormals[i + 0] = (GLubyte)((cos(theta) * 0.5f + 0.5f) * 255.0f);
398                //randomNormals[i + 1] = (GLubyte)((sin(theta) * 0.5f + 0.5f) * 255.0f);
399                randomNormals[i + 0] = cos(theta);
400                randomNormals[i + 1] = sin(theta);
401                randomNormals[i + 2] = 0;
402        }
403
404        glEnable(GL_TEXTURE_2D);
405        glGenTextures(1, &noiseTex);
406        glBindTexture(GL_TEXTURE_2D, noiseTex);
407               
408        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
409        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
410        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
411        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
412
413        //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, randomNormals);
414        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, mWidth, mHeight, 0, GL_RGB, GL_FLOAT, randomNormals);
415
416        glBindTexture(GL_TEXTURE_2D, 0);
417        glDisable(GL_TEXTURE_2D);
418
419        delete [] randomNormals;
420
421        cout << "created noise texture" << endl;
422
423        PrintGLerror("noisetexture");
424}
425
426
427
428static void SetVertex(float x, float y, float x_offs, float y_offs)
429{
430        glMultiTexCoord2fARB(GL_TEXTURE0_ARB, x, y); // center
431        glMultiTexCoord2fARB(GL_TEXTURE1_ARB, x - x_offs, y + y_offs); // left top
432        glMultiTexCoord2fARB(GL_TEXTURE2_ARB, x + x_offs, y - y_offs); // right bottom
433        glMultiTexCoord2fARB(GL_TEXTURE3_ARB, x + x_offs, y + y_offs); // right top
434        glMultiTexCoord2fARB(GL_TEXTURE4_ARB, x - x_offs, y - y_offs); // left bottom
435
436        glMultiTexCoord4fARB(GL_TEXTURE5_ARB, x - x_offs, y, x + x_offs, y); // left right
437        glMultiTexCoord4fARB(GL_TEXTURE6_ARB, x, y + y_offs, x, y - y_offs); // top bottom
438
439        glVertex3f(x - 0.5f, y - 0.5f, -0.5f);
440}
441
442
443void SsaoShader::AntiAliasing(FrameBufferObject *fbo)
444{
445        GLuint colorsTex = mFbo4->GetColorBuffer(0)->GetTexture();
446        //GLuint colorsTex = mNewFbo->GetColorBuffer(0)->GetTexture();
447        GLuint normalsTex = fbo->GetColorBuffer(2)->GetTexture();
448       
449        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
450
451        cgGLEnableProfile(RenderState::sCgFragmentProfile);
452        cgGLBindProgram(sCgAntiAliasingProgram);
453       
454        cgGLSetTextureParameter(sColorsTexAntiAliasingParam, colorsTex);
455        cgGLEnableTextureParameter(sColorsTexAntiAliasingParam);
456
457        cgGLSetTextureParameter(sNormalsTexAntiAliasingParam, normalsTex);
458        cgGLEnableTextureParameter(sNormalsTexAntiAliasingParam);
459
460        glColor3f(1.0f, 1.0f, 1.0f);
461
462        float offs2 = 0.5f;
463
464        glBegin(GL_QUADS);
465
466        // the neighbouring texels
467        float x_offs = 1.0f / mWidth;
468        float y_offs = 1.0f / mHeight;
469
470        SetVertex(0, 0, x_offs, y_offs);
471        SetVertex(1, 0, x_offs, y_offs);
472        SetVertex(1, 1, x_offs, y_offs);
473        SetVertex(0, 1, x_offs, y_offs);
474
475        glEnd();
476
477        cgGLDisableTextureParameter(sColorsTexAntiAliasingParam);
478        cgGLDisableTextureParameter(sNormalsTexAntiAliasingParam);
479
480        PrintGLerror("antialiasing");
481}
482
483
484void SsaoShader::FirstPass(FrameBufferObject *fbo)
485{
486        GLuint colorsTex = fbo->GetColorBuffer(0)->GetTexture();
487        GLuint positionsTex = fbo->GetColorBuffer(1)->GetTexture();
488        GLuint normalsTex = fbo->GetColorBuffer(2)->GetTexture();
489
490        mFbo3->Bind();
491        //mNewFbo->Bind();
492
493        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
494       
495        glDrawBuffers(1, mymrt);
496
497        cgGLEnableProfile(RenderState::sCgFragmentProfile);
498
499        cgGLBindProgram(sCgDeferredProgram2);
500
501        cgGLSetTextureParameter(sColorsTexDeferredParam, colorsTex);
502        cgGLEnableTextureParameter(sColorsTexDeferredParam);
503
504        cgGLSetTextureParameter(sPositionsTexDeferredParam, positionsTex);
505        cgGLEnableTextureParameter(sPositionsTexDeferredParam);
506
507        cgGLSetTextureParameter(sNormalsTexDeferredParam, normalsTex);
508        cgGLEnableTextureParameter(sNormalsTexDeferredParam);
509       
510        glColor3f(1.0f, 1.0f, 1.0f);
511
512        const float offs = 0.5f;
513
514        glBegin(GL_QUADS);
515
516        glTexCoord2f(0, 0); glVertex3f(-offs, -offs, -0.5f);
517        glTexCoord2f(1, 0); glVertex3f( offs, -offs, -0.5f);
518        glTexCoord2f(1, 1); glVertex3f( offs,  offs, -0.5f);
519        glTexCoord2f(0, 1); glVertex3f(-offs,  offs, -0.5f);
520
521        glEnd();
522
523        cgGLDisableTextureParameter(sColorsTexDeferredParam);
524        cgGLDisableTextureParameter(sPositionsTexDeferredParam);
525        cgGLDisableTextureParameter(sNormalsTexDeferredParam);
526
527        cgGLDisableProfile(RenderState::sCgFragmentProfile);
528
529        FrameBufferObject::Release();
530
531        PrintGLerror("deferred shading");
532}
533
534
535void SsaoShader::Combine(FrameBufferObject *fbo)
536{
537        GLuint colorsTex = mFbo3->GetColorBuffer(0)->GetTexture();
538        GLuint ssaoTex = mNewFbo->GetColorBuffer(0)->GetTexture();
539
540        mFbo4->Bind();
541        //mNewFbo->Bind();
542
543        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
544       
545        glDrawBuffers(1, mymrt);
546
547        cgGLEnableProfile(RenderState::sCgFragmentProfile);
548
549        cgGLBindProgram(sCgCombineProgram);
550
551        cgGLSetTextureParameter(sColorsTexCombineParam, colorsTex);
552        cgGLEnableTextureParameter(sColorsTexCombineParam);
553
554        cgGLSetTextureParameter(sSsaoTexCombineParam, ssaoTex);
555        cgGLEnableTextureParameter(sSsaoTexCombineParam);
556
557        glColor3f(1.0f, 1.0f, 1.0f);
558
559        const float offs = 0.5f;
560
561        glBegin(GL_QUADS);
562
563        glTexCoord2f(0, 0); glVertex3f(-offs, -offs, -0.5f);
564        glTexCoord2f(1, 0); glVertex3f( offs, -offs, -0.5f);
565        glTexCoord2f(1, 1); glVertex3f( offs,  offs, -0.5f);
566        glTexCoord2f(0, 1); glVertex3f(-offs,  offs, -0.5f);
567
568        glEnd();
569
570        cgGLDisableTextureParameter(sColorsTexCombineParam);
571        cgGLDisableTextureParameter(sSsaoTexCombineParam);
572
573        cgGLDisableProfile(RenderState::sCgFragmentProfile);
574
575        FrameBufferObject::Release();
576
577        PrintGLerror("deferred shading");
578}
579
580
581} // namespace
Note: See TracBrowser for help on using the repository browser.