diff --git a/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h b/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h index ad40bb137..263c47421 100644 --- a/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h +++ b/src/common/rendering/hwrenderer/data/hw_surfaceuniforms.h @@ -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; + } }; diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 899f8f55b..f33f56ff5 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -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; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.h b/src/rendering/hwrenderer/scene/hw_drawinfo.h index bebe4593e..ce6f7836e 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.h +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.h @@ -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); diff --git a/src/rendering/hwrenderer/scene/hw_lighting.h b/src/rendering/hwrenderer/scene/hw_lighting.h index f4cc44380..f21adf1fa 100644 --- a/src/rendering/hwrenderer/scene/hw_lighting.h +++ b/src/rendering/hwrenderer/scene/hw_lighting.h @@ -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; + } +} diff --git a/src/rendering/hwrenderer/scene/hw_setcolor.cpp b/src/rendering/hwrenderer/scene/hw_setcolor.cpp index f8b150f67..2b277313a 100644 --- a/src/rendering/hwrenderer/scene/hw_setcolor.cpp +++ b/src/rendering/hwrenderer/scene/hw_setcolor.cpp @@ -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 diff --git a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl index b090d0009..3abe60a43 100644 --- a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl +++ b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl @@ -81,8 +81,8 @@ struct SurfaceLightUniforms vec4 uVertexColor; float uDesaturationFactor; float uLightLevel; - uint uLightIndex; - uint padding; + uint padding0; + uint padding1; }; struct Fogball diff --git a/wadsrc/static/shaders/scene/layout_shared.glsl b/wadsrc/static/shaders/scene/layout_shared.glsl index a994c66c8..9160e4588 100644 --- a/wadsrc/static/shaders/scene/layout_shared.glsl +++ b/wadsrc/static/shaders/scene/layout_shared.glsl @@ -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