From ef9723744ba5bfdb3c90911f864bca3a5a4926d0 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Thu, 26 Sep 2019 18:33:40 +0100 Subject: [PATCH] Precalced shadow casters working --- ldebug.h | 10 +-- ldob.cpp | 30 ++++++++ ldob.h | 2 + lportal.cpp | 36 +++++++++ lportal.h | 3 + lroom.cpp | 54 +++++++++----- lroom_converter.cpp | 177 +++++++++++++++++++++++++++++++++++++++----- lroom_converter.h | 7 +- lroom_manager.cpp | 72 +++++++++++++++++- lroom_manager.h | 12 ++- 10 files changed, 358 insertions(+), 45 deletions(-) diff --git a/ldebug.h b/ldebug.h index 8f5cd09..393f6a4 100644 --- a/ldebug.h +++ b/ldebug.h @@ -1,11 +1,11 @@ #pragma once -#define LPRINT_RUN(a, b) ; +//#define LPRINT_RUN(a, b) ; -//#define LPRINT_RUN(a, b) {String sz;\ -//for (int n=0; n= Lawn::LDebug::m_iLoggingLevel)\ diff --git a/ldob.cpp b/ldob.cpp index ee5e83e..f6fd7ae 100644 --- a/ldob.cpp +++ b/ldob.cpp @@ -34,6 +34,24 @@ Spatial * LSob::GetSpatial() const } +bool LSob::IsShadowCaster() const +{ + Object * pObj = ObjectDB::get_instance(m_ID); + GeometryInstance * pGI = Object::cast_to(pObj); + + if (pGI) + { + if (pGI->get_cast_shadows_setting() == GeometryInstance::SHADOW_CASTING_SETTING_OFF) + return false; + + return true; + } + + // not sure yet, maybe this should be true, depends what the non geometry objects are + return false; +} + + VisualInstance * LSob::GetVI() const { Object * pObj = ObjectDB::get_instance(m_ID); @@ -41,6 +59,18 @@ VisualInstance * LSob::GetVI() const return pVI; } +void LSob::Show(bool bShow) +{ + Spatial * pS = GetSpatial(); + if (!pS) + return; + + if (bShow) + pS->show(); + else + pS->hide(); +} + Spatial * LDob::GetSpatial() const diff --git a/ldob.h b/ldob.h index 443a27a..f60af90 100644 --- a/ldob.h +++ b/ldob.h @@ -35,6 +35,8 @@ class LSob public: Spatial * GetSpatial() const; VisualInstance * GetVI() const; + void Show(bool bShow); + bool IsShadowCaster() const; ObjectID m_ID; // godot object AABB m_aabb; // world space diff --git a/lportal.cpp b/lportal.cpp index f9f458d..d393a97 100644 --- a/lportal.cpp +++ b/lportal.cpp @@ -71,6 +71,42 @@ String LPortal::FindNameAfter(Node * pNode, String szStart) ////////////////////////////////////////////////////////// +// preprocess +void LPortal::AddLightPlanes(const LLight &light, LVector &planes) const +{ + const Vector &pts = m_ptsWorld; + + // assuming ortho light + int nPoints = pts.size(); + ERR_FAIL_COND(nPoints < 3); + + const int max_points = 32; + Vector3 pushed_pts[max_points]; + + if (nPoints > max_points) + nPoints = max_points; + + // transform pushed points + for (int n=0; n &planes) const { diff --git a/lportal.h b/lportal.h index 29a9154..3e60e15 100644 --- a/lportal.h +++ b/lportal.h @@ -38,6 +38,8 @@ class LLight { public: Vector3 m_ptDir; + Vector3 m_ptPos; + ObjectID m_GodotID; }; @@ -60,6 +62,7 @@ public: LPortal::eClipResult ClipWithPlane(const Plane &p) const; void AddPlanes(LRoomManager &manager, const Vector3 &ptCam, LVector &planes) const; + void AddLightPlanes(const LLight &light, LVector &planes) const; // normal determined by winding order Vector m_ptsWorld; diff --git a/lroom.cpp b/lroom.cpp index 805bb5d..cbb2860 100644 --- a/lroom.cpp +++ b/lroom.cpp @@ -172,8 +172,29 @@ void LRoom::SoftShow(VisualInstance * pVI, bool bShow) // naive version, adds all the non visible objects in visible rooms as shadow casters void LRoom::AddShadowCasters(LRoomManager &manager) { -// return; + LPRINT(2, "ADDSHADOWCASTERS room " + get_name() + ", " + itos(m_iNumShadowCasters_SOB) + " shadow casters"); + // new!! use precalced list of shadow casters + int last = m_iFirstShadowCaster_SOB + m_iNumShadowCasters_SOB; + for (int n=m_iFirstShadowCaster_SOB; nget_name()); + manager.m_BF_caster_SOBs.SetBit(sobID, true); + manager.m_CasterList_SOBs.push_back(sobID); + } + else + { + LPRINT(2, "\t" + itos(sobID) + ", ALREADY CASTER " + manager.m_SOBs[sobID].GetSpatial()->get_name()); + } + } + + +/* int last_sob = m_iFirstSOB + m_iNumSOBs; for (int n=m_iFirstSOB; nshow(); - else - pS->hide(); - } +// if (manager.m_BF_master_SOBs.GetBit(n)) +// pS->show(); +// else +// pS->hide(); +// } //print_line("FinalizeVisibility room " + get_name() + " NumSOBs " + itos(m_SOBs.size()) + ", NumDOBs " + itos(m_DOBs.size())); @@ -253,7 +274,7 @@ void LRoom::Room_MakeVisible(bool bVisible) if (m_bVisible) { // show room - GetGodotRoom()->show(); +// GetGodotRoom()->show(); // show all dobs for (int n=0; nhide(); +// GetGodotRoom()->hide(); // hide all dobs for (int n=0; nm_SOBs.clear(); LMAN->m_ShadowCasters_SOB.clear(); - LMAN->m_Lights.clear(); + int num_global_lights = LMAN->m_Lights.size(); // make sure bitfield is right size for number of rooms LMAN->m_BF_visible_rooms.Create(count); @@ -59,7 +59,6 @@ void LRoomConverter::Convert(LRoomManager &manager) Convert_Rooms(); Convert_Portals(); Convert_Bounds(); - Convert_ShadowCasters(); // make sure manager bitfields are the correct size for number of objects int num_sobs = LMAN->m_SOBs.size(); @@ -67,12 +66,19 @@ void LRoomConverter::Convert(LRoomManager &manager) LMAN->m_BF_caster_SOBs.Create(num_sobs); LMAN->m_BF_visible_SOBs.Create(num_sobs); LMAN->m_BF_master_SOBs.Create(num_sobs); + LMAN->m_BF_master_SOBs_prev.Create(num_sobs); + // must be done after the bitfields + Convert_ShadowCasters(); + + // hide all in preparation for first frame + Convert_HideAll(); // temp rooms no longer needed m_TempRooms.clear(true); - + // clear out the local room lights, leave only global lights + LMAN->m_Lights.resize(num_global_lights); Lawn::LDebug::m_bRunning = true; } @@ -293,12 +299,23 @@ bool LRoomConverter::Convert_Bound(LRoom &lroom, MeshInstance * pMI) return false; } +// hide all in preparation for first frame +void LRoomConverter::Convert_HideAll() +{ + for (int n=0; nm_SOBs.size(); n++) + { + LSob &sob = LMAN->m_SOBs[n]; + sob.Show(false); + } +} + void LRoomConverter::Convert_ShadowCasters() { - LPRINT(5,"Convert_ShadowCasters"); + LPRINT(5,"Convert_ShadowCasters ... numlights " + itos (LMAN->m_Lights.size())); for (int n=0; nm_Rooms.size(); n++) { + LPRINT(2,"\tRoom " + itos(n)); LRoom &lroom = LMAN->m_Rooms[n]; LRoom_FindShadowCasters(lroom); } @@ -386,19 +403,51 @@ int LRoomConverter::CountRooms() // find all objects that cast shadows onto the objects in this room void LRoomConverter::LRoom_FindShadowCasters(LRoom &lroom) { - return; - - // first add all objects in this room as casters - for (int n=0; nm_Lights.size(); n++) { - - + LRoom_FindShadowCasters_FromLight(lroom, LMAN->m_Lights[n]); } + + return; +} + +void LRoomConverter::LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID) +{ + // we will reuse the rendering bitflags for shadow casters for this ... to check for double entries (fnaa fnaa) + if (LMAN->m_BF_caster_SOBs.GetBit(sobID)) + return; + + LMAN->m_BF_caster_SOBs.SetBit(sobID, true); + + // first? + if (!lroom.m_iNumShadowCasters_SOB) + lroom.m_iFirstShadowCaster_SOB = LMAN->m_ShadowCasters_SOB.size(); + + LMAN->m_ShadowCasters_SOB.push_back(sobID); + lroom.m_iNumShadowCasters_SOB++; +} + + +void LRoomConverter::LRoom_FindShadowCasters_FromLight(LRoom &lroom, const LLight &light) +{ + // blank this each time as it is used to create the list of casters + LMAN->m_BF_caster_SOBs.Blank(); + + // first add all objects in this room as casters +// int last_sob = lroom.m_iFirstSOB + lroom.m_iNumSOBs; +// for (int n=lroom.m_iFirstSOB; nm_Pool.Reset(); @@ -411,13 +460,66 @@ void LRoomConverter::LRoom_FindShadowCasters(LRoom &lroom) LVector &planes = LMAN->m_Pool.Get(pool_member); planes.clear(); - LRoom_FindShadowCasters_Recursive(lroom, light, planes); - + Lawn::LDebug::m_iTabDepth = 0; + LRoom_FindShadowCasters_Recursive(lroom, 0, lroom, light, planes); } -void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &lroom, const LLight &light, const LVector &planes) + +void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int depth, LRoom &lroom, const LLight &light, const LVector &planes) { + // prevent too much depth + if (depth > 8) + { + LPRINT_RUN(2, "\t\t\tLRoom_FindShadowCasters_Recursive DEPTH LIMIT REACHED"); +// WARN_PRINT_ONCE("LPortal Depth Limit reached (seeing through > 8 portals)"); + return; + } + + Lawn::LDebug::m_iTabDepth = depth; + LPRINT_RUN(2, "ROOM " + lroom.get_name()); + + + // every object in this room is added that is within the planes + int last_sob = lroom.m_iFirstSOB + lroom.m_iNumSOBs; + for (int n=lroom.m_iFirstSOB; nm_SOBs[n]; + + // not a shadow caster? don't add to the list + if (!sob.IsShadowCaster()) + continue; + + bool bShow = true; + const AABB &bb = sob.m_aabb; + +// print("\t\t\tculling object " + pObj->get_name()); + + for (int p=0; p 0.0f) + { + bShow = false; + break; + } + } + + if (bShow) + { + LPRINT_RUN(2, "\tcaster " + itos(n) + ", " + sob.GetSpatial()->get_name()); + LRoom_AddShadowCaster_SOB(source_lroom, n); + } + } + // look through every portal out for (int n=0; nm_Portals[portalID]; + LPRINT_RUN(2, "\tPORTAL " + itos (n) + " (" + itos(portalID) + ") " + port.get_name() + " normal " + port.m_Plane.normal); // cull with light direction float dot = port.m_Plane.normal.dot(light.m_ptDir); if (dot <= 0.0f) + { + LPRINT_RUN(2, "\t\tCULLED (wrong direction)"); continue; + } + + // is it culled by the planes? + LPortal::eClipResult overall_res = LPortal::eClipResult::CLIP_INSIDE; + + // cull portal with planes + for (int l=0; lPortal_GetLinkedRoom(port); @@ -445,12 +583,11 @@ void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &lroom, const LLigh new_planes.copy_from(planes); // add the planes for the portal -// port.AddPlanes(manager, cam.m_ptPos, new_planes); + port.AddLightPlanes(light, new_planes); - - LRoom_FindShadowCasters_Recursive(linked_room, light, new_planes); + LRoom_FindShadowCasters_Recursive(source_lroom, depth + 1, linked_room, light, new_planes); // for debugging need to reset tab depth - //Lawn::LDebug::m_iTabDepth = depth; + Lawn::LDebug::m_iTabDepth = depth; // we no longer need these planes LMAN->m_Pool.Free(uiPoolMem); diff --git a/lroom_converter.h b/lroom_converter.h index 2a7f1ea..ff4fdf3 100644 --- a/lroom_converter.h +++ b/lroom_converter.h @@ -94,6 +94,7 @@ private: void Convert_Bounds(); bool Convert_Bound(LRoom &lroom, MeshInstance * pMI); void Convert_ShadowCasters(); + void Convert_HideAll(); void LRoom_DetectPortalMeshes(LRoom &lroom, LTempRoom &troom); @@ -102,8 +103,12 @@ private: void LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, MeshInstance * pMeshInstance, String szLinkRoom); LPortal * LRoom_RequestNewPortal(LRoom &lroom); void LRoom_PushBackSOB(LRoom &lroom, const LSob &sob); + + // shadows void LRoom_FindShadowCasters(LRoom &lroom); - void LRoom_FindShadowCasters_Recursive(LRoom &lroom, const LLight &light, const LVector &planes); + void LRoom_FindShadowCasters_FromLight(LRoom &lroom, const LLight &light); + void LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int depth, LRoom &lroom, const LLight &light, const LVector &planes); + void LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID); void TRoom_MakeOppositePortal(const LPortal &port, int iRoomOrig); diff --git a/lroom_manager.cpp b/lroom_manager.cpp index 9454012..12b92d1 100644 --- a/lroom_manager.cpp +++ b/lroom_manager.cpp @@ -25,6 +25,7 @@ #include "lroom_converter.h" #include "ldebug.h" #include "scene/3d/immediate_geometry.h" +#include "scene/3d/light.h" #include "lroom.h" LRoomManager::LRoomManager() @@ -451,6 +452,39 @@ bool LRoomManager::dob_unregister(Node * pDOB) return false; } + +bool LRoomManager::light_register(Node * pLightNode) +{ + if (!pLightNode) + { + WARN_PRINT_ONCE("light_register : pLightNode is NULL"); + return false; + } + + LPRINT(3, "light_register " + pLightNode->get_name()); + + Light * pLight = Object::cast_to(pLightNode); + if (!pLight) + { + WARN_PRINT_ONCE("light_register : Node is not a light"); + return false; + } + + // create new light + LLight l; + l.m_GodotID = pLight->get_instance_id(); + + // direction + Transform tr = pLight->get_global_transform(); + l.m_ptPos = tr.origin; + l.m_ptDir = tr.basis.get_axis(2); // or possibly get_axis .. z is what we want + + m_Lights.push_back(l); + + return true; +} + + void LRoomManager::DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew) { bool bVisOld = false; @@ -589,6 +623,12 @@ void LRoomManager::rooms_convert() conv.Convert(*this); } +// free memory for current set of rooms, prepare for converting a new game level +void LRoomManager::rooms_release() +{ + m_Lights.clear(); +} + // debugging emulate view frustum void LRoomManager::FrameUpdate_FrustumOnly() @@ -603,8 +643,15 @@ void LRoomManager::FrameUpdate_Prepare() // clear the visible room list to write to each frame m_pCurr_VisibleRoomList->clear(); + // keep previous + m_BF_master_SOBs_prev.CopyFrom(m_BF_master_SOBs); + + // note this can be done more efficiently with swapping pointer + m_MasterList_SOBs_prev.copy_from(m_MasterList_SOBs); + m_VisibleList_SOBs.clear(); m_CasterList_SOBs.clear(); + m_MasterList_SOBs.clear(); m_BF_caster_SOBs.Blank(); m_BF_visible_SOBs.Blank(); @@ -807,6 +854,7 @@ void LRoomManager::FrameUpdate_FinalizeVisibility_SoftShow() LRoom::SoftShow(pVI, bVisible); } } + } @@ -822,6 +870,24 @@ void LRoomManager::FrameUpdate_FinalizeVisibility_WithinRooms() m_Rooms[r].FinalizeVisibility(*this); } + // NEW shows and hides dobs according to the difference between the current and previous master list + for (int n=0; n m_VisibleList_SOBs; LVector m_CasterList_SOBs; + LVector m_MasterList_SOBs; @@ -61,6 +62,10 @@ class LRoomManager : public Spatial { Lawn::LBitField_Dynamic m_BF_caster_SOBs; Lawn::LBitField_Dynamic m_BF_master_SOBs; + // previous frame + LVector m_MasterList_SOBs_prev; + Lawn::LBitField_Dynamic m_BF_master_SOBs_prev; + LVector m_VisibleRoomList_A; LVector m_VisibleRoomList_B; @@ -159,6 +164,9 @@ public: // convert empties and meshes to rooms and portals void rooms_convert(); + // free memory for current set of rooms, prepare for converting a new game level + void rooms_release(); + // choose which camera you want to use to determine visibility. // normally this will be your main camera, but you can choose another for debugging void rooms_set_camera(Node * pCam); @@ -200,7 +208,9 @@ public: // helper func, not needed usually as dob_update returns the room int dob_get_room_id(Node * pDOB); - + // LIGHTS + // global lights that will apply to all rooms + bool light_register(Node * pLightNode); }; #endif