mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-25 21:41:03 +00:00
store shadow map index in the light actor instead of a separate TMap
This frees another file of a direct renderer dependency and generally also should be faster
This commit is contained in:
parent
4a3f7e8dd5
commit
f57c804a5a
4 changed files with 25 additions and 31 deletions
|
@ -229,5 +229,7 @@ public:
|
||||||
LightFlags lightflags;
|
LightFlags lightflags;
|
||||||
DAngle SpotInnerAngle = 10.0;
|
DAngle SpotInnerAngle = 10.0;
|
||||||
DAngle SpotOuterAngle = 25.0;
|
DAngle SpotOuterAngle = 25.0;
|
||||||
|
|
||||||
|
int mShadowmapIndex = 1024;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,6 @@
|
||||||
CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR (Bool, gl_lights_checkside, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR (Bool, gl_light_sprites, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR (Bool, gl_light_particles, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR (Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
|
||||||
|
|
||||||
CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option.
|
CVAR(Int, gl_attenuate, -1, 0); // This is mainly a debug option.
|
||||||
|
|
||||||
|
@ -117,10 +116,10 @@ void gl_AddLightToList(int group, ADynamicLight * light, FDynLightData &ldata)
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store attenuate flag in the sign bit of the float.
|
float shadowIndex = light->mShadowmapIndex + 1.0f;
|
||||||
float shadowIndex = GLRenderer->mShadowMap.ShadowMapIndex(light) + 1.0f;
|
|
||||||
bool attenuate;
|
bool attenuate;
|
||||||
|
|
||||||
|
// Store attenuate flag in the sign bit of the float.
|
||||||
if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE);
|
if (gl_attenuate == -1) attenuate = !!(light->lightflags & LF_ATTENUATE);
|
||||||
else attenuate = !!gl_attenuate;
|
else attenuate = !!gl_attenuate;
|
||||||
|
|
||||||
|
|
|
@ -42,12 +42,7 @@
|
||||||
the fragment shader (main.fp) needs to sample from row 20. That is, the V texture coordinate needs
|
the fragment shader (main.fp) needs to sample from row 20. That is, the V texture coordinate needs
|
||||||
to be 20.5/1024.
|
to be 20.5/1024.
|
||||||
|
|
||||||
mLightToShadowmap is a hash map storing which line each ADynamicLight is assigned to. The public
|
The texel row for each light is split into four parts. One for each direction, like a cube texture,
|
||||||
ShadowMapIndex function allows the main rendering to find the index and upload that along with the
|
|
||||||
normal light data. From there, the main.fp shader can sample from the shadow map texture, which
|
|
||||||
is currently always bound to texture unit 16.
|
|
||||||
|
|
||||||
The texel row for each light is split into four parts. One for each direction, like a cube texture,
|
|
||||||
but then only in 2D where this reduces itself to a square. When main.fp samples from the shadow map
|
but then only in 2D where this reduces itself to a square. When main.fp samples from the shadow map
|
||||||
it first decides in which direction the fragment is (relative to the light), like cubemap sampling does
|
it first decides in which direction the fragment is (relative to the light), like cubemap sampling does
|
||||||
for 3D, but once again just for the 2D case.
|
for 3D, but once again just for the 2D case.
|
||||||
|
@ -97,6 +92,20 @@ CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR (Bool, gl_light_shadowmap, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
if (!self)
|
||||||
|
{
|
||||||
|
// Unset any residual shadow map indices in the light actors.
|
||||||
|
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||||
|
while (auto light = it.Next())
|
||||||
|
{
|
||||||
|
light->mShadowmapIndex = 1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FShadowMap::Update()
|
void FShadowMap::Update()
|
||||||
{
|
{
|
||||||
UpdateCycles.Reset();
|
UpdateCycles.Reset();
|
||||||
|
@ -152,42 +161,32 @@ bool FShadowMap::IsEnabled() const
|
||||||
return gl_light_shadowmap && !!(gl.flags & RFL_SHADER_STORAGE_BUFFER);
|
return gl_light_shadowmap && !!(gl.flags & RFL_SHADER_STORAGE_BUFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FShadowMap::ShadowMapIndex(ADynamicLight *light)
|
|
||||||
{
|
|
||||||
if (IsEnabled())
|
|
||||||
{
|
|
||||||
auto val = mLightToShadowmap.CheckKey(light);
|
|
||||||
if (val != nullptr) return *val;
|
|
||||||
}
|
|
||||||
return 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FShadowMap::UploadLights()
|
void FShadowMap::UploadLights()
|
||||||
{
|
{
|
||||||
if (mLights.Size() != 1024 * 4) mLights.Resize(1024 * 4);
|
if (mLights.Size() != 1024 * 4) mLights.Resize(1024 * 4);
|
||||||
int lightindex = 0;
|
int lightindex = 0;
|
||||||
mLightToShadowmap.Clear(mLightToShadowmap.CountUsed() * 2); // To do: allow clearing a TMap while building up a reserve
|
|
||||||
|
|
||||||
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
|
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
|
||||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||||
while (auto light = it.Next())
|
while (auto light = it.Next())
|
||||||
{
|
{
|
||||||
LightsProcessed++;
|
LightsProcessed++;
|
||||||
if (light->shadowmapped)
|
if (light->shadowmapped && lightindex < 1024 * 4)
|
||||||
{
|
{
|
||||||
LightsShadowmapped++;
|
LightsShadowmapped++;
|
||||||
|
|
||||||
mLightToShadowmap[light] = lightindex >> 2;
|
light->mShadowmapIndex = lightindex >> 2;
|
||||||
|
|
||||||
mLights[lightindex] = light->X();
|
mLights[lightindex] = light->X();
|
||||||
mLights[lightindex+1] = light->Y();
|
mLights[lightindex+1] = light->Y();
|
||||||
mLights[lightindex+2] = light->Z();
|
mLights[lightindex+2] = light->Z();
|
||||||
mLights[lightindex+3] = light->GetRadius();
|
mLights[lightindex+3] = light->GetRadius();
|
||||||
lightindex += 4;
|
lightindex += 4;
|
||||||
|
|
||||||
if (lightindex == 1024*4) // Only 1024 lights for now
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
light->mShadowmapIndex = 1024;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,6 @@ public:
|
||||||
// Update shadow map texture
|
// Update shadow map texture
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
// Return the assigned shadow map index for a given light
|
|
||||||
int ShadowMapIndex(ADynamicLight *light);
|
|
||||||
|
|
||||||
// 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(ADynamicLight *light, const DVector3 &pos);
|
bool ShadowTest(ADynamicLight *light, const DVector3 &pos);
|
||||||
|
|
||||||
|
@ -42,9 +39,6 @@ private:
|
||||||
// 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
|
||||||
TArray<float> mLights;
|
TArray<float> mLights;
|
||||||
|
|
||||||
// The assigned shadow map index for each light
|
|
||||||
TMap<ADynamicLight*, int> mLightToShadowmap;
|
|
||||||
|
|
||||||
// OpenGL storage buffers for the AABB tree
|
// OpenGL storage buffers for the AABB tree
|
||||||
int mNodesBuffer = 0;
|
int mNodesBuffer = 0;
|
||||||
int mLinesBuffer = 0;
|
int mLinesBuffer = 0;
|
||||||
|
|
Loading…
Reference in a new issue