mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-26 13:10:59 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
This commit is contained in:
commit
3559f7dffb
22 changed files with 599 additions and 602 deletions
|
@ -801,7 +801,7 @@ static inline bool isFakePain(AActor *target, AActor *inflictor, int damage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// [MC] Completely ripped out of DamageMobj to make it less messy.
|
// [MC] Completely ripped out of DamageMobj to make it less messy.
|
||||||
static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags)
|
static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags, int originaldamage)
|
||||||
{
|
{
|
||||||
bool justhit = false;
|
bool justhit = false;
|
||||||
int painchance = 0;
|
int painchance = 0;
|
||||||
|
@ -827,7 +827,7 @@ static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int
|
||||||
// Are we attempting to cause pain?
|
// Are we attempting to cause pain?
|
||||||
if (!noPain)
|
if (!noPain)
|
||||||
{
|
{
|
||||||
fakedPain = (isFakePain(target, inflictor, damage));
|
fakedPain = (isFakePain(target, inflictor, originaldamage));
|
||||||
forcedPain = (MustForcePain(target, inflictor));
|
forcedPain = (MustForcePain(target, inflictor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1456,7 +1456,7 @@ static int DoDamageMobj(AActor *target, AActor *inflictor, AActor *source, int d
|
||||||
bool needevent = true;
|
bool needevent = true;
|
||||||
int realdamage = DamageMobj(target, inflictor, source, damage, mod, flags, angle, needevent);
|
int realdamage = DamageMobj(target, inflictor, source, damage, mod, flags, angle, needevent);
|
||||||
if (realdamage >= 0) //Keep this check separated. Mods relying upon negative numbers may break otherwise.
|
if (realdamage >= 0) //Keep this check separated. Mods relying upon negative numbers may break otherwise.
|
||||||
ReactToDamage(target, inflictor, source, realdamage, mod, flags);
|
ReactToDamage(target, inflictor, source, realdamage, mod, flags, damage);
|
||||||
|
|
||||||
if (realdamage > 0 && needevent)
|
if (realdamage > 0 && needevent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,19 +54,20 @@
|
||||||
|
|
||||||
namespace swrenderer
|
namespace swrenderer
|
||||||
{
|
{
|
||||||
void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, int lightlevel, bool foggy, float lightleft, float lightstep, FDynamicColormap *basecolormap)
|
void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, const ProjectedWallLight &wallLight)
|
||||||
{
|
{
|
||||||
// This is essentially the same as R_MapVisPlane but with an extra step
|
// This is essentially the same as R_MapVisPlane but with an extra step
|
||||||
// to create new horizontal spans whenever the light changes enough that
|
// to create new horizontal spans whenever the light changes enough that
|
||||||
// we need to use a new colormap.
|
// we need to use a new colormap.
|
||||||
|
|
||||||
int wallshade = LightVisibility::LightLevelToShade(lightlevel, foggy, thread->Viewport.get());
|
int wallshade = LightVisibility::LightLevelToShade(wallLight.GetLightLevel(), wallLight.GetFoggy(), thread->Viewport.get());
|
||||||
float light = lightleft + lightstep*(x2 - x1 - 1);
|
|
||||||
int x = x2 - 1;
|
int x = x2 - 1;
|
||||||
int t2 = uclip[x];
|
int t2 = uclip[x];
|
||||||
int b2 = dclip[x];
|
int b2 = dclip[x];
|
||||||
|
float light = wallLight.GetLightPos(x);
|
||||||
int rcolormap = GETPALOOKUP(light, wallshade);
|
int rcolormap = GETPALOOKUP(light, wallshade);
|
||||||
int lcolormap;
|
int lcolormap;
|
||||||
|
FDynamicColormap *basecolormap = wallLight.GetBaseColormap();
|
||||||
uint8_t *basecolormapdata = basecolormap->Maps;
|
uint8_t *basecolormapdata = basecolormap->Maps;
|
||||||
|
|
||||||
if (b2 > t2)
|
if (b2 > t2)
|
||||||
|
@ -75,7 +76,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
drawerargs.SetBaseColormap(basecolormap);
|
drawerargs.SetBaseColormap(basecolormap);
|
||||||
drawerargs.SetLight(light, lightlevel, foggy, thread->Viewport.get());
|
drawerargs.SetLight(light, wallLight.GetLightLevel(), wallLight.GetFoggy(), thread->Viewport.get());
|
||||||
|
|
||||||
uint8_t *fake_dc_colormap = basecolormap->Maps + (GETPALOOKUP(light, wallshade) << COLORMAPSHIFT);
|
uint8_t *fake_dc_colormap = basecolormap->Maps + (GETPALOOKUP(light, wallshade) << COLORMAPSHIFT);
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ namespace swrenderer
|
||||||
const int xr = x + 1;
|
const int xr = x + 1;
|
||||||
int stop;
|
int stop;
|
||||||
|
|
||||||
light -= lightstep;
|
light -= wallLight.GetLightStep();
|
||||||
lcolormap = GETPALOOKUP(light, wallshade);
|
lcolormap = GETPALOOKUP(light, wallshade);
|
||||||
if (lcolormap != rcolormap)
|
if (lcolormap != rcolormap)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace swrenderer
|
||||||
class RenderFogBoundary
|
class RenderFogBoundary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, int lightlevel, bool foggy, float lightleft, float lightstep, FDynamicColormap *basecolormap);
|
void Render(RenderThread *thread, int x1, int x2, const short *uclip, const short *dclip, const ProjectedWallLight &wallLight);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RenderSection(RenderThread *thread, int y, int y2, int x1);
|
void RenderSection(RenderThread *thread, int y, int y2, int x1);
|
||||||
|
|
|
@ -71,15 +71,13 @@ namespace swrenderer
|
||||||
Thread = thread;
|
Thread = thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWRenderLine::Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, bool infog, FDynamicColormap *colormap, Fake3DOpaque opaque3dfloor)
|
void SWRenderLine::Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, Fake3DOpaque opaque3dfloor)
|
||||||
{
|
{
|
||||||
mSubsector = subsector;
|
mSubsector = subsector;
|
||||||
mFrontSector = sector;
|
mFrontSector = sector;
|
||||||
mBackSector = fakebacksector;
|
mBackSector = fakebacksector;
|
||||||
mFloorPlane = linefloorplane;
|
mFloorPlane = linefloorplane;
|
||||||
mCeilingPlane = lineceilingplane;
|
mCeilingPlane = lineceilingplane;
|
||||||
foggy = infog;
|
|
||||||
basecolormap = colormap;
|
|
||||||
mLineSegment = line;
|
mLineSegment = line;
|
||||||
m3DFloor = opaque3dfloor;
|
m3DFloor = opaque3dfloor;
|
||||||
|
|
||||||
|
@ -314,7 +312,7 @@ namespace swrenderer
|
||||||
if (!rw_prepped)
|
if (!rw_prepped)
|
||||||
{
|
{
|
||||||
rw_prepped = true;
|
rw_prepped = true;
|
||||||
SetWallVariables(true);
|
SetWallVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
side_t *sidedef = mLineSegment->sidedef;
|
side_t *sidedef = mLineSegment->sidedef;
|
||||||
|
@ -326,26 +324,15 @@ namespace swrenderer
|
||||||
|
|
||||||
// 3D floors code abuses the line render code to update plane clipping
|
// 3D floors code abuses the line render code to update plane clipping
|
||||||
// lists but doesn't actually draw anything.
|
// lists but doesn't actually draw anything.
|
||||||
bool onlyUpdatePlaneClip = (m3DFloor.type != Fake3DOpaque::Normal);
|
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||||
if (!onlyUpdatePlaneClip)
|
|
||||||
Thread->DrawSegments->Push(draw_segment);
|
Thread->DrawSegments->Push(draw_segment);
|
||||||
|
|
||||||
draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||||
draw_segment->sx1 = WallC.sx1;
|
draw_segment->WallC = WallC;
|
||||||
draw_segment->sx2 = WallC.sx2;
|
|
||||||
draw_segment->sz1 = WallC.sz1;
|
|
||||||
draw_segment->sz2 = WallC.sz2;
|
|
||||||
draw_segment->cx = WallC.tleft.X;
|
|
||||||
draw_segment->cy = WallC.tleft.Y;
|
|
||||||
draw_segment->cdx = WallC.tright.X - WallC.tleft.X;
|
|
||||||
draw_segment->cdy = WallC.tright.Y - WallC.tleft.Y;
|
|
||||||
draw_segment->tmapvals = WallT;
|
draw_segment->tmapvals = WallT;
|
||||||
draw_segment->siz1 = 1 / WallC.sz1;
|
|
||||||
draw_segment->siz2 = 1 / WallC.sz2;
|
|
||||||
draw_segment->x1 = start;
|
draw_segment->x1 = start;
|
||||||
draw_segment->x2 = stop;
|
draw_segment->x2 = stop;
|
||||||
draw_segment->curline = mLineSegment;
|
draw_segment->curline = mLineSegment;
|
||||||
draw_segment->foggy = foggy;
|
|
||||||
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
||||||
|
|
||||||
bool markportal = ShouldMarkPortal();
|
bool markportal = ShouldMarkPortal();
|
||||||
|
@ -400,7 +387,9 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!onlyUpdatePlaneClip && r_3dfloors)
|
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||||
|
{
|
||||||
|
if (r_3dfloors)
|
||||||
{
|
{
|
||||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||||
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||||
|
@ -422,7 +411,6 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!onlyUpdatePlaneClip)
|
|
||||||
// allocate space for masked texture tables, if needed
|
// allocate space for masked texture tables, if needed
|
||||||
// [RH] Don't just allocate the space; fill it in too.
|
// [RH] Don't just allocate the space; fill it in too.
|
||||||
if ((sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls() || IsFogBoundary(mFrontSector, mBackSector)) &&
|
if ((sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls() || IsFogBoundary(mFrontSector, mBackSector)) &&
|
||||||
|
@ -452,8 +440,8 @@ namespace swrenderer
|
||||||
lwal = draw_segment->maskedtexturecol;
|
lwal = draw_segment->maskedtexturecol;
|
||||||
swal = draw_segment->swall;
|
swal = draw_segment->swall;
|
||||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||||
FSoftwareTexture *pic = tex && tex->isValid()? tex->GetSoftwareTexture() : nullptr;
|
FSoftwareTexture *pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||||
double yscale = (pic? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid);
|
double yscale = (pic ? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid);
|
||||||
fixed_t xoffset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
fixed_t xoffset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||||
|
|
||||||
if (pic && pic->useWorldPanning())
|
if (pic && pic->useWorldPanning())
|
||||||
|
@ -490,21 +478,9 @@ namespace swrenderer
|
||||||
draw_segment->iscalestep = 0;
|
draw_segment->iscalestep = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
draw_segment->light = rw_lightleft + rw_lightstep * (start - WallC.sx1);
|
|
||||||
draw_segment->lightstep = rw_lightstep;
|
|
||||||
|
|
||||||
// Masked mMiddlePart.Textures should get the light level from the sector they reference,
|
draw_segment->light = mLight.GetLightPos(start);
|
||||||
// not from the current subsector, which is what the current lightlevel value
|
draw_segment->lightstep = mLight.GetLightStep();
|
||||||
// comes from. We make an exeption for polyobjects, however, since their "home"
|
|
||||||
// sector should be whichever one they move into.
|
|
||||||
if (mLineSegment->sidedef->Flags & WALLF_POLYOBJ)
|
|
||||||
{
|
|
||||||
draw_segment->lightlevel = lightlevel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
draw_segment->lightlevel = mLineSegment->sidedef->GetLightLevel(foggy, mLineSegment->frontsector->lightlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
|
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -512,6 +488,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ClipSegmentTopBottom(start, stop);
|
ClipSegmentTopBottom(start, stop);
|
||||||
|
|
||||||
|
@ -552,7 +529,7 @@ namespace swrenderer
|
||||||
// [ZZ] Only if not an active mirror
|
// [ZZ] Only if not an active mirror
|
||||||
if (!markportal)
|
if (!markportal)
|
||||||
{
|
{
|
||||||
RenderDecal::RenderDecals(Thread, mLineSegment->sidedef, draw_segment, lightlevel, rw_lightleft, rw_lightstep, mLineSegment, WallC, foggy, basecolormap, walltop.ScreenY, wallbottom.ScreenY, false);
|
RenderDecal::RenderDecals(Thread, mLineSegment->sidedef, draw_segment, mLineSegment, mLight, walltop.ScreenY, wallbottom.ScreenY, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (markportal)
|
if (markportal)
|
||||||
|
@ -700,7 +677,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWRenderLine::SetWallVariables(bool needlights)
|
void SWRenderLine::SetWallVariables()
|
||||||
{
|
{
|
||||||
RenderPortal *renderportal = Thread->Portal.get();
|
RenderPortal *renderportal = Thread->Portal.get();
|
||||||
|
|
||||||
|
@ -775,8 +752,13 @@ namespace swrenderer
|
||||||
|
|
||||||
bool segtextured = ftex != NULL || mTopPart.Texture != NULL || mBottomPart.Texture != NULL;
|
bool segtextured = ftex != NULL || mTopPart.Texture != NULL || mBottomPart.Texture != NULL;
|
||||||
|
|
||||||
|
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||||
|
{
|
||||||
|
mLight.SetColormap(mFrontSector, mLineSegment);
|
||||||
|
}
|
||||||
|
|
||||||
// calculate light table
|
// calculate light table
|
||||||
if (needlights && (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector))))
|
if (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector)))
|
||||||
{
|
{
|
||||||
lwallscale =
|
lwallscale =
|
||||||
ftex ? ((midtex? midtex->GetScale().X : 1.0) * sidedef->GetTextureXScale(side_t::mid)) :
|
ftex ? ((midtex? midtex->GetScale().X : 1.0) * sidedef->GetTextureXScale(side_t::mid)) :
|
||||||
|
@ -786,18 +768,7 @@ namespace swrenderer
|
||||||
|
|
||||||
walltexcoords.Project(Thread->Viewport.get(), sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT);
|
walltexcoords.Project(Thread->Viewport.get(), sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT);
|
||||||
|
|
||||||
CameraLight *cameraLight = CameraLight::Instance();
|
mLight.SetLightLeft(Thread, WallC);
|
||||||
if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0)
|
|
||||||
{
|
|
||||||
lightlevel = mLineSegment->sidedef->GetLightLevel(foggy, mFrontSector->lightlevel);
|
|
||||||
rw_lightleft = float(Thread->Light->WallVis(WallC.sz1, foggy));
|
|
||||||
rw_lightstep = float((Thread->Light->WallVis(WallC.sz2, foggy) - rw_lightleft) / (WallC.sx2 - WallC.sx1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rw_lightleft = 1;
|
|
||||||
rw_lightstep = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,10 +1135,8 @@ namespace swrenderer
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1);
|
|
||||||
|
|
||||||
RenderWallPart renderWallpart(Thread);
|
RenderWallPart renderWallpart(Thread);
|
||||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, lightlevel, offset, rw_light, rw_lightstep, GetLightList(), foggy, basecolormap);
|
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, offset, mLight, GetLightList());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWRenderLine::RenderMiddleTexture(int x1, int x2)
|
void SWRenderLine::RenderMiddleTexture(int x1, int x2)
|
||||||
|
@ -1197,10 +1166,8 @@ namespace swrenderer
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1);
|
|
||||||
|
|
||||||
RenderWallPart renderWallpart(Thread);
|
RenderWallPart renderWallpart(Thread);
|
||||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, lightlevel, offset, rw_light, rw_lightstep, GetLightList(), foggy, basecolormap);
|
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWRenderLine::RenderBottomTexture(int x1, int x2)
|
void SWRenderLine::RenderBottomTexture(int x1, int x2)
|
||||||
|
@ -1231,10 +1198,8 @@ namespace swrenderer
|
||||||
offset = -offset;
|
offset = -offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1);
|
|
||||||
|
|
||||||
RenderWallPart renderWallpart(Thread);
|
RenderWallPart renderWallpart(Thread);
|
||||||
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, lightlevel, offset, rw_light, rw_lightstep, GetLightList(), foggy, basecolormap);
|
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList());
|
||||||
}
|
}
|
||||||
|
|
||||||
FLightNode *SWRenderLine::GetLightList()
|
FLightNode *SWRenderLine::GetLightList()
|
||||||
|
|
|
@ -72,13 +72,13 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SWRenderLine(RenderThread *thread);
|
SWRenderLine(RenderThread *thread);
|
||||||
void Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap, Fake3DOpaque fake3DOpaque);
|
void Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, Fake3DOpaque fake3DOpaque);
|
||||||
|
|
||||||
RenderThread *Thread = nullptr;
|
RenderThread *Thread = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool RenderWallSegment(int x1, int x2) override;
|
bool RenderWallSegment(int x1, int x2) override;
|
||||||
void SetWallVariables(bool needlights);
|
void SetWallVariables();
|
||||||
void SetTopTexture();
|
void SetTopTexture();
|
||||||
void SetMiddleTexture();
|
void SetMiddleTexture();
|
||||||
void SetBottomTexture();
|
void SetBottomTexture();
|
||||||
|
@ -128,16 +128,11 @@ namespace swrenderer
|
||||||
FWallCoords WallC;
|
FWallCoords WallC;
|
||||||
FWallTmapVals WallT;
|
FWallTmapVals WallT;
|
||||||
|
|
||||||
bool foggy;
|
|
||||||
FDynamicColormap *basecolormap;
|
|
||||||
|
|
||||||
// Wall segment variables:
|
// Wall segment variables:
|
||||||
|
|
||||||
bool rw_prepped;
|
bool rw_prepped;
|
||||||
|
|
||||||
int lightlevel;
|
ProjectedWallLight mLight;
|
||||||
float rw_lightstep;
|
|
||||||
float rw_lightleft;
|
|
||||||
|
|
||||||
double lwallscale;
|
double lwallscale;
|
||||||
|
|
||||||
|
|
|
@ -80,12 +80,8 @@ namespace swrenderer
|
||||||
sector_t tempsec;
|
sector_t tempsec;
|
||||||
const sector_t *sec = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0);
|
const sector_t *sec = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0);
|
||||||
|
|
||||||
FDynamicColormap *basecolormap = GetColorTable(sec->Colormap, sec->SpecialColors[sector_t::walltop]); // [RH] Set basecolormap
|
mLight.SetColormap(sec, curline);
|
||||||
|
mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1);
|
||||||
bool foggy = ds->foggy;
|
|
||||||
int lightlevel = ds->lightlevel;
|
|
||||||
rw_lightstep = ds->lightstep;
|
|
||||||
rw_light = ds->light + (x1 - ds->x1) * rw_lightstep;
|
|
||||||
|
|
||||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||||
|
|
||||||
|
@ -94,10 +90,7 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0())
|
if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0())
|
||||||
{
|
{
|
||||||
lightlist_t *lit = &frontsector->e->XFloor.lightlist[i];
|
mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]);
|
||||||
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag
|
|
||||||
lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +100,7 @@ namespace swrenderer
|
||||||
|
|
||||||
SpriteDrawerArgs columndrawerargs;
|
SpriteDrawerArgs columndrawerargs;
|
||||||
ColormapLight cmlight;
|
ColormapLight cmlight;
|
||||||
cmlight.SetColormap(Thread, MINZ, lightlevel, foggy, basecolormap, false, false, false, false, false);
|
cmlight.SetColormap(Thread, MINZ, mLight.GetLightLevel(), mLight.GetFoggy(), mLight.GetBaseColormap(), false, false, false, false, false);
|
||||||
bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, cmlight);
|
bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, cmlight);
|
||||||
if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls())
|
if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls())
|
||||||
{
|
{
|
||||||
|
@ -123,7 +116,7 @@ namespace swrenderer
|
||||||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||||
|
|
||||||
RenderFogBoundary renderfog;
|
RenderFogBoundary renderfog;
|
||||||
renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, lightlevel, ds->foggy, rw_light, rw_lightstep, basecolormap);
|
renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, mLight);
|
||||||
|
|
||||||
if (ds->maskedtexturecol == nullptr)
|
if (ds->maskedtexturecol == nullptr)
|
||||||
renderwall = false;
|
renderwall = false;
|
||||||
|
@ -134,7 +127,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderwall)
|
if (renderwall)
|
||||||
notrelevant = RenderWall(ds, x1, x2, basecolormap, columndrawerargs, visible, lightlevel, foggy);
|
notrelevant = RenderWall(ds, x1, x2, columndrawerargs, visible);
|
||||||
|
|
||||||
if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls())
|
if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls())
|
||||||
{
|
{
|
||||||
|
@ -147,7 +140,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, FDynamicColormap *basecolormap, SpriteDrawerArgs &columndrawerargs, bool visible, int lightlevel, bool foggy)
|
bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2, SpriteDrawerArgs &columndrawerargs, bool visible)
|
||||||
{
|
{
|
||||||
auto renderstyle = DefaultRenderStyle();
|
auto renderstyle = DefaultRenderStyle();
|
||||||
auto viewport = Thread->Viewport.get();
|
auto viewport = Thread->Viewport.get();
|
||||||
|
@ -226,12 +219,12 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Don't bother drawing segs that are completely offscreen
|
// [RH] Don't bother drawing segs that are completely offscreen
|
||||||
if (viewport->globaldclip * ds->sz1 < -textop && viewport->globaldclip * ds->sz2 < -textop)
|
if (viewport->globaldclip * ds->WallC.sz1 < -textop && viewport->globaldclip * ds->WallC.sz2 < -textop)
|
||||||
{ // Texture top is below the bottom of the screen
|
{ // Texture top is below the bottom of the screen
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewport->globaluclip * ds->sz1 > texheight - textop && viewport->globaluclip * ds->sz2 > texheight - textop)
|
if (viewport->globaluclip * ds->WallC.sz1 > texheight - textop && viewport->globaluclip * ds->WallC.sz2 > texheight - textop)
|
||||||
{ // Texture bottom is above the top of the screen
|
{ // Texture bottom is above the top of the screen
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -245,10 +238,10 @@ namespace swrenderer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WallC.sz1 = ds->sz1;
|
WallC.sz1 = ds->WallC.sz1;
|
||||||
WallC.sz2 = ds->sz2;
|
WallC.sz2 = ds->WallC.sz2;
|
||||||
WallC.sx1 = ds->sx1;
|
WallC.sx1 = ds->WallC.sx1;
|
||||||
WallC.sx2 = ds->sx2;
|
WallC.sx2 = ds->WallC.sx2;
|
||||||
|
|
||||||
// Unclipped vanilla Doom range for the wall. Relies on ceiling/floor clip to clamp the wall in range.
|
// Unclipped vanilla Doom range for the wall. Relies on ceiling/floor clip to clamp the wall in range.
|
||||||
double ceilZ = textop;
|
double ceilZ = textop;
|
||||||
|
@ -317,10 +310,11 @@ namespace swrenderer
|
||||||
if (visible)
|
if (visible)
|
||||||
{
|
{
|
||||||
Thread->PrepareTexture(tex, renderstyle);
|
Thread->PrepareTexture(tex, renderstyle);
|
||||||
|
float lightpos = mLight.GetLightPos(x1);
|
||||||
for (int x = x1; x < x2; ++x)
|
for (int x = x1; x < x2; ++x)
|
||||||
{
|
{
|
||||||
if (needslight)
|
if (needslight)
|
||||||
columndrawerargs.SetLight(rw_light, lightlevel, foggy, Thread->Viewport.get());
|
columndrawerargs.SetLight(lightpos, mLight.GetLightLevel(), mLight.GetFoggy(), Thread->Viewport.get());
|
||||||
|
|
||||||
fixed_t iscale = xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY);
|
fixed_t iscale = xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY);
|
||||||
double sprtopscreen;
|
double sprtopscreen;
|
||||||
|
@ -331,7 +325,7 @@ namespace swrenderer
|
||||||
|
|
||||||
columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, renderstyle);
|
columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, renderstyle);
|
||||||
|
|
||||||
rw_light += rw_lightstep;
|
lightpos += mLight.GetLightStep();
|
||||||
spryscale += rw_scalestep;
|
spryscale += rw_scalestep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,10 +345,10 @@ namespace swrenderer
|
||||||
texturemid = (texturemid - Thread->Viewport->viewpoint.Pos.Z) * MaskedScaleY + rowoffset;
|
texturemid = (texturemid - Thread->Viewport->viewpoint.Pos.Z) * MaskedScaleY + rowoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
WallC.sz1 = ds->sz1;
|
WallC.sz1 = ds->WallC.sz1;
|
||||||
WallC.sz2 = ds->sz2;
|
WallC.sz2 = ds->WallC.sz2;
|
||||||
WallC.sx1 = ds->sx1;
|
WallC.sx1 = ds->WallC.sx1;
|
||||||
WallC.sx2 = ds->sx2;
|
WallC.sx2 = ds->WallC.sx2;
|
||||||
|
|
||||||
if (clip3d->CurrentSkybox)
|
if (clip3d->CurrentSkybox)
|
||||||
{ // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor
|
{ // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor
|
||||||
|
@ -399,14 +393,14 @@ namespace swrenderer
|
||||||
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
|
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
|
||||||
|
|
||||||
RenderWallPart renderWallpart(Thread);
|
RenderWallPart renderWallpart(Thread);
|
||||||
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, additive, alpha, lightlevel, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap);
|
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, additive, alpha, rw_offset, mLight, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// kg3D - render one fake wall
|
// kg3D - render one fake wall
|
||||||
void RenderDrawSegment::RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int lightlevel, FDynamicColormap *basecolormap, double clipTop, double clipBottom, FSoftwareTexture *rw_pic)
|
void RenderDrawSegment::RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double xscale;
|
double xscale;
|
||||||
|
@ -416,8 +410,7 @@ namespace swrenderer
|
||||||
if (Alpha <= 0)
|
if (Alpha <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rw_lightstep = ds->lightstep;
|
mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1);
|
||||||
rw_light = ds->light + (x1 - ds->x1) * rw_lightstep;
|
|
||||||
|
|
||||||
const short *mfloorclip = ds->sprbottomclip - ds->x1;
|
const short *mfloorclip = ds->sprbottomclip - ds->x1;
|
||||||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||||
|
@ -469,14 +462,7 @@ namespace swrenderer
|
||||||
texturemid += rowoffset;
|
texturemid += rowoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
WallC.sz1 = ds->sz1;
|
WallC = ds->WallC;
|
||||||
WallC.sz2 = ds->sz2;
|
|
||||||
WallC.sx1 = ds->sx1;
|
|
||||||
WallC.sx2 = ds->sx2;
|
|
||||||
WallC.tleft.X = ds->cx;
|
|
||||||
WallC.tleft.Y = ds->cy;
|
|
||||||
WallC.tright.X = ds->cx + ds->cdx;
|
|
||||||
WallC.tright.Y = ds->cy + ds->cdy;
|
|
||||||
WallT = ds->tmapvals;
|
WallT = ds->tmapvals;
|
||||||
|
|
||||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||||
|
@ -495,15 +481,15 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectedWallTexcoords walltexcoords;
|
ProjectedWallTexcoords walltexcoords;
|
||||||
walltexcoords.ProjectPos(Thread->Viewport.get(), curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2, WallT);
|
walltexcoords.ProjectPos(Thread->Viewport.get(), curline->sidedef->TexelLength*xscale, ds->WallC.sx1, ds->WallC.sx2, WallT);
|
||||||
|
|
||||||
double top, bot;
|
double top, bot;
|
||||||
GetMaskedWallTopBottom(ds, top, bot);
|
GetMaskedWallTopBottom(ds, top, bot);
|
||||||
|
|
||||||
RenderWallPart renderWallpart(Thread);
|
RenderWallPart renderWallpart(Thread);
|
||||||
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, lightlevel, rw_offset, rw_light, rw_lightstep, nullptr, ds->foggy, basecolormap);
|
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, rw_offset, mLight, nullptr);
|
||||||
|
|
||||||
RenderDecal::RenderDecals(Thread, curline->sidedef, ds, lightlevel, rw_light, rw_lightstep, curline, WallC, ds->foggy, basecolormap, wallupper.ScreenY, walllower.ScreenY, true);
|
RenderDecal::RenderDecals(Thread, curline->sidedef, ds, curline, mLight, wallupper.ScreenY, walllower.ScreenY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// kg3D - walls of fake floors
|
// kg3D - walls of fake floors
|
||||||
|
@ -695,9 +681,11 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
rw_pic = rw_tex && rw_tex->isValid() ? rw_tex->GetSoftwareTexture() : nullptr;
|
rw_pic = rw_tex && rw_tex->isValid() ? rw_tex->GetSoftwareTexture() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rw_pic && !swimmable_found)
|
||||||
|
{
|
||||||
// correct colors now
|
// correct colors now
|
||||||
FDynamicColormap *basecolormap = nullptr;
|
lightlist_t *lit = nullptr;
|
||||||
int lightlevel = ds->lightlevel;
|
|
||||||
CameraLight *cameraLight = CameraLight::Instance();
|
CameraLight *cameraLight = CameraLight::Instance();
|
||||||
if (cameraLight->FixedLightLevel() < 0)
|
if (cameraLight->FixedLightLevel() < 0)
|
||||||
{
|
{
|
||||||
|
@ -707,10 +695,7 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||||
{
|
{
|
||||||
lightlist_t *lit = &backsector->e->XFloor.lightlist[j];
|
lit = &backsector->e->XFloor.lightlist[j];
|
||||||
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
//bool foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag
|
|
||||||
lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -721,20 +706,17 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||||
{
|
{
|
||||||
lightlist_t *lit = &frontsector->e->XFloor.lightlist[j];
|
lit = &frontsector->e->XFloor.lightlist[j];
|
||||||
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
//bool foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag
|
|
||||||
lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (basecolormap == nullptr) basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
|
|
||||||
if (rw_pic && !swimmable_found)
|
//mLight.lightlevel = ds->lightlevel;
|
||||||
{
|
mLight.SetColormap(frontsector, curline, lit);
|
||||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, lightlevel, basecolormap, clipTop, clipBottom, rw_pic);
|
|
||||||
|
RenderFakeWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -882,9 +864,11 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
rw_pic = rw_tex && rw_tex->isValid() ? rw_tex->GetSoftwareTexture() : nullptr;
|
rw_pic = rw_tex && rw_tex->isValid() ? rw_tex->GetSoftwareTexture() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rw_pic && !swimmable_found)
|
||||||
|
{
|
||||||
// correct colors now
|
// correct colors now
|
||||||
FDynamicColormap *basecolormap = nullptr;
|
lightlist_t *lit = nullptr;
|
||||||
int lightlevel = ds->lightlevel;
|
|
||||||
CameraLight *cameraLight = CameraLight::Instance();
|
CameraLight *cameraLight = CameraLight::Instance();
|
||||||
if (cameraLight->FixedLightLevel() < 0)
|
if (cameraLight->FixedLightLevel() < 0)
|
||||||
{
|
{
|
||||||
|
@ -894,10 +878,7 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||||
{
|
{
|
||||||
lightlist_t *lit = &backsector->e->XFloor.lightlist[j];
|
lit = &backsector->e->XFloor.lightlist[j];
|
||||||
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
bool foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag
|
|
||||||
lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -908,20 +889,16 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||||
{
|
{
|
||||||
lightlist_t *lit = &frontsector->e->XFloor.lightlist[j];
|
lit = &frontsector->e->XFloor.lightlist[j];
|
||||||
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
bool foggy = (level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE)); // [RH] set foggy flag
|
|
||||||
lightlevel = curline->sidedef->GetLightLevel(ds->foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (basecolormap == nullptr) basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
//mLight.lightlevel = ds->lightlevel;
|
||||||
|
mLight.SetColormap(frontsector, curline, lit);
|
||||||
|
|
||||||
if (rw_pic && !swimmable_found)
|
RenderFakeWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||||
{
|
|
||||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, lightlevel, basecolormap, clipTop, clipBottom, rw_pic);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,9 +37,9 @@ namespace swrenderer
|
||||||
RenderThread *Thread = nullptr;
|
RenderThread *Thread = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool RenderWall(DrawSegment *ds, int x1, int x2, FDynamicColormap *basecolormap, SpriteDrawerArgs &columndrawerargs, bool visible, int lightlevel, bool foggy);
|
bool RenderWall(DrawSegment *ds, int x1, int x2, SpriteDrawerArgs &columndrawerargs, bool visible);
|
||||||
void ClipMidtex(int x1, int x2);
|
void ClipMidtex(int x1, int x2);
|
||||||
void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, int lightlevel, FDynamicColormap *basecolormap, double clipTop, double clipBottom, FSoftwareTexture *rw_pic);
|
void RenderFakeWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic);
|
||||||
void RenderFakeWallRange(DrawSegment *ds, int x1, int x2);
|
void RenderFakeWallRange(DrawSegment *ds, int x1, int x2);
|
||||||
void GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot);
|
void GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot);
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ namespace swrenderer
|
||||||
FWallCoords WallC;
|
FWallCoords WallC;
|
||||||
FWallTmapVals WallT;
|
FWallTmapVals WallT;
|
||||||
|
|
||||||
float rw_light = 0.0f;
|
ProjectedWallLight mLight;
|
||||||
float rw_lightstep = 0.0f;
|
|
||||||
fixed_t rw_offset = 0;
|
fixed_t rw_offset = 0;
|
||||||
|
|
||||||
ProjectedWallLine wallupper;
|
ProjectedWallLine wallupper;
|
||||||
|
|
|
@ -54,30 +54,198 @@
|
||||||
|
|
||||||
namespace swrenderer
|
namespace swrenderer
|
||||||
{
|
{
|
||||||
WallSampler::WallSampler(RenderViewport *viewport, int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FSoftwareTexture *texture)
|
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
||||||
{
|
{
|
||||||
xoffset += FLOAT2FIXED(xmagnitude * 0.5);
|
if (rw_pic == nullptr)
|
||||||
xoffset *= texture->GetPhysicalScale();
|
return;
|
||||||
|
|
||||||
if (!viewport->RenderTarget->IsBgra())
|
int fracbits = 32 - rw_pic->GetHeightBits();
|
||||||
|
if (fracbits == 32)
|
||||||
|
{ // Hack for one pixel tall textures
|
||||||
|
fracbits = 0;
|
||||||
|
yrepeat = 0;
|
||||||
|
texturemid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WallDrawerArgs drawerargs;
|
||||||
|
drawerargs.SetTextureFracBits(Thread->Viewport->RenderTarget->IsBgra() ? FRACBITS : fracbits);
|
||||||
|
|
||||||
|
// Textures that aren't masked can use the faster opaque drawer
|
||||||
|
if (!rw_pic->GetTexture()->isMasked() && mask && alpha >= OPAQUE && !additive)
|
||||||
{
|
{
|
||||||
height = texture->GetPhysicalHeight();
|
drawerargs.SetStyle(true, false, OPAQUE, mLight.GetBaseColormap());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drawerargs.SetStyle(mask, additive, alpha, mLight.GetBaseColormap());
|
||||||
|
}
|
||||||
|
|
||||||
int uv_fracbits = 32 - texture->GetHeightBits();
|
RenderViewport *viewport = Thread->Viewport.get();
|
||||||
|
|
||||||
|
CameraLight *cameraLight = CameraLight::Instance();
|
||||||
|
bool fixed = (cameraLight->FixedColormap() || cameraLight->FixedLightLevel() >= 0);
|
||||||
|
|
||||||
|
bool haslights = r_dynlights && light_list;
|
||||||
|
|
||||||
|
if (haslights)
|
||||||
|
{
|
||||||
|
float dx = WallC.tright.X - WallC.tleft.X;
|
||||||
|
float dy = WallC.tright.Y - WallC.tleft.Y;
|
||||||
|
float length = sqrt(dx * dx + dy * dy);
|
||||||
|
drawerargs.dc_normal.X = dy / length;
|
||||||
|
drawerargs.dc_normal.Y = -dx / length;
|
||||||
|
drawerargs.dc_normal.Z = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
double xmagnitude = 1.0;
|
||||||
|
|
||||||
|
float curlight = mLight.GetLightPos(x1);
|
||||||
|
float lightstep = mLight.GetLightStep();
|
||||||
|
|
||||||
|
if (viewport->RenderTarget->IsBgra())
|
||||||
|
{
|
||||||
|
for (int x = x1; x < x2; x++, curlight += lightstep)
|
||||||
|
{
|
||||||
|
int y1 = uwal[x];
|
||||||
|
int y2 = dwal[x];
|
||||||
|
if (y2 <= y1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!fixed)
|
||||||
|
drawerargs.SetLight(curlight, mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
|
||||||
|
|
||||||
|
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||||
|
|
||||||
|
fixed_t xxoffset = (lwal[x] + xoffset + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale();
|
||||||
|
|
||||||
|
// Normalize to 0-1 range:
|
||||||
|
double uv_stepd = swal[x] * yrepeat;
|
||||||
|
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||||
|
v = v - floor(v);
|
||||||
|
double v_step = uv_stepd / rw_pic->GetHeight();
|
||||||
|
|
||||||
|
if (std::isnan(v) || std::isnan(v_step)) // this should never happen, but it apparently does..
|
||||||
|
{
|
||||||
|
uv_stepd = 0.0;
|
||||||
|
v = 0.0;
|
||||||
|
v_step = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to uint32_t:
|
||||||
|
uint32_t uv_pos = (uint32_t)(int64_t)(v * 0x100000000LL);
|
||||||
|
uint32_t uv_step = (uint32_t)(int64_t)(v_step * 0x100000000LL);
|
||||||
|
|
||||||
|
// Texture mipmap and filter selection:
|
||||||
|
double ymagnitude = fabs(uv_stepd);
|
||||||
|
double magnitude = MAX(ymagnitude, xmagnitude);
|
||||||
|
double min_lod = -1000.0;
|
||||||
|
double lod = MAX(log2(magnitude) + r_lod_bias, min_lod);
|
||||||
|
bool magnifying = lod < 0.0f;
|
||||||
|
|
||||||
|
int mipmap_offset = 0;
|
||||||
|
int mip_width = rw_pic->GetPhysicalWidth();
|
||||||
|
int mip_height = rw_pic->GetPhysicalHeight();
|
||||||
|
if (r_mipmap && rw_pic->Mipmapped() && mip_width > 1 && mip_height > 1)
|
||||||
|
{
|
||||||
|
uint32_t xpos = (uint32_t)((((uint64_t)xxoffset) << FRACBITS) / mip_width);
|
||||||
|
|
||||||
|
int level = (int)lod;
|
||||||
|
while (level > 0 && mip_width > 1 && mip_height > 1)
|
||||||
|
{
|
||||||
|
mipmap_offset += mip_width * mip_height;
|
||||||
|
level--;
|
||||||
|
mip_width = MAX(mip_width >> 1, 1);
|
||||||
|
mip_height = MAX(mip_height >> 1, 1);
|
||||||
|
}
|
||||||
|
xxoffset = (xpos >> FRACBITS) * mip_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t *pixels = rw_pic->GetPixelsBgra() + mipmap_offset;
|
||||||
|
|
||||||
|
const uint8_t *source;
|
||||||
|
const uint8_t *source2;
|
||||||
|
uint32_t texturefracx;
|
||||||
|
uint32_t height;
|
||||||
|
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
|
||||||
|
if (filter_nearest)
|
||||||
|
{
|
||||||
|
int tx = (xxoffset >> FRACBITS) % mip_width;
|
||||||
|
if (tx < 0)
|
||||||
|
tx += mip_width;
|
||||||
|
source = (uint8_t*)(pixels + tx * mip_height);
|
||||||
|
source2 = nullptr;
|
||||||
|
height = mip_height;
|
||||||
|
texturefracx = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xxoffset -= FRACUNIT / 2;
|
||||||
|
int tx0 = (xxoffset >> FRACBITS) % mip_width;
|
||||||
|
if (tx0 < 0)
|
||||||
|
tx0 += mip_width;
|
||||||
|
int tx1 = (tx0 + 1) % mip_width;
|
||||||
|
source = (uint8_t*)(pixels + tx0 * mip_height);
|
||||||
|
source2 = (uint8_t*)(pixels + tx1 * mip_height);
|
||||||
|
height = mip_height;
|
||||||
|
texturefracx = (xxoffset >> (FRACBITS - 4)) & 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawerargs.SetTexture(source, source2, height);
|
||||||
|
|
||||||
|
if (haslights)
|
||||||
|
SetLights(drawerargs, x, y1);
|
||||||
|
else
|
||||||
|
drawerargs.dc_num_lights = 0;
|
||||||
|
|
||||||
|
drawerargs.SetTextureUPos(texturefracx);
|
||||||
|
drawerargs.SetTextureVStep(uv_step);
|
||||||
|
|
||||||
|
int count = y2 - y1;
|
||||||
|
|
||||||
|
drawerargs.SetDest(viewport, x, y1);
|
||||||
|
drawerargs.SetCount(count);
|
||||||
|
drawerargs.SetTextureVPos(uv_pos);
|
||||||
|
drawerargs.DrawColumn(Thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t height = rw_pic->GetPhysicalHeight();
|
||||||
|
|
||||||
|
uint32_t uv_max;
|
||||||
|
int uv_fracbits = 32 - rw_pic->GetHeightBits();
|
||||||
if (uv_fracbits != 32)
|
if (uv_fracbits != 32)
|
||||||
{
|
|
||||||
uv_max = height << uv_fracbits;
|
uv_max = height << uv_fracbits;
|
||||||
|
|
||||||
|
for (int x = x1; x < x2; x++, curlight += lightstep)
|
||||||
|
{
|
||||||
|
int y1 = uwal[x];
|
||||||
|
int y2 = dwal[x];
|
||||||
|
if (y2 <= y1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!fixed)
|
||||||
|
drawerargs.SetLight(curlight, mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
|
||||||
|
|
||||||
|
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||||
|
|
||||||
|
uint32_t uv_pos;
|
||||||
|
uint32_t uv_step;
|
||||||
|
|
||||||
|
fixed_t xxoffset = (lwal[x] + xoffset + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale();
|
||||||
|
|
||||||
|
if (uv_fracbits != 32)
|
||||||
|
{
|
||||||
// Find start uv in [0-base_height[ range.
|
// Find start uv in [0-base_height[ range.
|
||||||
// Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range.
|
// Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range.
|
||||||
double uv_stepd = swal * yrepeat;
|
double uv_stepd = swal[x] * yrepeat;
|
||||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / texture->GetHeight();
|
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||||
v = v - floor(v);
|
v = v - floor(v);
|
||||||
v *= height;
|
v *= height;
|
||||||
v *= (1 << uv_fracbits);
|
v *= (1 << uv_fracbits);
|
||||||
|
|
||||||
uv_pos = (uint32_t)(int64_t)v;
|
uv_pos = (uint32_t)(int64_t)v;
|
||||||
uv_step = xs_ToFixed(uv_fracbits, uv_stepd * texture->GetPhysicalScale());
|
uv_step = xs_ToFixed(uv_fracbits, uv_stepd * rw_pic->GetPhysicalScale());
|
||||||
if (uv_step == 0) // To prevent divide by zero elsewhere
|
if (uv_step == 0) // To prevent divide by zero elsewhere
|
||||||
uv_step = 1;
|
uv_step = 1;
|
||||||
}
|
}
|
||||||
|
@ -88,112 +256,101 @@ namespace swrenderer
|
||||||
uv_max = 1;
|
uv_max = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int col = xoffset >> FRACBITS;
|
int col = xxoffset >> FRACBITS;
|
||||||
|
|
||||||
// If the texture's width isn't a power of 2, then we need to make it a
|
// If the texture's width isn't a power of 2, then we need to make it a
|
||||||
// positive offset for proper clamping.
|
// positive offset for proper clamping.
|
||||||
int width;
|
int width;
|
||||||
if (col < 0 && (width = texture->GetPhysicalWidth()) != (1 << texture->GetWidthBits()))
|
if (col < 0 && (width = rw_pic->GetPhysicalWidth()) != (1 << rw_pic->GetWidthBits()))
|
||||||
{
|
{
|
||||||
col = width + (col % width);
|
col = width + (col % width);
|
||||||
}
|
}
|
||||||
|
|
||||||
source = texture->GetColumn(DefaultRenderStyle(), col, nullptr);
|
drawerargs.SetTexture(rw_pic->GetColumn(DefaultRenderStyle(), col, nullptr), nullptr, height);
|
||||||
source2 = nullptr;
|
|
||||||
texturefracx = 0;
|
if (haslights)
|
||||||
|
SetLights(drawerargs, x, y1);
|
||||||
|
else
|
||||||
|
drawerargs.dc_num_lights = 0;
|
||||||
|
|
||||||
|
drawerargs.SetTextureVStep(uv_step);
|
||||||
|
|
||||||
|
if (uv_max == 0 || uv_step == 0) // power of two
|
||||||
|
{
|
||||||
|
int count = y2 - y1;
|
||||||
|
|
||||||
|
drawerargs.SetDest(viewport, x, y1);
|
||||||
|
drawerargs.SetCount(count);
|
||||||
|
drawerargs.SetTextureVPos(uv_pos);
|
||||||
|
drawerargs.DrawColumn(Thread);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Normalize to 0-1 range:
|
uint32_t left = y2 - y1;
|
||||||
double uv_stepd = swal * yrepeat;
|
int y = y1;
|
||||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / texture->GetHeight();
|
while (left > 0)
|
||||||
v = v - floor(v);
|
|
||||||
double v_step = uv_stepd / texture->GetHeight();
|
|
||||||
|
|
||||||
if (std::isnan(v) || std::isnan(v_step)) // this should never happen, but it apparently does..
|
|
||||||
{
|
{
|
||||||
uv_stepd = 0.0;
|
uint32_t available = uv_max - uv_pos;
|
||||||
v = 0.0;
|
uint32_t next_uv_wrap = available / uv_step;
|
||||||
v_step = 0.0;
|
if (available % uv_step != 0)
|
||||||
|
next_uv_wrap++;
|
||||||
|
uint32_t count = MIN(left, next_uv_wrap);
|
||||||
|
|
||||||
|
drawerargs.SetDest(viewport, x, y);
|
||||||
|
drawerargs.SetCount(count);
|
||||||
|
drawerargs.SetTextureVPos(uv_pos);
|
||||||
|
drawerargs.DrawColumn(Thread);
|
||||||
|
|
||||||
|
y += count;
|
||||||
|
left -= count;
|
||||||
|
uv_pos += uv_step * count;
|
||||||
|
if (uv_pos >= uv_max)
|
||||||
|
uv_pos -= uv_max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to uint32_t:
|
if (r_modelscene)
|
||||||
uv_pos = (uint32_t)(int64_t)(v * 0x100000000LL);
|
|
||||||
uv_step = (uint32_t)(int64_t)(v_step * 0x100000000LL);
|
|
||||||
uv_max = 0;
|
|
||||||
|
|
||||||
// Texture mipmap and filter selection:
|
|
||||||
double ymagnitude = fabs(uv_stepd);
|
|
||||||
double magnitude = MAX(ymagnitude, xmagnitude);
|
|
||||||
double min_lod = -1000.0;
|
|
||||||
double lod = MAX(log2(magnitude) + r_lod_bias, min_lod);
|
|
||||||
bool magnifying = lod < 0.0f;
|
|
||||||
|
|
||||||
int mipmap_offset = 0;
|
|
||||||
int mip_width = texture->GetPhysicalWidth();
|
|
||||||
int mip_height = texture->GetPhysicalHeight();
|
|
||||||
if (r_mipmap && texture->Mipmapped() && mip_width > 1 && mip_height > 1)
|
|
||||||
{
|
{
|
||||||
uint32_t xpos = (uint32_t)((((uint64_t)xoffset) << FRACBITS) / mip_width);
|
for (int x = x1; x < x2; x++)
|
||||||
|
|
||||||
int level = (int)lod;
|
|
||||||
while (level > 0 && mip_width > 1 && mip_height > 1)
|
|
||||||
{
|
{
|
||||||
mipmap_offset += mip_width * mip_height;
|
int y1 = uwal[x];
|
||||||
level--;
|
int y2 = dwal[x];
|
||||||
mip_width = MAX(mip_width >> 1, 1);
|
if (y2 > y1)
|
||||||
mip_height = MAX(mip_height >> 1, 1);
|
|
||||||
}
|
|
||||||
xoffset = (xpos >> FRACBITS) * mip_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32_t *pixels = texture->GetPixelsBgra() + mipmap_offset;
|
|
||||||
|
|
||||||
bool filter_nearest = (magnifying && !r_magfilter) || (!magnifying && !r_minfilter);
|
|
||||||
if (filter_nearest)
|
|
||||||
{
|
{
|
||||||
int tx = (xoffset >> FRACBITS) % mip_width;
|
int count = y2 - y1;
|
||||||
if (tx < 0)
|
|
||||||
tx += mip_width;
|
float w1 = 1.0f / WallC.sz1;
|
||||||
source = (uint8_t*)(pixels + tx * mip_height);
|
float w2 = 1.0f / WallC.sz2;
|
||||||
source2 = nullptr;
|
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||||
height = mip_height;
|
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||||
texturefracx = 0;
|
float zcol = 1.0f / wcol;
|
||||||
|
float zbufferdepth = 1.0f / (zcol / viewport->viewwindow.FocalTangent);
|
||||||
|
|
||||||
|
drawerargs.SetDest(viewport, x, y1);
|
||||||
|
drawerargs.SetCount(count);
|
||||||
|
drawerargs.DrawDepthColumn(Thread, zbufferdepth);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
xoffset -= FRACUNIT / 2;
|
|
||||||
int tx0 = (xoffset >> FRACBITS) % mip_width;
|
|
||||||
if (tx0 < 0)
|
|
||||||
tx0 += mip_width;
|
|
||||||
int tx1 = (tx0 + 1) % mip_width;
|
|
||||||
source = (uint8_t*)(pixels + tx0 * mip_height);
|
|
||||||
source2 = (uint8_t*)(pixels + tx1 * mip_height);
|
|
||||||
height = mip_height;
|
|
||||||
texturefracx = (xoffset >> (FRACBITS - 4)) & 15;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a column with support for non-power-of-two ranges
|
void RenderWallPart::SetLights(WallDrawerArgs &drawerargs, int x, int y1)
|
||||||
void RenderWallPart::Draw1Column(int x, int y1, int y2, WallSampler &sampler)
|
|
||||||
{
|
{
|
||||||
|
bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP);
|
||||||
|
int tx = x;
|
||||||
|
if (mirror)
|
||||||
|
tx = viewwidth - tx - 1;
|
||||||
|
|
||||||
|
RenderViewport *viewport = Thread->Viewport.get();
|
||||||
|
|
||||||
// Find column position in view space
|
// Find column position in view space
|
||||||
float w1 = 1.0f / WallC.sz1;
|
float w1 = 1.0f / WallC.sz1;
|
||||||
float w2 = 1.0f / WallC.sz2;
|
float w2 = 1.0f / WallC.sz2;
|
||||||
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||||
float zcol = 1.0f / wcol;
|
float zcol = 1.0f / wcol;
|
||||||
float zbufferdepth = 1.0f / (zcol / Thread->Viewport->viewwindow.FocalTangent);
|
|
||||||
|
|
||||||
if (r_dynlights && light_list)
|
|
||||||
{
|
|
||||||
auto viewport = Thread->Viewport.get();
|
|
||||||
|
|
||||||
int tx = x;
|
|
||||||
bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP);
|
|
||||||
if (mirror)
|
|
||||||
tx = viewwidth - tx - 1;
|
|
||||||
|
|
||||||
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
|
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
|
||||||
drawerargs.dc_viewpos.Y = zcol;
|
drawerargs.dc_viewpos.Y = zcol;
|
||||||
|
@ -219,12 +376,12 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||||
{
|
{
|
||||||
double lightX = cur_node->lightsource->X() - Thread->Viewport->viewpoint.Pos.X;
|
double lightX = cur_node->lightsource->X() - viewport->viewpoint.Pos.X;
|
||||||
double lightY = cur_node->lightsource->Y() - Thread->Viewport->viewpoint.Pos.Y;
|
double lightY = cur_node->lightsource->Y() - viewport->viewpoint.Pos.Y;
|
||||||
double lightZ = cur_node->lightsource->Z() - Thread->Viewport->viewpoint.Pos.Z;
|
double lightZ = cur_node->lightsource->Z() - viewport->viewpoint.Pos.Z;
|
||||||
|
|
||||||
float lx = (float)(lightX * Thread->Viewport->viewpoint.Sin - lightY * Thread->Viewport->viewpoint.Cos) - drawerargs.dc_viewpos.X;
|
float lx = (float)(lightX * viewport->viewpoint.Sin - lightY * viewport->viewpoint.Cos) - drawerargs.dc_viewpos.X;
|
||||||
float ly = (float)(lightX * Thread->Viewport->viewpoint.TanCos + lightY * Thread->Viewport->viewpoint.TanSin) - drawerargs.dc_viewpos.Y;
|
float ly = (float)(lightX * viewport->viewpoint.TanCos + lightY * viewport->viewpoint.TanSin) - drawerargs.dc_viewpos.Y;
|
||||||
float lz = (float)lightZ;
|
float lz = (float)lightZ;
|
||||||
|
|
||||||
// Precalculate the constant part of the dot here so the drawer doesn't have to.
|
// Precalculate the constant part of the dot here so the drawer doesn't have to.
|
||||||
|
@ -252,147 +409,6 @@ namespace swrenderer
|
||||||
cur_node = cur_node->nextLight;
|
cur_node = cur_node->nextLight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
drawerargs.dc_num_lights = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Thread->Viewport->RenderTarget->IsBgra())
|
|
||||||
{
|
|
||||||
int count = y2 - y1;
|
|
||||||
|
|
||||||
drawerargs.SetTexture(sampler.source, sampler.source2, sampler.height);
|
|
||||||
drawerargs.SetTextureUPos(sampler.texturefracx);
|
|
||||||
drawerargs.SetDest(Thread->Viewport.get(), x, y1);
|
|
||||||
drawerargs.SetCount(count);
|
|
||||||
drawerargs.SetTextureVStep(sampler.uv_step);
|
|
||||||
drawerargs.SetTextureVPos(sampler.uv_pos);
|
|
||||||
drawerargs.DrawColumn(Thread);
|
|
||||||
if (r_modelscene)
|
|
||||||
drawerargs.DrawDepthColumn(Thread, zbufferdepth);
|
|
||||||
|
|
||||||
uint64_t step64 = sampler.uv_step;
|
|
||||||
uint64_t pos64 = sampler.uv_pos;
|
|
||||||
sampler.uv_pos = (uint32_t)(pos64 + step64 * count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (sampler.uv_max == 0 || sampler.uv_step == 0) // power of two
|
|
||||||
{
|
|
||||||
int count = y2 - y1;
|
|
||||||
|
|
||||||
drawerargs.SetTexture(sampler.source, sampler.source2, sampler.height);
|
|
||||||
drawerargs.SetTextureUPos(sampler.texturefracx);
|
|
||||||
drawerargs.SetDest(Thread->Viewport.get(), x, y1);
|
|
||||||
drawerargs.SetCount(count);
|
|
||||||
drawerargs.SetTextureVStep(sampler.uv_step);
|
|
||||||
drawerargs.SetTextureVPos(sampler.uv_pos);
|
|
||||||
drawerargs.DrawColumn(Thread);
|
|
||||||
if (r_modelscene)
|
|
||||||
drawerargs.DrawDepthColumn(Thread, zbufferdepth);
|
|
||||||
|
|
||||||
uint64_t step64 = sampler.uv_step;
|
|
||||||
uint64_t pos64 = sampler.uv_pos;
|
|
||||||
sampler.uv_pos = (uint32_t)(pos64 + step64 * count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t uv_pos = sampler.uv_pos;
|
|
||||||
|
|
||||||
uint32_t left = y2 - y1;
|
|
||||||
int y = y1;
|
|
||||||
while (left > 0)
|
|
||||||
{
|
|
||||||
uint32_t available = sampler.uv_max - uv_pos;
|
|
||||||
uint32_t next_uv_wrap = available / sampler.uv_step;
|
|
||||||
if (available % sampler.uv_step != 0)
|
|
||||||
next_uv_wrap++;
|
|
||||||
uint32_t count = MIN(left, next_uv_wrap);
|
|
||||||
|
|
||||||
drawerargs.SetTexture(sampler.source, sampler.source2, sampler.height);
|
|
||||||
drawerargs.SetTextureUPos(sampler.texturefracx);
|
|
||||||
drawerargs.SetDest(Thread->Viewport.get(), x, y);
|
|
||||||
drawerargs.SetCount(count);
|
|
||||||
drawerargs.SetTextureVStep(sampler.uv_step);
|
|
||||||
drawerargs.SetTextureVPos(uv_pos);
|
|
||||||
drawerargs.DrawColumn(Thread);
|
|
||||||
if (r_modelscene)
|
|
||||||
drawerargs.DrawDepthColumn(Thread, zbufferdepth);
|
|
||||||
|
|
||||||
y += count;
|
|
||||||
left -= count;
|
|
||||||
uv_pos += sampler.uv_step * count;
|
|
||||||
if (uv_pos >= sampler.uv_max)
|
|
||||||
uv_pos -= sampler.uv_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
sampler.uv_pos = uv_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderWallPart::ProcessWallWorker(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
|
||||||
{
|
|
||||||
if (rw_pic == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int fracbits = 32 - rw_pic->GetHeightBits();
|
|
||||||
if (fracbits == 32)
|
|
||||||
{ // Hack for one pixel tall textures
|
|
||||||
fracbits = 0;
|
|
||||||
yrepeat = 0;
|
|
||||||
texturemid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawerargs.SetTextureFracBits(Thread->Viewport->RenderTarget->IsBgra() ? FRACBITS : fracbits);
|
|
||||||
|
|
||||||
// Textures that aren't masked can use the faster opaque drawer
|
|
||||||
if (!rw_pic->GetTexture()->isMasked() && mask && alpha >= OPAQUE && !additive)
|
|
||||||
{
|
|
||||||
drawerargs.SetStyle(true, false, OPAQUE, basecolormap);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drawerargs.SetStyle(mask, additive, alpha, basecolormap);
|
|
||||||
}
|
|
||||||
|
|
||||||
CameraLight *cameraLight = CameraLight::Instance();
|
|
||||||
bool fixed = (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0);
|
|
||||||
|
|
||||||
float dx = WallC.tright.X - WallC.tleft.X;
|
|
||||||
float dy = WallC.tright.Y - WallC.tleft.Y;
|
|
||||||
float length = sqrt(dx * dx + dy * dy);
|
|
||||||
drawerargs.dc_normal.X = dy / length;
|
|
||||||
drawerargs.dc_normal.Y = -dx / length;
|
|
||||||
drawerargs.dc_normal.Z = 0.0f;
|
|
||||||
|
|
||||||
double xmagnitude = 1.0;
|
|
||||||
|
|
||||||
float curlight = light;
|
|
||||||
for (int x = x1; x < x2; x++, curlight += lightstep)
|
|
||||||
{
|
|
||||||
int y1 = uwal[x];
|
|
||||||
int y2 = dwal[x];
|
|
||||||
if (y2 <= y1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!fixed)
|
|
||||||
drawerargs.SetLight(curlight, lightlevel, foggy, Thread->Viewport.get());
|
|
||||||
|
|
||||||
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
|
||||||
|
|
||||||
WallSampler sampler(Thread->Viewport.get(), y1, texturemid, swal[x], yrepeat, lwal[x] + xoffset, xmagnitude, rw_pic);
|
|
||||||
Draw1Column(x, y1, y2, sampler);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Thread->MainThread)
|
|
||||||
NetUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
|
||||||
{
|
|
||||||
ProcessWallWorker(uwal, dwal, texturemid, swal, lwal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
||||||
{
|
{
|
||||||
|
@ -423,9 +439,7 @@ namespace swrenderer
|
||||||
down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY;
|
down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY;
|
||||||
}
|
}
|
||||||
|
|
||||||
lightlist_t *lit = &frontsector->e->XFloor.lightlist[i];
|
mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]);
|
||||||
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
lightlevel = curline->sidedef->GetLightLevel(foggy, *lit->p_lightlevel, lit->lightsource != NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessNormalWall(up, dwal, texturemid, swal, lwal);
|
ProcessNormalWall(up, dwal, texturemid, swal, lwal);
|
||||||
|
@ -516,7 +530,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, float *swall, fixed_t *lwall, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, int lightlevel, fixed_t xoffset, float light, float lightstep, FLightNode *light_list, bool foggy, FDynamicColormap *basecolormap)
|
void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, float *swall, fixed_t *lwall, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, fixed_t xoffset, const ProjectedWallLight &light, FLightNode *light_list)
|
||||||
{
|
{
|
||||||
this->x1 = x1;
|
this->x1 = x1;
|
||||||
this->x2 = x2;
|
this->x2 = x2;
|
||||||
|
@ -524,18 +538,17 @@ namespace swrenderer
|
||||||
this->curline = curline;
|
this->curline = curline;
|
||||||
this->WallC = WallC;
|
this->WallC = WallC;
|
||||||
this->yrepeat = yscale;
|
this->yrepeat = yscale;
|
||||||
this->lightlevel = lightlevel;
|
this->mLight = light;
|
||||||
this->xoffset = xoffset;
|
this->xoffset = xoffset;
|
||||||
this->light = light;
|
|
||||||
this->lightstep = lightstep;
|
|
||||||
this->foggy = foggy;
|
|
||||||
this->basecolormap = basecolormap;
|
|
||||||
this->light_list = light_list;
|
this->light_list = light_list;
|
||||||
this->rw_pic = pic;
|
this->rw_pic = pic;
|
||||||
this->mask = mask;
|
this->mask = mask;
|
||||||
this->additive = additive;
|
this->additive = additive;
|
||||||
this->alpha = alpha;
|
this->alpha = alpha;
|
||||||
|
|
||||||
|
if (Thread->MainThread)
|
||||||
|
NetUpdate();
|
||||||
|
|
||||||
Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here.
|
Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here.
|
||||||
|
|
||||||
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
|
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
|
||||||
|
|
|
@ -63,13 +63,9 @@ namespace swrenderer
|
||||||
bool mask,
|
bool mask,
|
||||||
bool additive,
|
bool additive,
|
||||||
fixed_t alpha,
|
fixed_t alpha,
|
||||||
int lightlevel,
|
|
||||||
fixed_t xoffset,
|
fixed_t xoffset,
|
||||||
float light,
|
const ProjectedWallLight &light,
|
||||||
float lightstep,
|
FLightNode *light_list);
|
||||||
FLightNode *light_list,
|
|
||||||
bool foggy,
|
|
||||||
FDynamicColormap *basecolormap);
|
|
||||||
|
|
||||||
RenderThread *Thread = nullptr;
|
RenderThread *Thread = nullptr;
|
||||||
|
|
||||||
|
@ -78,8 +74,7 @@ namespace swrenderer
|
||||||
void ProcessWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
void ProcessWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
||||||
void ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
void ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
||||||
void ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
void ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
||||||
void ProcessWallWorker(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
void SetLights(WallDrawerArgs &drawerargs, int x, int y1);
|
||||||
void Draw1Column(int x, int y1, int y2, WallSampler &sampler);
|
|
||||||
|
|
||||||
int x1 = 0;
|
int x1 = 0;
|
||||||
int x2 = 0;
|
int x2 = 0;
|
||||||
|
@ -88,33 +83,13 @@ namespace swrenderer
|
||||||
seg_t *curline = nullptr;
|
seg_t *curline = nullptr;
|
||||||
FWallCoords WallC;
|
FWallCoords WallC;
|
||||||
|
|
||||||
|
ProjectedWallLight mLight;
|
||||||
|
|
||||||
double yrepeat = 0.0;
|
double yrepeat = 0.0;
|
||||||
int lightlevel = 0;
|
|
||||||
fixed_t xoffset = 0;
|
fixed_t xoffset = 0;
|
||||||
float light = 0.0f;
|
|
||||||
float lightstep = 0.0f;
|
|
||||||
bool foggy = false;
|
|
||||||
FDynamicColormap *basecolormap = nullptr;
|
|
||||||
FLightNode *light_list = nullptr;
|
FLightNode *light_list = nullptr;
|
||||||
bool mask = false;
|
bool mask = false;
|
||||||
bool additive = false;
|
bool additive = false;
|
||||||
fixed_t alpha = 0;
|
fixed_t alpha = 0;
|
||||||
|
|
||||||
WallDrawerArgs drawerargs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WallSampler
|
|
||||||
{
|
|
||||||
WallSampler() { }
|
|
||||||
WallSampler(RenderViewport *viewport, int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FSoftwareTexture *texture);
|
|
||||||
|
|
||||||
uint32_t uv_pos;
|
|
||||||
uint32_t uv_step;
|
|
||||||
uint32_t uv_max;
|
|
||||||
|
|
||||||
const uint8_t *source;
|
|
||||||
const uint8_t *source2;
|
|
||||||
uint32_t texturefracx;
|
|
||||||
uint32_t height;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,4 +241,43 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void ProjectedWallLight::SetLightLeft(RenderThread *thread, const FWallCoords &wallc)
|
||||||
|
{
|
||||||
|
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, lightlist_t *lit)
|
||||||
|
{
|
||||||
|
if (!lit)
|
||||||
|
{
|
||||||
|
basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||||
|
foggy = level.fadeto || frontsector->Colormap.FadeColor || (level.flags & LEVEL_HASFADETABLE);
|
||||||
|
|
||||||
|
if (!(lineseg->sidedef->Flags & WALLF_POLYOBJ))
|
||||||
|
lightlevel = lineseg->sidedef->GetLightLevel(foggy, frontsector->lightlevel);
|
||||||
|
else
|
||||||
|
lightlevel = frontsector->GetLightLevel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
basecolormap = GetColorTable(lit->extra_colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||||
|
foggy = level.fadeto || basecolormap->Fade || (level.flags & LEVEL_HASFADETABLE);
|
||||||
|
lightlevel = lineseg->sidedef->GetLightLevel(foggy, *lit->p_lightlevel, lit->lightsource != nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,4 +56,29 @@ namespace swrenderer
|
||||||
void Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT);
|
void Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT);
|
||||||
void ProjectPos(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT);
|
void ProjectPos(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ProjectedWallLight
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int GetLightLevel() const { return lightlevel; }
|
||||||
|
bool GetFoggy() const { return foggy; }
|
||||||
|
FDynamicColormap *GetBaseColormap() const { return basecolormap; }
|
||||||
|
|
||||||
|
float GetLightPos(int x) const { return lightleft + lightstep * (x - x1); }
|
||||||
|
float GetLightStep() const { return lightstep; }
|
||||||
|
|
||||||
|
void SetColormap(const sector_t *frontsector, seg_t *lineseg, lightlist_t *lit = nullptr);
|
||||||
|
|
||||||
|
void SetLightLeft(float left, float step, int startx) { lightleft = left; lightstep = step; x1 = startx; }
|
||||||
|
void SetLightLeft(RenderThread *thread, const FWallCoords &wallc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int lightlevel;
|
||||||
|
bool foggy;
|
||||||
|
FDynamicColormap *basecolormap;
|
||||||
|
|
||||||
|
int x1;
|
||||||
|
float lightleft;
|
||||||
|
float lightstep;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -451,7 +451,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// kg3D - add fake segs, never rendered
|
// kg3D - add fake segs, never rendered
|
||||||
void RenderOpaquePass::FakeDrawLoop(subsector_t *sub, sector_t *frontsector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap, Fake3DOpaque opaque3dfloor)
|
void RenderOpaquePass::FakeDrawLoop(subsector_t *sub, sector_t *frontsector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, Fake3DOpaque opaque3dfloor)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
seg_t* line;
|
seg_t* line;
|
||||||
|
@ -463,7 +463,7 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if ((line->sidedef) && !(line->sidedef->Flags & WALLF_POLYOBJ))
|
if ((line->sidedef) && !(line->sidedef->Flags & WALLF_POLYOBJ))
|
||||||
{
|
{
|
||||||
renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap, opaque3dfloor);
|
renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, opaque3dfloor);
|
||||||
}
|
}
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
|
@ -622,8 +622,6 @@ namespace swrenderer
|
||||||
|
|
||||||
DVector2 viewpointPos = Thread->Viewport->viewpoint.Pos.XY();
|
DVector2 viewpointPos = Thread->Viewport->viewpoint.Pos.XY();
|
||||||
|
|
||||||
basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
|
||||||
|
|
||||||
seg_t *line = sub->firstline;
|
seg_t *line = sub->firstline;
|
||||||
int count = sub->numlines;
|
int count = sub->numlines;
|
||||||
while (count--)
|
while (count--)
|
||||||
|
@ -637,8 +635,8 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
else if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
|
else if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
|
||||||
{
|
{
|
||||||
Add3DFloorLine(line, frontsector, basecolormap, foggy);
|
Add3DFloorLine(line, frontsector);
|
||||||
renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap, Fake3DOpaque::Normal); // now real
|
renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, Fake3DOpaque::Normal); // now real
|
||||||
}
|
}
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
|
@ -648,7 +646,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderOpaquePass::Add3DFloorLine(seg_t *line, sector_t *frontsector, FDynamicColormap *basecolormap, bool foggy)
|
void RenderOpaquePass::Add3DFloorLine(seg_t *line, sector_t *frontsector)
|
||||||
{
|
{
|
||||||
// kg3D - fake planes bounding calculation
|
// kg3D - fake planes bounding calculation
|
||||||
if (r_3dfloors && line->backsector && frontsector->e && line->backsector->e->XFloor.ffloors.Size())
|
if (r_3dfloors && line->backsector && frontsector->e && line->backsector->e->XFloor.ffloors.Size())
|
||||||
|
@ -669,7 +667,7 @@ namespace swrenderer
|
||||||
clip3d->fakeFloor->validcount = validcount;
|
clip3d->fakeFloor->validcount = validcount;
|
||||||
clip3d->NewClip();
|
clip3d->NewClip();
|
||||||
}
|
}
|
||||||
renderline.Render(line, InSubsector, frontsector, &tempsec, nullptr, nullptr, foggy, basecolormap, opaque3dfloor); // fake
|
renderline.Render(line, InSubsector, frontsector, &tempsec, nullptr, nullptr, opaque3dfloor); // fake
|
||||||
}
|
}
|
||||||
clip3d->fakeFloor = nullptr;
|
clip3d->fakeFloor = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -744,7 +742,7 @@ namespace swrenderer
|
||||||
|
|
||||||
floorplane3d->AddLights(Thread, sub->section->lighthead);
|
floorplane3d->AddLights(Thread, sub->section->lighthead);
|
||||||
|
|
||||||
FakeDrawLoop(sub, &tempsec, floorplane3d, nullptr, foggy, basecolormap, Fake3DOpaque::FakeFloor);
|
FakeDrawLoop(sub, &tempsec, floorplane3d, nullptr, Fake3DOpaque::FakeFloor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// and now ceilings
|
// and now ceilings
|
||||||
|
@ -812,7 +810,7 @@ namespace swrenderer
|
||||||
|
|
||||||
ceilingplane3d->AddLights(Thread, sub->section->lighthead);
|
ceilingplane3d->AddLights(Thread, sub->section->lighthead);
|
||||||
|
|
||||||
FakeDrawLoop(sub, &tempsec, nullptr, ceilingplane3d, foggy, basecolormap, Fake3DOpaque::FakeCeiling);
|
FakeDrawLoop(sub, &tempsec, nullptr, ceilingplane3d, Fake3DOpaque::FakeCeiling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clip3d->fakeFloor = nullptr;
|
clip3d->fakeFloor = nullptr;
|
||||||
|
|
|
@ -86,8 +86,8 @@ namespace swrenderer
|
||||||
void AddPolyobjs(subsector_t *sub);
|
void AddPolyobjs(subsector_t *sub);
|
||||||
|
|
||||||
void Add3DFloorPlanes(subsector_t *sub, sector_t *frontsector, FDynamicColormap *basecolormap, bool foggy, int adjusted_ceilinglightlevel, int adjusted_floorlightlevel);
|
void Add3DFloorPlanes(subsector_t *sub, sector_t *frontsector, FDynamicColormap *basecolormap, bool foggy, int adjusted_ceilinglightlevel, int adjusted_floorlightlevel);
|
||||||
void FakeDrawLoop(subsector_t *sub, sector_t *frontsector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, bool foggy, FDynamicColormap *basecolormap, Fake3DOpaque opaque3dfloor);
|
void FakeDrawLoop(subsector_t *sub, sector_t *frontsector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, Fake3DOpaque opaque3dfloor);
|
||||||
void Add3DFloorLine(seg_t *line, sector_t *frontsector, FDynamicColormap *basecolormap, bool foggy);
|
void Add3DFloorLine(seg_t *line, sector_t *frontsector);
|
||||||
|
|
||||||
void AddSprites(sector_t *sec, int lightlevel, WaterFakeSide fakeside, bool foggy, FDynamicColormap *basecolormap);
|
void AddSprites(sector_t *sec, int lightlevel, WaterFakeSide fakeside, bool foggy, FDynamicColormap *basecolormap);
|
||||||
bool IsPotentiallyVisible(AActor *thing);
|
bool IsPotentiallyVisible(AActor *thing);
|
||||||
|
|
|
@ -206,10 +206,8 @@ namespace swrenderer
|
||||||
// Create a drawseg to clip sprites to the sky plane
|
// Create a drawseg to clip sprites to the sky plane
|
||||||
DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
|
DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
|
||||||
draw_segment->CurrentPortalUniq = CurrentPortalUniq;
|
draw_segment->CurrentPortalUniq = CurrentPortalUniq;
|
||||||
draw_segment->siz1 = INT_MAX;
|
draw_segment->WallC.sz1 = 0;
|
||||||
draw_segment->siz2 = INT_MAX;
|
draw_segment->WallC.sz2 = 0;
|
||||||
draw_segment->sz1 = 0;
|
|
||||||
draw_segment->sz2 = 0;
|
|
||||||
draw_segment->x1 = pl->left;
|
draw_segment->x1 = pl->left;
|
||||||
draw_segment->x2 = pl->right;
|
draw_segment->x2 = pl->right;
|
||||||
draw_segment->silhouette = SIL_BOTH;
|
draw_segment->silhouette = SIL_BOTH;
|
||||||
|
@ -219,7 +217,6 @@ namespace swrenderer
|
||||||
draw_segment->swall = nullptr;
|
draw_segment->swall = nullptr;
|
||||||
draw_segment->bFogBoundary = false;
|
draw_segment->bFogBoundary = false;
|
||||||
draw_segment->curline = nullptr;
|
draw_segment->curline = nullptr;
|
||||||
draw_segment->foggy = false;
|
|
||||||
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||||
memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||||
drawseglist->Push(draw_segment);
|
drawseglist->Push(draw_segment);
|
||||||
|
|
|
@ -107,18 +107,18 @@ namespace swrenderer
|
||||||
group.EndIndex = MIN(index + groupSize, SegmentsCount());
|
group.EndIndex = MIN(index + groupSize, SegmentsCount());
|
||||||
group.x1 = ds->x1;
|
group.x1 = ds->x1;
|
||||||
group.x2 = ds->x2;
|
group.x2 = ds->x2;
|
||||||
group.neardepth = MIN(ds->sz1, ds->sz2);
|
group.neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2);
|
||||||
group.fardepth = MAX(ds->sz1, ds->sz2);
|
group.fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2);
|
||||||
|
|
||||||
for (unsigned int groupIndex = group.BeginIndex + 1; groupIndex < group.EndIndex; groupIndex++)
|
for (unsigned int groupIndex = group.BeginIndex + 1; groupIndex < group.EndIndex; groupIndex++)
|
||||||
{
|
{
|
||||||
ds = Segment(groupIndex);
|
ds = Segment(groupIndex);
|
||||||
group.x1 = MIN(group.x1, ds->x1);
|
group.x1 = MIN(group.x1, ds->x1);
|
||||||
group.x2 = MAX(group.x2, ds->x2);
|
group.x2 = MAX(group.x2, ds->x2);
|
||||||
group.neardepth = MIN(group.neardepth, ds->sz1);
|
group.neardepth = MIN(group.neardepth, ds->WallC.sz1);
|
||||||
group.neardepth = MIN(group.neardepth, ds->sz2);
|
group.neardepth = MIN(group.neardepth, ds->WallC.sz2);
|
||||||
group.fardepth = MAX(ds->sz1, group.fardepth);
|
group.fardepth = MAX(ds->WallC.sz1, group.fardepth);
|
||||||
group.fardepth = MAX(ds->sz2, group.fardepth);
|
group.fardepth = MAX(ds->WallC.sz2, group.fardepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int x = group.x1; x < group.x2; x++)
|
for (int x = group.x1; x < group.x2; x++)
|
||||||
|
|
|
@ -31,15 +31,10 @@ namespace swrenderer
|
||||||
float light, lightstep;
|
float light, lightstep;
|
||||||
float iscale, iscalestep;
|
float iscale, iscalestep;
|
||||||
short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg
|
short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg
|
||||||
short sx1, sx2; // left, right of parent seg on screen
|
FWallCoords WallC;
|
||||||
float sz1, sz2; // z for left, right of parent seg on screen
|
|
||||||
float siz1, siz2; // 1/z for left, right of parent seg on screen
|
|
||||||
float cx, cy, cdx, cdy;
|
|
||||||
float yscale;
|
float yscale;
|
||||||
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
||||||
bool bFogBoundary = false;
|
bool bFogBoundary = false;
|
||||||
int lightlevel = 0;
|
|
||||||
bool foggy = false;
|
|
||||||
|
|
||||||
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
|
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
|
||||||
short *sprtopclip = nullptr;
|
short *sprtopclip = nullptr;
|
||||||
|
|
|
@ -57,15 +57,15 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
||||||
|
|
||||||
namespace swrenderer
|
namespace swrenderer
|
||||||
{
|
{
|
||||||
void RenderDecal::RenderDecals(RenderThread *thread, side_t *sidedef, DrawSegment *draw_segment, int lightlevel, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass)
|
void RenderDecal::RenderDecals(RenderThread *thread, side_t *sidedef, DrawSegment *draw_segment, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass)
|
||||||
{
|
{
|
||||||
for (DBaseDecal *decal = sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
|
for (DBaseDecal *decal = sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
|
||||||
{
|
{
|
||||||
Render(thread, sidedef, decal, draw_segment, lightlevel, lightleft, lightstep, curline, wallC, foggy, basecolormap, walltop, wallbottom, drawsegPass);
|
Render(thread, sidedef, decal, draw_segment, curline, light, walltop, wallbottom, drawsegPass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, int lightlevel, float lightleft, float lightstep, seg_t *curline, const FWallCoords &savecoord, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass)
|
void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass)
|
||||||
{
|
{
|
||||||
DVector2 decal_left, decal_right, decal_pos;
|
DVector2 decal_left, decal_right, decal_pos;
|
||||||
int x1, x2;
|
int x1, x2;
|
||||||
|
@ -75,7 +75,6 @@ namespace swrenderer
|
||||||
int needrepeat = 0;
|
int needrepeat = 0;
|
||||||
sector_t *back;
|
sector_t *back;
|
||||||
FDynamicColormap *usecolormap;
|
FDynamicColormap *usecolormap;
|
||||||
float light = 0;
|
|
||||||
const short *mfloorclip;
|
const short *mfloorclip;
|
||||||
const short *mceilingclip;
|
const short *mceilingclip;
|
||||||
|
|
||||||
|
@ -257,7 +256,7 @@ namespace swrenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare lighting
|
// Prepare lighting
|
||||||
usecolormap = basecolormap;
|
usecolormap = light.GetBaseColormap();
|
||||||
|
|
||||||
// Decals that are added to the scene must fade to black.
|
// Decals that are added to the scene must fade to black.
|
||||||
if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0)
|
if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0)
|
||||||
|
@ -265,7 +264,7 @@ namespace swrenderer
|
||||||
usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate);
|
usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate);
|
||||||
}
|
}
|
||||||
|
|
||||||
light = lightleft + (x1 - savecoord.sx1) * lightstep;
|
float lightpos = light.GetLightPos(x1);
|
||||||
|
|
||||||
cameraLight = CameraLight::Instance();
|
cameraLight = CameraLight::Instance();
|
||||||
|
|
||||||
|
@ -288,7 +287,7 @@ namespace swrenderer
|
||||||
int x = x1;
|
int x = x1;
|
||||||
|
|
||||||
ColormapLight cmlight;
|
ColormapLight cmlight;
|
||||||
cmlight.SetColormap(thread, MINZ, lightlevel, foggy, usecolormap, decal->RenderFlags & RF_FULLBRIGHT, false, false, false, false);
|
cmlight.SetColormap(thread, MINZ, light.GetLightLevel(), light.GetFoggy(), usecolormap, decal->RenderFlags & RF_FULLBRIGHT, false, false, false, false);
|
||||||
|
|
||||||
SpriteDrawerArgs drawerargs;
|
SpriteDrawerArgs drawerargs;
|
||||||
bool visible = drawerargs.SetStyle(thread->Viewport.get(), decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor, cmlight);
|
bool visible = drawerargs.SetStyle(thread->Viewport.get(), decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor, cmlight);
|
||||||
|
@ -301,10 +300,10 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (calclighting)
|
if (calclighting)
|
||||||
{ // calculate lighting
|
{ // calculate lighting
|
||||||
drawerargs.SetLight(light, lightlevel, foggy, thread->Viewport.get());
|
drawerargs.SetLight(lightpos, light.GetLightLevel(), light.GetFoggy(), thread->Viewport.get());
|
||||||
}
|
}
|
||||||
DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle);
|
DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle);
|
||||||
light += lightstep;
|
lightpos += light.GetLightStep();
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@ namespace swrenderer
|
||||||
class RenderDecal
|
class RenderDecal
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void RenderDecals(RenderThread *thread, side_t *wall, DrawSegment *draw_segment, int lightlevel, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass);
|
static void RenderDecals(RenderThread *thread, side_t *wall, DrawSegment *draw_segment, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, int lightlevel, float lightleft, float lightstep, seg_t *curline, const FWallCoords &wallC, bool foggy, FDynamicColormap *basecolormap, const short *walltop, const short *wallbottom, bool drawsegPass);
|
static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass);
|
||||||
static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FSoftwareTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style);
|
static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FSoftwareTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,9 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((ds->siz2 - ds->siz1) * ((x2 + x1) / 2 - ds->sx1) / (ds->sx2 - ds->sx1) + ds->siz1 < idepth)
|
float siz1 = 1 / ds->WallC.sz1;
|
||||||
|
float siz2 = 1 / ds->WallC.sz2;
|
||||||
|
if ((siz2 - siz1) * ((x2 + x1) / 2 - ds->WallC.sx1) / (ds->WallC.sx2 - ds->WallC.sx1) + siz1 < idepth)
|
||||||
{
|
{
|
||||||
// [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves
|
// [ZZ] only draw stuff that's inside the same portal as the particle, other portals will care for themselves
|
||||||
if (ds->CurrentPortalUniq == CurrentPortalUniq)
|
if (ds->CurrentPortalUniq == CurrentPortalUniq)
|
||||||
|
|
|
@ -340,8 +340,8 @@ namespace swrenderer
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float neardepth = MIN(ds->sz1, ds->sz2);
|
float neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2);
|
||||||
float fardepth = MAX(ds->sz1, ds->sz2);
|
float fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2);
|
||||||
|
|
||||||
// Check if sprite is in front of draw seg:
|
// Check if sprite is in front of draw seg:
|
||||||
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
|
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
|
||||||
|
@ -414,8 +414,8 @@ namespace swrenderer
|
||||||
int r1 = MAX<int>(ds->x1, x1);
|
int r1 = MAX<int>(ds->x1, x1);
|
||||||
int r2 = MIN<int>(ds->x2, x2);
|
int r2 = MIN<int>(ds->x2, x2);
|
||||||
|
|
||||||
float neardepth = MIN(ds->sz1, ds->sz2);
|
float neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2);
|
||||||
float fardepth = MAX(ds->sz1, ds->sz2);
|
float fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2);
|
||||||
|
|
||||||
// Check if sprite is in front of draw seg:
|
// Check if sprite is in front of draw seg:
|
||||||
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
|
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
|
||||||
|
|
|
@ -48,16 +48,16 @@ const char *GetVersionString();
|
||||||
#ifdef GIT_DESCRIPTION
|
#ifdef GIT_DESCRIPTION
|
||||||
#define VERSIONSTR GIT_DESCRIPTION
|
#define VERSIONSTR GIT_DESCRIPTION
|
||||||
#else
|
#else
|
||||||
#define VERSIONSTR "3.7pre"
|
#define VERSIONSTR "3.8pre"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The version as seen in the Windows resource
|
// The version as seen in the Windows resource
|
||||||
#define RC_FILEVERSION 3,6,9999,0
|
#define RC_FILEVERSION 3,7,9999,0
|
||||||
#define RC_PRODUCTVERSION 3,6,9999,0
|
#define RC_PRODUCTVERSION 3,7,9999,0
|
||||||
#define RC_PRODUCTVERSION2 VERSIONSTR
|
#define RC_PRODUCTVERSION2 VERSIONSTR
|
||||||
// These are for content versioning.
|
// These are for content versioning.
|
||||||
#define VER_MAJOR 3
|
#define VER_MAJOR 3
|
||||||
#define VER_MINOR 7
|
#define VER_MINOR 8
|
||||||
#define VER_REVISION 0
|
#define VER_REVISION 0
|
||||||
|
|
||||||
// Version identifier for network games.
|
// Version identifier for network games.
|
||||||
|
|
|
@ -146,6 +146,12 @@ class LevelCompatibility native play
|
||||||
SetLineActivation(959, SPAC_Cross);
|
SetLineActivation(959, SPAC_Cross);
|
||||||
SetLineSpecial(960, Floor_RaiseToNearest, 16, 32);
|
SetLineSpecial(960, Floor_RaiseToNearest, 16, 32);
|
||||||
SetLineActivation(960, SPAC_Cross);
|
SetLineActivation(960, SPAC_Cross);
|
||||||
|
// Dropping into the holes themselves raises sectors
|
||||||
|
for(int i=0; i<9; i++)
|
||||||
|
{
|
||||||
|
SetLineSpecial(999+i, Floor_RaiseToNearest, 16, 32);
|
||||||
|
SetLineActivation(999+i, SPAC_Cross);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +185,7 @@ class LevelCompatibility native play
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'A53AE580A4AF2B5D0B0893F86914781E': // TNT: Evilution map31
|
case 'A53AE580A4AF2B5D0B0893F86914781E': // TNT: Evilution map31
|
||||||
|
case '55192065F7FAA7D161767145DA008293': // TNT Anthology/GOG MAP31
|
||||||
{
|
{
|
||||||
// The famous missing yellow key...
|
// The famous missing yellow key...
|
||||||
SetThingFlags(470, 2016);
|
SetThingFlags(470, 2016);
|
||||||
|
@ -234,6 +241,15 @@ class LevelCompatibility native play
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'ECA0559E85EFFB6966ECB8DE01E3A35B': // Plutonia Experiment MAP16
|
||||||
|
{
|
||||||
|
// Have it so that the slime pit at the end of the level can
|
||||||
|
// actually kill the player.
|
||||||
|
SetSectorSpecial(95, 768);
|
||||||
|
SetSectorSpecial(96, 768);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case '9D84B423D8FD28553DDE23B55F97CF4A': // Plutonia Experiment MAP25
|
case '9D84B423D8FD28553DDE23B55F97CF4A': // Plutonia Experiment MAP25
|
||||||
{
|
{
|
||||||
// Missing texture at level exit.
|
// Missing texture at level exit.
|
||||||
|
|
Loading…
Reference in a new issue