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

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