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

Revision 2868, 14.2 KB checked in by mattausch, 16 years ago (diff)

changed ssao to multipass algorithm

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