Per-wall lighting

This commit is contained in:
spherallic 2024-06-12 14:25:45 +02:00
parent 332445ae55
commit 28dfe91b4f
6 changed files with 170 additions and 19 deletions

View file

@ -309,6 +309,30 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
return (FUINT)finallight;
}
static FUINT HWR_SideLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light +
((side->lightabsolute) ? 0 : base_lightlevel);
}
static FUINT HWR_TopLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light_top +
((side->lightabsolute_top) ? 0 : HWR_SideLightLevel(side, base_lightlevel));
}
static FUINT HWR_MidLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light_mid +
((side->lightabsolute_mid) ? 0 : HWR_SideLightLevel(side, base_lightlevel));
}
static FUINT HWR_BottomLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light_bottom +
((side->lightabsolute_bottom) ? 0 : HWR_SideLightLevel(side, base_lightlevel));
}
// ==========================================================================
// FLOOR/CEILING GENERATION FROM SUBSECTORS
// ==========================================================================
@ -705,8 +729,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
fixed_t v2x = FloatToFixed(wallVerts[1].x);
fixed_t v2y = FloatToFixed(wallVerts[1].z);
FUINT lightnum = HWR_SideLightLevel(gl_sidedef, sector->lightlevel);
const UINT8 alpha = Surf->PolyColor.s.alpha;
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
lightnum = HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL;
if (!r_renderwalls)
@ -750,13 +775,13 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
{
if (pfloor && (pfloor->fofflags & FOF_FOG))
{
lightnum = pfloor->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, pfloor->master->frontsector->lightlevel);
colormap = pfloor->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
else
{
lightnum = *list[i].lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, *list[i].lightlevel);
colormap = *list[i].extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
@ -1167,7 +1192,7 @@ static void HWR_ProcessSeg(void)
float cliplow = (float)gl_curline->offset;
float cliphigh = cliplow + (gl_curline->flength * FRACUNIT);
FUINT lightnum = gl_frontsector->lightlevel;
FUINT lightnum = HWR_SideLightLevel(gl_sidedef, gl_frontsector->lightlevel);
extracolormap_t *colormap = gl_frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
@ -1628,11 +1653,11 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel);
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap);
if (gl_frontsector->numlights)
HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->fofflags, rover, blendmode);
@ -1785,7 +1810,7 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel);
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);

View file

@ -213,6 +213,14 @@ enum side_e {
side_sector,
side_special,
side_repeatcnt,
side_light,
side_light_top,
side_light_mid,
side_light_bottom,
side_lightabsolute,
side_lightabsolute_top,
side_lightabsolute_mid,
side_lightabsolute_bottom,
side_text
};
@ -241,6 +249,14 @@ static const char *const side_opt[] = {
"sector",
"special",
"repeatcnt",
"light",
"light_top",
"light_mid",
"light_bottom",
"lightabsolute",
"lightabsolute_top",
"lightabsolute_mid",
"lightabsolute_bottom",
"text",
NULL};
@ -1311,6 +1327,30 @@ static int side_get(lua_State *L)
case side_repeatcnt:
lua_pushinteger(L, side->repeatcnt);
return 1;
case side_light:
lua_pushinteger(L, side->light);
return 1;
case side_light_top:
lua_pushinteger(L, side->light_top);
return 1;
case side_light_mid:
lua_pushinteger(L, side->light_mid);
return 1;
case side_light_bottom:
lua_pushinteger(L, side->light_bottom);
return 1;
case side_lightabsolute:
lua_pushboolean(L, side->lightabsolute);
return 1;
case side_lightabsolute_top:
lua_pushboolean(L, side->lightabsolute_top);
return 1;
case side_lightabsolute_mid:
lua_pushboolean(L, side->lightabsolute_mid);
return 1;
case side_lightabsolute_bottom:
lua_pushboolean(L, side->lightabsolute_bottom);
return 1;
// TODO: 2.3: Delete
case side_text:
{
@ -1413,6 +1453,30 @@ static int side_set(lua_State *L)
case side_repeatcnt:
side->repeatcnt = luaL_checkinteger(L, 3);
break;
case side_light:
side->repeatcnt = luaL_checkinteger(L, 3);
break;
case side_light_top:
side->repeatcnt = luaL_checkinteger(L, 3);
break;
case side_light_mid:
side->repeatcnt = luaL_checkinteger(L, 3);
break;
case side_light_bottom:
side->repeatcnt = luaL_checkinteger(L, 3);
break;
case side_lightabsolute:
side->lightabsolute = luaL_checkboolean(L, 3);
break;
case side_lightabsolute_top:
side->lightabsolute_top = luaL_checkboolean(L, 3);
break;
case side_lightabsolute_mid:
side->lightabsolute_mid = luaL_checkboolean(L, 3);
break;
case side_lightabsolute_bottom:
side->lightabsolute_bottom = luaL_checkboolean(L, 3);
break;
}
return 0;
}

View file

@ -919,7 +919,11 @@ enum
LD_SDMIDLIGHT = 1<<19,
LD_SDBOTLIGHT = 1<<20,
LD_SDREPEATCNT = 1<<21,
LD_SDFLAGS = 1<<22
LD_SDFLAGS = 1<<22,
LD_SDLIGHTABS = 1<<23,
LD_SDTOPLIGHTABS = 1<<24,
LD_SDMIDLIGHTABS = 1<<25,
LD_SDBOTLIGHTABS = 1<<26
};
static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli)
@ -1393,6 +1397,16 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi)
diff |= LD_SDBOTSCALEY;
if (si->repeatcnt != spawnsi->repeatcnt)
diff |= LD_SDREPEATCNT;
if (si->light != spawnsi->light)
diff |= LD_SDLIGHT;
if (si->light_top != spawnsi->light_top)
diff |= LD_SDTOPLIGHT;
if (si->light_mid != spawnsi->light_mid)
diff |= LD_SDMIDLIGHT;
if (si->light_bottom != spawnsi->light_bottom)
diff |= LD_SDBOTLIGHT;
if (si->lightabsolute != spawnsi->lightabsolute)
diff |= LD_SDLIGHTABS;
return diff;
}
@ -1436,6 +1450,10 @@ static void ArchiveSide(const side_t *si, UINT32 diff)
WRITEFIXED(save_p, si->scaley_bottom);
if (diff & LD_SDREPEATCNT)
WRITEINT16(save_p, si->repeatcnt);
if (diff & LD_SDLIGHT)
WRITEINT16(save_p, si->light);
if (diff & LD_SDLIGHTABS)
WRITEINT16(save_p, si->lightabsolute);
}
static void ArchiveLines(void)
@ -1576,6 +1594,10 @@ static void UnArchiveSide(side_t *si)
si->scaley_bottom = READFIXED(save_p);
if (diff & LD_SDREPEATCNT)
si->repeatcnt = READINT16(save_p);
if (diff & LD_SDLIGHT)
si->light = READINT16(save_p);
if (diff & LD_SDLIGHTABS)
si->lightabsolute = READINT16(save_p);
}
static void UnArchiveLines(void)

View file

@ -1367,6 +1367,9 @@ static void P_LoadSidedefs(UINT8 *data)
sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT;
sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
P_SetSidedefSector(i, (UINT16)SHORT(msd->sector));
// Special info stored in texture fields!
@ -1977,6 +1980,10 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char
P_SetSidedefSector(i, atol(val));
else if (fastcmp(param, "repeatcnt"))
sides[i].repeatcnt = atol(val);
else if (fastcmp(param, "light"))
sides[i].light = atol(val);
else if (fastcmp(param, "lightabsolute") && fastcmp("true", val))
sides[i].lightabsolute = true;
}
static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val)
@ -2704,6 +2711,10 @@ static void P_WriteTextmap(void)
fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name);
if (wsides[i].repeatcnt != 0)
fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt);
if (wsides[i].light != 0)
fprintf(f, "light = %d;\n", wsides[i].light);
if (wsides[i].lightabsolute != 0)
fprintf(f, "lightabsolute = %d;\n", wsides[i].lightabsolute);
fprintf(f, "}\n");
fprintf(f, "\n");
}
@ -3106,6 +3117,7 @@ static void P_LoadTextmap(void)
sd->bottomtexture = R_TextureNumForName("-");
sd->sector = NULL;
sd->repeatcnt = 0;
sd->light = sd->lightabsolute = 0;
TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter);

View file

@ -631,6 +631,11 @@ typedef struct
fixed_t scalex_top, scalex_mid, scalex_bottom;
fixed_t scaley_top, scaley_mid, scaley_bottom;
// per-wall lighting for UDMF
// TODO: implement per-texture lighting
INT16 light, light_top, light_mid, light_bottom;
boolean lightabsolute, lightabsolute_top, lightabsolute_mid, lightabsolute_bottom;
// Texture indices.
// We do not maintain names here.
INT32 toptexture, bottomtexture, midtexture;

View file

@ -94,6 +94,30 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha)
return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1);
}
static INT16 R_SideLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light +
((side->lightabsolute) ? 0 : base_lightlevel);
}
static INT16 R_TopLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light_top +
((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel));
}
static INT16 R_MidLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light_mid +
((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel));
}
static INT16 R_BottomLightLevel(side_t *side, UINT8 base_lightlevel)
{
return side->light_bottom +
((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel));
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{
size_t pindex;
@ -223,7 +247,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (rlight->flags & FOF_FOG)
|| (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
else
lightnum = LIGHTLEVELS - 1;
@ -241,7 +265,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else
lightnum = LIGHTLEVELS - 1;
@ -697,9 +721,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Check if the current light effects the colormap/lightlevel
if (pfloor->fofflags & FOF_FOG)
rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else
rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT);
rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
;
@ -717,18 +741,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{
// Get correct light level!
if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (fog)
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (fuzzy)
lightnum = LIGHTLEVELS-1;
else
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
->lightlevel >> LIGHTSEGSHIFT;
lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)));
else if (curline->v1->y == curline->v2->y)
lightnum--;
lightnum--;
else if (curline->v1->x == curline->v2->x)
lightnum++;
@ -1353,7 +1376,7 @@ static void R_RenderSegLoop (void)
for (i = 0; i < dc_numlights; i++)
{
INT32 lightnum;
lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT;
if (dc_lightlist[i].extra_colormap)
;
@ -2540,7 +2563,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// use different light tables
// for horizontal / vertical / diagonal
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
if (curline->v1->y == curline->v2->y)
lightnum--;