Precalced shadow casters working

This commit is contained in:
lawnjelly 2019-09-26 18:33:40 +01:00 committed by GitHub
parent 47fc1fa319
commit ef9723744b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 358 additions and 45 deletions

View File

@ -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_iTabDepth; n++)\
//sz += "\t";\
//LPRINT(a, sz + b);}
#define LPRINT_RUN(a, b) {String sz;\
for (int n=0; n<Lawn::LDebug::m_iTabDepth; n++)\
sz += "\t";\
LPRINT(a, sz + b);}
#define LPRINT(a, b) if (!Lawn::LDebug::m_bRunning) {\
if (a >= Lawn::LDebug::m_iLoggingLevel)\

View File

@ -34,6 +34,24 @@ Spatial * LSob::GetSpatial() const
}
bool LSob::IsShadowCaster() const
{
Object * pObj = ObjectDB::get_instance(m_ID);
GeometryInstance * pGI = Object::cast_to<GeometryInstance>(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

2
ldob.h
View File

@ -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

View File

@ -71,6 +71,42 @@ String LPortal::FindNameAfter(Node * pNode, String szStart)
//////////////////////////////////////////////////////////
// preprocess
void LPortal::AddLightPlanes(const LLight &light, LVector<Plane> &planes) const
{
const Vector<Vector3> &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<nPoints; n++)
{
pushed_pts[n] = pts[n] + light.m_ptDir;
}
Plane p;
for (int n=1; n<nPoints; n++)
{
p = Plane(pts[n-1], pts[n], pushed_pts[n]);
planes.push_back(p);
}
// first and last
p = Plane(pts[nPoints-1], pts[0], pushed_pts[0]);
planes.push_back(p);
}
// add clipping planes to the vector formed by each portal edge and the camera
void LPortal::AddPlanes(LRoomManager &manager, const Vector3 &ptCam, LVector<Plane> &planes) const
{

View File

@ -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<Plane> &planes) const;
void AddLightPlanes(const LLight &light, LVector<Plane> &planes) const;
// normal determined by winding order
Vector<Vector3> m_ptsWorld;

View File

@ -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; n<last; n++)
{
int sobID = manager.m_ShadowCasters_SOB[n];
// only add to the caster list if not in it already
if (!manager.m_BF_caster_SOBs.GetBit(sobID))
{
LPRINT(2, "\t" + itos(sobID) + ", " + manager.m_SOBs[sobID].GetSpatial()->get_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; n<last_sob; n++)
{
@ -186,7 +207,7 @@ void LRoom::AddShadowCasters(LRoomManager &manager)
manager.m_BF_caster_SOBs.SetBit(n, true);
manager.m_CasterList_SOBs.push_back(n);
}
*/
}
@ -194,19 +215,19 @@ void LRoom::AddShadowCasters(LRoomManager &manager)
// (it might be expensive)
void LRoom::FinalizeVisibility(LRoomManager &manager)
{
int last_sob = m_iFirstSOB + m_iNumSOBs;
for (int n=m_iFirstSOB; n<last_sob; n++)
{
LSob &sob = manager.m_SOBs[n];
Spatial * pS = sob.GetSpatial();
if (!pS)
continue;
// int last_sob = m_iFirstSOB + m_iNumSOBs;
// for (int n=m_iFirstSOB; n<last_sob; n++)
// {
// LSob &sob = manager.m_SOBs[n];
// Spatial * pS = sob.GetSpatial();
// if (!pS)
// continue;
if (manager.m_BF_master_SOBs.GetBit(n))
pS->show();
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; n<m_DOBs.size(); n++)
@ -267,7 +288,7 @@ void LRoom::Room_MakeVisible(bool bVisible)
else
{
// hide room
GetGodotRoom()->hide();
// GetGodotRoom()->hide();
// hide all dobs
for (int n=0; n<m_DOBs.size(); n++)
@ -405,7 +426,6 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
if (bShow)
{
//sob.m_bSOBVisible = true;
// sob is renderable and visible (not shadow only)
manager.m_BF_visible_SOBs.SetBit(n, true);
//manager.m_BF_render_SOBs.SetBit(n, true);

View File

@ -43,7 +43,7 @@ void LRoomConverter::Convert(LRoomManager &manager)
LMAN->m_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; n<LMAN->m_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; n<LMAN->m_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; n<lroom.m_iNumSOBs; n++)
// each global light, and each light affecting this room
for (int n=0; n<LMAN->m_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; n<last_sob; n++)
// {
// //LSob &sob = manager.m_SOBs[n];
// LRoom_AddShadowCaster_SOB(lroom, n);
// }
// just a constant light direction for now
LLight light;
light.m_ptDir = Vector3(1.0f, -1.0f, 0.0f);
light.m_ptDir.normalize();
// LLight light;
// light.m_ptDir = Vector3(1.0f, -1.0f, 0.0f);
// light.m_ptDir.normalize();
// reset the planes pool for each render out from the source room
LMAN->m_Pool.Reset();
@ -411,13 +460,66 @@ void LRoomConverter::LRoom_FindShadowCasters(LRoom &lroom)
LVector<Plane> &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<Plane> &planes)
void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int depth, LRoom &lroom, const LLight &light, const LVector<Plane> &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; n<last_sob; n++)
{
LSob &sob = LMAN->m_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<planes.size(); p++)
{
// float dist = planes[p].distance_to(pt);
// print("\t\t\t\t" + itos(p) + " : dist " + String(Variant(dist)));
float r_min, r_max;
bb.project_range_in_plane(planes[p], r_min, r_max);
// print("\t\t\t\t" + itos(p) + " : r_min " + String(Variant(r_min)) + ", r_max " + String(Variant(r_max)));
if (r_min > 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; n<lroom.m_iNumPortals; n++)
{
@ -425,11 +527,47 @@ void LRoomConverter::LRoom_FindShadowCasters_Recursive(LRoom &lroom, const LLigh
const LPortal &port = LMAN->m_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; l<planes.size(); l++)
{
LPortal::eClipResult res = port.ClipWithPlane(planes[l]);
switch (res)
{
case LPortal::eClipResult::CLIP_OUTSIDE:
overall_res = res;
break;
case LPortal::eClipResult::CLIP_PARTIAL:
overall_res = res;
break;
default: // suppress warning
break;
}
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
break;
}
// this portal is culled
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
{
LPRINT_RUN(2, "\t\tCULLED (outside planes)");
continue;
}
LRoom &linked_room = LMAN->Portal_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);

View File

@ -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<Plane> &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<Plane> &planes);
void LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID);
void TRoom_MakeOppositePortal(const LPortal &port, int iRoomOrig);

View File

@ -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<Light>(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_MasterList_SOBs_prev.size(); n++)
{
int ID = m_MasterList_SOBs_prev[n];
if (m_BF_master_SOBs.GetBit(ID) == 0)
{
LSob &sob = m_SOBs[ID];
sob.Show(false);
}
}
// show all in current master list
for (int n=0; n<m_MasterList_SOBs.size(); n++)
{
int ID = m_MasterList_SOBs[n];
LSob &sob = m_SOBs[ID];
sob.Show(true);
}
}
@ -912,6 +978,8 @@ void LRoomManager::_bind_methods()
{
// main functions
ClassDB::bind_method(D_METHOD("rooms_convert"), &LRoomManager::rooms_convert);
ClassDB::bind_method(D_METHOD("rooms_release"), &LRoomManager::rooms_release);
ClassDB::bind_method(D_METHOD("rooms_set_camera"), &LRoomManager::rooms_set_camera);
ClassDB::bind_method(D_METHOD("rooms_get_room"), &LRoomManager::rooms_get_room);
@ -934,6 +1002,8 @@ void LRoomManager::_bind_methods()
ClassDB::bind_method(D_METHOD("dob_register_hint"), &LRoomManager::dob_register_hint);
ClassDB::bind_method(D_METHOD("dob_teleport_hint"), &LRoomManager::dob_teleport_hint);
ClassDB::bind_method(D_METHOD("dob_get_room_id"), &LRoomManager::dob_get_room_id);
ClassDB::bind_method(D_METHOD("light_register"), &LRoomManager::light_register);
}

View File

@ -54,6 +54,7 @@ class LRoomManager : public Spatial {
// and also objects out of view but casting shadows INTO the view
LVector<int> m_VisibleList_SOBs;
LVector<int> m_CasterList_SOBs;
LVector<int> 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<int> m_MasterList_SOBs_prev;
Lawn::LBitField_Dynamic m_BF_master_SOBs_prev;
LVector<int> m_VisibleRoomList_A;
LVector<int> 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