aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ILightManager.h66
-rw-r--r--include/ISceneManager.h6
-rw-r--r--include/irrlicht.h1
-rw-r--r--source/Irrlicht/CSceneManager.cpp187
-rw-r--r--source/Irrlicht/CSceneManager.h8
5 files changed, 244 insertions, 24 deletions
diff --git a/include/ILightManager.h b/include/ILightManager.h
new file mode 100644
index 0000000..b156e70
--- /dev/null
+++ b/include/ILightManager.h
@@ -0,0 +1,66 @@
+// Written by Colin MacDonald - all rights assigned to Nikolaus Gebhardt
+// Copyright (C) 2008-2012 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#ifndef IRR_I_LIGHT_MANAGER_H_INCLUDED
+#define IRR_I_LIGHT_MANAGER_H_INCLUDED
+
+#include "IReferenceCounted.h"
+#include "irrArray.h"
+#include "ISceneManager.h" // for E_SCENE_NODE_RENDER_PASS, could probably move that to own header?
+
+namespace irr
+{
+namespace scene
+{
+ class ISceneNode;
+
+ //! ILightManager provides an interface for user applications to manipulate the list of lights in the scene.
+ /** The light list can be trimmed or re-ordered before device/ hardware
+ lights are created, and/or individual lights can be switched on and off
+ before or after each scene node is rendered. It is assumed that the
+ ILightManager implementation will store any data that it wishes to
+ retain, i.e. the ISceneManager to which it is assigned, the lightList,
+ the current render pass, and the current scene node.
+
+ It can also be useful for shaders as it allows finding out the currently rendered SceneNode.
+ */
+ class ILightManager : public IReferenceCounted
+ {
+ public:
+ //! Called after the scene's light list has been built, but before rendering has begun.
+ /** As actual device/hardware lights are not created until the
+ ESNRP_LIGHT render pass, this provides an opportunity for the
+ light manager to trim or re-order the light list, before any
+ device/hardware lights have actually been created.
+ \param lightList: the Scene Manager's light list, which
+ the light manager may modify. This reference will remain valid
+ until OnPostRender().
+ */
+ virtual void OnPreRender(core::array<ISceneNode*> & lightList) {};
+
+ //! Called after the last scene node is rendered.
+ /** After this call returns, the lightList passed to OnPreRender() becomes invalid. */
+ virtual void OnPostRender(void) {};
+
+ //! Called before a render pass begins
+ /** \param renderPass: the render pass that's about to begin */
+ virtual void OnRenderPassPreRender(E_SCENE_NODE_RENDER_PASS renderPass) {};
+
+ //! Called after the render pass specified in OnRenderPassPreRender() ends
+ /** \param[in] renderPass: the render pass that has finished */
+ virtual void OnRenderPassPostRender(E_SCENE_NODE_RENDER_PASS renderPass) {};
+
+ //! Called before the given scene node is rendered
+ /** \param[in] node: the scene node that's about to be rendered */
+ virtual void OnNodePreRender(ISceneNode* node) {};
+
+ //! Called after the the node specified in OnNodePreRender() has been rendered
+ /** \param[in] node: the scene node that has just been rendered */
+ virtual void OnNodePostRender(ISceneNode* node) {};
+ };
+} // end namespace scene
+} // end namespace irr
+
+#endif
diff --git a/include/ISceneManager.h b/include/ISceneManager.h
index 4cd31e2..d4f0a8f 100644
--- a/include/ISceneManager.h
+++ b/include/ISceneManager.h
@@ -102,6 +102,7 @@ namespace scene
class IBillboardSceneNode;
class ICameraSceneNode;
class IDummyTransformationSceneNode;
+ class ILightManager;
class ILightSceneNode;
class IMesh;
class IMeshBuffer;
@@ -650,6 +651,11 @@ namespace scene
//! Get ambient color of the scene
virtual const video::SColorf& getAmbientLight() const = 0;
+ //! Register a custom callbacks manager which gets callbacks during scene rendering.
+ /** \param[in] lightManager: the new callbacks manager. You may pass 0 to remove the
+ current callbacks manager and restore the default behavior. */
+ virtual void setLightManager(ILightManager* lightManager) = 0;
+
//! Get current render pass.
virtual E_SCENE_NODE_RENDER_PASS getCurrentRenderPass() const =0;
diff --git a/include/irrlicht.h b/include/irrlicht.h
index 37b961d..cfefcf7 100644
--- a/include/irrlicht.h
+++ b/include/irrlicht.h
@@ -112,6 +112,7 @@
#include "IVertexBuffer.h"
#include "IVideoDriver.h"
#include "IWriteFile.h"
+#include "ILightManager.h"
#include "Keycodes.h"
#include "line2d.h"
#include "line3d.h"
diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp
index 6882a5b..de80609 100644
--- a/source/Irrlicht/CSceneManager.cpp
+++ b/source/Irrlicht/CSceneManager.cpp
@@ -46,7 +46,7 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver,
: ISceneNode(0, 0), Driver(driver),
CursorControl(cursorControl),
ActiveCamera(0), ShadowColor(150,0,0,0), AmbientLight(0,0,0,0), Parameters(0),
- MeshCache(cache), CurrentRenderPass(ESNRP_NONE)
+ MeshCache(cache), CurrentRenderPass(ESNRP_NONE), LightManager(0)
{
#ifdef _DEBUG
ISceneManager::setDebugName("CSceneManager ISceneManager");
@@ -117,6 +117,9 @@ CSceneManager::~CSceneManager()
if (Parameters)
Parameters->drop();
+ if (LightManager)
+ LightManager->drop();
+
// remove all nodes before dropping the driver
// as render targets may be destroyed twice
@@ -585,15 +588,24 @@ void CSceneManager::drawAll()
// let all nodes register themselves
OnRegisterSceneNode();
+ if (LightManager)
+ LightManager->OnPreRender(LightList);
+
//render camera scenes
{
CurrentRenderPass = ESNRP_CAMERA;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
+ if (LightManager)
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+
for (i=0; i<CameraList.size(); ++i)
CameraList[i]->render();
CameraList.set_used(0);
+
+ if (LightManager)
+ LightManager->OnRenderPassPostRender(CurrentRenderPass);
}
//render lights scenes
@@ -601,20 +613,28 @@ void CSceneManager::drawAll()
CurrentRenderPass = ESNRP_LIGHT;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
- core::vector3df camWorldPos(0, 0, 0);
- if (ActiveCamera)
- camWorldPos = ActiveCamera->getAbsolutePosition();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+ }
+ else
+ {
+ // Sort the lights by distance from the camera
+ core::vector3df camWorldPos(0, 0, 0);
+ if (ActiveCamera)
+ camWorldPos = ActiveCamera->getAbsolutePosition();
- core::array<DistanceNodeEntry> SortedLights;
- SortedLights.set_used(LightList.size());
- for (s32 light = (s32)LightList.size() - 1; light >= 0; --light)
- SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos);
+ core::array<DistanceNodeEntry> SortedLights;
+ SortedLights.set_used(LightList.size());
+ for (s32 light = (s32)LightList.size() - 1; light >= 0; --light)
+ SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos);
- SortedLights.set_sorted(false);
- SortedLights.sort();
+ SortedLights.set_sorted(false);
+ SortedLights.sort();
- for(s32 light = (s32)LightList.size() - 1; light >= 0; --light)
- LightList[light] = SortedLights[light].Node;
+ for(s32 light = (s32)LightList.size() - 1; light >= 0; --light)
+ LightList[light] = SortedLights[light].Node;
+ }
Driver->deleteAllDynamicLights();
@@ -622,8 +642,14 @@ void CSceneManager::drawAll()
u32 maxLights = LightList.size();
+ if (!LightManager)
+ maxLights = core::min_ ( Driver->getMaximalDynamicLightAmount(), maxLights);
+
for (i=0; i< maxLights; ++i)
LightList[i]->render();
+
+ if (LightManager)
+ LightManager->OnRenderPassPostRender(CurrentRenderPass);
}
// render skyboxes
@@ -631,10 +657,27 @@ void CSceneManager::drawAll()
CurrentRenderPass = ESNRP_SKY_BOX;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
- for (i=0; i<SkyBoxList.size(); ++i)
- SkyBoxList[i]->render();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+ for (i=0; i<SkyBoxList.size(); ++i)
+ {
+ ISceneNode* node = SkyBoxList[i];
+ LightManager->OnNodePreRender(node);
+ node->render();
+ LightManager->OnNodePostRender(node);
+ }
+ }
+ else
+ {
+ for (i=0; i<SkyBoxList.size(); ++i)
+ SkyBoxList[i]->render();
+ }
SkyBoxList.set_used(0);
+
+ if (LightManager)
+ LightManager->OnRenderPassPostRender(CurrentRenderPass);
}
// render default objects
@@ -644,10 +687,27 @@ void CSceneManager::drawAll()
SolidNodeList.sort(); // sort by textures
- for (i=0; i<SolidNodeList.size(); ++i)
- SolidNodeList[i].Node->render();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+ for (i=0; i<SolidNodeList.size(); ++i)
+ {
+ ISceneNode* node = SolidNodeList[i].Node;
+ LightManager->OnNodePreRender(node);
+ node->render();
+ LightManager->OnNodePostRender(node);
+ }
+ }
+ else
+ {
+ for (i=0; i<SolidNodeList.size(); ++i)
+ SolidNodeList[i].Node->render();
+ }
SolidNodeList.set_used(0);
+
+ if (LightManager)
+ LightManager->OnRenderPassPostRender(CurrentRenderPass);
}
// render shadows
@@ -655,14 +715,31 @@ void CSceneManager::drawAll()
CurrentRenderPass = ESNRP_SHADOW;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
- for (i=0; i<ShadowNodeList.size(); ++i)
- ShadowNodeList[i]->render();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+ for (i=0; i<ShadowNodeList.size(); ++i)
+ {
+ ISceneNode* node = ShadowNodeList[i];
+ LightManager->OnNodePreRender(node);
+ node->render();
+ LightManager->OnNodePostRender(node);
+ }
+ }
+ else
+ {
+ for (i=0; i<ShadowNodeList.size(); ++i)
+ ShadowNodeList[i]->render();
+ }
if (!ShadowNodeList.empty())
Driver->drawStencilShadow(true,ShadowColor, ShadowColor,
ShadowColor, ShadowColor);
ShadowNodeList.set_used(0);
+
+ if (LightManager)
+ LightManager->OnRenderPassPostRender(CurrentRenderPass);
}
// render transparent objects.
@@ -671,10 +748,28 @@ void CSceneManager::drawAll()
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
TransparentNodeList.sort(); // sort by distance from camera
- for (i=0; i<TransparentNodeList.size(); ++i)
- TransparentNodeList[i].Node->render();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+
+ for (i=0; i<TransparentNodeList.size(); ++i)
+ {
+ ISceneNode* node = TransparentNodeList[i].Node;
+ LightManager->OnNodePreRender(node);
+ node->render();
+ LightManager->OnNodePostRender(node);
+ }
+ }
+ else
+ {
+ for (i=0; i<TransparentNodeList.size(); ++i)
+ TransparentNodeList[i].Node->render();
+ }
TransparentNodeList.set_used(0);
+
+ if (LightManager)
+ LightManager->OnRenderPassPostRender(CurrentRenderPass);
}
// render transparent effect objects.
@@ -684,8 +779,23 @@ void CSceneManager::drawAll()
TransparentEffectNodeList.sort(); // sort by distance from camera
- for (i=0; i<TransparentEffectNodeList.size(); ++i)
- TransparentEffectNodeList[i].Node->render();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+
+ for (i=0; i<TransparentEffectNodeList.size(); ++i)
+ {
+ ISceneNode* node = TransparentEffectNodeList[i].Node;
+ LightManager->OnNodePreRender(node);
+ node->render();
+ LightManager->OnNodePostRender(node);
+ }
+ }
+ else
+ {
+ for (i=0; i<TransparentEffectNodeList.size(); ++i)
+ TransparentEffectNodeList[i].Node->render();
+ }
TransparentEffectNodeList.set_used(0);
}
@@ -695,18 +805,47 @@ void CSceneManager::drawAll()
CurrentRenderPass = ESNRP_GUI;
Driver->getOverrideMaterial().Enabled = ((Driver->getOverrideMaterial().EnablePasses & CurrentRenderPass) != 0);
- for (i=0; i<GuiNodeList.size(); ++i)
- GuiNodeList[i]->render();
+ if (LightManager)
+ {
+ LightManager->OnRenderPassPreRender(CurrentRenderPass);
+
+ for (i=0; i<GuiNodeList.size(); ++i)
+ {
+ ISceneNode* node = GuiNodeList[i];
+ LightManager->OnNodePreRender(node);
+ node->render();
+ LightManager->OnNodePostRender(node);
+ }
+ }
+ else
+ {
+ for (i=0; i<GuiNodeList.size(); ++i)
+ GuiNodeList[i]->render();
+ }
GuiNodeList.set_used(0);
}
+
+ if (LightManager)
+ LightManager->OnPostRender();
+
LightList.set_used(0);
clearDeletionList();
CurrentRenderPass = ESNRP_NONE;
}
+void CSceneManager::setLightManager(ILightManager* lightManager)
+{
+ if (lightManager)
+ lightManager->grab();
+ if (LightManager)
+ LightManager->drop();
+
+ LightManager = lightManager;
+}
+
//! Sets the color of stencil buffers shadows drawn by the scene manager.
void CSceneManager::setShadowColor(video::SColor color)
diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h
index fded7f8..d2fa156 100644
--- a/source/Irrlicht/CSceneManager.h
+++ b/source/Irrlicht/CSceneManager.h
@@ -12,6 +12,7 @@
#include "irrArray.h"
#include "IMeshLoader.h"
#include "CAttributes.h"
+#include "ILightManager.h"
namespace irr
{
@@ -198,6 +199,9 @@ namespace scene
//! Returns ambient color of the scene
const video::SColorf& getAmbientLight() const override;
+ //! Register a custom callbacks manager which gets callbacks during scene rendering.
+ virtual void setLightManager(ILightManager* lightManager) override;
+
//! Get current render time.
E_SCENE_NODE_RENDER_PASS getCurrentRenderPass() const override { return CurrentRenderPass; }
@@ -325,6 +329,10 @@ namespace scene
IMeshCache* MeshCache;
E_SCENE_NODE_RENDER_PASS CurrentRenderPass;
+
+ //! An optional callbacks manager to allow the user app finer control
+ //! over the scene lighting and rendering.
+ ILightManager* LightManager;
};
} // end namespace video