1 | /****************************************************************************** |
---|
2 | Copyright (c) W.J. van der Laan |
---|
3 | |
---|
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of |
---|
5 | this software and associated documentation files (the "Software"), to deal in |
---|
6 | the Software without restriction, including without limitation the rights to use, |
---|
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the |
---|
8 | Software, and to permit persons to whom the Software is furnished to do so, subject |
---|
9 | to the following conditions: |
---|
10 | |
---|
11 | The above copyright notice and this permission notice shall be included in all copies |
---|
12 | or substantial portions of the Software. |
---|
13 | |
---|
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
---|
15 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A |
---|
16 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
---|
17 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
---|
18 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE |
---|
19 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
---|
20 | ******************************************************************************/ |
---|
21 | |
---|
22 | #include "DeferredShading.h" |
---|
23 | |
---|
24 | #include "OgreConfigFile.h" |
---|
25 | #include "OgreStringConverter.h" |
---|
26 | #include "OgreException.h" |
---|
27 | |
---|
28 | #include "OgreHardwarePixelBuffer.h" |
---|
29 | #include "OgreRoot.h" |
---|
30 | #include "OgreRenderSystem.h" |
---|
31 | #include "OgreMaterialManager.h" |
---|
32 | |
---|
33 | #include "OgreEntity.h" |
---|
34 | #include "OgreSubEntity.h" |
---|
35 | #include "OgreRoot.h" |
---|
36 | |
---|
37 | #include "OgreCompositor.h" |
---|
38 | #include "OgreCompositorManager.h" |
---|
39 | #include "OgreCompositorChain.h" |
---|
40 | #include "OgreCompositorInstance.h" |
---|
41 | #include "OgreCompositionTechnique.h" |
---|
42 | #include "OgreCompositionPass.h" |
---|
43 | #include "OgreCompositionTargetPass.h" |
---|
44 | |
---|
45 | #include "MLight.h" |
---|
46 | #include "LightMaterialGenerator.h" |
---|
47 | |
---|
48 | #include "OgreHighLevelGpuProgram.h" |
---|
49 | #include "OgreHighLevelGpuProgramManager.h" |
---|
50 | |
---|
51 | using namespace Ogre; |
---|
52 | |
---|
53 | /// XXX make this a .compositor script |
---|
54 | void createPostFilters() |
---|
55 | { |
---|
56 | /** Postfilter for rendering to fat render target. Excludes skies, backgrounds and other unwanted |
---|
57 | objects. |
---|
58 | */ |
---|
59 | CompositorPtr comp7 = CompositorManager::getSingleton().create( |
---|
60 | "DeferredShading/Fat", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME |
---|
61 | ); |
---|
62 | { |
---|
63 | CompositionTechnique *t = comp7->createTechnique(); |
---|
64 | { |
---|
65 | CompositionTargetPass *tp = t->getOutputTargetPass(); |
---|
66 | tp->setInputMode(CompositionTargetPass::IM_NONE); |
---|
67 | tp->setVisibilityMask(DeferredShadingSystem::SceneVisibilityMask); |
---|
68 | /// Clear |
---|
69 | { CompositionPass *pass = tp->createPass(); |
---|
70 | pass->setType(CompositionPass::PT_CLEAR); |
---|
71 | pass->setClearColour(ColourValue(0,0,0,0)); |
---|
72 | } |
---|
73 | /// Render geometry |
---|
74 | { CompositionPass *pass = tp->createPass(); |
---|
75 | pass->setType(CompositionPass::PT_RENDERSCENE); |
---|
76 | pass->setFirstRenderQueue(RENDER_QUEUE_1); |
---|
77 | pass->setLastRenderQueue(RENDER_QUEUE_9); |
---|
78 | } |
---|
79 | } |
---|
80 | } |
---|
81 | /** Postfilter doing full deferred shading with two lights in one pass |
---|
82 | */ |
---|
83 | CompositorPtr comp = CompositorManager::getSingleton().create( |
---|
84 | "DeferredShading/Single", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME |
---|
85 | ); |
---|
86 | { |
---|
87 | CompositionTechnique *t = comp->createTechnique(); |
---|
88 | { |
---|
89 | CompositionTargetPass *tp = t->getOutputTargetPass(); |
---|
90 | tp->setInputMode(CompositionTargetPass::IM_NONE); |
---|
91 | tp->setVisibilityMask(DeferredShadingSystem::PostVisibilityMask); |
---|
92 | /// Render skies |
---|
93 | { CompositionPass *pass = tp->createPass(); |
---|
94 | pass->setType(CompositionPass::PT_RENDERSCENE); |
---|
95 | pass->setFirstRenderQueue(RENDER_QUEUE_SKIES_EARLY); |
---|
96 | pass->setLastRenderQueue(RENDER_QUEUE_SKIES_EARLY); |
---|
97 | } |
---|
98 | /// Render ambient pass |
---|
99 | { CompositionPass *pass = tp->createPass(); |
---|
100 | pass->setType(CompositionPass::PT_RENDERQUAD); |
---|
101 | pass->setMaterialName("DeferredShading/Post/Single"); |
---|
102 | pass->setIdentifier(1); |
---|
103 | } |
---|
104 | /// Render overlayed geometry |
---|
105 | { CompositionPass *pass = tp->createPass(); |
---|
106 | pass->setType(CompositionPass::PT_RENDERSCENE); |
---|
107 | pass->setFirstRenderQueue(RENDER_QUEUE_1); |
---|
108 | pass->setLastRenderQueue(RENDER_QUEUE_9); |
---|
109 | } |
---|
110 | } |
---|
111 | } |
---|
112 | /** Postfilter doing full deferred shading with an ambient pass and multiple light passes |
---|
113 | */ |
---|
114 | CompositorPtr comp2 = CompositorManager::getSingleton().create( |
---|
115 | "DeferredShading/Multi", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME |
---|
116 | ); |
---|
117 | { |
---|
118 | CompositionTechnique *t = comp2->createTechnique(); |
---|
119 | { |
---|
120 | CompositionTargetPass *tp = t->getOutputTargetPass(); |
---|
121 | tp->setInputMode(CompositionTargetPass::IM_NONE); |
---|
122 | tp->setVisibilityMask(DeferredShadingSystem::PostVisibilityMask); |
---|
123 | /// Render skies |
---|
124 | { CompositionPass *pass = tp->createPass(); |
---|
125 | pass->setType(CompositionPass::PT_RENDERSCENE); |
---|
126 | pass->setFirstRenderQueue(RENDER_QUEUE_SKIES_EARLY); |
---|
127 | pass->setLastRenderQueue(RENDER_QUEUE_SKIES_EARLY); |
---|
128 | } |
---|
129 | /// Render ambient pass |
---|
130 | { CompositionPass *pass = tp->createPass(); |
---|
131 | pass->setType(CompositionPass::PT_RENDERQUAD); |
---|
132 | pass->setMaterialName("DeferredShading/Post/Multi"); |
---|
133 | pass->setIdentifier(1); |
---|
134 | } |
---|
135 | /// Render overlayed geometry |
---|
136 | { |
---|
137 | CompositionPass *pass = tp->createPass(); |
---|
138 | pass->setType(CompositionPass::PT_RENDERSCENE); |
---|
139 | pass->setFirstRenderQueue(RENDER_QUEUE_1); |
---|
140 | pass->setLastRenderQueue(RENDER_QUEUE_9); |
---|
141 | } |
---|
142 | } |
---|
143 | } |
---|
144 | /** Postfilter that shows the normal channel |
---|
145 | */ |
---|
146 | CompositorPtr comp3 = CompositorManager::getSingleton().create( |
---|
147 | "DeferredShading/ShowNormal", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME |
---|
148 | ); |
---|
149 | { |
---|
150 | CompositionTechnique *t = comp3->createTechnique(); |
---|
151 | { |
---|
152 | CompositionTargetPass *tp = t->getOutputTargetPass(); |
---|
153 | tp->setInputMode(CompositionTargetPass::IM_NONE); |
---|
154 | { CompositionPass *pass = tp->createPass(); |
---|
155 | pass->setType(CompositionPass::PT_RENDERQUAD); |
---|
156 | pass->setMaterialName("DeferredShading/Post/ShowNormal"); |
---|
157 | pass->setIdentifier(1); |
---|
158 | } |
---|
159 | } |
---|
160 | } |
---|
161 | /** Postfilter that shows the depth and specular channel |
---|
162 | */ |
---|
163 | CompositorPtr comp4 = CompositorManager::getSingleton().create( |
---|
164 | "DeferredShading/ShowDepthSpecular", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME |
---|
165 | ); |
---|
166 | { |
---|
167 | CompositionTechnique *t = comp4->createTechnique(); |
---|
168 | { |
---|
169 | CompositionTargetPass *tp = t->getOutputTargetPass(); |
---|
170 | tp->setInputMode(CompositionTargetPass::IM_NONE); |
---|
171 | { CompositionPass *pass = tp->createPass(); |
---|
172 | pass->setType(CompositionPass::PT_RENDERQUAD); |
---|
173 | pass->setMaterialName("DeferredShading/Post/ShowDS"); |
---|
174 | pass->setIdentifier(1); |
---|
175 | } |
---|
176 | } |
---|
177 | } |
---|
178 | /** Postfilter that shows the depth and specular channel |
---|
179 | */ |
---|
180 | CompositorPtr comp5 = CompositorManager::getSingleton().create( |
---|
181 | "DeferredShading/ShowColour", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME |
---|
182 | ); |
---|
183 | { |
---|
184 | CompositionTechnique *t = comp5->createTechnique(); |
---|
185 | { |
---|
186 | CompositionTargetPass *tp = t->getOutputTargetPass(); |
---|
187 | tp->setInputMode(CompositionTargetPass::IM_NONE); |
---|
188 | { CompositionPass *pass = tp->createPass(); |
---|
189 | pass->setType(CompositionPass::PT_RENDERQUAD); |
---|
190 | pass->setMaterialName("DeferredShading/Post/ShowColour"); |
---|
191 | pass->setIdentifier(1); |
---|
192 | } |
---|
193 | } |
---|
194 | } |
---|
195 | } |
---|
196 | |
---|
197 | |
---|
198 | DeferredShadingSystem::DeferredShadingSystem( |
---|
199 | Viewport *vp, SceneManager *sm, Camera *cam |
---|
200 | ): |
---|
201 | mSceneMgr(sm), mViewport(vp), mCamera(cam), |
---|
202 | mLightMaterialGenerator(0) |
---|
203 | { |
---|
204 | for(int i=0; i<DSM_COUNT; ++i) |
---|
205 | mInstance[i]=0; |
---|
206 | |
---|
207 | mActive = true; |
---|
208 | mCurrentMode = DSM_MULTIPASS; |
---|
209 | |
---|
210 | rttTex = 0; |
---|
211 | |
---|
212 | createPostFilters(); |
---|
213 | |
---|
214 | createResources(); |
---|
215 | // Hide post geometry |
---|
216 | mSceneMgr->setVisibilityMask(mSceneMgr->getVisibilityMask() & ~PostVisibilityMask); |
---|
217 | // Default to normal deferred shading mode |
---|
218 | setMode(mCurrentMode); |
---|
219 | setActive(true); |
---|
220 | } |
---|
221 | |
---|
222 | DeferredShadingSystem::~DeferredShadingSystem() |
---|
223 | { |
---|
224 | // Delete mini lights |
---|
225 | for(std::set<MLight*>::iterator i=mLights.begin(); i!=mLights.end(); ++i) |
---|
226 | { |
---|
227 | delete (*i); |
---|
228 | } |
---|
229 | |
---|
230 | Ogre::CompositorChain *chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mViewport); |
---|
231 | for(int i=0; i<DSM_COUNT; ++i) |
---|
232 | chain->_removeInstance(mInstance[i]); |
---|
233 | |
---|
234 | delete mLightMaterialGenerator; |
---|
235 | } |
---|
236 | void DeferredShadingSystem::setMode(DSMode mode) |
---|
237 | { |
---|
238 | for(int i=0; i<DSM_COUNT; ++i) |
---|
239 | { |
---|
240 | if(i == mode) |
---|
241 | mInstance[i]->setEnabled(mActive); |
---|
242 | else |
---|
243 | mInstance[i]->setEnabled(false); |
---|
244 | } |
---|
245 | mCurrentMode = mode; |
---|
246 | } |
---|
247 | void DeferredShadingSystem::setActive(bool active) |
---|
248 | { |
---|
249 | mActive = active; |
---|
250 | setMode(mCurrentMode); |
---|
251 | } |
---|
252 | void DeferredShadingSystem::createResources(void) |
---|
253 | { |
---|
254 | Ogre::CompositorManager &compMan = Ogre::CompositorManager::getSingleton(); |
---|
255 | // Create 'fat' render target |
---|
256 | unsigned int width = mViewport->getActualWidth(); |
---|
257 | unsigned int height = mViewport->getActualHeight(); |
---|
258 | PixelFormat format = PF_FLOAT16_RGBA; |
---|
259 | //PixelFormat format = PF_SHORT_RGBA; |
---|
260 | |
---|
261 | mTexture0 = TextureManager::getSingleton().createManual("RttTex0", |
---|
262 | ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, |
---|
263 | width, height, 0, format, TU_RENDERTARGET ); |
---|
264 | mTexture1 = TextureManager::getSingleton().createManual("RttTex1", |
---|
265 | ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, |
---|
266 | width, height, 0, format, TU_RENDERTARGET ); |
---|
267 | //assert(mTexture0->getFormat() == format); |
---|
268 | //assert(mTexture1->getFormat() == format); |
---|
269 | rttTex = Ogre::Root::getSingleton().getRenderSystem()->createMultiRenderTarget("MRT"); |
---|
270 | RenderTexture* rt0 = mTexture0->getBuffer()->getRenderTarget(); |
---|
271 | RenderTexture* rt1 = mTexture1->getBuffer()->getRenderTarget(); |
---|
272 | rt0->setAutoUpdated(false); |
---|
273 | rt1->setAutoUpdated(false); |
---|
274 | rttTex->bindSurface(0, rt0); |
---|
275 | rttTex->bindSurface(1, rt1); |
---|
276 | rttTex->setAutoUpdated( false ); |
---|
277 | |
---|
278 | // Setup viewport on 'fat' render target |
---|
279 | Viewport* v = rttTex->addViewport( mCamera ); |
---|
280 | v->setClearEveryFrame( false ); |
---|
281 | v->setOverlaysEnabled( false ); |
---|
282 | // Should disable skies for MRT due it's not designed for that, and |
---|
283 | // will causing NVIDIA refusing write anything to other render targets |
---|
284 | // for some reason. |
---|
285 | v->setSkiesEnabled(false); |
---|
286 | v->setBackgroundColour( ColourValue( 0, 0, 0, 0) ); |
---|
287 | compMan.addCompositor(v, "DeferredShading/Fat"); |
---|
288 | |
---|
289 | // Create lights material generator |
---|
290 | setupMaterial(MaterialManager::getSingleton().getByName("DeferredShading/LightMaterialQuad")); |
---|
291 | setupMaterial(MaterialManager::getSingleton().getByName("DeferredShading/LightMaterial")); |
---|
292 | if(Root::getSingleton().getRenderSystem()->getName()=="OpenGL Rendering Subsystem") |
---|
293 | mLightMaterialGenerator = new LightMaterialGenerator("glsl"); |
---|
294 | else |
---|
295 | mLightMaterialGenerator = new LightMaterialGenerator("hlsl"); |
---|
296 | |
---|
297 | // Create filters |
---|
298 | mInstance[DSM_SINGLEPASS] = compMan.addCompositor(mViewport, "DeferredShading/Single"); |
---|
299 | mInstance[DSM_MULTIPASS] = compMan.addCompositor(mViewport, "DeferredShading/Multi"); |
---|
300 | mInstance[DSM_SHOWNORMALS] = compMan.addCompositor(mViewport, "DeferredShading/ShowNormal"); |
---|
301 | mInstance[DSM_SHOWDSP] = compMan.addCompositor(mViewport, "DeferredShading/ShowDepthSpecular"); |
---|
302 | mInstance[DSM_SHOWCOLOUR] = compMan.addCompositor(mViewport, "DeferredShading/ShowColour"); |
---|
303 | |
---|
304 | // Add material setup callback |
---|
305 | for(int i=0; i<DSM_COUNT; ++i) |
---|
306 | mInstance[i]->addListener(this); |
---|
307 | } |
---|
308 | void DeferredShadingSystem::setupMaterial(const MaterialPtr &mat) |
---|
309 | { |
---|
310 | for(unsigned short i=0; i<mat->getNumTechniques(); ++i) |
---|
311 | { |
---|
312 | Pass *pass = mat->getTechnique(i)->getPass(0); |
---|
313 | pass->getTextureUnitState(0)->setTextureName(mTexture0->getName()); |
---|
314 | pass->getTextureUnitState(1)->setTextureName(mTexture1->getName()); |
---|
315 | } |
---|
316 | } |
---|
317 | |
---|
318 | MLight *DeferredShadingSystem::createMLight() |
---|
319 | { |
---|
320 | MLight *rv = new MLight(mLightMaterialGenerator); |
---|
321 | rv->setVisibilityFlags(PostVisibilityMask); |
---|
322 | mLights.insert(rv); |
---|
323 | |
---|
324 | return rv; |
---|
325 | } |
---|
326 | void DeferredShadingSystem::destroyMLight(MLight *m) |
---|
327 | { |
---|
328 | mLights.erase(m); |
---|
329 | delete m; |
---|
330 | } |
---|
331 | |
---|
332 | void DeferredShadingSystem::update() |
---|
333 | { |
---|
334 | rttTex->update(); |
---|
335 | } |
---|
336 | |
---|
337 | void DeferredShadingSystem::notifyMaterialSetup(uint32 pass_id, MaterialPtr &mat) |
---|
338 | { |
---|
339 | /// Local pass identifier 1 is the render quad pass |
---|
340 | if(pass_id == 1) |
---|
341 | { |
---|
342 | setupMaterial(mat); |
---|
343 | } |
---|
344 | } |
---|