]> git.lizzy.rs Git - irrlicht.git/commitdiff
Add back LightManager light
authorLizzy Fleckenstein <eliasfleckenstein@web.de>
Thu, 13 Apr 2023 16:07:12 +0000 (18:07 +0200)
committerLizzy Fleckenstein <eliasfleckenstein@web.de>
Thu, 13 Apr 2023 16:07:12 +0000 (18:07 +0200)
include/ILightManager.h [new file with mode: 0644]
include/ISceneManager.h
include/irrlicht.h
source/Irrlicht/CSceneManager.cpp
source/Irrlicht/CSceneManager.h

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