Culling via layers

Changed culling to via the Godot layers mechanism, as a hack to allow shadows.
This commit is contained in:
lawnjelly 2019-09-24 15:37:38 +01:00 committed by GitHub
parent 6795a2e05d
commit 9e7b392651
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 237 additions and 55 deletions

View File

@ -34,11 +34,26 @@ Spatial * LSob::GetSpatial() const
}
VisualInstance * LSob::GetVI() const
{
Object * pObj = ObjectDB::get_instance(m_ID);
VisualInstance * pVI = Object::cast_to<VisualInstance>(pObj);
return pVI;
}
Spatial * LDob::GetSpatial() const
{
Object * pObj = ObjectDB::get_instance(m_ID);
Object * pObj = ObjectDB::get_instance(m_ID_Spatial);
Spatial * pSpat = Object::cast_to<Spatial>(pObj);
return pSpat;
}
VisualInstance * LDob::GetVI() const
{
Object * pObj = ObjectDB::get_instance(m_ID_VI);
VisualInstance * pVI = Object::cast_to<VisualInstance>(pObj);
return pVI;
}

5
ldob.h
View File

@ -34,6 +34,7 @@ class LSob
{
public:
Spatial * GetSpatial() const;
VisualInstance * GetVI() const;
ObjectID m_ID; // godot object
AABB m_aabb; // world space
@ -45,8 +46,10 @@ class LDob
{
public:
Spatial * GetSpatial() const;
VisualInstance * GetVI() const;
ObjectID m_ID;
ObjectID m_ID_Spatial;
ObjectID m_ID_VI;
bool m_bVisible;
float m_fRadius;
};

177
lroom.cpp
View File

@ -32,6 +32,7 @@ LRoom::LRoom() {
m_uiFrameTouched = 0;
m_iFirstPortal = 0;
m_iNumPortals = 0;
m_bVisible = true;
}
@ -63,7 +64,7 @@ unsigned int LRoom::DOB_Find(Node * pDOB) const
for (int n=0; n<m_DOBs.size(); n++)
{
if (m_DOBs[n].m_ID == id)
if (m_DOBs[n].m_ID_Spatial == id)
{
return n;
}
@ -119,6 +120,49 @@ LRoom * LRoom::DOB_Update(LRoomManager &manager, Spatial * pDOB)
return 0;
}
// instead of directly showing and hiding objects we now set their layer,
// and the camera will hide them with a cull mask. This is so that
// objects can still be rendered outside immediate view for casting shadows.
// All objects in view (that are set to cast shadows) should cast shadows, so the actual
// shown objects are a superset of the softshown.
void LRoom::SoftShow(VisualInstance * pVI, bool bShow) const
{
// hijack this layer number
uint32_t mask = pVI->get_layer_mask();
uint32_t orig_mask = mask;
const int SOFT_SHOW_MASK = 1 << SOFT_SHOW_BIT;
const int SOFT_HIDE_MASK = 1 << SOFT_HIDE_BIT;
if (bShow)
{
// set
mask |= SOFT_SHOW_MASK;
// clear
mask &= ~(1 | SOFT_HIDE_MASK);
}
else
{
// set
mask |= SOFT_HIDE_MASK;
// clear
mask &= ~(1 | SOFT_SHOW_MASK);
}
// noop? don't touch the visual server if no change to mask
if (mask == orig_mask)
return;
pVI->set_layer_mask(mask);
// pVI->set_layer_mask_bit(0, false);
// pVI->set_layer_mask_bit(SOFT_HIDE_BIT, bShow == false);
// pVI->set_layer_mask_bit(SOFT_SHOW_BIT, bShow);
}
// hide all the objects not hit on this frame .. instead of calling godot hide without need
// (it might be expensive)
void LRoom::FinalizeVisibility(LRoomManager &manager)
@ -128,14 +172,15 @@ void LRoom::FinalizeVisibility(LRoomManager &manager)
for (int n=0; n<m_SOBs.size(); n++)
{
const LSob &sob = m_SOBs[n];
Spatial * pS = sob.GetSpatial();
VisualInstance * pVI = sob.GetVI();
if (pS)
if (pVI)
{
if (sob.m_bVisible)
pS->show();
else
pS->hide();
SoftShow(pVI, sob.m_bVisible);
// if (sob.m_bVisible)
// pVI->show();
// else
// pVI->hide();
}
}
@ -144,57 +189,99 @@ void LRoom::FinalizeVisibility(LRoomManager &manager)
const LDob &dob = m_DOBs[n];
// don't cull the main camera
if (dob.m_ID == manager.m_ID_camera)
if (dob.m_ID_Spatial == manager.m_ID_camera)
continue;
Spatial * pS = dob.GetSpatial();
if (pS)
// Spatial * pSpat = dob.GetSpatial();
// if (pSpat)
// {
// // all should be showing .. this is mostly a no op
// pSpat->show();
// }
VisualInstance * pVI = dob.GetVI();
if (pVI)
{
if (dob.m_bVisible)
{
//print("LRoom::FinalizeVisibility making visible dob " + pS->get_name());
pS->show();
}
else
pS->hide();
SoftShow(pVI, dob.m_bVisible);
// if (dob.m_bVisible)
// {
// //print("LRoom::FinalizeVisibility making visible dob " + pS->get_name());
// pS->show();
// }
// else
// pS->hide();
}
}
}
// hide godot room and all linked dobs
void LRoom::Hide_All()
// allows us to show / hide all dobs as the room visibility changes
void LRoom::Room_MakeVisible(bool bVisible)
{
GetGodotRoom()->hide();
// noop
if (bVisible == m_bVisible)
return;
for (int n=0; n<m_DOBs.size(); n++)
m_bVisible = bVisible;
if (m_bVisible)
{
LDob &dob = m_DOBs[n];
Spatial * pS = dob.GetSpatial();
if (pS)
pS->hide();
// show room
GetGodotRoom()->show();
// show all dobs
for (int n=0; n<m_DOBs.size(); n++)
{
LDob &dob = m_DOBs[n];
Spatial * pS = dob.GetSpatial();
if (pS)
pS->show();
}
}
else
{
// hide room
GetGodotRoom()->hide();
// hide all dobs
for (int n=0; n<m_DOBs.size(); n++)
{
LDob &dob = m_DOBs[n];
Spatial * p = dob.GetSpatial();
if (p)
p->hide();
}
}
}
// hide godot room and all linked dobs
//void LRoom::Hide_All()
//{
// GetGodotRoom()->hide();
// for (int n=0; n<m_DOBs.size(); n++)
// {
// LDob &dob = m_DOBs[n];
// Spatial * p = dob.GetSpatial();
// if (p)
// p->hide();
// }
//}
// show godot room and all linked dobs and all sobs
void LRoom::Show_All()
void LRoom::Debug_ShowAll()
{
GetGodotRoom()->show();
Room_MakeVisible(true);
for (int n=0; n<m_SOBs.size(); n++)
{
LSob &sob = m_SOBs[n];
Spatial * pS = sob.GetSpatial();
if (pS)
pS->show();
}
// NYI .. change layers to all be visible
// for (int n=0; n<m_SOBs.size(); n++)
// {
// LSob &sob = m_SOBs[n];
// Spatial * pS = sob.GetSpatial();
// if (pS)
// pS->show();
// }
for (int n=0; n<m_DOBs.size(); n++)
{
LDob &dob = m_DOBs[n];
Spatial * pS = dob.GetSpatial();
if (pS)
pS->show();
}
}
@ -203,6 +290,11 @@ void LRoom::FirstTouch(LRoomManager &manager)
// set the frame counter
m_uiFrameTouched = manager.m_uiFrameCounter;
// show this room and add to visible list of rooms
Room_MakeVisible(true);
manager.m_BF_visible_rooms.SetBit(m_RoomID, true);
// keep track of which rooms are shown this frame
manager.m_pCurr_VisibleRoomList->push_back(m_RoomID);
@ -238,9 +330,6 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons
if (m_uiFrameTouched < manager.m_uiFrameCounter)
FirstTouch(manager);
// show this room and add to visible list of rooms
GetGodotRoom()->show();
manager.m_BF_visible_rooms.SetBit(m_RoomID, true);
#define LPORTAL_CULL_STATIC
#ifdef LPORTAL_CULL_STATIC

24
lroom.h
View File

@ -54,6 +54,8 @@ class LRoom
private:
public:
static const int SOFT_SHOW_BIT = 18;
static const int SOFT_HIDE_BIT = 19;
// static objects
LVector<LSob> m_SOBs;
@ -81,7 +83,6 @@ public:
// when registering DOBs and teleporting them
LBound m_Bound;
String m_szName;
////////////////////////////////////////////////////////////
@ -91,13 +92,16 @@ public:
void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &planes, int portalID_from = -1);
void FirstTouch(LRoomManager &manager);
// allows us to show / hide all dobs as the room visibility changes
void Room_MakeVisible(bool bVisible);
// hide godot room and all linked dobs
// USED AT RUNTIME
void Hide_All();
// void Hide_All();
// show godot room and all linked dobs and all sobs
// ONLY USED IN DEBUGGING to turn LPortal on and off
void Show_All();
void Debug_ShowAll();
// hide all the objects not hit on this frame .. instead of calling godot hide without need
// (it might be expensive)
@ -115,6 +119,18 @@ public:
// retained purely for debugging visualization
Geometry::MeshData m_Bound_MeshData;
bool IsVisible() const {return m_bVisible;}
private:
// instead of directly showing and hiding objects we now set their layer,
// and the camera will hide them with a cull mask. This is so that
// objects can still be rendered outside immediate view for casting shadows.
void SoftShow(VisualInstance * pVI, bool bShow) const;
// whether lportal thinks this room is currently visible
// this allows us to show / hide dobs as they cross room boundaries
bool m_bVisible;
};

View File

@ -25,6 +25,7 @@
#include "lroom_converter.h"
#include "ldebug.h"
#include "scene/3d/immediate_geometry.h"
#include "lroom.h"
LRoomManager::LRoomManager()
{
@ -224,6 +225,24 @@ void LRoomManager::CreateDebug()
}
ObjectID LRoomManager::DobRegister_FindVIRecursive(Node * pNode) const
{
// is the node a VI?
VisualInstance * pVI = Object::cast_to<VisualInstance>(pNode);
if (pVI)
return pVI->get_instance_id();
// try the children
for (int n=0; n<pNode->get_child_count(); n++)
{
ObjectID res = DobRegister_FindVIRecursive(pNode->get_child(n));
if (res)
return res;
}
return 0;
}
bool LRoomManager::DobRegister(Spatial * pDOB, float radius, int iRoom)
{
//LPRINT(3, "register_dob " + pDOB->get_name());
@ -238,14 +257,22 @@ bool LRoomManager::DobRegister(Spatial * pDOB, float radius, int iRoom)
if (!pRoom)
return false;
// The dob is derived from spatial, but the visual instances may be children of the dob
// rather than the node itself .. we need visual instances for layer culling for shadows
LDob dob;
dob.m_ID = pDOB->get_instance_id();
dob.m_ID_Spatial = pDOB->get_instance_id();
dob.m_fRadius = radius;
dob.m_ID_VI = DobRegister_FindVIRecursive(pDOB);
pRoom->DOB_Add(dob);
// save the room ID on the dob metadata
Obj_SetRoomNum(pDOB, iRoom);
// change visibility
DobChangeVisibility(pDOB, 0, pRoom);
return true;
}
@ -305,7 +332,8 @@ int LRoomManager::dob_update(Node * pDOB)
// remove from old room
pRoom->DOB_Remove(dob_id);
// change visibility
DobChangeVisibility(pSpat, pRoom, pNewRoom);
// save the room ID on the dob metadata
Obj_SetRoomNum(pSpat, iRoomNum);
@ -383,6 +411,9 @@ bool LRoomManager::DobTeleport(Spatial * pDOB, int iNewRoomID)
// save the room ID on the dob metadata
Obj_SetRoomNum(pDOB, iNewRoomID);
// change visibility
DobChangeVisibility(pDOB, pOldRoom, pNewRoom);
return true;
}
@ -420,6 +451,29 @@ bool LRoomManager::dob_unregister(Node * pDOB)
return false;
}
void LRoomManager::DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew)
{
bool bVisOld = false;
bool bVisNew = false;
if (pOld)
bVisOld = pOld->IsVisible();
if (pNew)
bVisNew = pNew->IsVisible();
if (bVisOld != bVisNew)
{
if (!bVisOld)
pDOB->show();
else
pDOB->hide();
}
}
int LRoomManager::dob_get_room_id(Node * pDOB)
{
return Obj_GetRoomNum(pDOB);
@ -486,7 +540,7 @@ void LRoomManager::rooms_set_active(bool bActive)
for (int n=0; n<m_Rooms.size(); n++)
{
LRoom &lroom = m_Rooms[n];
lroom.Show_All();
lroom.Debug_ShowAll();
}
@ -521,6 +575,9 @@ void LRoomManager::rooms_set_camera(Node * pCam)
m_ID_camera = pCam->get_instance_id();
// new .. select the cull layer
pCamera->set_cull_mask_bit(LRoom::SOFT_HIDE_BIT, false);
// use this temporarily to force debug
// rooms_log_frame();
}
@ -637,7 +694,7 @@ void LRoomManager::FrameUpdate()
{
if (!m_BF_visible_rooms.GetBit(n))
{
m_Rooms[n].Hide_All();
m_Rooms[n].Room_MakeVisible(false);
}
}
}
@ -649,7 +706,7 @@ void LRoomManager::FrameUpdate()
int r = (*m_pPrev_VisibleRoomList)[n];
if (!m_BF_visible_rooms.GetBit(r))
m_Rooms[r].Hide_All();
m_Rooms[r].Room_MakeVisible(false);
}
}

View File

@ -125,8 +125,10 @@ protected:
private:
// internal
bool DobRegister(Spatial * pDOB, float radius, int iRoom);
ObjectID DobRegister_FindVIRecursive(Node * pNode) const;
bool DobTeleport(Spatial * pDOB, int iNewRoomID);
void CreateDebug();
void DobChangeVisibility(Spatial * pDOB, const LRoom * pOld, const LRoom * pNew);
// helper funcs