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

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