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

Revision 2863, 9.8 KB checked in by mattausch, 16 years ago (diff)

repaired view vector correction for ssao

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