From 437b6619f6d3838b38aae0b6468ce7b4f7b2d891 Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Thu, 13 Apr 2023 18:07:12 +0200 Subject: [PATCH] Add back LightManager --- include/ILightManager.h | 66 +++++++++++ include/ISceneManager.h | 6 + include/irrlicht.h | 1 + source/Irrlicht/CSceneManager.cpp | 187 ++++++++++++++++++++++++++---- source/Irrlicht/CSceneManager.h | 8 ++ 5 files changed, 244 insertions(+), 24 deletions(-) create mode 100644 include/ILightManager.h 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 & 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; irender(); 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 SortedLights; - SortedLights.set_used(LightList.size()); - for (s32 light = (s32)LightList.size() - 1; light >= 0; --light) - SortedLights[light].setNodeAndDistanceFromPosition(LightList[light], camWorldPos); + core::array 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; irender(); + if (LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRenderPass); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } 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; irender(); + if (LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRenderPass); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } 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; irender(); + if (LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRenderPass); + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } 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; irender(); + if (LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRenderPass); + + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } 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; irender(); + if (LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRenderPass); + + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } 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; irender(); + if (LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRenderPass); + + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } 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 -- 2.44.0