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

Revision 2860, 8.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;
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 expFactor,
64                                           float scaleFactor
65                                           ):
66mWidth(w), mHeight(h),
67mCamera(cam),
68mExpFactor(expFactor),
69mScaleFactor(scaleFactor)
70{}
71
72
73void SsaoShader::Init(CGcontext context)
74{
75       
76        ///////////////
77
78        sCgSsaoProgram =
79                cgCreateProgramFromFile(context,
80                                                                CG_SOURCE,
81                                                                "src/shaders/deferred.cg",
82                                                                RenderState::sCgFragmentProfile,
83                                                                "main_ssao",
84                                                                NULL);
85
86        if (sCgSsaoProgram != NULL)
87        {
88                cgGLLoadProgram(sCgSsaoProgram);
89
90                // we need size of texture for scaling
91                sPositionsTexParam = cgGetNamedParameter(sCgSsaoProgram, "positions"); 
92                sColorsTexParam = cgGetNamedParameter(sCgSsaoProgram, "colors"); 
93                sNormalsTexParam = cgGetNamedParameter(sCgSsaoProgram, "normals"); 
94                sNoiseTexParam = cgGetNamedParameter(sCgSsaoProgram, "noiseTexture");
95                sNoiseMultiplierParam = cgGetNamedParameter(sCgSsaoProgram, "noiseMultiplier");
96                sOldModelViewProjMatrixParam = cgGetNamedParameter(sCgSsaoProgram, "oldModelViewProj");
97                sMaxDepthParam = cgGetNamedParameter(sCgSsaoProgram, "maxDepth");
98                sExpFactorParam = cgGetNamedParameter(sCgSsaoProgram, "expFactor");
99
100                sSamplesParam = cgGetNamedParameter(sCgSsaoProgram, "samples");
101                sOldTexParam = cgGetNamedParameter(sCgSsaoProgram, "oldTex"); 
102
103                // generate samples for ssao kernel
104                GenerateSamples();
105                cgGLSetParameterArray2f(sSamplesParam, 0, NUM_SAMPLES, (const float *)samples);
106        }
107        else
108                cerr << "ssao program failed to load" << endl;
109
110        PrintGLerror("init");
111}
112
113
114void SsaoShader::Render(FrameBufferObject *fbo, FrameBufferObject *fbo2)
115{
116        FirstPass(fbo, fbo2);
117        SecondPass(fbo, fbo2);
118}
119
120
121void SsaoShader::FirstPass(FrameBufferObject *fbo, FrameBufferObject *fbo2)
122{
123        GLuint positionsTex = fbo->GetColorBuffer(0)->GetTexture();
124        GLuint colorsTex = fbo->GetColorBuffer(0)->GetTexture();
125        GLuint normalsTex = fbo->GetColorBuffer(0)->GetTexture();
126
127        GLuint oldTex = fbo2->GetColorBuffer(0)->GetTexture();
128
129        glPushAttrib(GL_VIEWPORT_BIT);
130        glViewport(0, 0, mWidth, mHeight);
131
132        glDrawBuffers(1, mymrt);
133
134        glDisable(GL_ALPHA_TEST);
135        glDisable(GL_TEXTURE_2D);
136        glDisable(GL_LIGHTING);
137
138        glMatrixMode(GL_PROJECTION);
139        glPushMatrix();
140        glLoadIdentity();
141
142        glMatrixMode(GL_MODELVIEW);
143        glPushMatrix();
144        glLoadIdentity();
145
146        const float offs = 0.5f;
147
148        glOrtho(-offs, offs, -offs, offs, 0, 1);
149
150        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
151
152        cgGLEnableProfile(RenderState::sCgFragmentProfile);
153
154        cgGLBindProgram(sCgSsaoProgram);
155
156        cgGLSetTextureParameter(sPositionsTexParam, positionsTex);
157        cgGLEnableTextureParameter(sPositionsTexParam);
158
159        cgGLSetTextureParameter(sColorsTexParam, colorsTex);
160        cgGLEnableTextureParameter(sColorsTexParam);
161
162        cgGLSetTextureParameter(sNormalsTexParam, normalsTex);
163        cgGLEnableTextureParameter(sNormalsTexParam);
164
165        cgGLSetTextureParameter(sNoiseTexParam, noiseTex);
166        cgGLEnableTextureParameter(sNoiseTexParam);
167
168        cgGLSetTextureParameter(sOldTexParam, oldTex);
169        cgGLEnableTextureParameter(sOldTexParam);
170
171        cgGLSetParameter1f(sNoiseMultiplierParam, RandomValue(3.0f, 17.0f));
172       
173        cgGLSetParameter1f(sMaxDepthParam, mScaleFactor);
174        cgGLSetParameter1f(sExpFactorParam, mExpFactor);
175
176
177        GenerateSamples();
178        cgGLSetParameterArray2f(sSamplesParam, 0, NUM_SAMPLES, (const float *)samples);
179
180        Vector3 tl, tr, bl, br;
181        ComputeViewVectors(tl, tr, bl, br);
182
183        glColor3f(1.0f, 1.0f, 1.0f);
184
185        glBegin(GL_QUADS);
186
187        // note: slightly larger texture hides ambient occlusion error on border but costs resolution
188        //const float new_offs = 0.55f;
189        const float new_offs = 0.5f;
190       
191        glColor3f(bl.x, bl.y, bl.z); glTexCoord2f(0, 0); glVertex3f(-new_offs, -new_offs, -0.5f);
192        glColor3f(br.x, br.y, br.z); glTexCoord2f(1, 0); glVertex3f( new_offs, -new_offs, -0.5f);
193        glColor3f(tr.x, tr.y, tr.z); glTexCoord2f(1, 1); glVertex3f( new_offs,  new_offs, -0.5f);
194        glColor3f(tl.x, tl.y, tl.z); glTexCoord2f(0, 1); glVertex3f(-new_offs,  new_offs, -0.5f);
195
196        glEnd();
197
198        cgGLDisableTextureParameter(sColorsTexParam);
199        cgGLDisableTextureParameter(sPositionsTexParam);
200        cgGLDisableTextureParameter(sNormalsTexParam);
201        cgGLDisableTextureParameter(sNoiseTexParam);
202        cgGLDisableTextureParameter(sOldTexParam);
203
204        cgGLDisableProfile(RenderState::sCgFragmentProfile);
205
206        glEnable(GL_LIGHTING);
207        glDisable(GL_TEXTURE_2D);
208
209        glMatrixMode(GL_PROJECTION);
210        glPopMatrix();
211
212        glMatrixMode(GL_MODELVIEW);
213        glPopMatrix();
214
215        glPopAttrib();
216
217        PrintGLerror("displaytexture");
218
219        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
220
221
222        PrintGLerror("ssao first pass");
223}
224
225
226void SsaoShader::SecondPass(FrameBufferObject *fbo, FrameBufferObject *fbo2)
227{
228        glEnable(GL_TEXTURE_2D);
229
230        glBindTexture(GL_TEXTURE_2D, fbo2->GetColorBuffer(0)->GetTexture());
231
232        glDisable(GL_LIGHTING);
233       
234        glMatrixMode(GL_PROJECTION);
235        glPushMatrix();
236        glLoadIdentity();
237
238        glMatrixMode(GL_MODELVIEW);
239        glPushMatrix();
240        glLoadIdentity();
241
242        const float offs = 0.5f;
243        glOrtho(-offs, offs, -offs, offs, 0, 1);
244       
245        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
246
247        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
248        glBegin(GL_QUADS);
249
250        glTexCoord2f(0, 0); glVertex3f(-offs, -offs, -0.5f);
251        glTexCoord2f(1, 0); glVertex3f( offs, -offs, -0.5f);
252        glTexCoord2f(1, 1); glVertex3f( offs,  offs, -0.5f);
253        glTexCoord2f(0, 1); glVertex3f(-offs,  offs, -0.5f);
254
255        glEnd();
256
257        glEnable(GL_LIGHTING);
258        glDisable(GL_TEXTURE_2D);
259       
260        glMatrixMode(GL_PROJECTION);
261        glPopMatrix();
262
263        glMatrixMode(GL_MODELVIEW);
264        glPopMatrix();
265
266        PrintGLerror("ssao second pass");
267}
268
269
270void SsaoShader::ComputeViewVectors(Vector3 &tl, Vector3 &tr, Vector3 &bl, Vector3 &br)
271{
272        Vector3 ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr;
273
274        mCamera->ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr);
275
276#if 1 // matT: debug this!!
277       
278        bl = Normalize(nbl - fbl);
279        br = Normalize(nbr - fbr);
280        tl = Normalize(ftl - ntl);
281        tr = Normalize(ftr - ntr);
282
283#else // just take camera direction
284       
285        bl = -Normalize(mCamera->GetDirection());
286        br = -Normalize(mCamera->GetDirection());
287        tl = -Normalize(mCamera->GetDirection());
288        tr = -Normalize(mCamera->GetDirection());
289
290#endif
291
292        // normalize to 0 .. 1
293        bl = bl * 0.5f + 0.5f;
294        br = br * 0.5f + 0.5f;
295        tl = tl * 0.5f + 0.5f;
296        tr = tr * 0.5f + 0.5f;
297}
298
299
300void SsaoShader::CreateNoiseTex2D()
301{
302        GLubyte *randomNormals = new GLubyte[mWidth * mHeight * 3];
303
304        for (int i = 0; i < mWidth * mHeight * 3; i += 3)
305        {
306                // create random samples over sphere
307                const float rx = RandomValue(0, 1);
308                const float theta = 2.0f * acos(sqrt(1.0f - rx));
309
310                randomNormals[i + 0] = (GLubyte)((cos(theta) * 0.5f + 0.5f) * 255.0f);
311                randomNormals[i + 1] = (GLubyte)((sin(theta) * 0.5f + 0.5f) * 255.0f);
312                randomNormals[i + 2] = 0;
313        }
314
315        glEnable(GL_TEXTURE_2D);
316        glGenTextures(1, &noiseTex);
317        glBindTexture(GL_TEXTURE_2D, noiseTex);
318               
319        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
320        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
321        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
322        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
323
324        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, randomNormals);
325
326        glBindTexture(GL_TEXTURE_2D, 0);
327        glDisable(GL_TEXTURE_2D);
328
329        delete [] randomNormals;
330
331        cout << "created noise texture" << endl;
332
333        PrintGLerror("noisetexture");
334}
335
336
337} // namespace
Note: See TracBrowser for help on using the repository browser.