Improve light level updates

This commit is contained in:
Magnus Norddahl 2024-09-29 14:21:57 +02:00
commit 7e83d726ca
7 changed files with 169 additions and 17 deletions

View file

@ -50,9 +50,46 @@ struct SurfaceUniforms
struct SurfaceLightUniforms
{
FVector4 uVertexColor; // HWDrawInfo::SetColor
float uDesaturationFactor; // HWDrawInfo::SetColor
float uLightLevel; // HWDrawInfo::SetColor
int uLightIndex;
int padding;
FVector4 uVertexColor;
float uDesaturationFactor;
float uLightLevel;
int padding0;
int padding1;
void SetColor(float r, float g, float b, float a = 1.f, int desat = 0)
{
uVertexColor = { r, g, b, a };
uDesaturationFactor = desat * (1.0f / 255.0f);
}
void SetColor(PalEntry pe, int desat = 0)
{
const float scale = 1.0f / 255.0f;
uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale };
uDesaturationFactor = desat * (1.0f / 255.0f);
}
void SetColorAlpha(PalEntry pe, float alpha = 1.f, int desat = 0)
{
const float scale = 1.0f / 255.0f;
uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, alpha };
uDesaturationFactor = desat * (1.0f / 255.0f);
}
void ResetColor()
{
uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f };
uDesaturationFactor = 0.0f;
}
void SetSoftLightLevel(int llevel, int blendfactor = 0)
{
if (blendfactor == 0) uLightLevel = llevel / 255.f;
else uLightLevel = -1.f;
}
void SetNoSoftLightLevel()
{
uLightLevel = -1.f;
}
};

View file

@ -10,6 +10,7 @@
#include "hw_renderstate.h"
#include "hw_vertexbuilder.h"
#include "hw_dynlightdata.h"
#include "hwrenderer/scene/hw_lighting.h"
#include "hwrenderer/scene/hw_drawstructs.h"
#include "hwrenderer/scene/hw_drawinfo.h"
#include "hwrenderer/scene/hw_walldispatcher.h"
@ -168,6 +169,13 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
SunDirection = doomMap.SunDirection;
LightmapSampleDistance = doomMap.LightmapSampleDistance;
// HWWall and HWFlat still looks at r_viewpoint when doing calculations,
// but we aren't rendering a specific viewpoint when this function gets called
int oldextralight = r_viewpoint.extralight;
AActor* oldcamera = r_viewpoint.camera;
r_viewpoint.extralight = 0;
r_viewpoint.camera = nullptr;
BuildSectorGroups(doomMap);
CreatePortals(doomMap);
CreateSurfaces(doomMap);
@ -178,6 +186,9 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap)
UploadPortals();
SortDrawLists();
r_viewpoint.extralight = oldextralight;
r_viewpoint.camera = oldcamera;
}
void DoomLevelMesh::SetLimits(FLevelLocals& doomMap)
@ -218,6 +229,13 @@ void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
LastFrameStats = CurFrameStats;
CurFrameStats = Stats();
// HWWall and HWFlat still looks at r_viewpoint when doing calculations,
// but we aren't rendering a specific viewpoint when this function gets called
int oldextralight = r_viewpoint.extralight;
AActor* oldcamera = r_viewpoint.camera;
r_viewpoint.extralight = 0;
r_viewpoint.camera = nullptr;
// To do: we don't need to always do this. UpdateLevelMesh should tell us when polyobjs move.
for (side_t* side : PolySides)
{
@ -256,6 +274,9 @@ void DoomLevelMesh::BeginFrame(FLevelLocals& doomMap)
UpdateWallPortals();
UploadDynLights(doomMap);
r_viewpoint.extralight = oldextralight;
r_viewpoint.camera = oldcamera;
}
void DoomLevelMesh::UploadDynLights(FLevelLocals& doomMap)
@ -785,6 +806,35 @@ void DoomLevelMesh::CreateFlat(FLevelLocals& doomMap, unsigned int sectorIndex)
void DoomLevelMesh::SetSideLights(FLevelLocals& doomMap, unsigned int sideIndex)
{
ELightMode lightmode = getRealLightmode(&doomMap, true);
side_t* side = &doomMap.sides[sideIndex];
// Global modifiers that affects EVERYTHING.
// We need to find a way to apply this in the shader.
int rel = getExtraLight();
bool fullbrightScene = isFullbrightScene();
// To do: we need to know where each uniform block came from:
sector_t* frontsector = side->sector;
FColormap Colormap = frontsector->Colormap; // To do: this may come from the lightlist
bool foggy = (!Colormap.FadeColor.isBlack() || doomMap.flags & LEVEL_HASFADETABLE); // fog disables fake contrast
float alpha = 1.0f;
if (side->linedef->alpha != 0)
{
switch (side->linedef->flags & ML_ADDTRANS)
{
case 0:
case ML_ADDTRANS:
alpha = side->linedef->alpha;
}
}
float absalpha = fabsf(alpha);
// GetLightLevel changes global extra light. Used for the fake contrast:
int orglightlevel = hw_ClampLight(frontsector->lightlevel);
int lightlevel = hw_ClampLight(side->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel));
for (UniformsAllocInfo& uinfo : Sides[sideIndex].Uniforms)
{
for (int i = 0, count = uinfo.Count; i < count; i++)
@ -796,6 +846,8 @@ void DoomLevelMesh::SetSideLights(FLevelLocals& doomMap, unsigned int sideIndex)
{
uinfo.LightUniforms[i].uLightLevel = clamp(doomMap.sides[sideIndex].sector->lightlevel * (1.0f / 255.0f), 0.0f, 1.0f);
}
SetColor(uinfo.LightUniforms[i], &doomMap, lightmode, lightlevel, rel, fullbrightScene, Colormap, absalpha);
}
AddRange(UploadRanges.LightUniforms, { uinfo.Start, uinfo.Start + uinfo.Count });
}
@ -803,17 +855,25 @@ void DoomLevelMesh::SetSideLights(FLevelLocals& doomMap, unsigned int sideIndex)
void DoomLevelMesh::SetFlatLights(FLevelLocals& doomMap, unsigned int sectorIndex)
{
ELightMode lightmode = getRealLightmode(&doomMap, true);
// Global modifiers that affects EVERYTHING.
// We need to find a way to apply this in the shader.
int rel = 0;// getExtraLight();
bool fullbrightScene = false; // isFullbrightScene();
// To do: we need to know where each uniform block came from:
sector_t* frontsector = &doomMap.sectors[sectorIndex];
int lightlevel = hw_ClampLight(frontsector->GetFloorLight());
FColormap Colormap = frontsector->Colormap;
FSectorPortal* portal = frontsector->ValidatePortal(sector_t::floor);
double alpha = portal ? frontsector->GetAlpha(sector_t::floor) : 1.0f - frontsector->GetReflect(sector_t::floor);
for (UniformsAllocInfo& uinfo : Flats[sectorIndex].Uniforms)
{
for (int i = 0, count = uinfo.Count; i < count; i++)
{
// To do: calculate this correctly (see HWDrawInfo::SetColor)
// uinfo.LightUniforms[i].uVertexColor
// uinfo.LightUniforms[i].uDesaturationFactor
if (uinfo.LightUniforms[i].uLightLevel >= 0.0f)
{
uinfo.LightUniforms[i].uLightLevel = clamp(doomMap.sectors[sectorIndex].lightlevel * (1.0f / 255.0f), 0.0f, 1.0f);
}
SetColor(uinfo.LightUniforms[i], &doomMap, lightmode, lightlevel, rel, fullbrightScene, Colormap, alpha);
}
AddRange(UploadRanges.LightUniforms, { uinfo.Start, uinfo.Start + uinfo.Count });
}
@ -916,7 +976,6 @@ void DoomLevelMesh::CreateWallSurface(side_t* side, HWWallDispatcher& disp, Mesh
curLightUniforms->uVertexColor = applyState.surfaceUniforms.uVertexColor;
curLightUniforms->uDesaturationFactor = applyState.surfaceUniforms.uDesaturationFactor;
curLightUniforms->uLightLevel = applyState.surfaceUniforms.uLightLevel;
curLightUniforms->uLightIndex = -1;
curLightUniforms++;
uniformsIndex++;
@ -1202,7 +1261,6 @@ void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state
uinfo.LightUniforms->uVertexColor = uniforms->uVertexColor;
uinfo.LightUniforms->uDesaturationFactor = uniforms->uDesaturationFactor;
uinfo.LightUniforms->uLightLevel = uniforms->uLightLevel;
uinfo.LightUniforms->uLightIndex = -1;
int uniformsIndex = uinfo.Start;
int vertIndex = ginfo.VertexStart;

View file

@ -396,3 +396,6 @@ bool CheckFog(FLevelLocals* Level, sector_t* frontsector, sector_t* backsector,
void SetColor(FRenderState& state, FLevelLocals* Level, ELightMode lightmode, int sectorlightlevel, int rellight, bool fullbright, const FColormap& cm, float alpha, bool weapon = false);
void SetShaderLight(FRenderState& state, FLevelLocals* Level, float level, float olight);
void SetFog(FRenderState& state, FLevelLocals* Level, ELightMode lightmode, int lightlevel, int rellight, bool fullbright, const FColormap* cmap, bool isadditive, bool inskybox);
struct SurfaceLightUniforms;
void SetColor(SurfaceLightUniforms& uniforms, FLevelLocals* Level, ELightMode lightmode, int sectorlightlevel, int rellight, bool fullbright, const FColormap& cm, float alpha, bool weapon = false);

View file

@ -19,3 +19,40 @@ inline int getExtraLight()
return r_viewpoint.extralight * gl_weaponlight;
}
inline int isFullbrightScene()
{
player_t* cplayer = r_viewpoint.camera ? r_viewpoint.camera->player : nullptr;
if (cplayer)
{
if (cplayer->extralight == INT_MIN)
{
return true;
}
else if (cplayer->fixedcolormap != NOFIXEDCOLORMAP)
{
return true;
}
else if (cplayer->fixedlightlevel != -1)
{
auto torchtype = PClass::FindActor(NAME_PowerTorch);
auto litetype = PClass::FindActor(NAME_PowerLightAmp);
for (AActor* in = cplayer->mo->Inventory; in; in = in->Inventory)
{
// Need special handling for light amplifiers
if (in->IsKindOf(torchtype))
{
return true;
}
else if (in->IsKindOf(litetype))
{
return true;
}
}
}
return false;
}
else
{
return false;
}
}

View file

@ -56,6 +56,24 @@ void SetColor(FRenderState &state, FLevelLocals* Level, ELightMode lightmode, in
}
}
void SetColor(SurfaceLightUniforms& uniforms, FLevelLocals* Level, ELightMode lightmode, int sectorlightlevel, int rellight, bool fullbright, const FColormap& cm, float alpha, bool weapon)
{
if (fullbright)
{
uniforms.SetColorAlpha(0xffffff, alpha, 0);
if (isSoftwareLighting(lightmode)) uniforms.SetSoftLightLevel(255);
else uniforms.SetNoSoftLightLevel();
}
else
{
int hwlightlevel = CalcLightLevel(lightmode, sectorlightlevel, rellight, weapon, cm.BlendFactor);
PalEntry pe = CalcLightColor(lightmode, hwlightlevel, cm.LightColor, cm.BlendFactor);
uniforms.SetColorAlpha(pe, alpha, cm.Desaturation);
if (isSoftwareLighting(lightmode)) uniforms.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight), cm.BlendFactor);
else uniforms.SetNoSoftLightLevel();
}
}
//==========================================================================
//
// Lighting stuff

View file

@ -81,8 +81,8 @@ struct SurfaceLightUniforms
vec4 uVertexColor;
float uDesaturationFactor;
float uLightLevel;
uint uLightIndex;
uint padding;
uint padding0;
uint padding1;
};
struct Fogball

View file

@ -73,7 +73,6 @@ layout(push_constant) uniform PushConstants
#define uVertexColor lightdata[uDataIndex].uVertexColor
#define uDesaturationFactor lightdata[uDataIndex].uDesaturationFactor
#define uLightLevel lightdata[uDataIndex].uLightLevel
//#define uLightIndex lightdata[uDataIndex].uLightIndex
int uLightIndex;
#else
#define uVertexColor data[uDataIndex].uVertexColor