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 |
|
---|
9 | using namespace std;
|
---|
10 |
|
---|
11 | static GLenum mymrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};
|
---|
12 |
|
---|
13 | namespace CHCDemoEngine
|
---|
14 | {
|
---|
15 |
|
---|
16 | // number of ssao samples
|
---|
17 | #define NUM_SAMPLES 16
|
---|
18 |
|
---|
19 |
|
---|
20 | static CGprogram sCgSsaoProgram = NULL;
|
---|
21 |
|
---|
22 | static CGparameter sColorsTexParam;
|
---|
23 | static CGparameter sPositionsTexParam;
|
---|
24 | static CGparameter sNormalsTexParam;
|
---|
25 | static CGparameter sOldModelViewProjMatrixParam;
|
---|
26 | static CGparameter sMaxDepthParam;
|
---|
27 | static CGparameter sSamplesParam;
|
---|
28 | static CGparameter sOldTexParam;
|
---|
29 | static CGparameter sNoiseTexParam;
|
---|
30 | static CGparameter sNoiseMultiplierParam;
|
---|
31 | static CGparameter sExpFactorParam;
|
---|
32 |
|
---|
33 | static GLuint noiseTex;
|
---|
34 |
|
---|
35 | // ssao random spherical samples
|
---|
36 | static Sample2 samples[NUM_SAMPLES];
|
---|
37 |
|
---|
38 |
|
---|
39 | static 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 | */
|
---|
54 | static void GenerateSamples()
|
---|
55 | {
|
---|
56 | static PoissonDiscSampleGenerator poisson(NUM_SAMPLES, 1.0f);
|
---|
57 | poisson.Generate((Sample2 *)samples);
|
---|
58 | }
|
---|
59 |
|
---|
60 |
|
---|
61 | SsaoShader::SsaoShader(int w, int h,
|
---|
62 | Camera *cam,
|
---|
63 | float expFactor,
|
---|
64 | float scaleFactor
|
---|
65 | ):
|
---|
66 | mWidth(w), mHeight(h),
|
---|
67 | mCamera(cam),
|
---|
68 | mExpFactor(expFactor),
|
---|
69 | mScaleFactor(scaleFactor)
|
---|
70 | {}
|
---|
71 |
|
---|
72 |
|
---|
73 | void 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 |
|
---|
114 | void SsaoShader::Render(FrameBufferObject *fbo, FrameBufferObject *fbo2)
|
---|
115 | {
|
---|
116 | FirstPass(fbo, fbo2);
|
---|
117 | SecondPass(fbo, fbo2);
|
---|
118 | }
|
---|
119 |
|
---|
120 |
|
---|
121 | void 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 |
|
---|
226 | void 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 |
|
---|
270 | void 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 |
|
---|
300 | void 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
|
---|