mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-11 05:01:09 +00:00
- removed the remaining dependencies of the shadowmap code on game data.
Everything is handled with callbacks now.
This commit is contained in:
parent
ba0b42465d
commit
c30165db0d
5 changed files with 71 additions and 76 deletions
|
@ -20,8 +20,7 @@
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "r_state.h"
|
#include <algorithm>
|
||||||
#include "g_levellocals.h"
|
|
||||||
#include "hw_aabbtree.h"
|
#include "hw_aabbtree.h"
|
||||||
|
|
||||||
namespace hwrenderer
|
namespace hwrenderer
|
||||||
|
@ -82,7 +81,7 @@ double LevelAABBTree::RayTest(const DVector3 &ray_start, const DVector3 &ray_end
|
||||||
else if (nodes[node_index].line_index != -1) // isLeaf(node_index)
|
else if (nodes[node_index].line_index != -1) // isLeaf(node_index)
|
||||||
{
|
{
|
||||||
// We reached a leaf node. Do a ray/line intersection test to see if we hit the line.
|
// We reached a leaf node. Do a ray/line intersection test to see if we hit the line.
|
||||||
hit_fraction = MIN(IntersectRayLine(ray_start, ray_end, nodes[node_index].line_index, raydelta, rayd, raydist2), hit_fraction);
|
hit_fraction = std::min(IntersectRayLine(ray_start, ray_end, nodes[node_index].line_index, raydelta, rayd, raydist2), hit_fraction);
|
||||||
stack_pos--;
|
stack_pos--;
|
||||||
}
|
}
|
||||||
else if (stack_pos == 32)
|
else if (stack_pos == 32)
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "actorinlines.h"
|
#include "actorinlines.h"
|
||||||
#include "a_dynlight.h"
|
#include "a_dynlight.h"
|
||||||
#include "hw_dynlightdata.h"
|
#include "hw_dynlightdata.h"
|
||||||
|
#include"hw_cvars.h"
|
||||||
#include "hwrenderer/scene/hw_drawstructs.h"
|
#include "hwrenderer/scene/hw_drawstructs.h"
|
||||||
|
|
||||||
// If we want to share the array to avoid constant allocations it needs to be thread local unless it'd be littered with expensive synchronization.
|
// If we want to share the array to avoid constant allocations it needs to be thread local unless it'd be littered with expensive synchronization.
|
||||||
|
@ -105,10 +106,15 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float shadowIndex = light->mShadowmapIndex + 1.0f;
|
float shadowIndex;
|
||||||
|
if (gl_light_shadowmap)
|
||||||
|
{
|
||||||
|
shadowIndex = light->mShadowmapIndex + 1.0f;
|
||||||
|
|
||||||
// Store attenuate flag in the sign bit of the float.
|
// Store attenuate flag in the sign bit of the float.
|
||||||
if (light->IsAttenuated() || forceAttenuate) shadowIndex = -shadowIndex;
|
if (light->IsAttenuated() || forceAttenuate) shadowIndex = -shadowIndex;
|
||||||
|
}
|
||||||
|
else shadowIndex = 1025.f;
|
||||||
|
|
||||||
float lightType = 0.0f;
|
float lightType = 0.0f;
|
||||||
float spotInnerAngle = 0.0f;
|
float spotInnerAngle = 0.0f;
|
||||||
|
|
|
@ -25,10 +25,6 @@
|
||||||
#include "hw_dynlightdata.h"
|
#include "hw_dynlightdata.h"
|
||||||
#include "hwrenderer/data/buffers.h"
|
#include "hwrenderer/data/buffers.h"
|
||||||
#include "hwrenderer/data/shaderuniforms.h"
|
#include "hwrenderer/data/shaderuniforms.h"
|
||||||
#include "stats.h"
|
|
||||||
#include "g_levellocals.h"
|
|
||||||
#include "v_video.h"
|
|
||||||
#include "a_dynlight.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -63,6 +59,8 @@ cycle_t IShadowMap::UpdateCycles;
|
||||||
int IShadowMap::LightsProcessed;
|
int IShadowMap::LightsProcessed;
|
||||||
int IShadowMap::LightsShadowmapped;
|
int IShadowMap::LightsShadowmapped;
|
||||||
|
|
||||||
|
CVAR(Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
ADD_STAT(shadowmap)
|
ADD_STAT(shadowmap)
|
||||||
{
|
{
|
||||||
FString out;
|
FString out;
|
||||||
|
@ -85,68 +83,14 @@ CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR (Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|
||||||
{
|
|
||||||
if (!self) for (auto Level : AllLevels())
|
|
||||||
{
|
|
||||||
auto light = Level->lights;
|
|
||||||
while (light)
|
|
||||||
{
|
|
||||||
light->mShadowmapIndex = 1024;
|
|
||||||
light = light->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos)
|
bool IShadowMap::ShadowTest(const DVector3 &lpos, const DVector3 &pos)
|
||||||
{
|
{
|
||||||
if (mAABBTree)
|
if (mAABBTree && gl_light_shadowmap)
|
||||||
return mAABBTree->RayTest(lpos, pos) >= 1.0f;
|
return mAABBTree->RayTest(lpos, pos) >= 1.0f;
|
||||||
else
|
else
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IShadowMap::IsEnabled() const
|
|
||||||
{
|
|
||||||
return gl_light_shadowmap && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IShadowMap::CollectLights()
|
|
||||||
{
|
|
||||||
if (mLights.Size() != 1024 * 4) mLights.Resize(1024 * 4);
|
|
||||||
int lightindex = 0;
|
|
||||||
auto Level = &level;
|
|
||||||
|
|
||||||
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
|
|
||||||
for (auto light = Level->lights; light; light = light->next)
|
|
||||||
{
|
|
||||||
LightsProcessed++;
|
|
||||||
if (light->shadowmapped && light->IsActive() && lightindex < 1024 * 4)
|
|
||||||
{
|
|
||||||
LightsShadowmapped++;
|
|
||||||
|
|
||||||
light->mShadowmapIndex = lightindex >> 2;
|
|
||||||
|
|
||||||
mLights[lightindex] = (float)light->X();
|
|
||||||
mLights[lightindex+1] = (float)light->Y();
|
|
||||||
mLights[lightindex+2] = (float)light->Z();
|
|
||||||
mLights[lightindex+3] = light->GetRadius();
|
|
||||||
lightindex += 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
light->mShadowmapIndex = 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; lightindex < 1024 * 4; lightindex++)
|
|
||||||
{
|
|
||||||
mLights[lightindex] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool IShadowMap::PerformUpdate()
|
bool IShadowMap::PerformUpdate()
|
||||||
{
|
{
|
||||||
UpdateCycles.Reset();
|
UpdateCycles.Reset();
|
||||||
|
@ -154,7 +98,7 @@ bool IShadowMap::PerformUpdate()
|
||||||
LightsProcessed = 0;
|
LightsProcessed = 0;
|
||||||
LightsShadowmapped = 0;
|
LightsShadowmapped = 0;
|
||||||
|
|
||||||
if (IsEnabled())
|
if (gl_light_shadowmap && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && CollectLights != nullptr)
|
||||||
{
|
{
|
||||||
UpdateCycles.Clock();
|
UpdateCycles.Clock();
|
||||||
UploadAABBTree();
|
UploadAABBTree();
|
||||||
|
@ -166,6 +110,7 @@ bool IShadowMap::PerformUpdate()
|
||||||
|
|
||||||
void IShadowMap::UploadLights()
|
void IShadowMap::UploadLights()
|
||||||
{
|
{
|
||||||
|
mLights.Resize(1024 * 4);
|
||||||
CollectLights();
|
CollectLights();
|
||||||
|
|
||||||
if (mLightList == nullptr)
|
if (mLightList == nullptr)
|
||||||
|
@ -207,3 +152,4 @@ IShadowMap::~IShadowMap()
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,7 @@
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
struct FDynamicLight;
|
|
||||||
struct level_info_t;
|
|
||||||
class IDataBuffer;
|
class IDataBuffer;
|
||||||
struct FLevelLocals;
|
|
||||||
|
|
||||||
class IShadowMap
|
class IShadowMap
|
||||||
{
|
{
|
||||||
|
@ -21,9 +18,6 @@ public:
|
||||||
// Test if a world position is in shadow relative to the specified light and returns false if it is
|
// Test if a world position is in shadow relative to the specified light and returns false if it is
|
||||||
bool ShadowTest(const DVector3 &lpos, const DVector3 &pos);
|
bool ShadowTest(const DVector3 &lpos, const DVector3 &pos);
|
||||||
|
|
||||||
// Returns true if gl_light_shadowmap is enabled and supported by the hardware
|
|
||||||
bool IsEnabled() const;
|
|
||||||
|
|
||||||
static cycle_t UpdateCycles;
|
static cycle_t UpdateCycles;
|
||||||
static int LightsProcessed;
|
static int LightsProcessed;
|
||||||
static int LightsShadowmapped;
|
static int LightsShadowmapped;
|
||||||
|
@ -46,13 +40,23 @@ public:
|
||||||
mNewTree = true;
|
mNewTree = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
void SetCollectLights(std::function<void()> func)
|
||||||
void CollectLights();
|
{
|
||||||
|
CollectLights = std::move(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLight(int index, float x, float y, float z, float r)
|
||||||
|
{
|
||||||
|
index *= 4;
|
||||||
|
mLights[index] = x;
|
||||||
|
mLights[index + 1] = y;
|
||||||
|
mLights[index + 2] = z;
|
||||||
|
mLights[index + 3] = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
// Upload the AABB-tree to the GPU
|
// Upload the AABB-tree to the GPU
|
||||||
void UploadAABBTree();
|
void UploadAABBTree();
|
||||||
|
|
||||||
// Upload light list to the GPU
|
|
||||||
void UploadLights();
|
void UploadLights();
|
||||||
|
|
||||||
// Working buffer for creating the list of lights. Stored here to avoid allocating memory each frame
|
// Working buffer for creating the list of lights. Stored here to avoid allocating memory each frame
|
||||||
|
@ -74,4 +78,6 @@ public:
|
||||||
IDataBuffer *mNodesBuffer = nullptr;
|
IDataBuffer *mNodesBuffer = nullptr;
|
||||||
IDataBuffer *mLinesBuffer = nullptr;
|
IDataBuffer *mLinesBuffer = nullptr;
|
||||||
|
|
||||||
|
std::function<void()> CollectLights = nullptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,6 +59,41 @@ void CleanSWDrawer()
|
||||||
swdrawer = nullptr;
|
swdrawer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "g_levellocals.h"
|
||||||
|
#include "a_dynlight.h"
|
||||||
|
|
||||||
|
|
||||||
|
void CollectLights(FLevelLocals* Level)
|
||||||
|
{
|
||||||
|
IShadowMap* sm = &screen->mShadowMap;
|
||||||
|
int lightindex = 0;
|
||||||
|
|
||||||
|
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
|
||||||
|
for (auto light = Level->lights; light; light = light->next)
|
||||||
|
{
|
||||||
|
IShadowMap::LightsProcessed++;
|
||||||
|
if (light->shadowmapped && light->IsActive() && lightindex < 1024 * 4)
|
||||||
|
{
|
||||||
|
IShadowMap::LightsShadowmapped++;
|
||||||
|
|
||||||
|
light->mShadowmapIndex = lightindex;
|
||||||
|
sm->SetLight(lightindex, (float)light->X(), (float)light->Y(), (float)light->Z(), light->GetRadius());
|
||||||
|
lightindex++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
light->mShadowmapIndex = 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; lightindex < 1024; lightindex++)
|
||||||
|
{
|
||||||
|
sm->SetLight(lightindex, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Renders one viewpoint in a scene
|
// Renders one viewpoint in a scene
|
||||||
|
@ -75,6 +110,9 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou
|
||||||
{
|
{
|
||||||
screen->SetAABBTree(camera->Level->aabbTree);
|
screen->SetAABBTree(camera->Level->aabbTree);
|
||||||
screen->UpdateShadowMap();
|
screen->UpdateShadowMap();
|
||||||
|
screen->mShadowMap.SetCollectLights([=] {
|
||||||
|
CollectLights(camera->Level);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the attenuation flag of all light defaults for each viewpoint.
|
// Update the attenuation flag of all light defaults for each viewpoint.
|
||||||
|
|
Loading…
Reference in a new issue