SO3Engine
SO3DeferredShading.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
35
36template<> SO3::SDeferredShading* Ogre::Singleton<SO3::SDeferredShading>::msSingleton = 0;
37
38namespace SO3
39{
40
41//Also change in SO3_Deferred.compositor "SO3/Deferred/GBuffer"
42const Ogre::uint8 SDeferredShading::PRE_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_2;
43const Ogre::uint8 SDeferredShading::POST_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_8;
44
46{
47 #if SO3_ENABLE_DEFERRED_CUSTOM_SHADOWS == 1
48 deferredShadowManager = new SDeferredShadowManager();
49 #else
50 deferredShadowManager = 0;
51 #endif
52 currentGBuffer = 0;
53 newViewportAdded = false;
54 gBufferSchemeHandler = 0;
55 noGBufferSchemeHandler = 0;
56 ssaoCompositorLogic = 0;
57 deferredLightCompositionPass = 0;
58
59 gbufferMaterialGenerator = new SGBufferMaterialGenerator();
60 deferredLightManager = new SDeferredLightManager();
61 compositorGBuffer = new SDeferredCompositorGBuffer();
62 compositorLighting = new SDeferredCompositorLighting();
63 compositorShowDepth = new SDeferredCompositorShowDepth();
64 compositorShowDiffuse = new SDeferredCompositorShowDiffuse();
65 compositorShowEmissive = new SDeferredCompositorShowEmissive();
66 compositorShowMaterialID = new SDeferredCompositorShowMaterialID();
67 compositorShowNormal = new SDeferredCompositorShowNormal();
68 compositorShowSpecular = new SDeferredCompositorShowSpecular();
69 compositorShowVelocity = new SDeferredCompositorShowVelocity();
70 compositorSSAO = new SDeferredCompositorSSAO();
71 compositorSSAA = new SDeferredCompositorSSAA();
72 compositorNFAA = new SDeferredCompositorNFAA();
73
76}
77
79{
81 SAFE_DELETE(deferredShadowManager);
82
83 // Remove GBuffer scheme listener.
84 if(gBufferSchemeHandler)
85 {
86 Ogre::MaterialManager::getSingleton().removeListener(gBufferSchemeHandler);
87 SO3_SAFE_DELETE(gBufferSchemeHandler);
88 }
89
90 // Remove NoGBuffer scheme listener.
91 if(noGBufferSchemeHandler)
92 {
93 Ogre::MaterialManager::getSingleton().removeListener(noGBufferSchemeHandler);
94 SO3_SAFE_DELETE(noGBufferSchemeHandler);
95 }
96
97 // UnHook the compositor logic.
98 Ogre::CompositorManager& compMan = Ogre::CompositorManager::getSingleton();
99 if(ssaoCompositorLogic)
100 {
101 compMan.unregisterCompositorLogic("SSAOLogic");
102 SO3_SAFE_DELETE(ssaoCompositorLogic);
103 }
104
105 // UnHook light composition pass.
106 /*if(deferredLightCompositionPass)
107 {
108 TODO!
109 compMan.unregisterCustomCompositionPass("DeferredLight", deferredLightCompositionPass);
110 SO3_SAFE_DELETE(deferredLightCompositionPass);
111 }*/
112
113 //
114 SO3_SAFE_DELETE(compositorGBuffer);
115 SO3_SAFE_DELETE(compositorLighting);
116 SO3_SAFE_DELETE(compositorShowDepth);
117 SO3_SAFE_DELETE(compositorShowDiffuse);
118 SO3_SAFE_DELETE(compositorShowEmissive);
119 SO3_SAFE_DELETE(compositorShowMaterialID);
120 SO3_SAFE_DELETE(compositorShowNormal);
121 SO3_SAFE_DELETE(compositorShowSpecular);
122 SO3_SAFE_DELETE(compositorShowVelocity);
123 SO3_SAFE_DELETE(compositorSSAO);
124 SO3_SAFE_DELETE(compositorSSAA);
125 SO3_SAFE_DELETE(compositorNFAA);
126 SO3_SAFE_DELETE(deferredLightManager);
127 SO3_SAFE_DELETE(gbufferMaterialGenerator);
128
129 //
130 AvailableGBufferMap::iterator iGBuffer = availableGBufferMap.begin();
131 while(iGBuffer != availableGBufferMap.end())
132 {
133 SO3_SAFE_DELETE(iGBuffer->second);
134 iGBuffer++;
135 }
136 availableGBufferMap.clear();
137}
138
140{
141 return msSingleton;
142}
143
145{
146 assert(msSingleton);
147 return (*msSingleton);
148}
149
151{
152 OgreViewportList::iterator ogreViewportSearched = ogreViewportList.find(targetViewport);
153 if (ogreViewportSearched != ogreViewportList.end())
154 SO3_EXCEPT(SExceptionItemIdentity, "Trying to register an already registered viewport!", "SDeferredShading::RegisterViewport", true);
155 else
156 {
157 Ogre::CompositorManager& compMan = Ogre::CompositorManager::getSingleton();
158 static bool firstTime = true;
159 if (firstTime)
160 {
161 // Check graphic card capabilities. We do this here cause we have to be certain that a render window exists before checking capabilities
162 Ogre::RenderSystem* ogreRenderSystem = Ogre::Root::getSingleton().getRenderSystem();
163 const Ogre::RenderSystemCapabilities* ogreCapabilities = ogreRenderSystem ->getCapabilities();
164
165 // Checking fragment and vertex programs availibility
166 if (!ogreCapabilities->hasCapability(Ogre::RSC_VERTEX_PROGRAM) || !(ogreCapabilities->hasCapability(Ogre::RSC_FRAGMENT_PROGRAM)))
167 SO3_EXCEPT(SExceptionUnimplemented, "Your card does not support vertex and fragment programs!", "SDeferredShading::SDeferredShading", true);
168
169 // Checking MRT availibility for 2 MRT Gbuffer
170 if (ogreCapabilities->getNumMultiRenderTargets()<2)
171 SO3_EXCEPT(SExceptionUnimplemented, "Your card does not support at least two simultaneous render targets!", "SDeferredShading::SDeferredShading", true);
172
173 // Generate GBuffer_Low
174 currentGBuffer = new SGBufferLow();
175 availableGBufferMap.insert(AvailableGBufferMap::value_type(currentGBuffer->GetName(), currentGBuffer));
176
177 // Checking MRT availibility for 4 MRT Gbuffer
178 if (ogreCapabilities->getNumMultiRenderTargets()<4)
179 {
180 Ogre::LogManager::getSingleton().logMessage("Your card does not support at least four simultaneous render targets, high resolution deferred will not be available!");
181 }
182 else
183 {
184 // Generate GBuffer_High, select it if available
185 currentGBuffer = new SGBufferHigh();
186 availableGBufferMap.insert(AvailableGBufferMap::value_type(currentGBuffer->GetName(), currentGBuffer));
187 }
188
189 // Hook up the scheme handlers.
190 gBufferSchemeHandler = new SGBufferSchemeHandler(gbufferMaterialGenerator);
191 noGBufferSchemeHandler = new SNoGBufferSchemeHandler();
192 Ogre::MaterialManager::getSingleton().addListener(gBufferSchemeHandler, "GBuffer");
193 Ogre::MaterialManager::getSingleton().addListener(noGBufferSchemeHandler, "NoGBuffer");
194
195 // Hook up the compositor logic.
196 ssaoCompositorLogic = new SSsaoLogic();
197 compMan.registerCompositorLogic("SSAOLogic", ssaoCompositorLogic);
198 deferredLightCompositionPass = new SDeferredLightCompositionPass();
199 compMan.registerCustomCompositionPass("DeferredLight", deferredLightCompositionPass);
200
201 firstTime = false;
202 }
203
204 // Create our viewport gbuffer filters instance
205 GBufferFilters* viewportGBufferFilters = new GBufferFilters();
206
207 // Create the main GBuffer compositor
208 Ogre::Viewport* ogreTargetViewport = targetViewport->GetOgreViewPortPointer();
209 viewportGBufferFilters->gBufferInstance = compMan.addCompositor(ogreTargetViewport, compositorGBuffer->GetCompositor(currentGBuffer)->getName(), 0);
210 //viewportGBufferFilters->gBufferInstance->getTechnique()->getTargetPass(0)->getPass(0)->setClearColour(targetViewport->getBackgroundColour());
211
212 // Create filters
213 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWLIT] = compMan.addCompositor(ogreTargetViewport, compositorLighting->GetCompositor(currentGBuffer)->getName(), 1);
214 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWCOLOUR] = compMan.addCompositor(ogreTargetViewport, compositorShowDiffuse->GetCompositor(currentGBuffer)->getName());
215 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWNORMALS] = compMan.addCompositor(ogreTargetViewport, compositorShowNormal->GetCompositor(currentGBuffer)->getName());
216 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWDEPTH] = compMan.addCompositor(ogreTargetViewport, compositorShowDepth->GetCompositor(currentGBuffer)->getName());
217 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWSPECULAR] = compMan.addCompositor(ogreTargetViewport, compositorShowSpecular->GetCompositor(currentGBuffer)->getName());
218 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWEMISSIVE] = compMan.addCompositor(ogreTargetViewport, compositorShowEmissive->GetCompositor(currentGBuffer)->getName());
219 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWVELOCITY] = compMan.addCompositor(ogreTargetViewport, compositorShowVelocity->GetCompositor(currentGBuffer)->getName());
220 viewportGBufferFilters->gBufferCompositors[SO3_DEFERRED_SHOWMATERIALID] = compMan.addCompositor(ogreTargetViewport, compositorShowMaterialID->GetCompositor(currentGBuffer)->getName());
221
222 // Create ssao compositor
223 viewportGBufferFilters->ssaoCompositor = compMan.addCompositor(ogreTargetViewport, compositorSSAO->GetCompositor(currentGBuffer)->getName(), 2);
224
225 // Create AA compositors
226 viewportGBufferFilters->antiAliasingCompositors[SO3_DEFERRED_SSAA - 1] = compMan.addCompositor(ogreTargetViewport, compositorSSAA->GetCompositor(currentGBuffer)->getName());
227 viewportGBufferFilters->antiAliasingCompositors[SO3_DEFERRED_NFAA - 1] = compMan.addCompositor(ogreTargetViewport, compositorNFAA->GetCompositor(currentGBuffer)->getName());
228
229 // Add to our list
230 ogreViewportList.insert(OgreViewportList::value_type(targetViewport, viewportGBufferFilters));
231
232 // Activate GBuffer
233 viewportGBufferFilters->gBufferInstance->setEnabled(true);
234
235 // Force synchro.
236 newViewportAdded = true;
238 }
239}
240
242{
243 OgreViewportList::iterator ogreViewportSearched = ogreViewportList.find(existingViewport);
244 if (ogreViewportSearched != ogreViewportList.end())
245 // SO3_EXCEPT(SExceptionItemNotFound, "Trying to unregister a viewport that is not registered!", "SDeferredShading::UnregisterViewport", true);
246 //else
247 {
248 Ogre::Viewport* ogreTargetViewport = existingViewport->GetOgreViewPortPointer();
249 Ogre::CompositorChain* chain = Ogre::CompositorManager::getSingleton().getCompositorChain(ogreTargetViewport);
250
251 for(int i=0; i<SO3_DEFERRED_COUNT; ++i)
252 chain->_removeInstance(ogreViewportSearched->second->gBufferCompositors[i]);
253
254 for(int i=0; i<SO3_DEFERRED_AA_COUNT; ++i)
255 chain->_removeInstance(ogreViewportSearched->second->antiAliasingCompositors[i]);
256
257 chain->_removeInstance(ogreViewportSearched->second->ssaoCompositor);
258 chain->_removeInstance(ogreViewportSearched->second->gBufferInstance);
259
260 chain->_markDirty();
261
262 if(chain->getNumCompositors() == 0)
263 Ogre::CompositorManager::getSingleton().removeCompositorChain(ogreTargetViewport);
264
265 // TODO verify that our filter struct is empty
266 // Delete our filter struct
267 SO3_SAFE_DELETE(ogreViewportSearched->second);
268
269 // Remove from our list
270 ogreViewportList.erase(ogreViewportSearched);
271 }
272}
273
275{
276 // Copy our internal viewport list cause it'll be modified.
277 OgreViewportList ogreViewportListCopy = ogreViewportList;
278 OgreViewportList::iterator iOgreViewportListCopy = ogreViewportListCopy.begin();
279 while (iOgreViewportListCopy != ogreViewportListCopy.end())
280 {
281 UnregisterViewport(iOgreViewportListCopy->first);
282 iOgreViewportListCopy++;
283 }
284}
285
287{
288 assert(0 <= mode && mode < SO3_DEFERRED_COUNT);
289
290 // prevent duplicate setups
291 if ((currentMode == mode) && (!newViewportAdded))
292 return;
293
294 // For each viewport
295 newViewportAdded = false;
296 OgreViewportList::iterator iOgreViewportList = ogreViewportList.begin();
297 while (iOgreViewportList != ogreViewportList.end())
298 {
299 for(int i=0; i<SO3_DEFERRED_COUNT; ++i)
300 {
301 if(i == mode)
302 {
303 iOgreViewportList->second->gBufferCompositors[i]->setEnabled(true);
304 }
305 else
306 {
307 iOgreViewportList->second->gBufferCompositors[i]->setEnabled(false);
308 }
309 }
310
311 // Activate ssao
312 if(iOgreViewportList->first->GetSSAOEnable())
313 iOgreViewportList->second->ssaoCompositor->setEnabled(mode == SO3_DEFERRED_SHOWLIT);
314
315 iOgreViewportList++;
316 }
317 currentMode = mode;
318}
319
320void SDeferredShading::SetSSAO(SViewPort* existingViewport, bool ssao)
321{
322 OgreViewportList::iterator iOgreViewportList = ogreViewportList.find(existingViewport);
323 if (iOgreViewportList != ogreViewportList.end())
324 {
326 {
327 iOgreViewportList->second->ssaoCompositor->setEnabled(ssao);
328 }
329 }
330}
331
333{
334 OgreViewportList::iterator iOgreViewportList = ogreViewportList.find(existingViewport);
335 if (iOgreViewportList != ogreViewportList.end())
336 {
337 for(int i=1; i<=SO3_DEFERRED_AA_COUNT; ++i)
338 {
339 if(i == newMode)
340 {
341 iOgreViewportList->second->antiAliasingCompositors[i - 1]->setEnabled(true);
342 }
343 else
344 {
345 iOgreViewportList->second->antiAliasingCompositors[i - 1]->setEnabled(false);
346 }
347 }
348 }
349}
350
355
357{
358 return currentGBuffer;
359}
360
362{
363 return gbufferMaterialGenerator;
364}
365
366}
librairies include
std::string GetName() const
Ogre::CompositorPtr GetCompositor(SGBuffer *gBuffer)
static SDeferredShading * getSingletonPtr()
static const Ogre::uint8 PRE_GBUFFER_RENDER_QUEUE
void SetAntiAliasing(SViewPort *existingViewport, DeferredShadingAntiAliasingMode newMode)
void SetSSAO(SViewPort *existingViewport, bool ssao)
void UnregisterViewport(SViewPort *existingViewport)
static SDeferredShading & getSingleton()
std::map< SViewPort *, GBufferFilters * > OgreViewportList
OgreViewportList ogreViewportList
static const Ogre::uint8 POST_GBUFFER_RENDER_QUEUE
void RegisterViewport(SViewPort *targetViewport)
DeferredShadingMode currentMode
DeferredShadingMode GetMode() const
@ SO3_DEFERRED_SHOWCOLOUR
Show diffuse (for debugging)
@ SO3_DEFERRED_SHOWNORMALS
Show normals (for debugging)
@ SO3_DEFERRED_SHOWLIT
The deferred shading mode.
@ SO3_DEFERRED_SHOWEMISSIVE
Show emissive channel (for debugging)
@ SO3_DEFERRED_SHOWVELOCITY
Show velocity vector (for debugging)
@ SO3_DEFERRED_SHOWSPECULAR
Show specular channel (for debugging)
@ SO3_DEFERRED_SHOWDEPTH
Show depth channel (for debugging)
void SetMode(DeferredShadingMode mode)
SGBufferMaterialGenerator * GetGBufferMaterialGenerator()
SException indicating that an attempt to create a new item with a given identifier fails cause anothe...
SException indicating that a call to an unimplemented functionnality was done.
Ogre::Viewport * GetOgreViewPortPointer()
Ogre::CompositorInstance * ssaoCompositor
AntiAliasingCompositors antiAliasingCompositors
Ogre::CompositorInstance * gBufferInstance