SO3Engine
SO3SsaoHandler.cpp
Go to the documentation of this file.
1
12
13namespace SO3
14{
15
16 bool SSsaoHandler::compositorCreated = false;
17 SSsaoHandler::SsaoTechniqueParametersByTechnique SSsaoHandler::ssaoTechniquesParameters;
18
20 {
21 compositorCreated = false;
22 ssaoTechniquesParameters.clear();
23 }
24
25 SSsaoHandler::SSsaoHandler()
26 {
27 }
28
29 SSsaoHandler::SSsaoHandler(SViewPort* targetViewportInstance)
30 {
31 // Initialize viewport
32 isEnable = false;
33 targetViewport = targetViewportInstance;
34 targetViewportScheme = targetViewport->GetOgreViewPortPointer()->getMaterialScheme();
35 inputCompositorInstance = 0;
36 ogreCompositorManager = Ogre::CompositorManager::getSingletonPtr();
37 ogreProgramManager = Ogre::GpuProgramManager::getSingletonPtr();
38 ogreMaterialManager = Ogre::MaterialManager::getSingletonPtr();
39 mSupportGbuffer = true;
40
41 //test if shaders are supported by the card
42 const Ogre::RenderSystemCapabilities* caps = SRoot::getSingleton().GetOgreRenderSystem()->getCapabilities();
43 Ogre::PixelFormat rttformat = Ogre::PF_BYTE_BGRA;
44 bool pfsupport = SRoot::getSingleton().GetRttPixelFormat(rttformat, false, true);
45
46 isSupported = pfsupport && caps && caps->hasCapability(Ogre::RSC_VERTEX_PROGRAM) &&
47 caps->hasCapability(Ogre::RSC_FRAGMENT_PROGRAM) &&
48 caps->hasCapability(Ogre::RSC_NON_POWER_OF_2_TEXTURES) &&
49 (caps->isShaderProfileSupported("ps_4_0") || caps->isShaderProfileSupported("ps_3_0") || caps->isShaderProfileSupported("arbfp1") || caps->isShaderProfileSupported("glsles") || caps->isShaderProfileSupported("glsl300es"));
50 if (isSupported)
51 {
52 // Generate compositor
53 CreateCompositors();
54
55 /* Setup compositors. This is a relatively complex chain:
56 -> "/Ssao/Input" stores RGB color texture and occlusion texture. Do not deactivate it!
57 -> "/Ssao/GBuffer" namespace holds compositors that fill a basic GBuffer, depending what the Ssao method needs to render. Only one compositor of this namespace must be activated at a time.
58 -> "/Ssao/Method" namespace holds ssao methods implementations. Only one compositor of this namespace must be activated at a time.
59 -> "/Ssao/Filter" namespace holds compositors that will blur the occlusion texture filled by a SSAO method. Zero or one compositor of this namespace should be activated at a time
60 -> "/Ssao/Output" namespace holds compositors that will render result to buffer. Only one compositor of this namespace must be activated at a time (Merging or one of Debug).
61 -> "/Ssao/Output/Debug" namespace holds compositors that will render debug visualizations to buffer. Merging compositor must be deactivated if one of those compositor is activated.
62 */
63
64 inputCompositorInstance = ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input");
65 if (mSupportGbuffer)
66 normalCompositorInstance = ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
67
68 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek");
69
70 if (mSupportGbuffer)
71 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric");
72
73 if (mSupportGbuffer)
74 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading");
75
76 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging");
77 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box");
78 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart");
79
80 if (mSupportGbuffer)
81 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2");
82
83 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug"); // Compositor chain should stop here if this compositor is activated.
84 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth"); // Compositor chain should stop here if this compositor is activated.
85
86 if (mSupportGbuffer)
87 {
88 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2"); // Compositor chain should stop here if this compositor is activated.
89 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal"); // Compositor chain should stop here if this compositor is activated.
90 ogreCompositorManager->addCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position"); // Compositor chain should stop here if this compositor is activated.
91 }
92
93 // Init ssao
94 currentSsaoGbufferLayout = static_cast<SsaoGBufferLayout>(-1);
95 currentSsaoTechnique = static_cast<SsaoTechnique>(-1);
96 currentSsaoFilter = static_cast<SsaoFilter>(-1);
97 currentSsaoDebugMode = static_cast<SsaoDebugMode>(-1);
101 }
102 }
103
105 {
106 if (isSupported)
107 {
108 // Force disable
109 SetEnable(false);
110
111 // Release compositor
112 if (mSupportGbuffer)
113 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position");
114
115 if (mSupportGbuffer)
116 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal");
117
118 if (mSupportGbuffer)
119 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2");
120
121 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth");
122 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug");
123
124 if (mSupportGbuffer)
125 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2");
126
127 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart");
128 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box");
129 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging");
130
131 if (mSupportGbuffer)
132 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading");
133
134 if (mSupportGbuffer)
135 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric");
136
137 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek");
138
139 if (mSupportGbuffer)
140 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
141
142 ogreCompositorManager->removeCompositor(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input");
143
144 inputCompositorInstance = 0;
145
146 Ogre::CompositorChain* compositorChain = ogreCompositorManager->getCompositorChain(targetViewport->GetOgreViewPortPointer());
147 if (compositorChain)
148 if (compositorChain->getCompositorInstances().empty())
149 ogreCompositorManager->removeCompositorChain(targetViewport->GetOgreViewPortPointer());
150
151 ogreCompositorManager = 0;
152 }
153 }
154
156 {
157 return isEnable;
158 }
159
160 void SSsaoHandler::SetEnable(bool enable)
161 {
162 if (isSupported)
163 {
164 if (enable != isEnable)
165 {
166 isEnable = enable;
167 if (enable)
168 {
169 if (mSupportGbuffer)
170 ogreMaterialManager->addListener(this, std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
171
172 // Enable base compositor
173 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", true))
174 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", true);
175
176 // Activate SSAO
177 SsaoTechnique techniqueToRestore = currentSsaoTechnique;
178 SsaoDebugMode debugModeToRestore = currentSsaoDebugMode;
179 SsaoFilter filterToRestore = currentSsaoFilter;
180 currentSsaoGbufferLayout = static_cast<SsaoGBufferLayout>(-1);
181 currentSsaoTechnique = static_cast<SsaoTechnique>(-1);
182 currentSsaoFilter = static_cast<SsaoFilter>(-1);
183 currentSsaoDebugMode = static_cast<SsaoDebugMode>(-1);
184 isEnable = enable;
185 SetTechnique(techniqueToRestore);
186 SetDebugMode(debugModeToRestore);
187 SetFilter(filterToRestore);
188 }
189 else
190 {
191 // Remove gbuffer material scheme listener
192 if (mSupportGbuffer)
193 ogreMaterialManager->removeListener(this, std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
194
195 // Stop others compositors
196 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", false))
197 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", false);
198
199 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", false))
200 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", false);
201
202 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", false))
203 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", false);
204
205 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", false))
206 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", false);
207
208 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", false))
209 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", false);
210
211 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", false))
212 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", false);
213
214 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", false))
215 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", false);
216
217 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", false))
218 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", false);
219
220 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", false))
221 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", false);
222
223 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", false))
224 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", false);
225
226 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", false))
227 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", false);
228
229 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", false))
230 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", false);
231
232 if (mSupportGbuffer && !targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", false))
233 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", false);
234
235 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", false))
236 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", false);
237 }
238 }
239 }
240 }
241
243 {
244 return currentSsaoTechnique;
245 }
246
248 {
249 //Force crytek when not supported
250 if ((newTechnique != SO3_SSAO_TECHNIQUE_NONE) && (!mSupportGbuffer && ((newTechnique == SO3_SSAO_TECHNIQUE_HEMISPHERIC) || (newTechnique == SO3_SSAO_TECHNIQUE_CREASE_SHADING))))
251 newTechnique = SO3_SSAO_TECHNIQUE_CRYTEK;
252
253 if (isSupported && (newTechnique < SO3_SSAO_TECHNIQUE_MAX) && (newTechnique != currentSsaoTechnique))
254 {
255 if (isEnable)
256 {
257 // Disable current technique
258 switch (currentSsaoTechnique)
259 {
261 break;
263 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", false))
264 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", false);
265 break;
267 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", false))
268 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", false);
269 break;
271 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", false))
272 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", false);
273 break;
274 }
275
276 // Check if we need to switch GBuffer
277 SsaoGBufferLayout newLayout = GetGBufferLayout(newTechnique);
278 if (currentSsaoGbufferLayout != newLayout)
279 {
280 // Store and reset debug mode before switching gbuffer layout.
281 SsaoDebugMode debugModeToRestore = currentSsaoDebugMode;
283
284 // Store and reset filter before switching gbuffer layout.
285 SsaoFilter filterToRestore = currentSsaoFilter;
287
288 // Disable old GBuffer layout
289 switch (currentSsaoGbufferLayout)
290 {
291 case SO3_SSAO_GBUFFER_DEPTH_ONLY:
292 break;
293 case SO3_SSAO_GBUFFER_NORMAL_POSITION:
294 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", false))
295 {
296 //normalCompositorInstance->getRenderTarget(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture")->removeListener(this);
297 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", false);
298 }
299 break;
300 }
301
302 // Enable new GBuffer layout
303 switch (newLayout)
304 {
305 case SO3_SSAO_GBUFFER_DEPTH_ONLY:
306 break;
307 case SO3_SSAO_GBUFFER_NORMAL_POSITION:
308 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", true))
309 {
310 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", true);
311 //normalCompositorInstance->getRenderTarget(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture")->addListener(this);
312 }
313 break;
314 }
315 currentSsaoGbufferLayout = newLayout;
316
317 // Restore debug mode after switching gbuffer layout.
318 SetDebugMode(debugModeToRestore);
319
320 // Restore filter after switching gbuffer layout.
321 SetFilter(filterToRestore);
322 }
323
324 // Enable new technique
325 switch (newTechnique)
326 {
328 break;
330 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", true))
331 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", true);
332 break;
334 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", true))
335 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", true);
336 break;
338 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", true))
339 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", true);
340 break;
341 }
342 }
343 currentSsaoTechnique = newTechnique;
344 }
345 }
346
348 {
349 return currentSsaoFilter;
350 }
351
352 void SSsaoHandler::SetFilter(const SsaoFilter& newFilter)
353 {
354 if (isSupported && (newFilter < SO3_SSAO_FILTER_MAX) && (newFilter != currentSsaoFilter))
355 {
356 if (isEnable)
357 {
358 // Disable current filter
359 switch (currentSsaoFilter)
360 {
362 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", false))
363 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", false);
364 break;
366 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", false))
367 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", false);
368 break;
370 {
371 switch (currentSsaoGbufferLayout)
372 {
373 case SO3_SSAO_GBUFFER_DEPTH_ONLY:
374 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", false))
375 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", false);
376 break;
377 case SO3_SSAO_GBUFFER_NORMAL_POSITION:
378 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", false))
379 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", false);
380 break;
381 }
382 break;
383 }
384 }
385
386 // Enable new filter
387 switch (newFilter)
388 {
390 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", true))
391 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", true);
392 break;
394 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", true))
395 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", true);
396 break;
398 {
399 switch (currentSsaoGbufferLayout)
400 {
401 case SO3_SSAO_GBUFFER_DEPTH_ONLY:
402 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", true))
403 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", true);
404 break;
405 case SO3_SSAO_GBUFFER_NORMAL_POSITION:
406 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", true))
407 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", true);
408 break;
409 }
410 break;
411 }
412 }
413 }
414 currentSsaoFilter = newFilter;
415 }
416 }
417
419 {
420 return currentSsaoDebugMode;
421 }
422
424 {
425 if ((newDebugMode < SO3_SSAO_DEBUG_MODE_MAX) && (newDebugMode != currentSsaoDebugMode))
426 {
427 if (isEnable)
428 {
429 // Disable current mode
430 switch (currentSsaoDebugMode)
431 {
433 //if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP)+"/Ssao/Output/Merging", false))
434 // ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP)+"/Ssao/Output/Merging", false);
435 break;
437 {
438 switch (currentSsaoGbufferLayout)
439 {
440 case SO3_SSAO_GBUFFER_DEPTH_ONLY:
441 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", false))
442 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", false);
443 break;
444 case SO3_SSAO_GBUFFER_NORMAL_POSITION:
445 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", false))
446 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", false);
447 break;
448 }
449 break;
450 }
452 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", false))
453 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", false);
454 break;
456 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", false))
457 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", false);
458 break;
460 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", false))
461 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", false);
462 break;
463 }
464
465 // Enable new mode
466 switch (newDebugMode)
467 {
469 //if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP)+"/Ssao/Output/Merging", true))
470 // ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP)+"/Ssao/Output/Merging", true);
471 break;
473 {
474 switch (currentSsaoGbufferLayout)
475 {
476 case SO3_SSAO_GBUFFER_DEPTH_ONLY:
477 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", true))
478 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", true);
479 break;
480 case SO3_SSAO_GBUFFER_NORMAL_POSITION:
481 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", true))
482 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", true);
483 break;
484 }
485 break;
486 }
488 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", true))
489 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", true);
490 break;
492 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", true))
493 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", true);
494 break;
496 if (!targetViewport->UpdateStereoCompositorState(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", true))
497 ogreCompositorManager->setCompositorEnabled(targetViewport->GetOgreViewPortPointer(), std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", true);
498 break;
499 }
500 }
501 currentSsaoDebugMode = newDebugMode;
502 }
503 }
504
505 void SSsaoHandler::CreateCompositors()
506 {
507 // Generate Ogre's resources for SSAO
508 if (!compositorCreated)
509 {
510 Ogre::StringVector resourceGroups = Ogre::ResourceGroupManager::getSingletonPtr()->getResourceGroups();
511 if (std::find(resourceGroups.begin(), resourceGroups.end(), SO3_INTERNAL_RESOURCE_GROUP) == resourceGroups.end())
512 Ogre::ResourceGroupManager::getSingletonPtr()->createResourceGroup(SO3_INTERNAL_RESOURCE_GROUP);
513
514 // Shared vertex shader.
515 GenerateRenderQuadVertexShader();
516
517 // Generate a compositor that will render the scene (without transparent objects), and will old a texture to the blurred SSAO
518 GenerateSsaoCompositor();
519
520 // Generate depth texture debug visualization compositor
521 GenerateDepthDebugCompositor();
522
523 // Generate ssao compositor that will use Crytek SSAO method
524 GenerateSsaoCrytekCompositor();
525
526 try
527 {
528 // Generate normal / view space position generator compositor
529 GenerateNormalPositionCompositor();
530
531 // Generate normal texture debug visualization compositor
532 GenerateNormalDebugCompositor();
533
534 // Generate view space position texture debug visualization compositor
535 GenerateViewPositionDebugCompositor();
536
537 // Generate depth texture debug visualization compositor, but for the normal/position compositor.
538 GenerateDepthDebugCompositor2();
539
540 // Generate ssao compositor that will use Hemispheric SSAO method
541 GenerateSsaoHemisphericCompositor();
542
543 // Generate ssao compositor that will use Crease Shading SSAO method
544 GenerateSsaoCreaseShadingCompositor();
545
546 // Generate ssao post filter that will use a more advanced 'smart box' method, but for the normal/position compositor.
547 GenerateFilterBoxSmartCompositor2();
548 }
549 catch (Ogre::Exception &)
550 {
551 mSupportGbuffer = false;
552 }
553
554 // Generate ssao post filter that will use a basic 'box' method
555 GenerateFilterBoxCompositor();
556
557 // Generate ssao post filter that will use a more advanced 'smart box' method
558 GenerateFilterBoxSmartCompositor();
559
560 // Generate ssao texture debug visualization compositor
561 GenerateSsaoDebugCompositor();
562
563 // Merge solids with occlusion, and renders transparents objects on top.
564 GenerateMergingCompositor();
565
566 // Everything was created.
567 compositorCreated = true;
568 }
569 else
570 {
571 normalPositionMaterial = ogreMaterialManager->getByName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Material/Solid", SO3_INTERNAL_RESOURCE_GROUP);
572 normalPositionMaterialTransparent = ogreMaterialManager->getByName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Material/Transparent", SO3_INTERNAL_RESOURCE_GROUP);
573 crytekSsaoMaterial = ogreMaterialManager->getByName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek/Material", SO3_INTERNAL_RESOURCE_GROUP);
574 hemisphericSsaoMaterial = ogreMaterialManager->getByName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric/Material", SO3_INTERNAL_RESOURCE_GROUP);
575 creaseShadingSsaoMaterial = ogreMaterialManager->getByName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading/Material", SO3_INTERNAL_RESOURCE_GROUP);
576 }
577 }
578
579 Ogre::Technique* SSsaoHandler::handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex, const Ogre::Renderable* rend)
580 {
581 //look if we didn't add the technique in a previous handleSchemeNotFound call
582 std::vector<Ogre::Technique*> techs = originalMaterial->getTechniques();
583 for (unsigned int i = 0; i < techs.size(); i++)
584 {
585 Ogre::Technique* schemeTechnique = techs[i];
586 if (schemeTechnique->getSchemeName() == schemeName)
587 return schemeTechnique;
588 }
589
590 // Change to the normal scheme, get the technique we should have without ssao, and get back to ssao scheme
591 Ogre::String targetScheme = schemeName;
592 ogreMaterialManager->setActiveScheme(targetViewportScheme);
593 Ogre::Technique* ogreTechnique = originalMaterial->getBestTechnique();
594 ogreMaterialManager->setActiveScheme(targetScheme);
595
596 bool hasOverlay = false;
597 Ogre::Any bindedSTechnique = ogreTechnique->getUserObjectBindings().getUserAny("STechnique");
598 if (bindedSTechnique.has_value())
599 {
600 STechnique* matTechnique = Ogre::any_cast<STechnique*> (bindedSTechnique);
601 hasOverlay = (matTechnique->GetParentMaterial()->GetAssociatedWidget() == 0) ? false : true;
602 }
603
604 bool forcePointsRender = false;
605 Ogre::Real pointSize = 1.0f;
606
607 if ((originalMaterial->getNumTechniques() > 0) && (originalMaterial->getTechnique(0)->getNumPasses() > 0) && (!originalMaterial->getTechnique(0)->getPass(0)->getPolygonModeOverrideable()) && (originalMaterial->getTechnique(0)->getPass(0)->getPolygonMode() == Ogre::PM_POINTS))
608 {
609 forcePointsRender = true;
610 pointSize = originalMaterial->getTechnique(0)->getPass(0)->getPointSize();
611 }
612
613 //look for SSAO scheme and use it for the test if exist
614 techs = originalMaterial->getSupportedTechniques();
615 for (unsigned int i = 0; i < techs.size(); i++)
616 {
617 Ogre::Technique* tech = techs[i];
618 if (tech->getSchemeName() == "SSAO")
619 {
620 ogreTechnique = tech;
621 break;
622 }
623 }
624
625 //new technique
626 Ogre::Technique* nTech = originalMaterial->createTechnique();
627
628 // If the technique is transparent, then ignore for rendering in depth texture
629 if (ogreTechnique && !hasOverlay && (!originalMaterial->getReceiveShadows() || (ogreTechnique->isTransparent() && (!ogreTechnique->isDepthWriteEnabled() || !ogreTechnique->isDepthCheckEnabled())) || ogreTechnique->hasColourWriteDisabled()))
630 {
631 if (targetScheme == (std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition"))
632 {
633 nTech->setSchemeName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
634 Ogre::Technique* btech = normalPositionMaterialTransparent->getTechnique(0);
635 *nTech = *btech;
636 }
637 }
638 else
639 {
640 //look to alpha rejection pass > 120
641 Ogre::TexturePtr alphaTex;
642 Ogre::Pass* alphaPass = 0;
643
644 if (ogreTechnique != 0)
645 {
646 bool goodTexFound = false;
647 unsigned short nbPass = ogreTechnique->getNumPasses();
648 for (unsigned short i = 0; i < nbPass && !goodTexFound; i++)
649 {
650 Ogre::Pass* pass = ogreTechnique->getPass(i);
651 if (pass && (pass->getIlluminationStage() != Ogre::IS_DECAL) && (hasOverlay || (Ogre::Real(pass->getAlphaRejectValue()) > 120.0f)))
652 {
653 unsigned short nbTex = pass->getNumTextureUnitStates();
654 for (unsigned short t = 0; t < nbTex && !goodTexFound; t++)
655 {
656 Ogre::TextureUnitState* ustate = pass->getTextureUnitState(t);
657 Ogre::TexturePtr texptr = ustate->_getTexturePtr();
658 // this is a candidate
659 if (texptr && texptr->hasAlpha() && (texptr->getTextureType() == Ogre::TEX_TYPE_2D))
660 {
661 alphaTex = texptr;
662 alphaPass = pass;
663
664 //now look if we get more chance to have a good one
665 //a texture with alpha in ambient pass should have the needed alpha
666 if (pass->getIlluminationStage() == Ogre::IS_AMBIENT)
667 goodTexFound = true;
668 }
669 }
670 }
671 }
672 }
673
674 if (alphaTex)
675 {
676 if (targetScheme == (std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition"))
677 {
678 Ogre::Technique* btech = normalPositionAlphaRejectionMaterial->getTechnique(0);
679 nTech->setName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/AlphaRejection");
680 nTech->setSchemeName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
681 *nTech = *btech;
682
683 Ogre::Pass* bpass = btech->getPass(0);
684 Ogre::Pass* nPass = nTech->getPass(0);
685 *nPass = *bpass;
686 nPass->setCullingMode(alphaPass->getCullingMode());
687 nPass->getTextureUnitState(0)->setTexture(alphaTex);
688 }
689 }
690 else
691 {
692 if (targetScheme == (std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition"))
693 {
694 nTech->setSchemeName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
695 Ogre::Technique* btech = normalPositionMaterial->getTechnique(0);
696 *nTech = *btech;
697 }
698 }
699 }
700
701 if (nTech && nTech->getNumPasses() > 0)
702 {
703 if (forcePointsRender)
704 {
705 nTech->getPass(0)->setPolygonMode(Ogre::PM_POINTS);
706 nTech->getPass(0)->setPointSize(pointSize);
707 }
708 else
709 {
710 nTech->getPass(0)->setPolygonMode(Ogre::PM_SOLID);
711 }
712 }
713 return nTech;
714 }
715
716 Ogre::GpuProgramPtr SSsaoHandler::createGpuProgram(const Ogre::String &Name, const bool& fragment, const Ogre::String& Data)
717 {
718 Ogre::GpuProgramPtr HLGpuProgram;
719 Ogre::String rendererName = Ogre::Root::getSingleton().getRenderSystem()->getName();
720 bool isGlslang = (rendererName == "Vulkan Rendering Subsystem") ? true : false;
721 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem" || rendererName == "Vulkan Rendering Subsystem") ? false : true;
722 Ogre::String language = ((rendererName == "OpenGL ES 2.x Rendering Subsystem") || (rendererName == "Metal Rendering Subsystem")) ? "glsles" : (rendererName == "Vulkan Rendering Subsystem") ? "glslang" : isGlSL ? "glsl" : "hlsl";
723
724 if (Ogre::GpuProgramManager::getSingletonPtr()->getByName(Name, std::string(SO3_INTERNAL_RESOURCE_GROUP)))
725 return HLGpuProgram;
726
727 HLGpuProgram = Ogre::GpuProgramManager::getSingletonPtr()->create(Name, std::string(SO3_INTERNAL_RESOURCE_GROUP), (!fragment) ? Ogre::GPT_VERTEX_PROGRAM : Ogre::GPT_FRAGMENT_PROGRAM, language);
728
729 //HLGpuProgram->setSource((isGlSL) ? "#version 150\n" + Data : Data);
730 HLGpuProgram->setSource(Data);
731
732 if (!isGlSL && !isGlslang)
733 {
734 if (!fragment)
735 HLGpuProgram->setParameter("target", "vs_3_0 vs_2_a");
736 else
737 HLGpuProgram->setParameter("target", "ps_3_0 ps_2_a");
738 }
739
740 return HLGpuProgram;
741 }
742
743 void SSsaoHandler::GenerateRenderQuadVertexShader()
744 {
745 Ogre::StringStream VertexProgramData;
746 // Create an unified vp for render fullscreen quad.
747 VertexProgramData << "#ifdef GL_ES" << std::endl;
748 VertexProgramData << " precision highp int;" << std::endl;
749 VertexProgramData << " precision highp float;" << std::endl;
750 VertexProgramData << "#endif" << std::endl;
751
752 VertexProgramData << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
753
754 VertexProgramData << "OGRE_UNIFORMS(" << std::endl;
755 VertexProgramData << "uniform mat4 cWorldViewProj;" << std::endl;
756 VertexProgramData << ")" << std::endl;
757
758 VertexProgramData << "MAIN_PARAMETERS" << std::endl;
759 VertexProgramData << "IN(vec4 vertex, POSITION)" << std::endl;
760 VertexProgramData << "IN(vec2 uv0, TEXCOORD0)" << std::endl;
761 VertexProgramData << "OUT(vec2 oUv, TEXCOORD0)" << std::endl;
762
763 VertexProgramData << "MAIN_DECLARATION" << std::endl;
764 VertexProgramData << "{" << std::endl;
765 VertexProgramData << " gl_Position = mul(cWorldViewProj, vertex);" << std::endl;
766 VertexProgramData << " vec2 inPos = sign(vertex.xy);" << std::endl;
767 //VertexProgramData << " oUv = (vec2(inPos.x, -inPos.y) + vec2_splat(1.0)) * vec2_splat(0.5);" << std::endl;
768 VertexProgramData << " oUv = uv0;" << std::endl;
769 VertexProgramData << "}" << std::endl;
770
771 // Load the program in Ogre
772 ssaoRenderQuadVp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP", false, VertexProgramData.str());
773
774 // Set auto param binding
775 Ogre::GpuProgramParametersSharedPtr ssaoRenderQuadVpParams = ssaoRenderQuadVp->getDefaultParameters();
776 ssaoRenderQuadVpParams->setNamedAutoConstant("cWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
777
778 // All defined, load!
779 ssaoRenderQuadVp->load();
780 }
781
782 void SSsaoHandler::GenerateSsaoCompositor()
783 {
784 // Create compositor
785 Ogre::CompositorPtr ssaoCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", SO3_INTERNAL_RESOURCE_GROUP);
786
787 // Create the technique
788 Ogre::CompositionTechnique* ssaoCompositionTechnique = ssaoCompositor->createTechnique();
789
790 Ogre::PixelFormat rttformat = Ogre::PF_BYTE_RGBA;
791 SRoot::getSingleton().GetRttPixelFormat(rttformat, true);
792
793 Ogre::PixelFormatList pixelFormatList;
794 pixelFormatList.push_back(rttformat);
795
796 Ogre::PixelFormatList pixelFormatListMRT;
797 pixelFormatListMRT.push_back(rttformat);
798
799 if (Ogre::TextureManager::getSingleton().isFormatSupported(Ogre::TEX_TYPE_2D, Ogre::PF_DEPTH32, Ogre::TU_RENDERTARGET))
800 pixelFormatListMRT.push_back(Ogre::PF_DEPTH32);
801 else
802 pixelFormatListMRT.push_back(Ogre::PF_DEPTH16);
803
804 // Create a texture that will hold the previous render with depth
805 Ogre::CompositionTechnique::TextureDefinition* previousTexture = ssaoCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous");
806 previousTexture->width = 0;
807 previousTexture->height = 0;
808 previousTexture->formatList = pixelFormatListMRT;
809 previousTexture->scope = Ogre::CompositionTechnique::TS_CHAIN;
810
811 // Create a texture that will hold blurred SSAO
812 Ogre::CompositionTechnique::TextureDefinition* occlusionTexture = ssaoCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
813 occlusionTexture->width = 0;
814 occlusionTexture->height = 0;
815 occlusionTexture->formatList = pixelFormatList;
816 occlusionTexture->scope = Ogre::CompositionTechnique::TS_CHAIN;
817
818 // Create the target that will get previous render
819 Ogre::CompositionTargetPass* compositionTargetPrevious = ssaoCompositionTechnique->createTargetPass();
820 compositionTargetPrevious->setShadowsEnabled(false);
821 compositionTargetPrevious->setOutputName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous");
822 compositionTargetPrevious->setInputMode(Ogre::CompositionTargetPass::IM_PREVIOUS);
823
824 // Create the target that will hold blurred ssao
825 Ogre::CompositionTargetPass* compositionTargetOcclusion = ssaoCompositionTechnique->createTargetPass();
826 compositionTargetOcclusion->setShadowsEnabled(false);
827 compositionTargetOcclusion->setOutputName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
828 compositionTargetOcclusion->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
829
830 // Just create a "clear" pass on the target, it will be filled by a specific SSAO method compositor, and then blurred with a filter
831 Ogre::CompositionPass* compositionTargetOcclusionClearPass = compositionTargetOcclusion->createPass();
832 compositionTargetOcclusionClearPass->setType(Ogre::CompositionPass::PT_CLEAR);
833 }
834
835 void SSsaoHandler::GenerateDepthDebugCompositor()
836 {
837 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
838 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
839
840 Ogre::StringStream programHeader;
841 programHeader << "#ifdef GL_ES" << std::endl;
842 programHeader << " precision highp int;" << std::endl;
843 programHeader << " precision highp float;" << std::endl;
844 programHeader << "#endif" << std::endl;
845
846 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
847
848 Ogre::StringStream FragmentProgramData;
849 FragmentProgramData << programHeader.str();
850
851 FragmentProgramData << "SAMPLER2D(sSceneDepthSampler, 0);" << std::endl;
852
853 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
854 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
855
856 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
857 FragmentProgramData << "{" << std::endl;
858 FragmentProgramData << " float depth = texture2D(sSceneDepthSampler, oUv).r;" << std::endl;
859 FragmentProgramData << " gl_FragColor = vec4(vec3_splat(depth), 1.0);" << std::endl;
860 FragmentProgramData << "}" << std::endl;
861
862 // Load the program in Ogre
863 ssaoDepthDebugCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth/Compositor_FP", true, FragmentProgramData.str());
864
865 Ogre::GpuProgramParametersSharedPtr FP_Parameters = ssaoDepthDebugCompositorFp->getDefaultParameters();
866 if (isGlSL)
867 FP_Parameters->setNamedConstant("sSceneDepthSampler", 0);
868
869 // All defined, load!
870 ssaoDepthDebugCompositorFp->load();
871
872 // Create material for depth debug compositor.
873 Ogre::MaterialPtr ssaoDepthDebugMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth/Material", SO3_INTERNAL_RESOURCE_GROUP);
874 Ogre::Pass* ogrePass = ssaoDepthDebugMaterial->getTechnique(0)->getPass(0);
875 ogrePass->setDepthCheckEnabled(false);
876 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState(); // Will be filled with depth texture
877 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
878 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
879 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
880 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 1);
881 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
882 ogrePass->setFragmentProgram(ssaoDepthDebugCompositorFp->getName());
883
884 // Create compositor
885 Ogre::CompositorPtr ssaoDepthDebugCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth", SO3_INTERNAL_RESOURCE_GROUP);
886
887 // Create the technique
888 Ogre::CompositionTechnique* ssaoDepthDebugCompositionTechnique = ssaoDepthDebugCompositor->createTechnique();
889
890 // Render as output
891 Ogre::CompositionTargetPass* ssaoDepthDebugOutputCompositionTargetPass = ssaoDepthDebugCompositionTechnique->getOutputTargetPass();
892 ssaoDepthDebugOutputCompositionTargetPass->setShadowsEnabled(false);
893 ssaoDepthDebugOutputCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
894
895 // Create the depth rendering pass
896 Ogre::CompositionPass* ssaoDepthDebugOutputRenderDepthCompositionPass = ssaoDepthDebugOutputCompositionTargetPass->createPass();
897 ssaoDepthDebugOutputRenderDepthCompositionPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
898 ssaoDepthDebugOutputRenderDepthCompositionPass->setMaterial(ssaoDepthDebugMaterial);
899 }
900
901 void SSsaoHandler::GenerateNormalPositionCompositor()
902 {
903 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
904 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
905
906 Ogre::StringStream programHeader;
907 programHeader << "#ifdef GL_ES" << std::endl;
908 programHeader << " precision highp int;" << std::endl;
909 programHeader << " precision highp float;" << std::endl;
910 programHeader << "#endif" << std::endl;
911
912 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
913
914 // Create an unified vp for depth generator.
915 Ogre::StringStream VertexProgramData;
916 // Create an unified vp for render fullscreen quad.
917 VertexProgramData << programHeader.str();
918
919 VertexProgramData << "OGRE_UNIFORMS(" << std::endl;
920 VertexProgramData << "uniform mat4 cWorldViewProj;" << std::endl;
921 VertexProgramData << "uniform mat4 cWorldView;" << std::endl;
922 VertexProgramData << "uniform mat4 cWorldPos;" << std::endl;
923 VertexProgramData << ")" << std::endl;
924
925 VertexProgramData << "MAIN_PARAMETERS" << std::endl;
926 VertexProgramData << "IN(vec4 vertex, POSITION)" << std::endl;
927 VertexProgramData << "IN(vec3 normal, NORMAL)" << std::endl;
928 VertexProgramData << "OUT(vec3 oViewPos, TEXCOORD0)" << std::endl;
929 VertexProgramData << "OUT(vec3 oNormal, TEXCOORD1)" << std::endl;
930 VertexProgramData << "OUT(vec4 oWp, TEXCOORD2)" << std::endl;
931
932 VertexProgramData << "MAIN_DECLARATION" << std::endl;
933 VertexProgramData << "{" << std::endl;
934 VertexProgramData << " gl_Position = mul(cWorldViewProj, vertex);" << std::endl;
935 VertexProgramData << " oViewPos = mul(cWorldView, vertex).xyz;" << std::endl;
936 VertexProgramData << " oWp = mul(cWorldPos, vertex);" << std::endl;
937 VertexProgramData << " oNormal = mul(cWorldView, vec4(normal.xyz, 0.0)).xyz;" << std::endl;
938 VertexProgramData << "}" << std::endl;
939
940 // Load the program in Ogre
941 normalPositionGeneratorVp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/NormalPositionGenerator_VP", false, VertexProgramData.str());
942
943 // Set auto param binding
944 Ogre::GpuProgramParametersSharedPtr normalPositionGeneratorVpParams = normalPositionGeneratorVp->getDefaultParameters();
945 normalPositionGeneratorVpParams->setNamedAutoConstant("cWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
946 normalPositionGeneratorVpParams->setNamedAutoConstant("cWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
947 normalPositionGeneratorVpParams->setNamedAutoConstant("cWorldPos", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
948
949 // All defined, load!
950 normalPositionGeneratorVp->load();
951
952 // Create an unified fp for normalPosition generator.
953 Ogre::StringStream FragmentProgramData;
954 // Need to enable the draw buffers extension
955 FragmentProgramData << "#if defined(OGRE_GLSL) || defined(OGRE_GLSLES)" << std::endl;
956 FragmentProgramData << "#extension GL_ARB_draw_buffers : enable" << std::endl;
957 FragmentProgramData << "#endif" << std::endl;
958 FragmentProgramData << programHeader.str();
959
960 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
961 FragmentProgramData << "uniform vec4 slicePlane;" << std::endl;
962 FragmentProgramData << ")" << std::endl;
963
964 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
965 FragmentProgramData << "IN(vec3 oViewPos, TEXCOORD0)" << std::endl;
966 FragmentProgramData << "IN(vec3 oNormal, TEXCOORD1)" << std::endl;
967 FragmentProgramData << "IN(vec4 oWp, TEXCOORD2)" << std::endl;
968
969 FragmentProgramData << "MAIN_DECLARATION_DATA" << std::endl;
970 FragmentProgramData << "{" << std::endl;
971 FragmentProgramData << " if (((slicePlane.x + slicePlane.y + slicePlane.z) != 0.0) && (slicePlane.x * oWp.x + slicePlane.y * oWp.y + slicePlane.z * oWp.z + slicePlane.w > 0.0))" << std::endl;
972 FragmentProgramData << " discard;" << std::endl;
973 FragmentProgramData << " gl_FragColor0 = vec4(normalize(oNormal), 0.0);" << std::endl;
974 FragmentProgramData << " gl_FragColor1 = vec4(oViewPos, 0.0);" << std::endl;
975 FragmentProgramData << "}" << std::endl;
976
977 // Load the program in Ogre
978 normalPositionGeneratorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "NormalPositionGenerator_FP", true, FragmentProgramData.str());
979
980 Ogre::GpuProgramParametersSharedPtr normalPositionGeneratorFpParams = normalPositionGeneratorFp->getDefaultParameters();
981 normalPositionGeneratorFpParams->addSharedParameters("SO3SlicePlaneParams");
982
983 // All defined, load!
984 normalPositionGeneratorFp->load();
985
986 // Create depth material for handleSchemeNotFound
987 normalPositionMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Material/Solid", SO3_INTERNAL_RESOURCE_GROUP);
988 normalPositionMaterial->getTechnique(0)->setSchemeName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
989 normalPositionMaterial->getTechnique(0)->setLightingEnabled(false);
990 normalPositionMaterial->getTechnique(0)->getPass(0)->setName("SO3/SSAO/NORMAPPASS");
991 normalPositionMaterial->getTechnique(0)->getPass(0)->setVertexProgram(normalPositionGeneratorVp->getName());
992 normalPositionMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(normalPositionGeneratorFp->getName());
993 normalPositionMaterial->load();
994
995 // Create depth transparent material for handleSchemeNotFound
996 normalPositionMaterialTransparent = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Material/Transparent", SO3_INTERNAL_RESOURCE_GROUP);
997 normalPositionMaterialTransparent->getTechnique(0)->setSchemeName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
998 normalPositionMaterialTransparent->getTechnique(0)->setColourWriteEnabled(false);
999 normalPositionMaterialTransparent->getTechnique(0)->setDepthCheckEnabled(false);
1000 normalPositionMaterialTransparent->getTechnique(0)->setDepthWriteEnabled(false);
1001 normalPositionMaterialTransparent->getTechnique(0)->getPass(0)->setName("SO3/SSAO/TRANSPARENT/NORMALPASS");
1002 normalPositionMaterialTransparent->getTechnique(0)->getPass(0)->setVertexProgram("SO3/Internal/Default_nolight_vp");
1003 normalPositionMaterialTransparent->getTechnique(0)->getPass(0)->setFragmentProgram("SO3/Internal/Default_fp");
1004 normalPositionMaterialTransparent->load();
1005
1006 // Create an unified vp for normalPosition with alpha rejection generator.
1007 VertexProgramData.str("");
1008 VertexProgramData.clear();
1009 // Create an unified vp for render fullscreen quad.
1010 VertexProgramData << programHeader.str();
1011
1012 VertexProgramData << "OGRE_UNIFORMS(" << std::endl;
1013 VertexProgramData << "uniform mat4 cWorldViewProj;" << std::endl;
1014 VertexProgramData << "uniform mat4 cWorldView;" << std::endl;
1015 VertexProgramData << "uniform mat4 cWorldPos;" << std::endl;
1016 VertexProgramData << ")" << std::endl;
1017
1018 VertexProgramData << "MAIN_PARAMETERS" << std::endl;
1019 VertexProgramData << "IN(vec4 vertex, POSITION)" << std::endl;
1020 VertexProgramData << "IN(vec3 normal, NORMAL)" << std::endl;
1021 VertexProgramData << "IN(vec2 uv0, TEXCOORD0)" << std::endl;
1022 VertexProgramData << "OUT(vec3 oViewPos, TEXCOORD0)" << std::endl;
1023 VertexProgramData << "OUT(vec3 oNormal, TEXCOORD1)" << std::endl;
1024 VertexProgramData << "OUT(vec2 oUv, TEXCOORD2)" << std::endl;
1025 VertexProgramData << "OUT(vec4 oWp, TEXCOORD3)" << std::endl;
1026
1027 VertexProgramData << "MAIN_DECLARATION" << std::endl;
1028 VertexProgramData << "{" << std::endl;
1029 VertexProgramData << " gl_Position = mul(cWorldViewProj, vertex);" << std::endl;
1030 VertexProgramData << " oViewPos = mul(cWorldView, vertex).xyz;" << std::endl;
1031 VertexProgramData << " oWp = mul(cWorldPos, vertex);" << std::endl;
1032 VertexProgramData << " oNormal = mul(cWorldView, vec4(normal.xyz, 0.0)).xyz;" << std::endl;
1033 VertexProgramData << " oUv = uv0;" << std::endl;
1034 VertexProgramData << "}" << std::endl;
1035
1036 // Load the program in Ogre
1037 normalPositionAlphaRejectionGeneratorVp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/normalPositionAlphaRejectionGenerator_VP", false, VertexProgramData.str());
1038
1039 // Set auto param binding
1040 Ogre::GpuProgramParametersSharedPtr normalPositionAlphaRejectionGeneratorVpParams = normalPositionAlphaRejectionGeneratorVp->getDefaultParameters();
1041 normalPositionAlphaRejectionGeneratorVpParams->setNamedAutoConstant("cWorldViewProj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
1042 normalPositionAlphaRejectionGeneratorVpParams->setNamedAutoConstant("cWorldView", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
1043 normalPositionAlphaRejectionGeneratorVpParams->setNamedAutoConstant("cWorldPos", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX);
1044
1045 // All defined, load!
1046 normalPositionAlphaRejectionGeneratorVp->load();
1047
1048 // Create an unified fp for normalPosition with alpha rejection generator.
1049 FragmentProgramData.str("");
1050 FragmentProgramData.clear();
1051 // Need to enable the draw buffers extension
1052 FragmentProgramData << "#if defined(OGRE_GLSL) || defined(OGRE_GLSLES)" << std::endl;
1053 FragmentProgramData << "#extension GL_ARB_draw_buffers : enable" << std::endl;
1054 FragmentProgramData << "#endif" << std::endl;
1055 FragmentProgramData << programHeader.str();
1056
1057 FragmentProgramData << "SAMPLER2D(sAlpha, 0);" << std::endl;
1058
1059 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1060 FragmentProgramData << "uniform vec4 slicePlane;" << std::endl;
1061 FragmentProgramData << ")" << std::endl;
1062
1063 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1064 FragmentProgramData << "IN(vec3 oViewPos, TEXCOORD0)" << std::endl;
1065 FragmentProgramData << "IN(vec3 oNormal, TEXCOORD1)" << std::endl;
1066 FragmentProgramData << "IN(vec2 oUv, TEXCOORD2)" << std::endl;
1067 FragmentProgramData << "IN(vec4 oWp, TEXCOORD3)" << std::endl;
1068
1069 FragmentProgramData << "MAIN_DECLARATION_DATA" << std::endl;
1070 FragmentProgramData << "{" << std::endl;
1071 FragmentProgramData << " if (((slicePlane.x + slicePlane.y + slicePlane.z) != 0.0) && (slicePlane.x * oWp.x + slicePlane.y * oWp.y + slicePlane.z * oWp.z + slicePlane.w > 0.0))" << std::endl;
1072 FragmentProgramData << " discard;" << std::endl;
1073 FragmentProgramData << " float alpha = texture2D(sAlpha, oUv).a;" << std::endl;
1074 FragmentProgramData << " if (alpha < 0.47)" << std::endl; // same as OGRE pass directive "alpha_rejection greater 120"
1075 FragmentProgramData << " discard;" << std::endl;
1076 FragmentProgramData << " gl_FragColor0 = vec4(normalize(oNormal), 0.0);" << std::endl;
1077 FragmentProgramData << " gl_FragColor1 = vec4(oViewPos, 0.0);" << std::endl;
1078 FragmentProgramData << "}" << std::endl;
1079
1080 // Load the program in Ogre
1081 normalPositionAlphaRejectionGeneratorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "NormalPositionAlphaGenerator_FP", true, FragmentProgramData.str());
1082
1083 Ogre::GpuProgramParametersSharedPtr normalPositionAlphaRejectionGeneratorFpParams = normalPositionAlphaRejectionGeneratorFp->getDefaultParameters();
1084 normalPositionAlphaRejectionGeneratorFpParams->addSharedParameters("SO3SlicePlaneParams");
1085
1086 if (isGlSL)
1087 normalPositionAlphaRejectionGeneratorFpParams->setNamedConstant("sAlpha", 0);
1088
1089 // All defined, load!
1090 normalPositionAlphaRejectionGeneratorFp->load();
1091
1092 // Create depth material for handleSchemeNotFound
1093 normalPositionAlphaRejectionMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Material/Solid/AlphaRejection", SO3_INTERNAL_RESOURCE_GROUP);
1094 normalPositionAlphaRejectionMaterial->getTechnique(0)->setSchemeName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
1095 normalPositionAlphaRejectionMaterial->getTechnique(0)->setLightingEnabled(false);
1096 normalPositionAlphaRejectionMaterial->getTechnique(0)->getPass(0)->setVertexProgram(normalPositionAlphaRejectionGeneratorVp->getName());
1097 normalPositionAlphaRejectionMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(normalPositionAlphaRejectionGeneratorFp->getName());
1098 normalPositionAlphaRejectionMaterial->getTechnique(0)->getPass(0)->createTextureUnitState();
1099
1100 // Create compositor
1101 Ogre::CompositorPtr normalPositionCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", SO3_INTERNAL_RESOURCE_GROUP);
1102
1103 // Create the technique
1104 Ogre::CompositionTechnique* normalPositionCompositionTechnique = normalPositionCompositor->createTechnique();
1105
1106 // Create a temporary texture that will hold 'late' (no sky nor water) solid objects normalPosition (from camera pov). It shall be used by next compositors in the chain.
1107 Ogre::CompositionTechnique::TextureDefinition* normalTexture = normalPositionCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture");
1108 normalTexture->width = 0;
1109 normalTexture->height = 0;
1110 normalTexture->heightFactor = 0.75f;
1111 normalTexture->widthFactor = 0.75f;
1112
1113 Ogre::PixelFormat rttformat = Ogre::PF_FLOAT32_RGB;
1114 SRoot::getSingleton().GetRttPixelFormat(rttformat, false, true);
1115
1116 Ogre::PixelFormatList pixelFormatList;
1117 pixelFormatList.push_back(rttformat);
1118 pixelFormatList.push_back(rttformat);
1119
1120 normalTexture->formatList = pixelFormatList;
1121 normalTexture->scope = Ogre::CompositionTechnique::TS_CHAIN;
1122
1123 // Create the target that will render normalPosition. Set a special material scheme.
1124 Ogre::CompositionTargetPass* normalPositionCompositionTargetPass = normalPositionCompositionTechnique->createTargetPass();
1125 normalPositionCompositionTargetPass->setShadowsEnabled(false);
1126 normalPositionCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1127 normalPositionCompositionTargetPass->setOutputName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture");
1128 normalPositionCompositionTargetPass->setMaterialScheme(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition");
1129
1130 // Create a "clear" pass on the normalPosition target
1131 Ogre::CompositionPass* normalPositionCompositionPassClear = normalPositionCompositionTargetPass->createPass();
1132 normalPositionCompositionPassClear->setType(Ogre::CompositionPass::PT_CLEAR);
1133 //normalPositionCompositionPassClear->setClearBuffers(Ogre::FBT_COLOUR | Ogre::FBT_DEPTH | Ogre::FBT_STENCIL);
1134 //normalPositionCompositionPassClear->setClearDepth(1.0f);
1135 normalPositionCompositionPassClear->setClearColour(Ogre::ColourValue(0, 0, 0, 1));
1136
1137 // Create the render normalPosition pass. Rendering this will call handleSchemeNotFound on objects.
1138 Ogre::CompositionPass* normalPositionCompositionPassRenderScene = normalPositionCompositionTargetPass->createPass();
1139 normalPositionCompositionPassRenderScene->setType(Ogre::CompositionPass::PT_RENDERSCENE);
1140 normalPositionCompositionPassRenderScene->setFirstRenderQueue(Ogre::RENDER_QUEUE_WORLD_GEOMETRY_1);
1141 normalPositionCompositionPassRenderScene->setLastRenderQueue(Ogre::RENDER_QUEUE_8);
1142 }
1143
1144 void SSsaoHandler::GenerateNormalDebugCompositor()
1145 {
1146 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1147 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1148
1149 // Create an unified fp for visualizing normal texture.
1150 Ogre::StringStream programHeader;
1151 programHeader << "#ifdef GL_ES" << std::endl;
1152 programHeader << " precision highp int;" << std::endl;
1153 programHeader << " precision highp float;" << std::endl;
1154 programHeader << "#endif" << std::endl;
1155
1156 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1157
1158 Ogre::StringStream FragmentProgramData;
1159 FragmentProgramData << programHeader.str();
1160
1161 FragmentProgramData << "SAMPLER2D(sNormalSampler, 0);" << std::endl;
1162
1163 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1164 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1165
1166 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1167 FragmentProgramData << "{" << std::endl;
1168 FragmentProgramData << " vec3 normal = texture2D(sNormalSampler, oUv).xyz;" << std::endl;
1169 FragmentProgramData << " gl_FragColor = vec4(normal / vec3_splat(2.0) + vec3_splat(0.5), 1.0);" << std::endl;
1170 FragmentProgramData << "}" << std::endl;
1171
1172 // Load the program in Ogre
1173 ssaoNormalDebugCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal/Compositor_FP", true, FragmentProgramData.str());
1174
1175 Ogre::GpuProgramParametersSharedPtr FP_Parameters = ssaoNormalDebugCompositorFp->getDefaultParameters();
1176 if (isGlSL)
1177 FP_Parameters->setNamedConstant("sNormalSampler", 0);
1178
1179 // All defined, load!
1180 ssaoNormalDebugCompositorFp->load();
1181
1182 // Create material for normal debug compositor.
1183 Ogre::MaterialPtr ssaoNormalDebugMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal/Material", SO3_INTERNAL_RESOURCE_GROUP);
1184 Ogre::Pass* ogrePass = ssaoNormalDebugMaterial->getTechnique(0)->getPass(0);
1185 ogrePass->setDepthCheckEnabled(false);
1186
1187 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
1188 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1189 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1190 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1191 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 0);
1192
1193 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1194 ogrePass->setFragmentProgram(ssaoNormalDebugCompositorFp->getName());
1195
1196 // Create compositor
1197 Ogre::CompositorPtr ssaoNormalDebugCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Normal", SO3_INTERNAL_RESOURCE_GROUP);
1198
1199 // Create the technique
1200 Ogre::CompositionTechnique* ssaoNormalDebugCompositionTechnique = ssaoNormalDebugCompositor->createTechnique();
1201
1202 // Render as output
1203 Ogre::CompositionTargetPass* ssaoNormalDebugOutputCompositionTargetPass = ssaoNormalDebugCompositionTechnique->getOutputTargetPass();
1204 ssaoNormalDebugOutputCompositionTargetPass->setShadowsEnabled(false);
1205 ssaoNormalDebugOutputCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1206
1207 // Create the normal rendering pass
1208 Ogre::CompositionPass* ssaoNormalDebugOutputRenderNormalCompositionPass = ssaoNormalDebugOutputCompositionTargetPass->createPass();
1209 ssaoNormalDebugOutputRenderNormalCompositionPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1210 ssaoNormalDebugOutputRenderNormalCompositionPass->setMaterial(ssaoNormalDebugMaterial);
1211 }
1212
1213 void SSsaoHandler::GenerateViewPositionDebugCompositor()
1214 {
1215 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1216 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1217
1218 // Create an unified fp for visualizing position texture.
1219 Ogre::StringStream programHeader;
1220 programHeader << "#ifdef GL_ES" << std::endl;
1221 programHeader << " precision highp int;" << std::endl;
1222 programHeader << " precision highp float;" << std::endl;
1223 programHeader << "#endif" << std::endl;
1224
1225 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1226
1227 Ogre::StringStream FragmentProgramData;
1228 FragmentProgramData << programHeader.str();
1229
1230 FragmentProgramData << "SAMPLER2D(sPositionSampler, 0);" << std::endl;
1231
1232 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1233 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1234
1235 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1236 FragmentProgramData << "{" << std::endl;
1237 FragmentProgramData << " vec4 position = vec4(texture2D(sPositionSampler, oUv).xyz, 1.0);" << std::endl;
1238 FragmentProgramData << " gl_FragColor = position * vec4(0.1, 0.1, -0.01, 1.0);" << std::endl;
1239 FragmentProgramData << "}" << std::endl;
1240
1241 // Load the program in Ogre
1242 ssaoPositionDebugCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position/Compositor_FP", true, FragmentProgramData.str());
1243
1244 Ogre::GpuProgramParametersSharedPtr FP_Parameters = ssaoPositionDebugCompositorFp->getDefaultParameters();
1245 if (isGlSL)
1246 FP_Parameters->setNamedConstant("sPositionSampler", 0);
1247
1248 // All defined, load!
1249 ssaoPositionDebugCompositorFp->load();
1250
1251 // Create material for position debug compositor.
1252 Ogre::MaterialPtr ssaoPositionDebugMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position/Material", SO3_INTERNAL_RESOURCE_GROUP);
1253 Ogre::Pass* ogrePass = ssaoPositionDebugMaterial->getTechnique(0)->getPass(0);
1254 ogrePass->setDepthCheckEnabled(false);
1255
1256 Ogre::TextureUnitState* ogreTextureUnit0 = ogrePass->createTextureUnitState(); // Will be filled with depth texture
1257 ogreTextureUnit0->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1258 ogreTextureUnit0->setTextureFiltering(Ogre::TFO_NONE);
1259 ogreTextureUnit0->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1260 ogreTextureUnit0->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 1);
1261
1262 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1263 ogrePass->setFragmentProgram(ssaoPositionDebugCompositorFp->getName());
1264
1265 // Create compositor
1266 Ogre::CompositorPtr ssaoPositionDebugCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Position", SO3_INTERNAL_RESOURCE_GROUP);
1267
1268 // Create the technique
1269 Ogre::CompositionTechnique* ssaoPositionDebugCompositionTechnique = ssaoPositionDebugCompositor->createTechnique();
1270
1271 // Render as output
1272 Ogre::CompositionTargetPass* ssaoPositionDebugOutputCompositionTargetPass = ssaoPositionDebugCompositionTechnique->getOutputTargetPass();
1273 ssaoPositionDebugOutputCompositionTargetPass->setShadowsEnabled(false);
1274 ssaoPositionDebugOutputCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1275
1276 // Create the position rendering pass
1277 Ogre::CompositionPass* ssaoPositionDebugOutputRenderPositionCompositionPass = ssaoPositionDebugOutputCompositionTargetPass->createPass();
1278 ssaoPositionDebugOutputRenderPositionCompositionPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1279 ssaoPositionDebugOutputRenderPositionCompositionPass->setMaterial(ssaoPositionDebugMaterial);
1280 }
1281
1282 void SSsaoHandler::GenerateDepthDebugCompositor2()
1283 {
1284 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1285 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1286
1287 // Create an unified fp for visualizing depth texture.
1288 Ogre::StringStream programHeader;
1289 programHeader << "#ifdef GL_ES" << std::endl;
1290 programHeader << " precision highp int;" << std::endl;
1291 programHeader << " precision highp float;" << std::endl;
1292 programHeader << "#endif" << std::endl;
1293
1294 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1295
1296 Ogre::StringStream FragmentProgramData;
1297 FragmentProgramData << programHeader.str();
1298
1299 FragmentProgramData << "SAMPLER2D(sSceneNormalPosDepthSampler, 0);" << std::endl;
1300
1301 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1302 FragmentProgramData << "uniform float cFarClipDistance;" << std::endl;
1303 FragmentProgramData << ")" << std::endl;
1304
1305 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1306 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1307
1308 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1309 FragmentProgramData << "{" << std::endl;
1310 FragmentProgramData << " float farClip = cFarClipDistance <= 0.0 ? 100.0 : cFarClipDistance;" << std::endl; // hack for infinite farclip
1311 FragmentProgramData << " float depth = texture2D(sSceneNormalPosDepthSampler, oUv).a / farClip;" << std::endl; // Inverse depth
1312 FragmentProgramData << " if(depth < 0.0)" << std::endl;
1313 FragmentProgramData << " depth = -depth;" << std::endl;
1314 FragmentProgramData << " gl_FragColor = vec4(vec3_splat(pow(depth, 0.3)), 1.0);" << std::endl;
1315 FragmentProgramData << "}" << std::endl;
1316
1317 // Load the program in Ogre
1318 ssaoDepth2DebugCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2/Compositor_FP", true, FragmentProgramData.str());
1319
1320 // Set auto param binding
1321 Ogre::GpuProgramParametersSharedPtr ssaoDepth2DebugCompositorFpParams = ssaoDepth2DebugCompositorFp->getDefaultParameters();
1322 ssaoDepth2DebugCompositorFpParams->setNamedAutoConstant("cFarClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
1323
1324 if (isGlSL)
1325 ssaoDepth2DebugCompositorFpParams->setNamedConstant("sSceneNormalPosDepthSampler", 0);
1326
1327 // All defined, load!
1328 ssaoDepth2DebugCompositorFp->load();
1329
1330 // Create material for depth debug compositor.
1331 Ogre::MaterialPtr ssaoDepth2DebugMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2/Material", SO3_INTERNAL_RESOURCE_GROUP);
1332 Ogre::Pass* ogrePass = ssaoDepth2DebugMaterial->getTechnique(0)->getPass(0);
1333 ogrePass->setDepthCheckEnabled(false);
1334 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState(); // Will be filled with depth texture
1335 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1336 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1337 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1338 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 1);
1339 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1340 ogrePass->setFragmentProgram(ssaoDepth2DebugCompositorFp->getName());
1341
1342 // Create compositor
1343 Ogre::CompositorPtr ssaoDepth2DebugCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Depth2", SO3_INTERNAL_RESOURCE_GROUP);
1344
1345 // Create the technique
1346 Ogre::CompositionTechnique* ssaoDepth2DebugCompositionTechnique = ssaoDepth2DebugCompositor->createTechnique();
1347
1348 // Render as output
1349 Ogre::CompositionTargetPass* ssaoDepth2DebugOutputCompositionTargetPass = ssaoDepth2DebugCompositionTechnique->getOutputTargetPass();
1350 ssaoDepth2DebugOutputCompositionTargetPass->setShadowsEnabled(false);
1351 ssaoDepth2DebugOutputCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1352
1353 // Create the depth rendering pass
1354 Ogre::CompositionPass* ssaoDepth2DebugOutputRenderDepthCompositionPass = ssaoDepth2DebugOutputCompositionTargetPass->createPass();
1355 ssaoDepth2DebugOutputRenderDepthCompositionPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1356 ssaoDepth2DebugOutputRenderDepthCompositionPass->setMaterial(ssaoDepth2DebugMaterial);
1357 }
1358
1359 void SSsaoHandler::GenerateSsaoCrytekCompositor()
1360 {
1361 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1362 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1363
1364 // Create an unified fp for SSAO.
1365 Ogre::StringStream programHeader;
1366 programHeader << "#ifdef GL_ES" << std::endl;
1367 programHeader << " precision highp int;" << std::endl;
1368 programHeader << " precision highp float;" << std::endl;
1369 programHeader << "#endif" << std::endl;
1370
1371 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1372
1373 Ogre::StringStream FragmentProgramData;
1374 FragmentProgramData << programHeader.str();
1375
1376 FragmentProgramData << "SAMPLER2D(sSceneDepthSampler, 0);" << std::endl;
1377 FragmentProgramData << "SAMPLER2D(sRotSampler4x4, 1);" << std::endl;
1378
1379 FragmentProgramData << "#define NSAMPLES 32" << std::endl; // number of samples
1380 FragmentProgramData << "#define NSAMPLESDIV 4" << std::endl;
1381 FragmentProgramData << "#define NSAMPLESINV 0.03125" << std::endl;
1382
1383 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1384 FragmentProgramData << "uniform vec4 cViewportSize;" << std::endl;
1385 FragmentProgramData << "uniform float cFov;" << std::endl;
1386 FragmentProgramData << "uniform float farClipDistance;" << std::endl;
1387 FragmentProgramData << "uniform float nearClipDistance;" << std::endl;
1388 FragmentProgramData << "uniform float cSampleInScreenspace;" << std::endl;
1389 FragmentProgramData << "uniform float cSampleLengthScreenSpace;" << std::endl;
1390 FragmentProgramData << "uniform float cSampleLengthWorldSpace;" << std::endl;
1391 FragmentProgramData << "uniform float cOffsetScale;" << std::endl;
1392 FragmentProgramData << "uniform float cDefaultAccessibility;" << std::endl;
1393 FragmentProgramData << "uniform float cEdgeHighlight;" << std::endl;
1394 FragmentProgramData << ")" << std::endl;
1395
1396 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1397 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1398
1399 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1400 FragmentProgramData << "{" << std::endl;
1401 FragmentProgramData << " float highlight = 2.0 - cEdgeHighlight;" << std::endl;
1402 FragmentProgramData << " float clipDepth = farClipDistance - nearClipDistance;" << std::endl; // compute the distance between the clipping planes to convert [0, 1] depth to world space units
1403 FragmentProgramData << " float fragmentWorldDepth = texture2D(sSceneDepthSampler, oUv).r;" << std::endl; // get the depth of the current pixel and convert into world space unit [0, inf]
1404 FragmentProgramData << " fragmentWorldDepth *= clipDepth;" << std::endl;
1405 FragmentProgramData << " vec2 rotationTC = oUv * cViewportSize.xy / vec2_splat(4.0);" << std::endl; // get rotation vector, rotation is tiled every 4 screen pixels
1406 FragmentProgramData << " vec3 rotationVector = vec3_splat(2.0) * texture2D(sRotSampler4x4, rotationTC).xyz - vec3_splat(1.0);" << std::endl; // [-1, 1]x[-1. 1]x[-1. 1]
1407 FragmentProgramData << " float rUV = 0.0;" << std::endl; // radius of influence in screen space
1408 FragmentProgramData << " float r = 0.0;" << std::endl; // radius of influence in world space
1409 FragmentProgramData << " if (cSampleInScreenspace == 1.0)" << std::endl;
1410 FragmentProgramData << " {" << std::endl;
1411 FragmentProgramData << " rUV = cSampleLengthScreenSpace;" << std::endl;
1412 FragmentProgramData << " r = tan(rUV * cFov) * fragmentWorldDepth;" << std::endl;
1413 FragmentProgramData << " }" << std::endl;
1414 FragmentProgramData << " else" << std::endl;
1415 FragmentProgramData << " {" << std::endl;
1416 FragmentProgramData << " rUV = atan(cSampleLengthWorldSpace / fragmentWorldDepth) / cFov;" << std::endl; // the radius of influence projected into screen space
1417 FragmentProgramData << " r = cSampleLengthWorldSpace;" << std::endl;
1418 FragmentProgramData << " }" << std::endl;
1419 FragmentProgramData << " float sampleLength = cOffsetScale;" << std::endl; // the offset for the first sample
1420 FragmentProgramData << " float sampleLengthStep = pow((rUV / sampleLength), NSAMPLESINV);" << std::endl;
1421 FragmentProgramData << " float accessibility = 0.0;" << std::endl; // sample the sphere and accumulate accessibility
1422 FragmentProgramData << " for (int i = 0; i < NSAMPLESDIV; i++)" << std::endl;
1423 FragmentProgramData << " {" << std::endl;
1424 FragmentProgramData << " for (int x = -1; x <= 1; x += 2)" << std::endl;
1425 FragmentProgramData << " for (int y = -1; y <= 1; y += 2)" << std::endl;
1426 FragmentProgramData << " for (int z = -1; z <= 1; z += 2)" << std::endl;
1427 FragmentProgramData << " {" << std::endl;
1428 FragmentProgramData << " vec3 offset = normalize(vec3(float(x), float(y), float(z))) * vec3_splat(sampleLength);" << std::endl; //generate offset vector
1429 FragmentProgramData << " sampleLength *= sampleLengthStep;" << std::endl; // update sample length
1430 FragmentProgramData << " vec3 rotatedOffset = reflect(offset, rotationVector);" << std::endl; // reflect offset vector by random rotation sample (i.e. rotating it)
1431 FragmentProgramData << " vec2 sampleTC = oUv + rotatedOffset.xy * vec2_splat(rUV);" << std::endl;
1432 FragmentProgramData << " float sampleWorldDepth = texture2D(sSceneDepthSampler, sampleTC).r * clipDepth;" << std::endl; // read scene depth at sampling point and convert into world space units (m or whatever).
1433 FragmentProgramData << " float fRangeIsInvalid = saturate((fragmentWorldDepth - sampleWorldDepth) / r);" << std::endl; // check if depths of both pixels are close enough and sampling point should affect our center pixel
1434 FragmentProgramData << " accessibility += mix(sampleWorldDepth > (fragmentWorldDepth + rotatedOffset.z * r) ? 1.0 : 0.0, cDefaultAccessibility, fRangeIsInvalid);" << std::endl; // accumulate accessibility, use default value of 0.5 if right computations are not possible
1435 FragmentProgramData << " }" << std::endl;
1436 FragmentProgramData << " }" << std::endl;
1437 FragmentProgramData << " accessibility /= float(NSAMPLES);" << std::endl; // get average value
1438 FragmentProgramData << " accessibility *= highlight;" << std::endl; // normalize, remove edge highlighting
1439 FragmentProgramData << " gl_FragColor = vec4(vec3_splat(accessibility), 1.0);" << std::endl;
1440 FragmentProgramData << "}" << std::endl;
1441
1442 // Load the program in Ogre
1443 ssaoCrytekCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek/Compositor_FP", true, FragmentProgramData.str());
1444
1445 // Set auto param binding
1446 Ogre::GpuProgramParametersSharedPtr ssaoCompositorFpParams = ssaoCrytekCompositorFp->getDefaultParameters();
1447 ssaoCompositorFpParams->setNamedAutoConstant("cViewportSize", Ogre::GpuProgramParameters::ACT_VIEWPORT_SIZE);
1448 ssaoCompositorFpParams->setNamedAutoConstant("nearClipDistance", Ogre::GpuProgramParameters::ACT_NEAR_CLIP_DISTANCE);
1449 ssaoCompositorFpParams->setNamedAutoConstant("farClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
1450 ssaoCompositorFpParams->setNamedAutoConstant("cFov", Ogre::GpuProgramParameters::ACT_FOV);
1451 ssaoCompositorFpParams->setNamedConstant("cSampleInScreenspace", 1.0f);
1452 ssaoCompositorFpParams->setNamedConstant("cSampleLengthScreenSpace", 0.25f);
1453 ssaoCompositorFpParams->setNamedConstant("cSampleLengthWorldSpace", 2.0f);
1454 ssaoCompositorFpParams->setNamedConstant("cOffsetScale", 0.001f);
1455 ssaoCompositorFpParams->setNamedConstant("cDefaultAccessibility", 0.5f);
1456 ssaoCompositorFpParams->setNamedConstant("cEdgeHighlight", 0.05f);
1457
1458 if (isGlSL)
1459 {
1460 ssaoCompositorFpParams->setNamedConstant("sSceneDepthSampler", 0);
1461 ssaoCompositorFpParams->setNamedConstant("sRotSampler4x4", 1);
1462 }
1463
1464 // All defined, load!
1465 ssaoCrytekCompositorFp->load();
1466
1467 // Create SSAO material for compositor.
1468 crytekSsaoMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek/Material", SO3_INTERNAL_RESOURCE_GROUP);
1469 Ogre::Pass* ogrePass = crytekSsaoMaterial->getTechnique(0)->getPass(0);
1470 ogrePass->setDepthCheckEnabled(false);
1471
1472 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
1473 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1474 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1475 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1476 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 1);
1477
1478 ogreTextureUnit = ogrePass->createTextureUnitState("regularSphereJittered4.png");
1479 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP);
1480 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1481
1482 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1483 ogrePass->setFragmentProgram(ssaoCrytekCompositorFp->getName());
1484
1485 // Configure technique parameters.
1486 SsaoTechniqueParameters crytekTechniqueParameters;
1487 crytekTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleInScreenspace", SsaoTechniqueParameter("Sample in screen space", SsaoTechniqueParameterRange(0.0f, 1.0f), 1.0f)));
1488 crytekTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleLengthScreenSpace", SsaoTechniqueParameter("Screen space length (%)", SsaoTechniqueParameterRange(0.00001f, 1.0f), 0.25f)));
1489 crytekTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleLengthWorldSpace", SsaoTechniqueParameter("World space length (units)", SsaoTechniqueParameterRange(0.00001f, 10.0f), 2.0f)));
1490 crytekTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cOffsetScale", SsaoTechniqueParameter("Offset scale (% of sample length)", SsaoTechniqueParameterRange(0.00001f, 1.0f), 0.001f)));
1491 crytekTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cDefaultAccessibility", SsaoTechniqueParameter("Default accessibility", SsaoTechniqueParameterRange(0.0f, 1.0f), 0.5f)));
1492 crytekTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cEdgeHighlight", SsaoTechniqueParameter("Edge highlight factor", SsaoTechniqueParameterRange(0.0f, 1.0f), 0.05f)));
1493 ssaoTechniquesParameters.insert(SsaoTechniqueParametersByTechnique::value_type(SO3_SSAO_TECHNIQUE_CRYTEK, crytekTechniqueParameters));
1494
1495 // Set SSAO default configuration
1496 SetTechniqueParameters(SO3_SSAO_TECHNIQUE_CRYTEK, crytekTechniqueParameters);
1497
1498 // Create compositor
1499 Ogre::CompositorPtr ssaoCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Crytek", SO3_INTERNAL_RESOURCE_GROUP);
1500
1501 // Create the technique
1502 Ogre::CompositionTechnique* ssaoCompositionTechnique = ssaoCompositor->createTechnique();
1503
1504 // Create a reference to the occlusion temporary texture
1505 Ogre::CompositionTechnique::TextureDefinition* occlusionTexture = ssaoCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1506 occlusionTexture->width = 0;
1507 occlusionTexture->height = 0;
1508 occlusionTexture->refCompName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input";
1509 occlusionTexture->refTexName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion";
1510
1511 // Render in first compositor occlusion texture
1512 Ogre::CompositionTargetPass* compositionTargetPass = ssaoCompositionTechnique->createTargetPass();
1513 compositionTargetPass->setShadowsEnabled(false);
1514 compositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1515 compositionTargetPass->setOutputName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1516
1517 // Create the SSAO rendering pass
1518 Ogre::CompositionPass* compositionTargetPassRenderSsaoPass = compositionTargetPass->createPass();
1519 compositionTargetPassRenderSsaoPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1520 compositionTargetPassRenderSsaoPass->setMaterial(crytekSsaoMaterial);
1521 }
1522
1523 void SSsaoHandler::GenerateSsaoHemisphericCompositor()
1524 {
1525 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1526 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1527
1528 // Create an unified fp for SSAO.
1529 Ogre::StringStream programHeader;
1530 programHeader << "#ifdef GL_ES" << std::endl;
1531 programHeader << " precision highp int;" << std::endl;
1532 programHeader << " precision highp float;" << std::endl;
1533 programHeader << "#endif" << std::endl;
1534
1535 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1536
1537 Ogre::StringStream FragmentProgramData;
1538 FragmentProgramData << programHeader.str();
1539
1540 FragmentProgramData << "SAMPLER2D(sSceneNormalSampler, 0);" << std::endl;
1541 FragmentProgramData << "SAMPLER2D(sScenePositionSampler, 1);" << std::endl;
1542 FragmentProgramData << "SAMPLER2D(sRand, 2);" << std::endl;
1543
1544 FragmentProgramData << "#define INTERLEAVED 4.0" << std::endl;
1545 FragmentProgramData << "#define MSAMPLES 4.0" << std::endl;
1546 FragmentProgramData << "#define NSAMPLES 4.0" << std::endl;
1547
1548 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1549 FragmentProgramData << "uniform vec4 cViewportSize;" << std::endl;
1550 FragmentProgramData << "uniform float cFov;" << std::endl;
1551 FragmentProgramData << "uniform float cSampleInScreenspace;" << std::endl;
1552 FragmentProgramData << "uniform float nearClipDistance;" << std::endl;
1553 FragmentProgramData << "uniform float cSampleLengthScreenSpace;" << std::endl;
1554 FragmentProgramData << "uniform float cSampleLengthWorldSpace;" << std::endl;
1555 FragmentProgramData << "uniform float cSampleLengthExponent;" << std::endl;
1556 FragmentProgramData << ")" << std::endl;
1557
1558 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1559 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1560
1561 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1562 FragmentProgramData << "{" << std::endl;
1563 FragmentProgramData << " float numSamples = MSAMPLES * NSAMPLES;" << std::endl;
1564 FragmentProgramData << " vec2 interleaveOffset = oUv * cViewportSize.xy / vec2_splat(INTERLEAVED);" << std::endl;
1565 FragmentProgramData << " vec3 fragmentPosition = texture2D(sScenePositionSampler, oUv).xyz;" << std::endl; // the current fragment in view space
1566 FragmentProgramData << " vec3 fragmentNormal = texture2D(sSceneNormalSampler, oUv).xyz;" << std::endl; // the fragment normal
1567 FragmentProgramData << " float rUV = 0.0;" << std::endl; // radius of influence in screen space
1568 FragmentProgramData << " float r = 0.0;" << std::endl; // radius of influence in world space
1569 FragmentProgramData << " if (cSampleInScreenspace == 1.0)" << std::endl;
1570 FragmentProgramData << " {" << std::endl;
1571 FragmentProgramData << " rUV = cSampleLengthScreenSpace;" << std::endl;
1572 FragmentProgramData << " r = tan(rUV * cFov) * -fragmentPosition.z;" << std::endl;
1573 FragmentProgramData << " }" << std::endl;
1574 FragmentProgramData << " else" << std::endl;
1575 FragmentProgramData << " {" << std::endl;
1576 FragmentProgramData << " rUV = atan(cSampleLengthWorldSpace / -fragmentPosition.z) / cFov;" << std::endl; // the radius of influence projected into screen space
1577 FragmentProgramData << " r = cSampleLengthWorldSpace;" << std::endl;
1578 FragmentProgramData << " }" << std::endl;
1579 FragmentProgramData << " if (rUV < (cViewportSize.z))" << std::endl; // abort if the projected radius of influence is smaller than 1 fragment
1580 FragmentProgramData << " {" << std::endl;
1581 FragmentProgramData << " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);" << std::endl;
1582 FragmentProgramData << " return;" << std::endl;
1583 FragmentProgramData << " }" << std::endl;
1584 FragmentProgramData << " float accessibility = 0.0;" << std::endl; // accessibility of the fragment
1585 FragmentProgramData << " vec3 viewVector = vec3(0.0, 0.0, 1.0);" << std::endl; // the constant view vector in view space
1586 FragmentProgramData << " vec3 reflector = normalize(fragmentNormal + viewVector) * vec3(-1.0, 1.0, 1.0);" << std::endl; // the reflection vector to align the hemisphere with the fragment normal somehow the x component must be flipped...???
1587 FragmentProgramData << " float count = 0.0;" << std::endl;
1588 FragmentProgramData << " float sampleLength;" << std::endl;
1589 FragmentProgramData << " for (float i = 0.0; i < MSAMPLES; i++)" << std::endl;
1590 FragmentProgramData << " for (float j = 0.0; j < NSAMPLES; j++)" << std::endl;
1591 FragmentProgramData << " {" << std::endl;
1592 FragmentProgramData << " count ++;" << std::endl;
1593 FragmentProgramData << " vec2 randomTC = interleaveOffset + vec2(i/(INTERLEAVED * MSAMPLES), j/(INTERLEAVED * NSAMPLES));" << std::endl;
1594 FragmentProgramData << " vec3 randomVector = (texture2D(sRand, randomTC).rgb * vec3_splat(2.0)) - vec3_splat(1.0);" << std::endl; // unpack to [-1, 1]x[-1, 1]x[1, 1]
1595 FragmentProgramData << " sampleLength = pow(count/numSamples, cSampleLengthExponent);" << std::endl;
1596 FragmentProgramData << " vec3 sampleVector = reflect(randomVector, reflector) * vec3_splat(sampleLength);" << std::endl;
1597 FragmentProgramData << " vec2 sampleTC = oUv + sampleVector.xy * vec2_splat(rUV);" << std::endl;
1598 FragmentProgramData << " vec3 samplePosition = texture2D(sScenePositionSampler, sampleTC).xyz;" << std::endl; // solid geometry
1599 FragmentProgramData << " if (samplePosition.z < (fragmentPosition.z - sampleVector.z))" << std::endl; // thin air
1600 FragmentProgramData << " accessibility++;" << std::endl;
1601 FragmentProgramData << " else" << std::endl; // solid geometry
1602 FragmentProgramData << " accessibility += length(fragmentPosition - samplePosition) > r;" << std::endl; // out of reach, i.e. false occluder // out of reach, i.e. false occluder
1603 FragmentProgramData << " }" << std::endl;
1604 FragmentProgramData << " accessibility /= numSamples;" << std::endl;
1605 FragmentProgramData << " gl_FragColor = vec4(vec3_splat(accessibility), 1.0);" << std::endl;
1606 FragmentProgramData << "}" << std::endl;
1607
1608 // Load the program in Ogre
1609 ssaoHemiCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric/Compositor_FP", true, FragmentProgramData.str());
1610
1611 // Set auto param binding
1612 Ogre::GpuProgramParametersSharedPtr ssaoCompositorFpParams = ssaoHemiCompositorFp->getDefaultParameters();
1613 ssaoCompositorFpParams->setNamedAutoConstant("cViewportSize", Ogre::GpuProgramParameters::ACT_VIEWPORT_SIZE);
1614 ssaoCompositorFpParams->setNamedAutoConstant("cFov", Ogre::GpuProgramParameters::ACT_FOV);
1615
1616 ssaoCompositorFpParams->setNamedConstant("cSampleInScreenspace", 1.0f);
1617 ssaoCompositorFpParams->setNamedConstant("cSampleLengthScreenSpace", 0.04f);
1618 ssaoCompositorFpParams->setNamedConstant("cSampleLengthWorldSpace", 2.0f);
1619 ssaoCompositorFpParams->setNamedConstant("cSampleLengthExponent", 1.0f);
1620
1621 if (isGlSL)
1622 {
1623 ssaoCompositorFpParams->setNamedConstant("sSceneNormalSampler", 0);
1624 ssaoCompositorFpParams->setNamedConstant("sScenePositionSampler", 1);
1625 ssaoCompositorFpParams->setNamedConstant("sRand", 2);
1626 }
1627
1628 // All defined, load!
1629 ssaoHemiCompositorFp->load();
1630
1631 // Create SSAO material for compositor.
1632 hemisphericSsaoMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric/Material", SO3_INTERNAL_RESOURCE_GROUP);
1633 Ogre::Pass* ogrePass = hemisphericSsaoMaterial->getTechnique(0)->getPass(0);
1634 ogrePass->setDepthCheckEnabled(false);
1635
1636 Ogre::TextureUnitState* ogreTextureUnit0 = ogrePass->createTextureUnitState(); // Will be filled with depth texture
1637 ogreTextureUnit0->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1638 ogreTextureUnit0->setTextureFiltering(Ogre::TFO_NONE);
1639 ogreTextureUnit0->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1640 ogreTextureUnit0->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 0);
1641
1642 Ogre::TextureUnitState* ogreTextureUnit1 = ogrePass->createTextureUnitState(); // Will be filled with depth texture
1643 ogreTextureUnit1->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1644 ogreTextureUnit1->setTextureFiltering(Ogre::TFO_NONE);
1645 ogreTextureUnit1->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1646 ogreTextureUnit1->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 1);
1647
1648 Ogre::TextureUnitState* ogreTextureUnit2 = ogrePass->createTextureUnitState("importance4InterleavedSphereHemisphere8x4.png");
1649 ogreTextureUnit2->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP);
1650 ogreTextureUnit2->setTextureFiltering(Ogre::TFO_NONE);
1651
1652 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1653 ogrePass->setFragmentProgram(ssaoHemiCompositorFp->getName());
1654
1655 // Configure technique parameters.
1656 SsaoTechniqueParameters hemisphericTechniqueParameters;
1657 hemisphericTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleInScreenspace", SsaoTechniqueParameter("Sample in screen space", SsaoTechniqueParameterRange(0.0f, 1.0f), 1.0f)));
1658 hemisphericTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleLengthScreenSpace", SsaoTechniqueParameter("Screen space length (%)", SsaoTechniqueParameterRange(0.00001f, 0.999f), 0.04f)));
1659 hemisphericTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleLengthWorldSpace", SsaoTechniqueParameter("World space length (units)", SsaoTechniqueParameterRange(0.00001f, 100.0f), 2.0f)));
1660 hemisphericTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cSampleLengthExponent", SsaoTechniqueParameter("Sample length exponent", SsaoTechniqueParameterRange(0.0f, 1.0f), 1.0f)));
1661 ssaoTechniquesParameters.insert(SsaoTechniqueParametersByTechnique::value_type(SO3_SSAO_TECHNIQUE_HEMISPHERIC, hemisphericTechniqueParameters));
1662
1663 // Set SSAO default configuration
1664 SetTechniqueParameters(SO3_SSAO_TECHNIQUE_HEMISPHERIC, hemisphericTechniqueParameters);
1665
1666 // Create compositor
1667 Ogre::CompositorPtr ssaoCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/Hemispheric", SO3_INTERNAL_RESOURCE_GROUP);
1668
1669 // Create the technique
1670 Ogre::CompositionTechnique* ssaoCompositionTechnique = ssaoCompositor->createTechnique();
1671
1672 // Create a reference to the occlusion temporary texture
1673 Ogre::CompositionTechnique::TextureDefinition* occlusionTexture = ssaoCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1674 occlusionTexture->width = 0;
1675 occlusionTexture->height = 0;
1676 occlusionTexture->refCompName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input";
1677 occlusionTexture->refTexName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion";
1678
1679 // Render in first compositor occlusion texture
1680 Ogre::CompositionTargetPass* compositionTargetPass = ssaoCompositionTechnique->createTargetPass();
1681 compositionTargetPass->setShadowsEnabled(false);
1682 compositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1683 compositionTargetPass->setOutputName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1684
1685 // Create the SSAO rendering pass
1686 Ogre::CompositionPass* compositionTargetPassRenderSsaoPass = compositionTargetPass->createPass();
1687 compositionTargetPassRenderSsaoPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1688 compositionTargetPassRenderSsaoPass->setMaterial(hemisphericSsaoMaterial);
1689 }
1690
1691 void SSsaoHandler::GenerateSsaoCreaseShadingCompositor()
1692 {
1693 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1694 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1695
1696 // Create an unified fp for SSAO.
1697 Ogre::StringStream programHeader;
1698 programHeader << "#ifdef GL_ES" << std::endl;
1699 programHeader << " precision highp int;" << std::endl;
1700 programHeader << " precision highp float;" << std::endl;
1701 programHeader << "#endif" << std::endl;
1702
1703 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1704
1705 Ogre::StringStream FragmentProgramData;
1706 FragmentProgramData << programHeader.str();
1707
1708 FragmentProgramData << "SAMPLER2D(sSceneNormalSampler, 0);" << std::endl;
1709 FragmentProgramData << "SAMPLER2D(sScenePositionSampler, 1);" << std::endl;
1710 FragmentProgramData << "SAMPLER2D(sRandom, 2);" << std::endl;
1711
1712 FragmentProgramData << "#define INTERLEAVED 4.0" << std::endl;
1713 FragmentProgramData << "#define MSAMPLES 4.0" << std::endl;
1714 FragmentProgramData << "#define NSAMPLES 4.0" << std::endl;
1715 FragmentProgramData << "#define STIPPLESIZE 11.0" << std::endl;
1716
1717 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1718 FragmentProgramData << "uniform vec4 cViewportSize;" << std::endl;
1719 FragmentProgramData << "uniform float cRange;" << std::endl;
1720 FragmentProgramData << "uniform float cBias;" << std::endl;
1721 FragmentProgramData << "uniform float cAverager;" << std::endl;
1722 FragmentProgramData << "uniform float cMinimumCrease;" << std::endl;
1723 FragmentProgramData << "uniform float cKernelSize;" << std::endl;
1724 FragmentProgramData << ")" << std::endl;
1725
1726 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1727 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1728
1729 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1730 FragmentProgramData << "{" << std::endl;
1731 FragmentProgramData << " vec3 fragmentPosition = texture2D(sScenePositionSampler, oUv).xyz;" << std::endl; // get the view space position of the fragment
1732 FragmentProgramData << " vec3 fragmentNormal = texture2D(sSceneNormalSampler, oUv).xyz;" << std::endl; // get the normal of the fragment
1733 FragmentProgramData << " float totalGI = 0.0;" << std::endl;
1734 FragmentProgramData << " for (float i = 0.0; i < (STIPPLESIZE + 1.0) / 2.0; i++)" << std::endl;
1735 FragmentProgramData << " {" << std::endl;
1736 FragmentProgramData << " vec2 diagonalStart = vec2(-(STIPPLESIZE - 1.0) / 2.0, 0.0) + i;" << std::endl;
1737 FragmentProgramData << " for(float j = 0.0; j < (STIPPLESIZE + 1.0) / 2.0; j++)" << std::endl;
1738 FragmentProgramData << " {" << std::endl;
1739 FragmentProgramData << " vec2 sampleOffset = diagonalStart + vec2(j, -j);" << std::endl;
1740 FragmentProgramData << " vec2 sampleUV = oUv + (sampleOffset * cViewportSize.zw * vec2_splat(cKernelSize));" << std::endl;
1741 FragmentProgramData << " vec3 samplePos = texture2D(sScenePositionSampler, sampleUV).xyz;" << std::endl;
1742 FragmentProgramData << " vec3 toCenter = samplePos - fragmentPosition;" << std::endl;
1743 FragmentProgramData << " float distance = length(toCenter);" << std::endl;
1744 FragmentProgramData << " toCenter = normalize(toCenter);" << std::endl;
1745 FragmentProgramData << " float centerContrib = saturate((dot(toCenter, fragmentNormal) - cMinimumCrease) * cBias);" << std::endl;
1746 FragmentProgramData << " float rangeAttenuation = 1.0 - saturate(distance / cRange);" << std::endl;
1747 FragmentProgramData << " totalGI += centerContrib * rangeAttenuation;" << std::endl;
1748 FragmentProgramData << " }" << std::endl;
1749 FragmentProgramData << " }" << std::endl;
1750 FragmentProgramData << " totalGI /= cAverager;" << std::endl;
1751 FragmentProgramData << " gl_FragColor = vec4_splat(1.0) - vec4(vec3_splat(totalGI), 1.0);" << std::endl;
1752 FragmentProgramData << "}" << std::endl;
1753
1754
1755 // Load the program in Ogre
1756 ssaoCreaseCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading/Compositor_FP", true, FragmentProgramData.str());
1757
1758 // Set auto param binding
1759 Ogre::GpuProgramParametersSharedPtr ssaoCompositorFpParams = ssaoCreaseCompositorFp->getDefaultParameters();
1760 ssaoCompositorFpParams->setNamedAutoConstant("cViewportSize", Ogre::GpuProgramParameters::ACT_VIEWPORT_SIZE);
1761 ssaoCompositorFpParams->setNamedConstant("cMinimumCrease", 0.2f);
1762 ssaoCompositorFpParams->setNamedConstant("cRange", 1.0f);
1763 ssaoCompositorFpParams->setNamedConstant("cBias", 1.0f);
1764 ssaoCompositorFpParams->setNamedConstant("cAverager", 24.0f);
1765 ssaoCompositorFpParams->setNamedConstant("cKernelSize", 3.0f);
1766
1767 if (isGlSL)
1768 {
1769 ssaoCompositorFpParams->setNamedConstant("sSceneNormalSampler", 0);
1770 ssaoCompositorFpParams->setNamedConstant("sScenePositionSampler", 1);
1771 ssaoCompositorFpParams->setNamedConstant("sRandom", 2);
1772 }
1773
1774 // All defined, load!
1775 ssaoCreaseCompositorFp->load();
1776
1777 // Create SSAO material for compositor.
1778 creaseShadingSsaoMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading/Material", SO3_INTERNAL_RESOURCE_GROUP);
1779 Ogre::Pass* ogrePass = creaseShadingSsaoMaterial->getTechnique(0)->getPass(0);
1780 ogrePass->setDepthCheckEnabled(false);
1781
1782 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
1783 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1784 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1785 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1786 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 0);
1787
1788 ogreTextureUnit = ogrePass->createTextureUnitState();
1789 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1790 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1791 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1792 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 1);
1793
1794 ogreTextureUnit = ogrePass->createTextureUnitState("rand1x32.png");
1795 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_WRAP);
1796 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1797
1798 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1799 ogrePass->setFragmentProgram(ssaoCreaseCompositorFp->getName());
1800
1801 // Configure technique parameters.
1802 SsaoTechniqueParameters creaseShadingTechniqueParameters;
1803 creaseShadingTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cMinimumCrease", SsaoTechniqueParameter("Minimum crease", SsaoTechniqueParameterRange(0.0f, 1.0f), 0.2f)));
1804 creaseShadingTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cRange", SsaoTechniqueParameter("Crease range", SsaoTechniqueParameterRange(0.0f, 10.0f), 1.0f)));
1805 creaseShadingTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cBias", SsaoTechniqueParameter("Bias", SsaoTechniqueParameterRange(0.0f, 10.0f), 1.0f)));
1806 creaseShadingTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cAverager", SsaoTechniqueParameter("Avenger", SsaoTechniqueParameterRange(1.0f, 1000.0f), 24.0f)));
1807 creaseShadingTechniqueParameters.insert(SsaoTechniqueParameters::value_type("cKernelSize", SsaoTechniqueParameter("Kernel size bias", SsaoTechniqueParameterRange(0.1f, 10.0f), 3.0f)));
1808 ssaoTechniquesParameters.insert(SsaoTechniqueParametersByTechnique::value_type(SO3_SSAO_TECHNIQUE_CREASE_SHADING, creaseShadingTechniqueParameters));
1809
1810 // Set SSAO default configuration
1811 SetTechniqueParameters(SO3_SSAO_TECHNIQUE_CREASE_SHADING, creaseShadingTechniqueParameters);
1812
1813 // Create compositor
1814 Ogre::CompositorPtr ssaoCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Method/CreaseShading", SO3_INTERNAL_RESOURCE_GROUP);
1815
1816 // Create the technique
1817 Ogre::CompositionTechnique* ssaoCompositionTechnique = ssaoCompositor->createTechnique();
1818
1819 // Create a reference to the occlusion temporary texture
1820 Ogre::CompositionTechnique::TextureDefinition* occlusionTexture = ssaoCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1821 occlusionTexture->width = 0;
1822 occlusionTexture->height = 0;
1823 occlusionTexture->refCompName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input";
1824 occlusionTexture->refTexName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion";
1825
1826 // Render in first compositor occlusion texture
1827 Ogre::CompositionTargetPass* compositionTargetPass = ssaoCompositionTechnique->createTargetPass();
1828 compositionTargetPass->setShadowsEnabled(false);
1829 compositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1830 compositionTargetPass->setOutputName(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1831
1832 // Create the SSAO rendering pass
1833 Ogre::CompositionPass* compositionTargetPassRenderSsaoPass = compositionTargetPass->createPass();
1834 compositionTargetPassRenderSsaoPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1835 compositionTargetPassRenderSsaoPass->setMaterial(creaseShadingSsaoMaterial);
1836 }
1837
1838 void SSsaoHandler::GenerateFilterBoxCompositor()
1839 {
1840 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1841 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1842
1843 // Create an unified fp for merging scene render with blurred ssao.
1844 Ogre::StringStream programHeader;
1845 programHeader << "#ifdef GL_ES" << std::endl;
1846 programHeader << " precision highp int;" << std::endl;
1847 programHeader << " precision highp float;" << std::endl;
1848 programHeader << "#endif" << std::endl;
1849
1850 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1851
1852 Ogre::StringStream FragmentProgramData;
1853 FragmentProgramData << programHeader.str();
1854
1855 FragmentProgramData << "SAMPLER2D(sSceneSolidSampler, 0);" << std::endl;
1856 FragmentProgramData << "SAMPLER2D(sSceneOcclusion, 1);" << std::endl;
1857
1858 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1859 FragmentProgramData << "uniform vec4 screenSize;" << std::endl;
1860 FragmentProgramData << ")" << std::endl;
1861
1862 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1863 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1864
1865 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1866 FragmentProgramData << "{" << std::endl;
1867 FragmentProgramData << " float occ = 0.0;" << std::endl;
1868 FragmentProgramData << " for (int x = -2; x < 3; x++)" << std::endl;
1869 FragmentProgramData << " for (int y = -2; y < 3; y++)" << std::endl;
1870 FragmentProgramData << " {" << std::endl;
1871 FragmentProgramData << " occ += texture2D(sSceneOcclusion, vec2(oUv.x + float(x) * screenSize.z, oUv.y + float(y) * screenSize.w)).x;" << std::endl;
1872 FragmentProgramData << " }" << std::endl;
1873 FragmentProgramData << " occ /= 25.0;" << std::endl;
1874 FragmentProgramData << " vec4 color = texture2D(sSceneSolidSampler, oUv);" << std::endl;
1875 FragmentProgramData << " gl_FragColor = vec4(color.r * occ, color.g * occ, color.b * occ, color.a);" << std::endl;
1876 FragmentProgramData << "}" << std::endl;
1877
1878 // Load the program in Ogre
1879 filterBoxCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box_FP", true, FragmentProgramData.str());
1880
1881 Ogre::GpuProgramParametersSharedPtr FP_Parameters = filterBoxCompositorFp->getDefaultParameters();
1882 FP_Parameters->setNamedAutoConstant("screenSize", Ogre::GpuProgramParameters::ACT_VIEWPORT_SIZE);
1883 if (isGlSL)
1884 {
1885 FP_Parameters->setNamedConstant("sSceneSolidSampler", 0);
1886 FP_Parameters->setNamedConstant("sSceneOcclusion", 1);
1887 }
1888
1889 // All defined, load!
1890 filterBoxCompositorFp->load();
1891
1892 // Create merging material for compositor.
1893 Ogre::MaterialPtr ssaoMergingMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box/Material", SO3_INTERNAL_RESOURCE_GROUP);
1894 Ogre::Pass* ogrePass = ssaoMergingMaterial->getTechnique(0)->getPass(0);
1895 ogrePass->setDepthCheckEnabled(false);
1896 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
1897 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1898 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1899 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1900 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 0);
1901
1902 ogreTextureUnit = ogrePass->createTextureUnitState();
1903 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1904 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
1905 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
1906 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
1907 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
1908 ogrePass->setFragmentProgram(filterBoxCompositorFp->getName());
1909
1910 // Create compositor
1911 Ogre::CompositorPtr filterBoxCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/Box", SO3_INTERNAL_RESOURCE_GROUP);
1912
1913 // Create the technique
1914 Ogre::CompositionTechnique* filterBoxCompositionTechnique = filterBoxCompositor->createTechnique();
1915
1916 // Render as output
1917 Ogre::CompositionTargetPass* filterBoxCompositionTargetPass = filterBoxCompositionTechnique->getOutputTargetPass();
1918 filterBoxCompositionTargetPass->setShadowsEnabled(false);
1919 filterBoxCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
1920
1921 // Create the SSAO rendering pass
1922 Ogre::CompositionPass* filterBoxCompositionPassRenderBlur = filterBoxCompositionTargetPass->createPass();
1923 filterBoxCompositionPassRenderBlur->setType(Ogre::CompositionPass::PT_RENDERQUAD);
1924 filterBoxCompositionPassRenderBlur->setMaterial(ssaoMergingMaterial);
1925 }
1926
1927 void SSsaoHandler::GenerateFilterBoxSmartCompositor()
1928 {
1929 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
1930 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
1931
1932 // Create an unified fp for ssao post filter.
1933 Ogre::StringStream programHeader;
1934 programHeader << "#ifdef GL_ES" << std::endl;
1935 programHeader << " precision highp int;" << std::endl;
1936 programHeader << " precision highp float;" << std::endl;
1937 programHeader << "#endif" << std::endl;
1938
1939 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
1940
1941 Ogre::StringStream FragmentProgramData;
1942 FragmentProgramData << programHeader.str();
1943
1944 FragmentProgramData << "SAMPLER2D(sSceneSolidSampler, 0);" << std::endl;
1945 FragmentProgramData << "SAMPLER2D(sSceneDepthSampler, 1);" << std::endl;
1946 FragmentProgramData << "SAMPLER2D(sSceneOcclusion, 2);" << std::endl;
1947
1948 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
1949 FragmentProgramData << "uniform vec4 screenSize;" << std::endl;
1950 FragmentProgramData << "uniform float farClipDistance;" << std::endl;
1951 FragmentProgramData << ")" << std::endl;
1952
1953 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
1954 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
1955
1956 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
1957 FragmentProgramData << "{" << std::endl;
1958 FragmentProgramData << " float fragmentDepth = texture2D(sSceneDepthSampler, oUv).r;" << std::endl;
1959 FragmentProgramData << " float occ = 0.0;" << std::endl;
1960 FragmentProgramData << " float weight = 0.0;" << std::endl;
1961 FragmentProgramData << " for (int x = -2; x < 3; x++)" << std::endl;
1962 FragmentProgramData << " for (int y = -2; y < 3; y++)" << std::endl;
1963 FragmentProgramData << " {" << std::endl;
1964 FragmentProgramData << " float sampleDepth = texture2D(sSceneDepthSampler, vec2(oUv.x + float(x) * screenSize.z, oUv.y + float(y) * screenSize.w)).x;" << std::endl;
1965 FragmentProgramData << " float dist = abs(fragmentDepth - sampleDepth) * farClipDistance + 0.5;" << std::endl;
1966 FragmentProgramData << " float sampleWeight = 1.0 / (pow(dist, 1.0) + 1.0);" << std::endl;
1967 FragmentProgramData << " occ += sampleWeight * texture2D(sSceneOcclusion, vec2(oUv.x + float(x) * screenSize.z, oUv.y + float(y) * screenSize.w)).x;" << std::endl;
1968 FragmentProgramData << " weight += sampleWeight;" << std::endl;
1969 FragmentProgramData << " }" << std::endl;
1970 FragmentProgramData << " occ /= weight;" << std::endl;
1971 FragmentProgramData << " vec4 color = texture2D(sSceneSolidSampler, oUv);" << std::endl;
1972 FragmentProgramData << " gl_FragColor = vec4(color.r * occ, color.g * occ, color.b * occ, color.a);" << std::endl;
1973 FragmentProgramData << "}" << std::endl;
1974
1975 // Load the program in Ogre
1976 filterBoxSmartCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart_FP", true, FragmentProgramData.str());
1977
1978 // Set auto param binding
1979 Ogre::GpuProgramParametersSharedPtr filterBoxSmartCompositorFpParams = filterBoxSmartCompositorFp->getDefaultParameters();
1980 filterBoxSmartCompositorFpParams->setNamedAutoConstant("screenSize", Ogre::GpuProgramParameters::ACT_VIEWPORT_SIZE);
1981 filterBoxSmartCompositorFpParams->setNamedAutoConstant("farClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
1982
1983 if (isGlSL)
1984 {
1985 filterBoxSmartCompositorFpParams->setNamedConstant("sSceneSolidSampler", 0);
1986 filterBoxSmartCompositorFpParams->setNamedConstant("sSceneDepthSampler", 1);
1987 filterBoxSmartCompositorFpParams->setNamedConstant("sSceneOcclusion", 2);
1988 }
1989
1990 // All defined, load!
1991 filterBoxSmartCompositorFp->load();
1992
1993 // Create blur material for compositor.
1994 Ogre::MaterialPtr filterBoxSmartMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart/Material", SO3_INTERNAL_RESOURCE_GROUP);
1995 Ogre::Pass* ogrePass = filterBoxSmartMaterial->getTechnique(0)->getPass(0);
1996 ogrePass->setDepthCheckEnabled(false);
1997 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
1998 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
1999 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2000 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2001 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 0);
2002
2003 ogreTextureUnit = ogrePass->createTextureUnitState();
2004 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2005 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2006 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2007 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 1);
2008
2009 ogreTextureUnit = ogrePass->createTextureUnitState();
2010 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2011 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2012 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2013 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
2014 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
2015 ogrePass->setFragmentProgram(filterBoxSmartCompositorFp->getName());
2016
2017 // Create compositor
2018 Ogre::CompositorPtr filterBoxSmartCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart", SO3_INTERNAL_RESOURCE_GROUP);
2019
2020 // Create the technique
2021 Ogre::CompositionTechnique* filterBoxSmartCompositionTechnique = filterBoxSmartCompositor->createTechnique();
2022
2023 // Create a reference to the occlusion temporary texture
2024 Ogre::CompositionTechnique::TextureDefinition* occlusionTexture = filterBoxSmartCompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
2025 occlusionTexture->width = 0;
2026 occlusionTexture->height = 0;
2027 occlusionTexture->refCompName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input";
2028 occlusionTexture->refTexName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion";
2029
2030 // Render in first compositor occlusion texture
2031 Ogre::CompositionTargetPass* filterBoxSmartCompositionTargetPass = filterBoxSmartCompositionTechnique->getOutputTargetPass();
2032 filterBoxSmartCompositionTargetPass->setShadowsEnabled(false);
2033 filterBoxSmartCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
2034
2035 // Create the Blur rendering pass
2036 Ogre::CompositionPass* filterBoxSmartCompositionPassRenderBlur = filterBoxSmartCompositionTargetPass->createPass();
2037 filterBoxSmartCompositionPassRenderBlur->setType(Ogre::CompositionPass::PT_RENDERQUAD);
2038 filterBoxSmartCompositionPassRenderBlur->setMaterial(filterBoxSmartMaterial);
2039 }
2040
2041 void SSsaoHandler::GenerateFilterBoxSmartCompositor2()
2042 {
2043 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
2044 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
2045
2046 // Create an unified fp for ssao post filter.
2047 Ogre::StringStream programHeader;
2048 programHeader << "#ifdef GL_ES" << std::endl;
2049 programHeader << " precision highp int;" << std::endl;
2050 programHeader << " precision highp float;" << std::endl;
2051 programHeader << "#endif" << std::endl;
2052
2053 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
2054
2055 Ogre::StringStream FragmentProgramData;
2056 FragmentProgramData << programHeader.str();
2057
2058 FragmentProgramData << "SAMPLER2D(sSceneSolidSampler, 0);" << std::endl;
2059 FragmentProgramData << "SAMPLER2D(sSceneDepthSampler, 1);" << std::endl;
2060 FragmentProgramData << "SAMPLER2D(sSceneOcclusion, 2);" << std::endl;
2061
2062 FragmentProgramData << "OGRE_UNIFORMS(" << std::endl;
2063 FragmentProgramData << "uniform vec4 screenSize;" << std::endl;
2064 FragmentProgramData << "uniform float farClipDistance;" << std::endl;
2065 FragmentProgramData << ")" << std::endl;
2066
2067 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
2068 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
2069
2070 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
2071 FragmentProgramData << "{" << std::endl;
2072 FragmentProgramData << " float fragmentDepth = texture2D(sSceneDepthSampler, oUv).w / farClipDistance;" << std::endl;
2073 FragmentProgramData << " float occ = 0.0;" << std::endl;
2074 FragmentProgramData << " float weight = 0.0;" << std::endl;
2075 FragmentProgramData << " for (float x = -2.0; x < 3.0; x++)" << std::endl;
2076 FragmentProgramData << " for (float y = -2.0; y < 3.0; y++)" << std::endl;
2077 FragmentProgramData << " {" << std::endl;
2078 FragmentProgramData << " float sampleDepth = texture2D(sSceneDepthSampler, vec2(oUv.x + float(x) * screenSize.z, oUv.y + float(y) * screenSize.w)).x / farClipDistance;" << std::endl;
2079 FragmentProgramData << " float dist = abs(fragmentDepth - sampleDepth) * farClipDistance + 0.5;" << std::endl;
2080 FragmentProgramData << " float sampleWeight = 1.0 / (pow(dist, 1.0) + 1.0);" << std::endl;
2081 FragmentProgramData << " occ += sampleWeight * texture2D(sSceneOcclusion, vec2(oUv.x + float(x) * screenSize.z, oUv.y + float(y) * screenSize.w)).x;" << std::endl;
2082 FragmentProgramData << " weight += sampleWeight;" << std::endl;
2083 FragmentProgramData << " }" << std::endl;
2084 FragmentProgramData << " occ /= weight;" << std::endl;
2085 FragmentProgramData << " vec4 color = texture2D(sSceneSolidSampler, oUv);" << std::endl;
2086 FragmentProgramData << " gl_FragColor = vec4(color.r * occ, color.g * occ, color.b * occ, color.a);" << std::endl;
2087 FragmentProgramData << "}" << std::endl;
2088
2089 // Load the program in Ogre
2090 filterBoxSmart2CompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2_FP", true, FragmentProgramData.str());
2091
2092 // Set auto param binding
2093 Ogre::GpuProgramParametersSharedPtr filterBoxSmart2CompositorFpParams = filterBoxSmart2CompositorFp->getDefaultParameters();
2094 filterBoxSmart2CompositorFpParams->setNamedAutoConstant("screenSize", Ogre::GpuProgramParameters::ACT_VIEWPORT_SIZE);
2095 filterBoxSmart2CompositorFpParams->setNamedAutoConstant("farClipDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
2096
2097 if (isGlSL)
2098 {
2099 filterBoxSmart2CompositorFpParams->setNamedConstant("sSceneSolidSampler", 0);
2100 filterBoxSmart2CompositorFpParams->setNamedConstant("sSceneDepthSampler", 1);
2101 filterBoxSmart2CompositorFpParams->setNamedConstant("sSceneOcclusion", 2);
2102 }
2103
2104 // All defined, load!
2105 filterBoxSmart2CompositorFp->load();
2106
2107 // Create blur material for compositor.
2108 Ogre::MaterialPtr filterBoxSmart2Material = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2/Material", SO3_INTERNAL_RESOURCE_GROUP);
2109 Ogre::Pass* ogrePass = filterBoxSmart2Material->getTechnique(0)->getPass(0);
2110 ogrePass->setDepthCheckEnabled(false);
2111 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
2112 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2113 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2114 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2115 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 0);
2116
2117 ogreTextureUnit = ogrePass->createTextureUnitState();
2118 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2119 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2120 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2121 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/GBuffer/NormalPosition/Texture", 1);
2122
2123 ogreTextureUnit = ogrePass->createTextureUnitState();
2124 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2125 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2126 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2127 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
2128 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
2129 ogrePass->setFragmentProgram(filterBoxSmart2CompositorFp->getName());
2130
2131 // Create compositor
2132 Ogre::CompositorPtr filterBoxSmart2Compositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Filter/BoxSmart2", SO3_INTERNAL_RESOURCE_GROUP);
2133
2134 // Create the technique
2135 Ogre::CompositionTechnique* filterBoxSmart2CompositionTechnique = filterBoxSmart2Compositor->createTechnique();
2136
2137 // Create a reference to the occlusion temporary texture
2138 Ogre::CompositionTechnique::TextureDefinition* occlusionTexture = filterBoxSmart2CompositionTechnique->createTextureDefinition(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
2139 occlusionTexture->width = 0;
2140 occlusionTexture->height = 0;
2141 occlusionTexture->refCompName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input";
2142 occlusionTexture->refTexName = std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion";
2143
2144 // Render in first compositor occlusion texture
2145 Ogre::CompositionTargetPass* filterBoxSmart2CompositionTargetPass = filterBoxSmart2CompositionTechnique->getOutputTargetPass();
2146 filterBoxSmart2CompositionTargetPass->setShadowsEnabled(false);
2147 filterBoxSmart2CompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
2148
2149 // Create the Blur rendering pass
2150 Ogre::CompositionPass* filterBoxSmart2CompositionPassRenderBlur = filterBoxSmart2CompositionTargetPass->createPass();
2151 filterBoxSmart2CompositionPassRenderBlur->setType(Ogre::CompositionPass::PT_RENDERQUAD);
2152 filterBoxSmart2CompositionPassRenderBlur->setMaterial(filterBoxSmart2Material);
2153 }
2154
2155 void SSsaoHandler::GenerateSsaoDebugCompositor()
2156 {
2157 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
2158 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
2159
2160 // Create an unified fp for visualizing depth texture.
2161 Ogre::StringStream programHeader;
2162 programHeader << "#ifdef GL_ES" << std::endl;
2163 programHeader << " precision highp int;" << std::endl;
2164 programHeader << " precision highp float;" << std::endl;
2165 programHeader << "#endif" << std::endl;
2166
2167 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
2168
2169 Ogre::StringStream FragmentProgramData;
2170 FragmentProgramData << programHeader.str();
2171
2172 FragmentProgramData << "SAMPLER2D(sSceneOcclusion, 0);" << std::endl;
2173
2174 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
2175 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
2176
2177 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
2178 FragmentProgramData << "{" << std::endl;
2179 FragmentProgramData << " gl_FragColor = vec4(texture2D(sSceneOcclusion, oUv).xyz, 1.0);" << std::endl;
2180 FragmentProgramData << "}" << std::endl;
2181
2182 // Load the program in Ogre
2183 ssaoDebugCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Compositor_FP", true, FragmentProgramData.str());
2184
2185 Ogre::GpuProgramParametersSharedPtr FP_Parameters = ssaoDebugCompositorFp->getDefaultParameters();
2186 if (isGlSL)
2187 FP_Parameters->setNamedConstant("sSceneOcclusion", 0);
2188
2189 // All defined, load!
2190 ssaoDebugCompositorFp->load();
2191
2192 // Create merging material for compositor.
2193 Ogre::MaterialPtr ssaoDebugMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug/Material", SO3_INTERNAL_RESOURCE_GROUP);
2194 Ogre::Pass* ogrePass = ssaoDebugMaterial->getTechnique(0)->getPass(0);
2195 ogrePass->setDepthCheckEnabled(false);
2196 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState(); // Will be filled with occlusion texture
2197 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2198 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2199 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2200 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
2201 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
2202 ogrePass->setFragmentProgram(ssaoDebugCompositorFp->getName());
2203
2204 // Create compositor
2205 Ogre::CompositorPtr ssaoDebugCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Debug", SO3_INTERNAL_RESOURCE_GROUP);
2206
2207 // Create the technique
2208 Ogre::CompositionTechnique* ssaoDebugCompositionTechnique = ssaoDebugCompositor->createTechnique();
2209
2210 // Render as output
2211 Ogre::CompositionTargetPass* ssaoDebugOutputCompositionTargetPass = ssaoDebugCompositionTechnique->getOutputTargetPass();
2212 ssaoDebugOutputCompositionTargetPass->setShadowsEnabled(false);
2213 ssaoDebugOutputCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
2214
2215 // Create the ssao debug rendering pass
2216 Ogre::CompositionPass* ssaoDebugOutputRenderDepthCompositionPass = ssaoDebugOutputCompositionTargetPass->createPass();
2217 ssaoDebugOutputRenderDepthCompositionPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
2218 ssaoDebugOutputRenderDepthCompositionPass->setMaterial(ssaoDebugMaterial);
2219 }
2220
2221 void SSsaoHandler::GenerateMergingCompositor()
2222 {
2223 Ogre::String rendererName = SRoot::getSingletonPtr()->GetOgreRenderSystem()->getName();
2224 bool isGlSL = (rendererName == "Direct3D9 Rendering Subsystem" || rendererName == "Direct3D11 Rendering Subsystem") ? false : true;
2225
2226 // Create an unified fp for merging scene render with blurred ssao.
2227 Ogre::StringStream programHeader;
2228 programHeader << "#ifdef GL_ES" << std::endl;
2229 programHeader << " precision highp int;" << std::endl;
2230 programHeader << " precision highp float;" << std::endl;
2231 programHeader << "#endif" << std::endl;
2232
2233 programHeader << "#define USE_OGRE_FROM_FUTURE\n#include <OgreUnifiedShader.h>" << std::endl;
2234
2235 Ogre::StringStream FragmentProgramData;
2236 FragmentProgramData << programHeader.str();
2237
2238 FragmentProgramData << "SAMPLER2D(sSceneSolidSampler, 0);" << std::endl;
2239 FragmentProgramData << "SAMPLER2D(sSceneOcclusion, 1);" << std::endl;
2240
2241 FragmentProgramData << "MAIN_PARAMETERS" << std::endl;
2242 FragmentProgramData << "IN(vec2 oUv, TEXCOORD0)" << std::endl;
2243
2244 FragmentProgramData << "MAIN_DECLARATION" << std::endl;
2245 FragmentProgramData << "{" << std::endl;
2246 //FragmentProgramData << " gl_FragColor = vec4(oUv.x, oUv.y, oUv.x * oUv.y, 1.0);" << std::endl;
2247 FragmentProgramData << " float occ = texture2D(sSceneOcclusion, oUv).x;" << std::endl;
2248 FragmentProgramData << " vec4 color = texture2D(sSceneSolidSampler, oUv);" << std::endl;
2249 FragmentProgramData << " gl_FragColor = vec4(color.r * occ, color.g * occ, color.b * occ, color.a);" << std::endl;
2250 FragmentProgramData << "}" << std::endl;
2251
2252 // Load the program in Ogre
2253 ssaoMergingCompositorFp = createGpuProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging/Compositor_FP", true, FragmentProgramData.str());
2254
2255 Ogre::GpuProgramParametersSharedPtr FP_Parameters = ssaoMergingCompositorFp->getDefaultParameters();
2256 if (isGlSL)
2257 {
2258 FP_Parameters->setNamedConstant("sSceneSolidSampler", 0);
2259 FP_Parameters->setNamedConstant("sSceneOcclusion", 1);
2260 }
2261
2262 // All defined, load!
2263 ssaoMergingCompositorFp->load();
2264
2265 // Create merging material for compositor.
2266 Ogre::MaterialPtr ssaoMergingMaterial = ogreMaterialManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging/Material", SO3_INTERNAL_RESOURCE_GROUP);
2267 Ogre::Pass* ogrePass = ssaoMergingMaterial->getTechnique(0)->getPass(0);
2268 ogrePass->setDepthCheckEnabled(false);
2269 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->createTextureUnitState();
2270 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2271 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2272 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2273 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Previous", 0);
2274
2275 ogreTextureUnit = ogrePass->createTextureUnitState();
2276 ogreTextureUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
2277 ogreTextureUnit->setTextureFiltering(Ogre::TFO_NONE);
2278 ogreTextureUnit->setContentType(Ogre::TextureUnitState::CONTENT_COMPOSITOR);
2279 ogreTextureUnit->setCompositorReference(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input", std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Input/Texture/Occlusion");
2280 ogrePass->setVertexProgram(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/RenderQuad_VP");
2281 ogrePass->setFragmentProgram(ssaoMergingCompositorFp->getName());
2282
2283 // Create compositor
2284 Ogre::CompositorPtr ssaoMergingCompositor = ogreCompositorManager->create(std::string(SO3_INTERNAL_RESOURCE_GROUP) + "/Ssao/Output/Merging", SO3_INTERNAL_RESOURCE_GROUP);
2285
2286 // Create the technique
2287 Ogre::CompositionTechnique* ssaoMergingCompositionTechnique = ssaoMergingCompositor->createTechnique();
2288
2289 // Render as output
2290 Ogre::CompositionTargetPass* ssaoMergingOutputCompositionTargetPass = ssaoMergingCompositionTechnique->getOutputTargetPass();
2291 ssaoMergingOutputCompositionTargetPass->setShadowsEnabled(false);
2292 ssaoMergingOutputCompositionTargetPass->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
2293
2294 // Create the SSAO rendering pass
2295 Ogre::CompositionPass* ssaoMergingOutputMergeCompositionPass = ssaoMergingOutputCompositionTargetPass->createPass();
2296 ssaoMergingOutputMergeCompositionPass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
2297 ssaoMergingOutputMergeCompositionPass->setMaterial(ssaoMergingMaterial);
2298 }
2299
2300 SSsaoHandler::SsaoGBufferLayout SSsaoHandler::GetGBufferLayout(const SSsaoHandler::SsaoTechnique& technique)
2301 {
2302 SsaoGBufferLayout techniqueGBufferLayout = SO3_SSAO_GBUFFER_NONE;
2303 if (technique < SO3_SSAO_TECHNIQUE_MAX)
2304 {
2305 switch (technique)
2306 {
2308 techniqueGBufferLayout = SO3_SSAO_GBUFFER_NONE;
2309 break;
2311 techniqueGBufferLayout = SO3_SSAO_GBUFFER_DEPTH_ONLY;
2312 break;
2314 techniqueGBufferLayout = SO3_SSAO_GBUFFER_NORMAL_POSITION;
2315 break;
2317 techniqueGBufferLayout = SO3_SSAO_GBUFFER_NORMAL_POSITION;
2318 break;
2319 }
2320 }
2321 return techniqueGBufferLayout;
2322 }
2323
2324 float SSsaoHandler::GetTechniqueParameterValue(const SSsaoHandler::SsaoTechnique& technique, const std::string& parameterName) const
2325 {
2326 // Get parameters for that technique
2327 SsaoTechniqueParametersByTechnique::iterator iSsaoTechniquesParameters = ssaoTechniquesParameters.find(technique);
2328 if (iSsaoTechniquesParameters != ssaoTechniquesParameters.end())
2329 {
2330 // Search technique parameter
2331 SsaoTechniqueParameters::iterator iTechniqueParameters = iSsaoTechniquesParameters->second.find(parameterName);
2332 if (iTechniqueParameters != iSsaoTechniquesParameters->second.end())
2333 {
2334 // Get this parameter value
2335 return iTechniqueParameters->second.value;
2336 }
2337 else
2338 SO3_EXCEPT(SExceptionInvalidParameters, "No parameter named " + parameterName + " for this SSAO technique, cannot retrieve parameter!", "SSsaoHandler::GetTechniqueParameterValue", true);
2339 }
2340 else
2341 SO3_EXCEPT(SExceptionInvalidParameters, "No such SSAO technique, or no parameters for this SSAO technique, cannot retrieve parameters!", "SSsaoHandler::GetTechniqueParameterValue", true);
2342
2343 // Not reachable, but happy compiler
2344 return 0.0f;
2345 }
2346
2347 void SSsaoHandler::SetTechniqueParameterValue(const SSsaoHandler::SsaoTechnique& technique, const std::string& parameterName, const float& parameterValue)
2348 {
2349 if (isSupported)
2350 {
2351 // Get technique material pass
2352 Ogre::Pass* ogrePass = 0;
2353 switch (technique)
2354 {
2356 ogrePass = crytekSsaoMaterial->getTechnique(0)->getPass(0);
2357 break;
2359 if (mSupportGbuffer)
2360 ogrePass = hemisphericSsaoMaterial->getTechnique(0)->getPass(0);
2361 break;
2363 if (mSupportGbuffer)
2364 ogrePass = creaseShadingSsaoMaterial->getTechnique(0)->getPass(0);
2365 break;
2366 }
2367
2368 if (ogrePass != 0)
2369 {
2370 // Get parameter ptr from shader
2371 Ogre::GpuProgramParametersSharedPtr ssaoShaderParams = ogrePass->getFragmentProgramParameters();
2372
2373 // Get parameters for that technique
2374 SsaoTechniqueParametersByTechnique::iterator iSsaoTechniquesParameters = ssaoTechniquesParameters.find(technique);
2375 if (iSsaoTechniquesParameters != ssaoTechniquesParameters.end())
2376 {
2377 // Search technique parameter
2378 SsaoTechniqueParameters::iterator iTechniqueParameters = iSsaoTechniquesParameters->second.find(parameterName);
2379 if (iTechniqueParameters != iSsaoTechniquesParameters->second.end())
2380 {
2381 // Check that value is in range
2382 if ((iTechniqueParameters->second.range.first <= parameterValue) && (iTechniqueParameters->second.range.second >= parameterValue))
2383 {
2384 // Set the param to the new value.
2385 ssaoShaderParams->setNamedConstant(parameterName, parameterValue);
2386
2387 // Store this parameter
2388 iTechniqueParameters->second.value = parameterValue;
2389
2390 // If SSAO is enabled, and the technique is the current technique, we need to disable and re-enable compositor in order to take the parameter in count (Ogre bug?)
2391 if ((isEnable) && (technique == currentSsaoTechnique))
2392 Ogre::CompositorManager::getSingleton().getCompositorChain(targetViewport->GetOgreViewPortPointer())->_markDirty();
2393 }
2394 else
2395 SO3_EXCEPT(SExceptionInvalidParameters, "New value for parameter " + parameterName + " is out of range, cannot set parameter!", "SSsaoHandler::SeTechniqueParameterValue", true);
2396 }
2397 else
2398 SO3_EXCEPT(SExceptionInvalidParameters, "No parameter named " + parameterName + " for this SSAO technique, cannot set parameter!", "SSsaoHandler::SeTechniqueParameterValue", true);
2399 }
2400 else
2401 SO3_EXCEPT(SExceptionInvalidParameters, "No parameters for this SSAO technique, cannot set parameters!", "SSsaoHandler::SeTechniqueParameterValue", true);
2402 }
2403 else
2404 SO3_EXCEPT(SExceptionInvalidParameters, "No such SSAO technique, cannot set parameters!", "SSsaoHandler::SeTechniqueParameterValue", true);
2405 }
2406 else
2407 SO3_EXCEPT(SExceptionInvalidParameters, "SSAO technique, not supported by the graphic card!", "SSsaoHandler::SeTechniqueParameterValue", true);
2408 }
2409
2411 {
2412 // Get parameters for that technique
2413 SsaoTechniqueParametersByTechnique::iterator iSsaoTechniquesParameters = ssaoTechniquesParameters.find(technique);
2414 if (iSsaoTechniquesParameters != ssaoTechniquesParameters.end())
2415 return iSsaoTechniquesParameters->second;
2416 else
2417 SO3_EXCEPT(SExceptionInvalidParameters, "No such SSAO technique, or no parameters for this SSAO technique, cannot retrieve parameters!", "SSsaoHandler::GetTechniqueParameters", true);
2418
2419 // Not reachable, but happy compiler
2420 return SsaoTechniqueParameters();
2421 }
2422
2424 {
2425 if (isSupported)
2426 {
2427 // Get technique material pass
2428 Ogre::Pass* ogrePass = 0;
2429 switch (technique)
2430 {
2432 ogrePass = crytekSsaoMaterial->getTechnique(0)->getPass(0);
2433 break;
2435 if (mSupportGbuffer)
2436 ogrePass = hemisphericSsaoMaterial->getTechnique(0)->getPass(0);
2437 break;
2439 if (mSupportGbuffer)
2440 ogrePass = creaseShadingSsaoMaterial->getTechnique(0)->getPass(0);
2441 break;
2442 }
2443
2444 if (ogrePass != 0)
2445 {
2446 // Get parameter ptr from shader
2447 Ogre::GpuProgramParametersSharedPtr ssaoShaderParams = ogrePass->getFragmentProgramParameters();
2448
2449 // Get parameters for that technique
2450 float tempValue = 0.0f;
2451 SsaoTechniqueParametersByTechnique::iterator iSsaoTechniquesParameters = ssaoTechniquesParameters.find(technique);
2452 if (iSsaoTechniquesParameters != ssaoTechniquesParameters.end())
2453 {
2454 // Iterate through parameters
2455 SsaoTechniqueParameters::iterator iTechniqueParameters = iSsaoTechniquesParameters->second.begin();
2456 while (iTechniqueParameters != iSsaoTechniquesParameters->second.end())
2457 {
2458 // Get this parameter value in the list passed as arguments
2459 SsaoTechniqueParameters::const_iterator iNewParameter = parameters.find(iTechniqueParameters->first);
2460 if (iNewParameter != parameters.end())
2461 {
2462 // Check that value is in range
2463 tempValue = iNewParameter->second.value;
2464 if ((iTechniqueParameters->second.range.first <= tempValue) && (iTechniqueParameters->second.range.second >= tempValue))
2465 {
2466 // Set the param to the new value.
2467 ssaoShaderParams->setNamedConstant(iNewParameter->first, tempValue);
2468
2469 // Store this parameter
2470 iTechniqueParameters->second.value = tempValue;
2471 }
2472 // Else warning in log?
2473 }
2474 // Else warning in log?
2475
2476 // Next parameter to set
2477 iTechniqueParameters++;
2478 }
2479 }
2480 else
2481 SO3_EXCEPT(SExceptionInvalidParameters, "No parameters for this SSAO technique, cannot set parameters!", "SSsaoHandler::SeTechniqueParameters", true);
2482 }
2483 else
2484 SO3_EXCEPT(SExceptionInvalidParameters, "No such SSAO technique, cannot set parameters!", "SSsaoHandler::SeTechniqueParameters", true);
2485 }
2486 else
2487 SO3_EXCEPT(SExceptionInvalidParameters, "SSAO technique, not supported by the graphic card!", "SSsaoHandler::SeTechniqueParameters", true);
2488 }
2489
2490 /*
2491 void SSsaoHandler::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
2492 {
2493 //Disable octree update
2494 SCamera* cam = targetViewport->GetCamera();
2495 if (cam)
2496 {
2497 cam->GetParentScene()->GetOgreScenePointer()->setFindVisibleObjects(false);
2498 cam->GetParentScene()->GetOgreScenePointer()->setLateMaterialResolving(false);
2499 }
2500 }
2501
2502 void SSsaoHandler::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt)
2503 {
2504 //Enable octree update
2505 SCamera* cam = targetViewport->GetCamera();
2506 if (cam)
2507 {
2508 cam->GetParentScene()->GetOgreScenePointer()->setFindVisibleObjects(true);
2509 cam->GetParentScene()->GetOgreScenePointer()->setLateMaterialResolving(true);
2510 }
2511 }
2512 */
2513}
SException indicating that at least one invalid parameter was provided on a functionnality call.
SWidget * GetAssociatedWidget()
bool GetRttPixelFormat(Ogre::PixelFormat &format, bool alpha=false, bool floattex=false)
Definition SO3Root.cpp:650
Ogre::RenderSystem * GetOgreRenderSystem()
Definition SO3Root.cpp:865
static SRoot & getSingleton()
Definition SO3Root.cpp:116
static SRoot * getSingletonPtr()
Definition SO3Root.cpp:111
std::pair< float, float > SsaoTechniqueParameterRange
float GetTechniqueParameterValue(const SsaoTechnique &technique, const std::string &parameterName) const
virtual Ogre::Technique * handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial, unsigned short lodIndex, const Ogre::Renderable *rend)
void SetTechniqueParameterValue(const SsaoTechnique &technique, const std::string &parameterName, const float &parameterValue)
SsaoDebugMode GetDebugMode()
void SetDebugMode(const SsaoDebugMode &newDebugMode)
SsaoTechnique GetTechnique()
void SetEnable(bool enable)
SsaoTechniqueParameters GetTechniqueParameters(const SsaoTechnique &technique) const
std::map< std::string, SsaoTechniqueParameter > SsaoTechniqueParameters
static void Reset()
void SetFilter(const SsaoFilter &newFilter)
void SetTechniqueParameters(const SsaoTechnique &technique, const SsaoTechniqueParameters &parameters)
void SetTechnique(SsaoTechnique newTechnique)
SMaterial * GetParentMaterial()
Ogre::Viewport * GetOgreViewPortPointer()
bool UpdateStereoCompositorState(const Ogre::String compname, bool state)