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:
Christoph Oelckers 2018-04-16 08:42:37 +02:00
parent 4a3f7e8dd5
commit f57c804a5a
4 changed files with 25 additions and 31 deletions

View file

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

View file

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

View file

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

View file

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