SO3Engine
SO3RenderToTexture.cpp
Go to the documentation of this file.
1
12#include "SO3Renderer/SO3Root.h"
14
15#include <OgreDepthBuffer.h>
16
17namespace SO3
18{
19
20SRenderToTexture::SRenderToTexture() : SNode(0, "", SNode::RENDER_TO_TEXTURE_ID)
21{
22 // Forbiden (private)
23}
24
25SRenderToTexture::SRenderToTexture(SScene* parent, const std::string& rttName, SCamera* povCamera) : SNode(parent, rttName, SNode::RENDER_TO_TEXTURE_ID)
26{
27 //if(!SRoot::getSingleton().GetOgreRenderSystem()->getCapabilities()->hasCapability(Ogre::RSC_???))
28 // OGRE_EXCEPT(Ogre::Exception::ERR_NOT_IMPLEMENTED, "Your graphics card does not support render to texture, so you cannot use this functionnality!", "SRenderToTexture::SRenderToTexture");
29
30 // Store the scheme that we will use to hide objects we dont want on the rtt.
31 material.reset();
32 textureUnitState = 0;
33 size = 256;
34 state = false;
35 autoUpdate = false;
36 needUpdate = false;
37 needTextureUpdate = false;
38 renderingEnable = false;
39 cameraOriginalRatio = 1.0f;
40 materialScheme = Ogre::MSN_SHADERGEN;
41
42 // create the camera used to render to our rtt
43 rttCamera = povCamera->GetOgreCameraPointer();
44
45 // create our dynamic texture
46 _CreateRenderTexture(size);
47
48 // Add frame listener
49 Ogre::Root::getSingleton().addFrameListener(this);
50}
51
53{
54 SetEnable(false);
55
56 // Clear all the compositors
58
59 // disable first
60 DisableRendering();
61
62 // remove frame listener for update on window events if autoUpdate is disable
63 if(!autoUpdate)
64 {
65 // Remove frame listener
66 Ogre::Root::getSingleton().removeFrameListener(this);
67 }
68
69 // Delete the rtt texture.
70 _DeleteRenderTexture();
71}
72
73void SRenderToTexture::SetSize(const unsigned int& newSize)
74{
75 if (size != newSize)
76 {
77 // is new size valid (2^n)?
78 double result = log((double)newSize)/log((double)2.0);
79 double fractpart, intpart;
80 fractpart = modf(result, &intpart);
81 if (fractpart==0)
82 {
83 bool savedState = state;
84
85 // Remove the render target listeners.
86 SetEnable(false);
87
88 _CreateRenderTexture(newSize);
89 size = newSize;
90 SetEnable(savedState);
91 }
92 else
93 {
94 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Render to texture size must be a power of 2 number!", "SRenderToTexture::SetSize");
95 }
96 }
97}
98
100{
101 return size;
102}
103
104void SRenderToTexture::SetMaterial(SMaterial* targetMaterial, const int& targetTechnique, const int& targetPass, const int& targetTextureUnit)
105{
106 if (targetMaterial != 0)
107 {
108 Ogre::MaterialPtr tmpMaterial = targetMaterial->getOgreMaterialPointer();
109 //update generated materials
111
112 Ogre::Pass* tmpPass = tmpMaterial->getTechnique(targetTechnique)->getPass(targetPass);
113
114 bool savedState = state;
115 SetEnable(false);
116 material = tmpMaterial;
117
118 // Check if the targetTextureUnit is inbound
119 int numTextureUnits = tmpPass->getNumTextureUnitStates();
120
121 if ((numTextureUnits>0) && (targetTextureUnit<numTextureUnits))
122 {
123 Ogre::TextureUnitState* tmpTextureUnitState = tmpPass->getTextureUnitState(targetTextureUnit);
124 if((tmpTextureUnitState != 0) && ((textureUnitState == 0) || (textureUnitState != tmpTextureUnitState)))
125 {
126 textureUnitState = tmpTextureUnitState;
127 }
128 }
129 else
130 {
131 textureUnitState = 0;
132 }
133 SetEnable(savedState);
134 }
135}
136
138{
139 if (scheme.empty() || (scheme == "Default") || (scheme == "DefaultScheme"))
140 materialScheme = Ogre::MSN_SHADERGEN;
141 else
142 materialScheme = scheme;
143
144 if (rttTarget != 0)
145 rttTarget->getViewport(0)->setMaterialScheme(materialScheme);
146}
147
148void SRenderToTexture::SetTextureUnit()
149{
150 if (textureUnitState != 0)
151 {
152 oldTexture = textureUnitState->_getTexturePtr();
153 textureUnitState->setTextureName(name + "_texture");
154
155 if (material)
157 }
158}
159
160void SRenderToTexture::ResetTextureUnit()
161{
162 if (textureUnitState != 0)
163 {
164 try
165 {
166 if (!oldTexture)
167 textureUnitState->setBlank();
168 else
169 textureUnitState->setTexture(oldTexture);
170 }
171 catch(Ogre::Exception&)
172 {
173 //not found
174 }
175
176 if (material)
178 }
179 oldTexture.reset();
180}
181
182void SRenderToTexture::SetEnable(const bool& newState)
183{
184 if (rttTexture)
185 {
186 DisableRendering();
187 if ((newState == true) && (state == false))
188 {
189 state = true;
190 SetTextureUnit();
191 needUpdate = true;
192
193 if(autoUpdate)
194 EnableRendering();
195 }
196 else if ((newState == false) && (state == true))
197 {
198 state = false;
199 needUpdate = false;
200 ResetTextureUnit();
201 }
202 }
203}
204
206{
207 return state;
208}
209
210void SRenderToTexture::SetAutoUpdate(const bool& newAutoUpdateValue)
211{
212 if ((newAutoUpdateValue == true) && (autoUpdate == false))
213 {
214 // Remove frame listener
215 Ogre::Root::getSingleton().removeFrameListener(this);
216
217 autoUpdate = true;
218 renderingEnable = false;
219 EnableRendering();
220 }
221 else if ((newAutoUpdateValue == false) && (autoUpdate == true))
222 {
223 autoUpdate = false;
224 DisableRendering();
225
226 // Add frame listener
227 Ogre::Root::getSingleton().addFrameListener(this);
228 }
229}
230
232{
233 return autoUpdate;
234}
235
237{
238 needUpdate = true;
239}
240
241void SRenderToTexture::EnableRendering()
242{
243 if(!renderingEnable)
244 {
245 rttTarget->setAutoUpdated(true);
246 renderingEnable = true;
247 }
248}
249
250void SRenderToTexture::DisableRendering()
251{
252 if(renderingEnable)
253 {
254 rttTarget->setAutoUpdated(false);
255 renderingEnable = false;
256 }
257}
258
259void SRenderToTexture::_CreateRenderTexture(const unsigned int& newSize)
260{
261 _DeleteRenderTexture();
262 try
263 {
264 Ogre::PixelFormat rttformat;
266 // Create a new texture and setup it as a render target.
267 rttTexture = Ogre::TextureManager::getSingleton().createManual(name + "_texture", SO3_INTERNAL_DYNAMIC_READABLE_RESOURCE_GROUP, Ogre::TEX_TYPE_2D, newSize, newSize, 0, rttformat, Ogre::TU_RENDERTARGET, this);
268 rttTarget = rttTexture->getBuffer(0)->getRenderTarget();
269 rttTarget->setAutoUpdated(false);
270 rttTarget->addListener(this);
271#if defined (RPI)
272 rttTarget->setDepthBufferPool(Ogre::DepthBuffer::POOL_NO_DEPTH);
273#endif
274
275 // addViewport function modify the camera ratio, so store it and reapply it once this function is finished.
276 cameraOriginalRatio = rttCamera->getAspectRatio();
277 Ogre::Viewport* viewport = rttTarget->addViewport(rttCamera);
278 rttCamera->setAspectRatio(cameraOriginalRatio);
279
280 viewport->setMaterialScheme(materialScheme);
281
282 UpdateCompositorViewport(viewport);
283
284 // Disable overlays rendering on rtt
285 viewport->setOverlaysEnabled(false);
286 }
287 catch (Ogre::Exception &e)
288 {
289 Ogre::LogManager::getSingleton().getDefaultLog()->logMessage("An exception has occurred: "+ e.getDescription());
290 rttTexture.reset();
291 }
292}
293
294void SRenderToTexture::_DeleteRenderTexture()
295{
296 if (rttTexture)
297 {
298 // IMPORTANT! Do not forget to detach the target, otherwise, the texture will not be deleted cause TexturePtr ref count still will be > 1
299 rttTarget->removeListener(this);
300 rttTarget->removeAllViewports();
301 Ogre::Root::getSingleton().detachRenderTarget(rttTarget);
302 rttTarget = 0;
303
304 Ogre::TextureManager::getSingleton().remove(rttTexture->getHandle());
305 rttTexture.reset();
306 }
307}
308
309bool SRenderToTexture::frameStarted(const Ogre::FrameEvent& evt)
310{
311 if(state && needUpdate)
312 {
313 if (needTextureUpdate)
314 {
315 _CreateRenderTexture(size);
316 needTextureUpdate = false;
317 }
318 EnableRendering();
319 }
320
321 return true;
322}
323
324bool SRenderToTexture::frameEnded(const Ogre::FrameEvent& evt)
325{
326 if (state && needUpdate)
327 {
328 DisableRendering();
329 needUpdate = false;
330 }
331 return true;
332}
333
334void SRenderToTexture::loadResource(Ogre::Resource* resource)
335{
336 //needTextureUpdate = true;
337 /*Ogre::Texture* tex = static_cast<Ogre::Texture*>(resource);
338 tex->setTextureType(Ogre::TEX_TYPE_CUBE_MAP);
339 tex->setWidth(size);
340 tex->setHeight(size);
341 tex->setFormat(Ogre::PF_R8G8B8);
342 tex->setUsage(Ogre::TU_RENDERTARGET|Ogre::TU_AUTOMIPMAP);
343 tex->createInternalResources();*/
344}
345
346void SRenderToTexture::windowResized(Ogre::RenderWindow* rw)
347{
348 Update();
349}
350
351void SRenderToTexture::preViewportUpdate(const Ogre::RenderTargetViewportEvent& evt)
352{
353 if(evt.source != 0)
354 {
355 Ogre::Camera* targetCamera = evt.source->getCamera();
356 if(targetCamera != 0)
357 {
358 // Store old ratio
359 cameraOriginalRatio = targetCamera->getAspectRatio();
360
361 // Target texture is squared, so ratio is 1.
362 targetCamera->setAspectRatio(1.0f);
363 }
364 }
365}
366
367void SRenderToTexture::postViewportUpdate(const Ogre::RenderTargetViewportEvent& evt)
368{
369 if(evt.source != 0)
370 {
371 Ogre::Camera* targetCamera = evt.source->getCamera();
372 if(targetCamera != 0)
373 {
374 // Reset old ratio
375 targetCamera->setAspectRatio(cameraOriginalRatio);
376 }
377 }
378}
379
380SCompositor* SRenderToTexture::GetCompositor(const std::string& compositorName)
381{
382 SCompositorMap::iterator iCompositorSearched = compList.find(compositorName);
383 if (iCompositorSearched != compList.end())
384 return iCompositorSearched->second;
385 else
386 return 0;
387}
388
390{
391 return compList;
392}
393
394SCompositor* SRenderToTexture::CreateCompositor(const std::string& newCompositorName, const std::string& newSchemeName)
395{
396 SCompositor* newCompositor = GetCompositor(newCompositorName);
397 if (newCompositor == 0)
398 {
399 newCompositor = new SCompositor(newCompositorName, newSchemeName);
400 if (rttTarget != 0)
401 newCompositor->SetViewport(rttTarget->getViewport(0));
402
403 AddCompositor(newCompositor);
404 }
405 return newCompositor;
406}
407
408void SRenderToTexture::DeleteCompositor(const std::string& existingCompositorName)
409{
410 DeleteCompositor(GetCompositor(existingCompositorName));
411}
412
414{
415 RemoveCompositor(existingCompositor);
416 SO3_SAFE_DELETE(existingCompositor);
417}
418
420{
421 // clear all compositors.
422 SCompositorMap::iterator iCompositorList = compList.begin();
423
424 // Do not use DeleteCompositor function here, cause this one use "RemoveCompositor" function, and it breaks the iterator!
425 while (iCompositorList != compList.end())
426 {
427 SO3_SAFE_DELETE(iCompositorList->second);
428 iCompositorList++;
429 }
430 compList.clear();
431}
432
434{
435 string name = existingCompositor->GetName();
436 SCompositorMap::iterator iCompositorSearched = compList.find(name);
437 if (iCompositorSearched == compList.end())
438 {
439 compList.insert(SCompositorMap::value_type(name, existingCompositor));
440 }
441 else
442 {
443 // Compositor already exist in the handled compositors list.
444 OGRE_EXCEPT(Ogre::Exception::ERR_DUPLICATE_ITEM, "Can not add Compositor named \"" + name + "\", an element with the same name already exist!", "SRenderToTexture::AddCompositor");
445 }
446}
447
449{
450 RemoveCompositor(existingCompositor->GetName());
451}
452
453void SRenderToTexture::RemoveCompositor(const std::string& compositorName)
454{
455 SCompositorMap::iterator iCompositorSearched = compList.find(compositorName);
456 if (iCompositorSearched != compList.end())
457 {
458 compList.erase(iCompositorSearched);
459 }
460 else
461 {
462 // Compositor not found in the handled Compositor list
463 OGRE_EXCEPT(Ogre::Exception::ERR_ITEM_NOT_FOUND, "Can not remove Compositor named \"" + compositorName + "\", element not found!", "SRenderToTexture::RemoveCompositor");
464 }
465}
466
467void SRenderToTexture::UpdateCompositorViewport(Ogre::Viewport* vp)
468{
469 SCompositorMap::iterator iCompositorList = compList.begin();
470 while (iCompositorList != compList.end())
471 {
472 iCompositorList->second->SetViewport(vp);
473 iCompositorList++;
474 }
475}
476
477}
Ogre::Camera * GetOgreCameraPointer()
Definition SO3Camera.cpp:50
void SetViewport(Ogre::Viewport *vp)
std::string GetName() const
std::string name
Definition SO3DataScol.h:44
Ogre::MaterialPtr getOgreMaterialPointer()
SCompositor * CreateCompositor(const std::string &newCompositorName, const std::string &newSchemeName)
void SetEnable(const bool &newState)
virtual void windowResized(Ogre::RenderWindow *rw)
void RemoveCompositor(SCompositor *existingCompositor)
virtual void postViewportUpdate(const Ogre::RenderTargetViewportEvent &evt)
void SetAutoUpdate(const bool &newAutoUpdateValue)
virtual void loadResource(Ogre::Resource *resource)
void AddCompositor(SCompositor *existingCompositor)
void SetMaterial(SMaterial *targetMaterial, const int &targetTechnique, const int &targetPass, const int &targetTextureUnit)
void SetSize(const unsigned int &newSize)
virtual bool frameEnded(const Ogre::FrameEvent &evt)
const SCompositorMap & GetCompositorList() const
void DeleteCompositor(SCompositor *existingCompositor)
void SetMaterialScheme(std::string scheme)
virtual void preViewportUpdate(const Ogre::RenderTargetViewportEvent &evt)
SCompositor * GetCompositor(const std::string &compositorName)
virtual bool frameStarted(const Ogre::FrameEvent &evt)
bool GetRttPixelFormat(Ogre::PixelFormat &format, bool alpha=false, bool floattex=false)
Definition SO3Root.cpp:650
void RemoveGeneratedMaterial(Ogre::Material *mat)
Definition SO3Root.cpp:2343
static SRoot & getSingleton()
Definition SO3Root.cpp:116
static SRoot * getSingletonPtr()
Definition SO3Root.cpp:111
std::unordered_map< std::string, SCompositor * > SCompositorMap