Add per-tier sidedef light levels to UDMF maps

This commit is contained in:
Nikolay Ambartsumov 2021-02-26 08:01:09 +02:00 committed by Rachael Alexanderson
parent a9eaae074f
commit df976e218e
13 changed files with 150 additions and 69 deletions

View File

@ -156,31 +156,40 @@ Note: All <bool> fields default to false unless mentioned otherwise.
sidedef
{
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
// When global texture offsets are used they will
// be added on top of these values.
light = <integer>; // This side's light level. Default is 0.
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
// relative to the owning sector's light level.
lightfog = <bool>; // true = This side's relative lighting is used even in
// foggy sectors. Default is to disable relative
// lighting in foggy sectors.
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
smoothlighting = <bool>; // Use smooth fake contrast.
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
wrapmidtex = <bool>; // Side's mid textures are wrapped.
nodecals = <bool>; // Disables decals on the sidedef.
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
scaley_top = <float>; // Y scale for upper texture, Default = 1.0.
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
scaley_mid = <float>; // Y scale for mid texture, Default = 1.0.
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
scaley_bottom = <float>; // Y scale for lower texture, Default = 1.0.
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
offsety_top = <float>; // Y offset for upper texture, Default = 0.0.
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
offsety_mid = <float>; // Y offset for mid texture, Default = 0.0.
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
offsety_bottom = <float>; // Y offset for lower texture, Default = 0.0.
// When global texture offsets are used they will
// be added on top of these values.
light = <integer>; // This side's light level. Default is 0.
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
// relative to the owning sector's light level.
light_top = <integer>; // This side's top tier light level. Default is 0.
lightabsolute_top = <bool>; // true = 'light_top' is an absolute value. Default is
// relative to the sidedef's resulting light level.
light_mid = <integer>; // This side's mid tier light level. Default is 0.
lightabsolute_mid = <bool>; // true = 'light_mid' is an absolute value. Default is
// relative to the sidedef's resulting light level.
light_bottom = <integer>; // This side's bottom tier light level. Default is 0.
lightabsolute_bottom = <bool>; // true = 'light_bottom' is an absolute value. Default is
// relative to the sidedef's resulting light level.
lightfog = <bool>; // true = This side's relative lighting is used even in
// foggy sectors. Default is to disable relative
// lighting in foggy sectors.
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
smoothlighting = <bool>; // Use smooth fake contrast.
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
wrapmidtex = <bool>; // Side's mid textures are wrapped.
nodecals = <bool>; // Disables decals on the sidedef.
nogradient_top = <bool>; // disables color gradient on upper tier. (Hardware rendering only.)
flipgradient_top = <bool>; // flips gradient colors on upper tier. (Hardware rendering only.)
@ -510,6 +519,9 @@ Coloriation options added
1.32 28.06.2021
Blocklandmonsters MBF21 flag
1.33 06.11.2021
Added separate light levels for sidedef tiers (top/mid/bottom)
===============================================================================
EOF
===============================================================================

View File

@ -1151,15 +1151,20 @@ class DBaseDecal;
enum
{
WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative
WALLF_NOAUTODECALS = 2, // Do not attach impact decals to this wall
WALLF_NOFAKECONTRAST = 4, // Don't do fake contrast for this wall in side_t::GetLightLevel
WALLF_SMOOTHLIGHTING = 8, // Similar to autocontrast but applies to all angles.
WALLF_CLIP_MIDTEX = 16, // Like the line counterpart, but only for this side.
WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side.
WALLF_POLYOBJ = 64, // This wall belongs to a polyobject.
WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog.
WALLF_EXTCOLOR = 256, // enables the extended color options (flagged to allow the renderer to easily skip the relevant code)
WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative
WALLF_NOAUTODECALS = 2, // Do not attach impact decals to this wall
WALLF_NOFAKECONTRAST = 4, // Don't do fake contrast for this wall in side_t::GetLightLevel
WALLF_SMOOTHLIGHTING = 8, // Similar to autocontrast but applies to all angles.
WALLF_CLIP_MIDTEX = 16, // Like the line counterpart, but only for this side.
WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side.
WALLF_POLYOBJ = 64, // This wall belongs to a polyobject.
WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog.
WALLF_EXTCOLOR = 256, // enables the extended color options (flagged to allow the renderer to easily skip the relevant code)
WALLF_ABSLIGHTING_TIER = 512, // Per-tier absolute lighting flags
WALLF_ABSLIGHTING_TOP = WALLF_ABSLIGHTING_TIER << 0, // Top tier light is absolute instead of relative
WALLF_ABSLIGHTING_MID = WALLF_ABSLIGHTING_TIER << 1, // Mid tier light is absolute instead of relative
WALLF_ABSLIGHTING_BOTTOM = WALLF_ABSLIGHTING_TIER << 2, // Bottom tier light is absolute instead of relative
};
struct side_t
@ -1216,6 +1221,7 @@ struct side_t
uint32_t LeftSide, RightSide; // [RH] Group walls into loops
uint16_t TexelLength;
int16_t Light;
int16_t TierLights[3]; // per-tier light levels
uint16_t Flags;
int UDMFIndex; // needed to access custom UDMF fields which are stored in loading order.
FLightNode * lighthead; // all dynamic lights that may affect this wall
@ -1224,13 +1230,19 @@ struct side_t
int numsegs;
int sidenum;
int GetLightLevel (bool foggy, int baselight, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const;
int GetLightLevel (bool foggy, int baselight, int which, bool is3dlight=false, int *pfakecontrast_usedbygzdoom=NULL) const;
void SetLight(int16_t l)
{
Light = l;
}
void SetLight(int16_t l, int which)
{
TierLights[which] = l;
}
FLevelLocals *GetLevel()
{
return sector->Level;

View File

@ -1323,6 +1323,30 @@ public:
Flag(sd->Flags, WALLF_ABSLIGHTING, key);
continue;
case NAME_light_top:
sd->SetLight(CheckInt(key), side_t::top);
continue;
case NAME_lightabsolute_top:
Flag(sd->Flags, WALLF_ABSLIGHTING_TOP, key);
continue;
case NAME_light_mid:
sd->SetLight(CheckInt(key), side_t::mid);
continue;
case NAME_lightabsolute_mid:
Flag(sd->Flags, WALLF_ABSLIGHTING_MID, key);
continue;
case NAME_light_bottom:
sd->SetLight(CheckInt(key), side_t::bottom);
continue;
case NAME_lightabsolute_bottom:
Flag(sd->Flags, WALLF_ABSLIGHTING_BOTTOM, key);
continue;
case NAME_lightfog:
Flag(sd->Flags, WALLF_LIGHT_FOG, key);
continue;

View File

@ -746,6 +746,12 @@ xx(scaley_bottom)
xx(light)
xx(lightabsolute)
xx(lightfog)
xx(light_top)
xx(lightabsolute_top)
xx(light_mid)
xx(lightabsolute_mid)
xx(light_bottom)
xx(lightabsolute_bottom)
xx(nofakecontrast)
xx(smoothlighting)
xx(blockprojectiles)

View File

@ -1533,11 +1533,18 @@ void line_t::AdjustLine()
//
//==========================================================================
int side_t::GetLightLevel (bool foggy, int baselight, bool is3dlight, int *pfakecontrast) const
int side_t::GetLightLevel (bool foggy, int baselight, int which, bool is3dlight, int *pfakecontrast) const
{
if (!is3dlight && (Flags & WALLF_ABSLIGHTING))
if (!is3dlight)
{
baselight = Light;
if (Flags & (WALLF_ABSLIGHTING_TIER << which))
{
baselight = TierLights[which];
}
else if (Flags & WALLF_ABSLIGHTING)
{
baselight = Light + TierLights[which];
}
}
if (pfakecontrast != NULL)
@ -1576,9 +1583,9 @@ int side_t::GetLightLevel (bool foggy, int baselight, bool is3dlight, int *pfake
}
}
}
if (!is3dlight && !(Flags & WALLF_ABSLIGHTING) && (!foggy || (Flags & WALLF_LIGHT_FOG)))
if (!is3dlight && !(Flags & WALLF_ABSLIGHTING) && !(Flags & (WALLF_ABSLIGHTING_TIER << which)) && (!foggy || (Flags & WALLF_LIGHT_FOG)))
{
baselight += this->Light;
baselight += this->Light + this->TierLights[which];
}
return baselight;
}
@ -1619,4 +1626,3 @@ void vertex_t::RecalcVertexHeights()
if (numheights <= 2) numheights = 0; // is not in need of any special attention
dirty = false;
}

View File

@ -1996,7 +1996,23 @@ void HWWall::DoFFloorBlocks(HWDrawInfo *di, seg_t * seg, sector_t * frontsector,
InverseFloors(di, seg, frontsector, topleft, topright, bottomleft, bottomright);
}
}
inline int CalcRelLight(int lightlevel, int orglightlevel, int rel)
{
if (orglightlevel >= 253) // with the software renderer fake contrast won't be visible above this.
{
return 0;
}
else if (lightlevel - rel > 256) // the brighter part of fake contrast will be clamped so also clamp the darker part by the same amount for better looks
{
return 256 - lightlevel + rel;
}
else
{
return rel;
}
}
//==========================================================================
//
//
@ -2103,19 +2119,6 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
int rel = 0;
int orglightlevel = hw_ClampLight(frontsector->lightlevel);
bool foggy = (!Colormap.FadeColor.isBlack() || di->Level->flags&LEVEL_HASFADETABLE); // fog disables fake contrast
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, false, &rel));
if (orglightlevel >= 253) // with the software renderer fake contrast won't be visible above this.
{
rellight = 0;
}
else if (lightlevel - rel > 256) // the brighter part of fake contrast will be clamped so also clamp the darker part by the same amount for better looks
{
rellight = 256 - lightlevel + rel;
}
else
{
rellight = rel;
}
alpha = 1.0f;
RenderStyle = STYLE_Normal;
@ -2161,6 +2164,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
else
{
// normal texture
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel));
rellight = CalcRelLight(lightlevel, orglightlevel, rel);
texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::mid), true);
if (texture && texture->isValid())
{
@ -2229,6 +2234,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
if (bch1a < fch1 || bch2a < fch2)
{
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::top, false, &rel));
rellight = CalcRelLight(lightlevel, orglightlevel, rel);
texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::top), true);
if (texture && texture->isValid())
{
@ -2279,6 +2286,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
texture = tex;
}
else texture = nullptr;
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::mid, false, &rel));
rellight = CalcRelLight(lightlevel, orglightlevel, rel);
if (isportal)
{
@ -2297,6 +2306,7 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
}
else
{
if (texture || drawfogboundary)
{
DoMidTexture(di, seg, drawfogboundary, frontsector, backsector, realfront, realback,
@ -2305,6 +2315,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
{
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::top, false, &rel));
rellight = CalcRelLight(lightlevel, orglightlevel, rel);
DoFFloorBlocks(di, seg, frontsector, backsector, fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2);
}
}
@ -2319,6 +2331,8 @@ void HWWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
if (bfh1 > ffh1 || bfh2 > ffh2)
{
lightlevel = hw_ClampLight(seg->sidedef->GetLightLevel(foggy, orglightlevel, side_t::bottom, false, &rel));
rellight = CalcRelLight(lightlevel, orglightlevel, rel);
texture = TexMan.GetGameTexture(seg->sidedef->GetTexture(side_t::bottom), true);
if (texture && texture->isValid())
{

View File

@ -873,7 +873,7 @@ namespace swrenderer
texcoords.ProjectTop(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC, mTopTexture);
RenderWallPart renderWallpart(Thread);
renderWallpart.Render(mFrontSector, mLineSegment, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, false, false, OPAQUE);
renderWallpart.Render(mFrontSector, mLineSegment, side_t::top, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, false, false, OPAQUE);
}
void SWRenderLine::RenderMiddleTexture(int x1, int x2)
@ -885,7 +885,7 @@ namespace swrenderer
texcoords.ProjectMid(Thread->Viewport.get(), mFrontSector, mLineSegment, WallC, mMiddleTexture);
RenderWallPart renderWallpart(Thread);
renderWallpart.Render(mFrontSector, mLineSegment, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE);
renderWallpart.Render(mFrontSector, mLineSegment, side_t::mid, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE);
}
void SWRenderLine::RenderBottomTexture(int x1, int x2)
@ -898,6 +898,6 @@ namespace swrenderer
texcoords.ProjectBottom(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC, mBottomTexture);
RenderWallPart renderWallpart(Thread);
renderWallpart.Render(mFrontSector, mLineSegment, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE);
renderWallpart.Render(mFrontSector, mLineSegment, side_t::bottom, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE);
}
}

View File

@ -195,7 +195,7 @@ namespace swrenderer
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
RenderWallPart renderWallpart(Thread);
renderWallpart.Render(lightsector, curline, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, true, additive, alpha);
renderWallpart.Render(lightsector, curline, side_t::mid, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, true, additive, alpha);
}
void RenderDrawSegment::Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic)
@ -216,7 +216,7 @@ namespace swrenderer
walltexcoords.Project3DFloor(Thread->Viewport.get(), rover, curline, ds->WallC, rw_pic);
RenderWallPart renderWallpart(Thread);
renderWallpart.Render(lightsector, curline, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha);
renderWallpart.Render(lightsector, curline, side_t::top, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha);
RenderDecal::RenderDecals(Thread, ds, curline, lightsector, wallupper.ScreenY, walllower.ScreenY, true);
}
@ -580,7 +580,7 @@ namespace swrenderer
const sector_t* lightsector = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0);
ProjectedWallLight walllight;
walllight.SetColormap(lightsector, curline);
walllight.SetColormap(lightsector, curline, side_t::mid);
walllight.SetLightLeft(Thread, ds->WallC);
RenderFogBoundary renderfog;

View File

@ -61,7 +61,7 @@ namespace swrenderer
Thread = thread;
}
void RenderWallPart::Render(const sector_t* lightsector, seg_t* curline, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, const ProjectedWallTexcoords& texcoords, bool mask, bool additive, fixed_t alpha)
void RenderWallPart::Render(const sector_t* lightsector, seg_t* curline, int tier, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, const ProjectedWallTexcoords& texcoords, bool mask, bool additive, fixed_t alpha)
{
if (pic == nullptr)
return;
@ -70,6 +70,7 @@ namespace swrenderer
this->x2 = x2;
this->lightsector = lightsector;
this->curline = curline;
this->tier = tier;
this->WallC = WallC;
this->pic = pic;
this->mask = mask;
@ -78,7 +79,7 @@ namespace swrenderer
light_list = GetLightList();
mLight.SetColormap(lightsector, curline);
mLight.SetColormap(lightsector, curline, tier);
mLight.SetLightLeft(Thread, WallC);
CameraLight* cameraLight = CameraLight::Instance();
@ -114,7 +115,7 @@ namespace swrenderer
down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY;
}
mLight.SetColormap(lightsector, curline, &lightsector->e->XFloor.lightlist[i]);
mLight.SetColormap(lightsector, curline, tier, &lightsector->e->XFloor.lightlist[i]);
}
ProcessNormalWall(up, dwal, texcoords);

View File

@ -47,6 +47,7 @@ namespace swrenderer
void Render(
const sector_t *lightsector,
seg_t *curline,
int tier,
const FWallCoords &WallC,
FSoftwareTexture *pic,
int x1,
@ -70,6 +71,7 @@ namespace swrenderer
FSoftwareTexture *pic = nullptr;
const sector_t *lightsector = nullptr;
seg_t *curline = nullptr;
int tier;
FWallCoords WallC;
ProjectedWallLight mLight;

View File

@ -687,7 +687,7 @@ namespace swrenderer
}
}
void ProjectedWallLight::SetColormap(const sector_t *frontsector, seg_t *lineseg, lightlist_t *lit)
void ProjectedWallLight::SetColormap(const sector_t *frontsector, seg_t *lineseg, int tier, lightlist_t *lit)
{
if (!lit)
{
@ -695,7 +695,7 @@ namespace swrenderer
foggy = frontsector->Level->fadeto || frontsector->Colormap.FadeColor || (frontsector->Level->flags & LEVEL_HASFADETABLE);
if (!(lineseg->sidedef->Flags & WALLF_POLYOBJ))
lightlevel = lineseg->sidedef->GetLightLevel(foggy, frontsector->lightlevel);
lightlevel = lineseg->sidedef->GetLightLevel(foggy, frontsector->lightlevel, tier);
else
lightlevel = frontsector->GetLightLevel();
}
@ -703,7 +703,7 @@ namespace swrenderer
{
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
foggy = frontsector->Level->fadeto || basecolormap->Fade || (frontsector->Level->flags & LEVEL_HASFADETABLE);
lightlevel = lineseg->sidedef->GetLightLevel(foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
lightlevel = lineseg->sidedef->GetLightLevel(foggy, *lit->p_lightlevel, tier, lit->lightsource != nullptr);
}
}
}

View File

@ -119,7 +119,7 @@ namespace swrenderer
float GetLightStep() const { return lightstep; }
bool IsSpriteLight() const { return spritelight; }
void SetColormap(const sector_t *frontsector, seg_t *lineseg, lightlist_t *lit = nullptr);
void SetColormap(const sector_t *frontsector, seg_t *lineseg, int tier, lightlist_t *lit = nullptr);
void SetLightLeft(RenderThread *thread, const FWallCoords &wallc);
void SetSpriteLight() { lightleft = 0.0f; lightstep = 0.0f; spritelight = true; }

View File

@ -157,6 +157,8 @@ namespace swrenderer
if (x1 >= clipper->x2 || x2 <= clipper->x1)
return;
int tier = side_t::mid;
if (drawsegPass)
{
uint32_t clipMode = decal->RenderFlags & RF_CLIPMASK;
@ -203,6 +205,7 @@ namespace swrenderer
break;
case RF_CLIPUPPER:
tier = side_t::top;
mceilingclip = walltop;
mfloorclip = thread->OpaquePass->ceilingclip;
break;
@ -211,6 +214,7 @@ namespace swrenderer
return;
case RF_CLIPLOWER:
tier = side_t::bottom;
mceilingclip = thread->OpaquePass->floorclip;
mfloorclip = wallbottom;
break;
@ -219,7 +223,7 @@ namespace swrenderer
// Prepare lighting
ProjectedWallLight light;
light.SetColormap(lightsector, curline);
light.SetColormap(lightsector, curline, tier);
light.SetLightLeft(thread, WallC);
usecolormap = light.GetBaseColormap();