vkdoom_m/src/rendering/swrenderer/line/r_wallsetup.cpp
2022-01-26 18:25:04 -05:00

709 lines
22 KiB
C++

//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
// Copyright 2016 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
#include <stdlib.h>
#include <stddef.h>
#include "doomdef.h"
#include "doomstat.h"
#include "doomdata.h"
#include "p_lnspec.h"
#include "r_sky.h"
#include "v_video.h"
#include "m_swap.h"
#include "filesystem.h"
#include "stats.h"
#include "a_sharedglobal.h"
#include "d_net.h"
#include "g_level.h"
#include "r_wallsetup.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
#include "r_walldraw.h"
#include "r_memory.h"
#include "swrenderer/line/r_line.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/viewport/r_viewport.h"
namespace swrenderer
{
// Transform and clip coordinates. Returns true if it was clipped away
bool FWallCoords::Init(RenderThread* thread, const DVector2& pt1, const DVector2& pt2, seg_t* lineseg)
{
auto viewport = thread->Viewport.get();
RenderPortal* renderportal = thread->Portal.get();
// Rotate to view direction:
tleft.X = float(pt1.X * viewport->viewpoint.Sin - pt1.Y * viewport->viewpoint.Cos);
tright.X = float(pt2.X * viewport->viewpoint.Sin - pt2.Y * viewport->viewpoint.Cos);
tleft.Y = float(pt1.X * viewport->viewpoint.TanCos + pt1.Y * viewport->viewpoint.TanSin);
tright.Y = float(pt2.X * viewport->viewpoint.TanCos + pt2.Y * viewport->viewpoint.TanSin);
if (renderportal->MirrorFlags & RF_XFLIP)
{
float t = -tleft.X;
tleft.X = -tright.X;
tright.X = t;
std::swap(tleft.Y, tright.Y);
}
// Edge clip:
float fsx1, fsz1, fsx2, fsz2;
if (tleft.X >= -tleft.Y)
{
if (tleft.X > tleft.Y) return true; // left edge is off the right side
if (tleft.Y == 0) return true;
fsx1 = viewport->CenterX + tleft.X * viewport->CenterX / tleft.Y;
fsz1 = tleft.Y;
tx1 = 0.0f;
}
else
{
if (tright.X < -tright.Y) return true; // wall is off the left side
float den = tleft.X - tright.X - tright.Y + tleft.Y;
if (den == 0) return true;
fsx1 = 0;
tx1 = (tleft.X + tleft.Y) / den;
fsz1 = tleft.Y + (tright.Y - tleft.Y) * tx1;
}
if (fsz1 < TOO_CLOSE_Z)
return true;
if (tright.X <= tright.Y)
{
if (tright.X < -tright.Y) return true; // right edge is off the left side
if (tright.Y == 0) return true;
fsx2 = viewport->CenterX + tright.X * viewport->CenterX / tright.Y;
fsz2 = tright.Y;
tx2 = 1.0f;
}
else
{
if (tleft.X > tleft.Y) return true; // wall is off the right side
float den = tright.Y - tleft.Y - tright.X + tleft.X;
if (den == 0) return true;
fsx2 = viewwidth;
tx2 = (tleft.X - tleft.Y) / den;
fsz2 = tleft.Y + (tright.Y - tleft.Y) * tx2;
}
if (fsz2 < TOO_CLOSE_Z)
return true;
// Find screen range covered by the line:
sx1 = xs_RoundToInt(fsx1);
sx2 = xs_RoundToInt(fsx2);
if (sx2 <= sx1)
return true;
// Remap texture coordinates to the part covered by the line segment:
if (lineseg && lineseg->linedef)
{
line_t* line = lineseg->linedef;
float t1, t2;
if (fabs(line->delta.X) > fabs(line->delta.Y))
{
t1 = (lineseg->v1->fX() - line->v1->fX()) / line->delta.X;
t2 = (lineseg->v2->fX() - line->v1->fX()) / line->delta.X;
}
else
{
t1 = (lineseg->v1->fY() - line->v1->fY()) / line->delta.Y;
t2 = (lineseg->v2->fY() - line->v1->fY()) / line->delta.Y;
}
if (line->sidedef[0] != lineseg->sidedef)
{
t1 = 1.0f - t1;
t2 = 1.0f - t2;
}
tx1 = t1 + tx1 * (t2 - t1);
tx2 = t1 + tx2 * (t2 - t1);
}
// Calculate screen depths for the start and end points (resulting values are at the pixel center):
float delta = fsx2 - fsx1;
float t1 = (sx1 + 0.5f - fsx1) / delta;
float t2 = (sx2 + 0.5f - fsx1) / delta;
float invZ1 = 1.0f / fsz1;
float invZ2 = 1.0f / fsz2;
sz1 = 1.0f / (invZ1 * (1.0f - t1) + invZ2 * t1);
sz2 = 1.0f / (invZ1 * (1.0f - t2) + invZ2 * t2);
// Adjust texture coordinates to also be at the pixel centers:
float ftx1 = tx1 * invZ1;
float ftx2 = tx2 * invZ2;
tx1 = (ftx1 * (1.0f - t1) + ftx2 * t1) * sz1;
tx2 = (ftx1 * (1.0f - t2) + ftx2 * t2) * sz2;
return false;
}
////////////////////////////////////////////////////////////////////////////
ProjectedWallCull ProjectedWallLine::Project(RenderViewport *viewport, double z, const FWallCoords *wallc)
{
return Project(viewport, z, z, wallc);
}
ProjectedWallCull ProjectedWallLine::Project(RenderViewport *viewport, double z1, double z2, const FWallCoords *wallc)
{
float y1 = (float)(viewport->CenterY - z1 * viewport->InvZtoScale / wallc->sz1);
float y2 = (float)(viewport->CenterY - z2 * viewport->InvZtoScale / wallc->sz2);
if (y1 < 0 && y2 < 0) // entire line is above screen
{
memset(&ScreenY[wallc->sx1], 0, (wallc->sx2 - wallc->sx1) * sizeof(ScreenY[0]));
return ProjectedWallCull::OutsideAbove;
}
else if (y1 > viewheight && y2 > viewheight) // entire line is below screen
{
fillshort(&ScreenY[wallc->sx1], wallc->sx2 - wallc->sx1, viewheight);
return ProjectedWallCull::OutsideBelow;
}
if (wallc->sx2 <= wallc->sx1)
return ProjectedWallCull::Visible;
float rcp_delta = 1.0f / (wallc->sx2 - wallc->sx1);
if (y1 >= 0.0f && y2 >= 0.0f && xs_RoundToInt(y1) <= viewheight && xs_RoundToInt(y2) <= viewheight)
{
for (int x = wallc->sx1; x < wallc->sx2; x++)
{
float t = (x - wallc->sx1) * rcp_delta;
float y = y1 * (1.0f - t) + y2 * t;
ScreenY[x] = (short)xs_RoundToInt(y);
}
}
else
{
for (int x = wallc->sx1; x < wallc->sx2; x++)
{
float t = (x - wallc->sx1) * rcp_delta;
float y = y1 * (1.0f - t) + y2 * t;
ScreenY[x] = (short)clamp(xs_RoundToInt(y), 0, viewheight);
}
}
return ProjectedWallCull::Visible;
}
ProjectedWallCull ProjectedWallLine::Project(RenderViewport *viewport, const secplane_t &plane, const FWallCoords *wallc, seg_t *curline, bool xflip)
{
if (!plane.isSlope())
{
return Project(viewport, plane.Zat0() - viewport->viewpoint.Pos.Z, wallc);
}
else
{
// Get Z coordinates at both ends of the line
double x, y, den, z1, z2;
if (xflip)
{
x = curline->v2->fX();
y = curline->v2->fY();
if (wallc->sx1 == 0 && 0 != (den = wallc->tleft.X - wallc->tright.X + wallc->tleft.Y - wallc->tright.Y))
{
double frac = (wallc->tleft.Y + wallc->tleft.X) / den;
x -= frac * (x - curline->v1->fX());
y -= frac * (y - curline->v1->fY());
}
z1 = plane.ZatPoint(x, y) - viewport->viewpoint.Pos.Z;
if (wallc->sx2 > wallc->sx1 + 1)
{
x = curline->v1->fX();
y = curline->v1->fY();
if (wallc->sx2 == viewwidth && 0 != (den = wallc->tleft.X - wallc->tright.X - wallc->tleft.Y + wallc->tright.Y))
{
double frac = (wallc->tright.Y - wallc->tright.X) / den;
x += frac * (curline->v2->fX() - x);
y += frac * (curline->v2->fY() - y);
}
z2 = plane.ZatPoint(x, y) - viewport->viewpoint.Pos.Z;
}
else
{
z2 = z1;
}
}
else
{
x = curline->v1->fX();
y = curline->v1->fY();
if (wallc->sx1 == 0 && 0 != (den = wallc->tleft.X - wallc->tright.X + wallc->tleft.Y - wallc->tright.Y))
{
double frac = (wallc->tleft.Y + wallc->tleft.X) / den;
x += frac * (curline->v2->fX() - x);
y += frac * (curline->v2->fY() - y);
}
z1 = plane.ZatPoint(x, y) - viewport->viewpoint.Pos.Z;
if (wallc->sx2 > wallc->sx1 + 1)
{
x = curline->v2->fX();
y = curline->v2->fY();
if (wallc->sx2 == viewwidth && 0 != (den = wallc->tleft.X - wallc->tright.X - wallc->tleft.Y + wallc->tright.Y))
{
double frac = (wallc->tright.Y - wallc->tright.X) / den;
x -= frac * (x - curline->v1->fX());
y -= frac * (y - curline->v1->fY());
}
z2 = plane.ZatPoint(x, y) - viewport->viewpoint.Pos.Z;
}
else
{
z2 = z1;
}
}
return Project(viewport, z1, z2, wallc);
}
}
void ProjectedWallLine::ClipTop(int x1, int x2, const DrawSegmentClipInfo& clip)
{
for (int i = x1; i < x2; i++)
{
ScreenY[i] = std::max(ScreenY[i], clip.sprtopclip[i]);
}
}
void ProjectedWallLine::ClipBottom(int x1, int x2, const DrawSegmentClipInfo& clip)
{
for (int i = x1; i < x2; i++)
{
ScreenY[i] = min(ScreenY[i], clip.sprbottomclip[i]);
}
}
/////////////////////////////////////////////////////////////////////////
void ProjectedWallTexcoords::ProjectTop(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, const FWallCoords& WallC, FSoftwareTexture* pic)
{
side_t* sidedef = lineseg->sidedef;
line_t* linedef = lineseg->linedef;
float yscale = GetYScale(sidedef, pic, side_t::top);
double cameraZ = viewport->viewpoint.Pos.Z;
double texturemid;
if (yscale >= 0)
{ // normal orientation
if (linedef->flags & ML_DONTPEGTOP)
{ // top of texture at top
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale;
}
else
{ // bottom of texture at bottom
texturemid = (backsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight();
}
}
else
{ // upside down
if (linedef->flags & ML_DONTPEGTOP)
{ // bottom of texture at top
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight();
}
else
{ // top of texture at bottom
texturemid = (backsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale;
}
}
texturemid += GetRowOffset(lineseg, pic, side_t::top);
fixed_t xoffset = GetXOffset(lineseg, pic, side_t::top);
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::top), WallC, pic, xoffset, texturemid, yscale, false);
}
void ProjectedWallTexcoords::ProjectMid(RenderViewport* viewport, sector_t* frontsector, seg_t* lineseg, const FWallCoords& WallC, FSoftwareTexture* pic)
{
side_t* sidedef = lineseg->sidedef;
line_t* linedef = lineseg->linedef;
float yscale = GetYScale(sidedef, pic, side_t::mid);
double cameraZ = viewport->viewpoint.Pos.Z;
double texturemid;
if (yscale >= 0)
{ // normal orientation
if (linedef->flags & ML_DONTPEGBOTTOM)
{ // bottom of texture at bottom
texturemid = (frontsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + pic->GetHeight();
}
else
{ // top of texture at top
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale;
}
}
else
{ // upside down
if (linedef->flags & ML_DONTPEGBOTTOM)
{ // top of texture at bottom
texturemid = (frontsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale;
}
else
{ // bottom of texture at top
texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight();
}
}
texturemid += GetRowOffset(lineseg, pic, side_t::mid);
fixed_t xoffset = GetXOffset(lineseg, pic, side_t::mid);
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), WallC, pic, xoffset, texturemid, yscale, false);
}
void ProjectedWallTexcoords::ProjectBottom(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, const FWallCoords& WallC, FSoftwareTexture* pic)
{
side_t* sidedef = lineseg->sidedef;
line_t* linedef = lineseg->linedef;
double frontlowertop = frontsector->GetPlaneTexZ(sector_t::ceiling);
if (frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum)
{
// Putting sky ceilings on the front and back of a line alters the way unpegged
// positioning works.
frontlowertop = backsector->GetPlaneTexZ(sector_t::ceiling);
}
float yscale = GetYScale(sidedef, pic, side_t::bottom);
double cameraZ = viewport->viewpoint.Pos.Z;
double texturemid;
if (yscale >= 0)
{ // normal orientation
if (linedef->flags & ML_DONTPEGBOTTOM)
{ // bottom of texture at bottom
texturemid = (frontlowertop - cameraZ) * yscale;
}
else
{ // top of texture at top
texturemid = (backsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale;
}
}
else
{ // upside down
if (linedef->flags & ML_DONTPEGBOTTOM)
{ // top of texture at bottom
texturemid = (frontlowertop - cameraZ) * yscale;
}
else
{ // bottom of texture at top
texturemid = (backsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + pic->GetHeight();
}
}
texturemid += GetRowOffset(lineseg, pic, side_t::bottom);
fixed_t xoffset = GetXOffset(lineseg, pic, side_t::bottom);
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::bottom), WallC, pic, xoffset, texturemid, yscale, false);
}
void ProjectedWallTexcoords::ProjectTranslucent(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, const FWallCoords& WallC, FSoftwareTexture* pic)
{
line_t* linedef = lineseg->linedef;
side_t* sidedef = lineseg->sidedef;
float yscale = GetYScale(sidedef, pic, side_t::mid);
double cameraZ = viewport->viewpoint.Pos.Z;
double texZFloor = max(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor));
double texZCeiling = min(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling));
double texturemid;
if (yscale >= 0)
{ // normal orientation
if (linedef->flags & ML_DONTPEGBOTTOM)
{ // bottom of texture at bottom
texturemid = (texZFloor - cameraZ) * yscale + pic->GetHeight();
}
else
{ // top of texture at top
texturemid = (texZCeiling - cameraZ) * yscale;
}
}
else
{ // upside down
if (linedef->flags & ML_DONTPEGBOTTOM)
{ // top of texture at bottom
texturemid = (texZFloor - cameraZ) * yscale;
}
else
{ // bottom of texture at top
texturemid = (texZCeiling - cameraZ) * yscale + pic->GetHeight();
}
}
texturemid += GetRowOffset(lineseg, pic, side_t::mid);
fixed_t xoffset = GetXOffset(lineseg, pic, side_t::mid);
Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), WallC, pic, xoffset, texturemid, yscale, false);
}
void ProjectedWallTexcoords::Project3DFloor(RenderViewport* viewport, F3DFloor* rover, seg_t* lineseg, const FWallCoords& WallC, FSoftwareTexture* pic)
{
// find positioning
side_t* scaledside;
side_t::ETexpart scaledpart;
if (rover->flags & FF_UPPERTEXTURE)
{
scaledside = lineseg->sidedef;
scaledpart = side_t::top;
}
else if (rover->flags & FF_LOWERTEXTURE)
{
scaledside = lineseg->sidedef;
scaledpart = side_t::bottom;
}
else
{
scaledside = rover->master->sidedef[0];
scaledpart = side_t::mid;
}
double xscale = pic->GetScale().X * scaledside->GetTextureXScale(scaledpart);
float yscale = pic->GetScale().Y * scaledside->GetTextureYScale(scaledpart);
double rowoffset = lineseg->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid);
double planez = rover->model->GetPlaneTexZ(sector_t::ceiling);
fixed_t xoffset = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid));
if (rowoffset < 0)
{
rowoffset += pic->GetHeight();
}
double texturemid = (planez - viewport->viewpoint.Pos.Z) * yscale;
if (pic->useWorldPanning(lineseg->GetLevel()))
{
// rowoffset is added before the multiply so that the masked texture will
// still be positioned in world units rather than texels.
texturemid = texturemid + rowoffset * yscale;
xoffset = xs_RoundToInt(xoffset * xscale);
}
else
{
// rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units.
texturemid += rowoffset;
}
Project(viewport, lineseg->sidedef->TexelLength * xscale, WallC, pic, xoffset, texturemid, yscale, false);
}
void ProjectedWallTexcoords::Project(RenderViewport *viewport, double walxrepeat, const FWallCoords& WallC, FSoftwareTexture* pic, fixed_t xoffset, double texturemid, float yscale, bool flipx)
{
float texwidth = pic->GetWidth();
float texheight = pic->GetHeight();
float texU1 = FIXED2FLOAT(xoffset) / texwidth;
float texU2 = texU1 + walxrepeat / texwidth;
if (walxrepeat < 0.0)
{
texU1 += 1.0f;
texU2 += 1.0f;
}
if (flipx)
{
texU1 = 1.0f - texU1;
texU2 = 1.0f - texU2;
}
float texV = texturemid / texheight;
// Set up some fake vertices as that makes it easier to calculate the gradients using code already known to work.
Vertex v1;
v1.x = WallC.sx1 + 0.5f;// WallC.tleft.X;
v1.y = 0.0f;
v1.w = WallC.sz1;//WallC.tleft.Y;
Vertex v2;
v2.x = WallC.sx2 + 0.5f;// WallC.tright.X;
v2.y = 0.0f;
v2.w = WallC.sz2;// WallC.tright.Y;
v1.u = texU1 * (1.0f - WallC.tx1) + texU2 * WallC.tx1;
v2.u = texU1 * (1.0f - WallC.tx2) + texU2 * WallC.tx2;
v1.v = texV;
v2.v = texV;
Vertex v3;
v3.x = v1.x;
v3.y = v1.y - 100.0f;
v3.w = v1.w;
v3.u = v1.u;
v3.v = v1.v + yscale * 100.0f / texheight;
// Project to screen space
v1.w = 1.0f / v1.w;
v2.w = 1.0f / v2.w;
v3.w = 1.0f / v3.w;
v1.y = viewport->CenterY - v1.y * v1.w * viewport->InvZtoScale;
v2.y = viewport->CenterY - v2.y * v2.w * viewport->InvZtoScale;
v3.y = viewport->CenterY - v3.y * v3.w * viewport->InvZtoScale;
// Calculate gradients
float bottomX = (v2.x - v3.x) * (v1.y - v3.y) - (v1.x - v3.x) * (v2.y - v3.y);
float bottomY = (v1.x - v3.x) * (v2.y - v3.y) - (v2.x - v3.x) * (v1.y - v3.y);
wstepX = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f, v1, v2, v3);
ustepX = FindGradientX(bottomX, v1.u, v2.u, v3.u, v1, v2, v3);
vstepX = FindGradientX(bottomX, v1.v, v2.v, v3.v, v1, v2, v3);
wstepY = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f, v1, v2, v3);
ustepY = FindGradientY(bottomY, v1.u, v2.u, v3.u, v1, v2, v3);
vstepY = FindGradientY(bottomY, v1.v, v2.v, v3.v, v1, v2, v3);
startX = v1.x;
upos = v1.u * v1.w;
vpos = v1.v * v1.w;
wpos = v1.w;
}
double ProjectedWallTexcoords::GetRowOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart)
{
double yrepeat = GetYScale(lineseg->sidedef, tex, texpart);
double rowoffset = lineseg->sidedef->GetTextureYOffset(texpart);
if (yrepeat >= 0)
{
// check if top of texture at top:
bool top_at_top =
(texpart == side_t::top && (lineseg->linedef->flags & ML_DONTPEGTOP)) ||
(texpart != side_t::top && !(lineseg->linedef->flags & ML_DONTPEGBOTTOM));
if (rowoffset < 0 && top_at_top)
{
rowoffset += tex->GetHeight();
}
}
else
{
rowoffset = -rowoffset;
}
if (tex->useWorldPanning(lineseg->GetLevel()))
{
return rowoffset * yrepeat;
}
else
{
// rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units.
return rowoffset;
}
}
fixed_t ProjectedWallTexcoords::GetXOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart)
{
fixed_t TextureOffsetU = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(texpart));
double xscale = GetXScale(lineseg->sidedef, tex, texpart);
fixed_t xoffset;
if (tex->useWorldPanning(lineseg->GetLevel()))
{
xoffset = xs_RoundToInt(TextureOffsetU * xscale);
}
else
{
xoffset = TextureOffsetU;
}
if (xscale < 0)
{
xoffset = -xoffset;
}
return xoffset;
}
double ProjectedWallTexcoords::GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart)
{
double TextureScaleU = sidedef->GetTextureXScale(texpart);
return tex->GetScale().X * TextureScaleU;
}
double ProjectedWallTexcoords::GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart)
{
double TextureScaleV = sidedef->GetTextureYScale(texpart);
return tex->GetScale().Y * TextureScaleV;
}
/////////////////////////////////////////////////////////////////////////
void ProjectedWallLight::SetLightLeft(RenderThread *thread, const FWallCoords &wallc)
{
spritelight = false;
x1 = wallc.sx1;
CameraLight *cameraLight = CameraLight::Instance();
if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0)
{
lightleft = float(thread->Light->WallVis(wallc.sz1, foggy));
lightstep = float((thread->Light->WallVis(wallc.sz2, foggy) - lightleft) / (wallc.sx2 - wallc.sx1));
}
else
{
lightleft = 1;
lightstep = 0;
}
}
void ProjectedWallLight::SetColormap(const sector_t *frontsector, seg_t *lineseg, int tier, lightlist_t *lit)
{
if (!lit)
{
basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
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, tier);
else
lightlevel = frontsector->GetLightLevel();
}
else
{
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, tier, lit->lightsource != nullptr);
}
}
}