mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 06:53:40 +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.
|
||||
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;
|
||||
int painchance = 0;
|
||||
|
@ -827,7 +827,7 @@ static void ReactToDamage(AActor *target, AActor *inflictor, AActor *source, int
|
|||
// Are we attempting to cause pain?
|
||||
if (!noPain)
|
||||
{
|
||||
fakedPain = (isFakePain(target, inflictor, damage));
|
||||
fakedPain = (isFakePain(target, inflictor, originaldamage));
|
||||
forcedPain = (MustForcePain(target, inflictor));
|
||||
}
|
||||
|
||||
|
@ -1456,7 +1456,7 @@ static int DoDamageMobj(AActor *target, AActor *inflictor, AActor *source, int d
|
|||
bool needevent = true;
|
||||
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.
|
||||
ReactToDamage(target, inflictor, source, realdamage, mod, flags);
|
||||
ReactToDamage(target, inflictor, source, realdamage, mod, flags, damage);
|
||||
|
||||
if (realdamage > 0 && needevent)
|
||||
{
|
||||
|
|
|
@ -54,19 +54,20 @@
|
|||
|
||||
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
|
||||
// to create new horizontal spans whenever the light changes enough that
|
||||
// we need to use a new colormap.
|
||||
|
||||
int wallshade = LightVisibility::LightLevelToShade(lightlevel, foggy, thread->Viewport.get());
|
||||
float light = lightleft + lightstep*(x2 - x1 - 1);
|
||||
int wallshade = LightVisibility::LightLevelToShade(wallLight.GetLightLevel(), wallLight.GetFoggy(), thread->Viewport.get());
|
||||
int x = x2 - 1;
|
||||
int t2 = uclip[x];
|
||||
int b2 = dclip[x];
|
||||
float light = wallLight.GetLightPos(x);
|
||||
int rcolormap = GETPALOOKUP(light, wallshade);
|
||||
int lcolormap;
|
||||
FDynamicColormap *basecolormap = wallLight.GetBaseColormap();
|
||||
uint8_t *basecolormapdata = basecolormap->Maps;
|
||||
|
||||
if (b2 > t2)
|
||||
|
@ -75,7 +76,7 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -86,7 +87,7 @@ namespace swrenderer
|
|||
const int xr = x + 1;
|
||||
int stop;
|
||||
|
||||
light -= lightstep;
|
||||
light -= wallLight.GetLightStep();
|
||||
lcolormap = GETPALOOKUP(light, wallshade);
|
||||
if (lcolormap != rcolormap)
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace swrenderer
|
|||
class RenderFogBoundary
|
||||
{
|
||||
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:
|
||||
void RenderSection(RenderThread *thread, int y, int y2, int x1);
|
||||
|
|
|
@ -71,15 +71,13 @@ namespace swrenderer
|
|||
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;
|
||||
mFrontSector = sector;
|
||||
mBackSector = fakebacksector;
|
||||
mFloorPlane = linefloorplane;
|
||||
mCeilingPlane = lineceilingplane;
|
||||
foggy = infog;
|
||||
basecolormap = colormap;
|
||||
mLineSegment = line;
|
||||
m3DFloor = opaque3dfloor;
|
||||
|
||||
|
@ -314,7 +312,7 @@ namespace swrenderer
|
|||
if (!rw_prepped)
|
||||
{
|
||||
rw_prepped = true;
|
||||
SetWallVariables(true);
|
||||
SetWallVariables();
|
||||
}
|
||||
|
||||
side_t *sidedef = mLineSegment->sidedef;
|
||||
|
@ -326,26 +324,15 @@ namespace swrenderer
|
|||
|
||||
// 3D floors code abuses the line render code to update plane clipping
|
||||
// lists but doesn't actually draw anything.
|
||||
bool onlyUpdatePlaneClip = (m3DFloor.type != Fake3DOpaque::Normal);
|
||||
if (!onlyUpdatePlaneClip)
|
||||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
Thread->DrawSegments->Push(draw_segment);
|
||||
|
||||
draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
draw_segment->sx1 = WallC.sx1;
|
||||
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->WallC = WallC;
|
||||
draw_segment->tmapvals = WallT;
|
||||
draw_segment->siz1 = 1 / WallC.sz1;
|
||||
draw_segment->siz2 = 1 / WallC.sz2;
|
||||
draw_segment->x1 = start;
|
||||
draw_segment->x2 = stop;
|
||||
draw_segment->curline = mLineSegment;
|
||||
draw_segment->foggy = foggy;
|
||||
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
||||
|
||||
bool markportal = ShouldMarkPortal();
|
||||
|
@ -400,29 +387,30 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
if (!onlyUpdatePlaneClip && r_3dfloors)
|
||||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
{
|
||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mBackSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) {
|
||||
draw_segment->SetHas3DFloorBackSectorWalls();
|
||||
break;
|
||||
if (r_3dfloors)
|
||||
{
|
||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mBackSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) {
|
||||
draw_segment->SetHas3DFloorBackSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFrontSector->e && mFrontSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mFrontSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mFrontSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) {
|
||||
draw_segment->SetHas3DFloorFrontSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFrontSector->e && mFrontSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mFrontSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mFrontSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) {
|
||||
draw_segment->SetHas3DFloorFrontSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!onlyUpdatePlaneClip)
|
||||
// allocate space for masked texture tables, if needed
|
||||
// [RH] Don't just allocate the space; fill it in too.
|
||||
if ((sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls() || IsFogBoundary(mFrontSector, mBackSector)) &&
|
||||
|
@ -452,8 +440,8 @@ namespace swrenderer
|
|||
lwal = draw_segment->maskedtexturecol;
|
||||
swal = draw_segment->swall;
|
||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
FSoftwareTexture *pic = tex && tex->isValid()? tex->GetSoftwareTexture() : nullptr;
|
||||
double yscale = (pic? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid);
|
||||
FSoftwareTexture *pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
double yscale = (pic ? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid);
|
||||
fixed_t xoffset = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||
|
||||
if (pic && pic->useWorldPanning())
|
||||
|
@ -490,27 +478,16 @@ namespace swrenderer
|
|||
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,
|
||||
// not from the current subsector, which is what the current lightlevel value
|
||||
// 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);
|
||||
}
|
||||
draw_segment->light = mLight.GetLightPos(start);
|
||||
draw_segment->lightstep = mLight.GetLightStep();
|
||||
|
||||
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
|
||||
{
|
||||
Thread->DrawSegments->PushTranslucent(draw_segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClipSegmentTopBottom(start, stop);
|
||||
|
@ -552,7 +529,7 @@ namespace swrenderer
|
|||
// [ZZ] Only if not an active mirror
|
||||
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)
|
||||
|
@ -700,7 +677,7 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
void SWRenderLine::SetWallVariables(bool needlights)
|
||||
void SWRenderLine::SetWallVariables()
|
||||
{
|
||||
RenderPortal *renderportal = Thread->Portal.get();
|
||||
|
||||
|
@ -775,8 +752,13 @@ namespace swrenderer
|
|||
|
||||
bool segtextured = ftex != NULL || mTopPart.Texture != NULL || mBottomPart.Texture != NULL;
|
||||
|
||||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
{
|
||||
mLight.SetColormap(mFrontSector, mLineSegment);
|
||||
}
|
||||
|
||||
// calculate light table
|
||||
if (needlights && (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector))))
|
||||
if (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector)))
|
||||
{
|
||||
lwallscale =
|
||||
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);
|
||||
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
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;
|
||||
}
|
||||
mLight.SetLightLeft(Thread, WallC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1164,10 +1135,8 @@ namespace swrenderer
|
|||
offset = -offset;
|
||||
}
|
||||
|
||||
float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1);
|
||||
|
||||
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)
|
||||
|
@ -1197,10 +1166,8 @@ namespace swrenderer
|
|||
offset = -offset;
|
||||
}
|
||||
|
||||
float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1);
|
||||
|
||||
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)
|
||||
|
@ -1231,10 +1198,8 @@ namespace swrenderer
|
|||
offset = -offset;
|
||||
}
|
||||
|
||||
float rw_light = rw_lightleft + rw_lightstep * (x1 - WallC.sx1);
|
||||
|
||||
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()
|
||||
|
|
|
@ -72,13 +72,13 @@ namespace swrenderer
|
|||
{
|
||||
public:
|
||||
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;
|
||||
|
||||
private:
|
||||
bool RenderWallSegment(int x1, int x2) override;
|
||||
void SetWallVariables(bool needlights);
|
||||
void SetWallVariables();
|
||||
void SetTopTexture();
|
||||
void SetMiddleTexture();
|
||||
void SetBottomTexture();
|
||||
|
@ -128,16 +128,11 @@ namespace swrenderer
|
|||
FWallCoords WallC;
|
||||
FWallTmapVals WallT;
|
||||
|
||||
bool foggy;
|
||||
FDynamicColormap *basecolormap;
|
||||
|
||||
// Wall segment variables:
|
||||
|
||||
bool rw_prepped;
|
||||
|
||||
int lightlevel;
|
||||
float rw_lightstep;
|
||||
float rw_lightleft;
|
||||
ProjectedWallLight mLight;
|
||||
|
||||
double lwallscale;
|
||||
|
||||
|
|
|
@ -80,12 +80,8 @@ namespace swrenderer
|
|||
sector_t tempsec;
|
||||
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
|
||||
|
||||
bool foggy = ds->foggy;
|
||||
int lightlevel = ds->lightlevel;
|
||||
rw_lightstep = ds->lightstep;
|
||||
rw_light = ds->light + (x1 - ds->x1) * rw_lightstep;
|
||||
mLight.SetColormap(sec, curline);
|
||||
mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1);
|
||||
|
||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||
|
||||
|
@ -94,10 +90,7 @@ namespace swrenderer
|
|||
{
|
||||
if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0())
|
||||
{
|
||||
lightlist_t *lit = &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);
|
||||
mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +100,7 @@ namespace swrenderer
|
|||
|
||||
SpriteDrawerArgs columndrawerargs;
|
||||
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);
|
||||
if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls())
|
||||
{
|
||||
|
@ -123,7 +116,7 @@ namespace swrenderer
|
|||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||
|
||||
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)
|
||||
renderwall = false;
|
||||
|
@ -134,7 +127,7 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
if (renderwall)
|
||||
notrelevant = RenderWall(ds, x1, x2, basecolormap, columndrawerargs, visible, lightlevel, foggy);
|
||||
notrelevant = RenderWall(ds, x1, x2, columndrawerargs, visible);
|
||||
|
||||
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 viewport = Thread->Viewport.get();
|
||||
|
@ -226,12 +219,12 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
// [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
|
||||
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
|
||||
return false;
|
||||
}
|
||||
|
@ -245,10 +238,10 @@ namespace swrenderer
|
|||
return true;
|
||||
}
|
||||
|
||||
WallC.sz1 = ds->sz1;
|
||||
WallC.sz2 = ds->sz2;
|
||||
WallC.sx1 = ds->sx1;
|
||||
WallC.sx2 = ds->sx2;
|
||||
WallC.sz1 = ds->WallC.sz1;
|
||||
WallC.sz2 = ds->WallC.sz2;
|
||||
WallC.sx1 = ds->WallC.sx1;
|
||||
WallC.sx2 = ds->WallC.sx2;
|
||||
|
||||
// Unclipped vanilla Doom range for the wall. Relies on ceiling/floor clip to clamp the wall in range.
|
||||
double ceilZ = textop;
|
||||
|
@ -317,10 +310,11 @@ namespace swrenderer
|
|||
if (visible)
|
||||
{
|
||||
Thread->PrepareTexture(tex, renderstyle);
|
||||
float lightpos = mLight.GetLightPos(x1);
|
||||
for (int x = x1; x < x2; ++x)
|
||||
{
|
||||
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);
|
||||
double sprtopscreen;
|
||||
|
@ -331,7 +325,7 @@ namespace swrenderer
|
|||
|
||||
columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, renderstyle);
|
||||
|
||||
rw_light += rw_lightstep;
|
||||
lightpos += mLight.GetLightStep();
|
||||
spryscale += rw_scalestep;
|
||||
}
|
||||
}
|
||||
|
@ -351,10 +345,10 @@ namespace swrenderer
|
|||
texturemid = (texturemid - Thread->Viewport->viewpoint.Pos.Z) * MaskedScaleY + rowoffset;
|
||||
}
|
||||
|
||||
WallC.sz1 = ds->sz1;
|
||||
WallC.sz2 = ds->sz2;
|
||||
WallC.sx1 = ds->sx1;
|
||||
WallC.sx2 = ds->sx2;
|
||||
WallC.sz1 = ds->WallC.sz1;
|
||||
WallC.sz2 = ds->WallC.sz2;
|
||||
WallC.sx1 = ds->WallC.sx1;
|
||||
WallC.sx2 = ds->WallC.sx2;
|
||||
|
||||
if (clip3d->CurrentSkybox)
|
||||
{ // 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
double xscale;
|
||||
|
@ -416,8 +410,7 @@ namespace swrenderer
|
|||
if (Alpha <= 0)
|
||||
return;
|
||||
|
||||
rw_lightstep = ds->lightstep;
|
||||
rw_light = ds->light + (x1 - ds->x1) * rw_lightstep;
|
||||
mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1);
|
||||
|
||||
const short *mfloorclip = ds->sprbottomclip - ds->x1;
|
||||
const short *mceilingclip = ds->sprtopclip - ds->x1;
|
||||
|
@ -469,14 +462,7 @@ namespace swrenderer
|
|||
texturemid += rowoffset;
|
||||
}
|
||||
|
||||
WallC.sz1 = ds->sz1;
|
||||
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;
|
||||
WallC = ds->WallC;
|
||||
WallT = ds->tmapvals;
|
||||
|
||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||
|
@ -495,15 +481,15 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
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;
|
||||
GetMaskedWallTopBottom(ds, top, bot);
|
||||
|
||||
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
|
||||
|
@ -695,46 +681,42 @@ namespace swrenderer
|
|||
}
|
||||
rw_pic = rw_tex && rw_tex->isValid() ? rw_tex->GetSoftwareTexture() : nullptr;
|
||||
}
|
||||
// correct colors now
|
||||
FDynamicColormap *basecolormap = nullptr;
|
||||
int lightlevel = ds->lightlevel;
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedLightLevel() < 0)
|
||||
{
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lightlist_t *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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lightlist_t *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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (basecolormap == nullptr) basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
|
||||
if (rw_pic && !swimmable_found)
|
||||
{
|
||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, lightlevel, basecolormap, clipTop, clipBottom, rw_pic);
|
||||
// correct colors now
|
||||
lightlist_t *lit = nullptr;
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedLightLevel() < 0)
|
||||
{
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lit = &backsector->e->XFloor.lightlist[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lit = &frontsector->e->XFloor.lightlist[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mLight.lightlevel = ds->lightlevel;
|
||||
mLight.SetColormap(frontsector, curline, lit);
|
||||
|
||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -882,46 +864,41 @@ namespace swrenderer
|
|||
}
|
||||
rw_pic = rw_tex && rw_tex->isValid() ? rw_tex->GetSoftwareTexture() : nullptr;
|
||||
}
|
||||
// correct colors now
|
||||
FDynamicColormap *basecolormap = nullptr;
|
||||
int lightlevel = ds->lightlevel;
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedLightLevel() < 0)
|
||||
{
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lightlist_t *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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lightlist_t *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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (basecolormap == nullptr) basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
|
||||
if (rw_pic && !swimmable_found)
|
||||
{
|
||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, lightlevel, basecolormap, clipTop, clipBottom, rw_pic);
|
||||
// correct colors now
|
||||
lightlist_t *lit = nullptr;
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedLightLevel() < 0)
|
||||
{
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lit = &backsector->e->XFloor.lightlist[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0())
|
||||
{
|
||||
lit = &frontsector->e->XFloor.lightlist[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//mLight.lightlevel = ds->lightlevel;
|
||||
mLight.SetColormap(frontsector, curline, lit);
|
||||
|
||||
RenderFakeWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -37,9 +37,9 @@ namespace swrenderer
|
|||
RenderThread *Thread = nullptr;
|
||||
|
||||
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 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 GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot);
|
||||
|
||||
|
@ -52,8 +52,8 @@ namespace swrenderer
|
|||
FWallCoords WallC;
|
||||
FWallTmapVals WallT;
|
||||
|
||||
float rw_light = 0.0f;
|
||||
float rw_lightstep = 0.0f;
|
||||
ProjectedWallLight mLight;
|
||||
|
||||
fixed_t rw_offset = 0;
|
||||
|
||||
ProjectedWallLine wallupper;
|
||||
|
|
|
@ -54,284 +54,7 @@
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
WallSampler::WallSampler(RenderViewport *viewport, int y1, double texturemid, float swal, double yrepeat, fixed_t xoffset, double xmagnitude, FSoftwareTexture *texture)
|
||||
{
|
||||
xoffset += FLOAT2FIXED(xmagnitude * 0.5);
|
||||
xoffset *= texture->GetPhysicalScale();
|
||||
|
||||
if (!viewport->RenderTarget->IsBgra())
|
||||
{
|
||||
height = texture->GetPhysicalHeight();
|
||||
|
||||
int uv_fracbits = 32 - texture->GetHeightBits();
|
||||
if (uv_fracbits != 32)
|
||||
{
|
||||
uv_max = height << uv_fracbits;
|
||||
|
||||
// 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.
|
||||
double uv_stepd = swal * yrepeat;
|
||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / texture->GetHeight();
|
||||
v = v - floor(v);
|
||||
v *= height;
|
||||
v *= (1 << uv_fracbits);
|
||||
|
||||
uv_pos = (uint32_t)(int64_t)v;
|
||||
uv_step = xs_ToFixed(uv_fracbits, uv_stepd * texture->GetPhysicalScale());
|
||||
if (uv_step == 0) // To prevent divide by zero elsewhere
|
||||
uv_step = 1;
|
||||
}
|
||||
else
|
||||
{ // Hack for one pixel tall textures
|
||||
uv_pos = 0;
|
||||
uv_step = 0;
|
||||
uv_max = 1;
|
||||
}
|
||||
|
||||
int col = xoffset >> FRACBITS;
|
||||
|
||||
// If the texture's width isn't a power of 2, then we need to make it a
|
||||
// positive offset for proper clamping.
|
||||
int width;
|
||||
if (col < 0 && (width = texture->GetPhysicalWidth()) != (1 << texture->GetWidthBits()))
|
||||
{
|
||||
col = width + (col % width);
|
||||
}
|
||||
|
||||
source = texture->GetColumn(DefaultRenderStyle(), col, nullptr);
|
||||
source2 = nullptr;
|
||||
texturefracx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normalize to 0-1 range:
|
||||
double uv_stepd = swal * yrepeat;
|
||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / texture->GetHeight();
|
||||
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;
|
||||
v = 0.0;
|
||||
v_step = 0.0;
|
||||
}
|
||||
|
||||
// Convert to uint32_t:
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
if (tx < 0)
|
||||
tx += mip_width;
|
||||
source = (uint8_t*)(pixels + tx * mip_height);
|
||||
source2 = nullptr;
|
||||
height = mip_height;
|
||||
texturefracx = 0;
|
||||
}
|
||||
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::Draw1Column(int x, int y1, int y2, WallSampler &sampler)
|
||||
{
|
||||
// Find column position in view space
|
||||
float w1 = 1.0f / WallC.sz1;
|
||||
float w2 = 1.0f / WallC.sz2;
|
||||
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||
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.Y = zcol;
|
||||
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol);
|
||||
drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale);
|
||||
|
||||
// Calculate max lights that can touch column so we can allocate memory for the list
|
||||
int max_lights = 0;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
drawerargs.dc_num_lights = 0;
|
||||
drawerargs.dc_lights = Thread->FrameMemory->AllocMemory<DrawerLight>(max_lights);
|
||||
|
||||
// Setup lights for column
|
||||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
{
|
||||
double lightX = cur_node->lightsource->X() - Thread->Viewport->viewpoint.Pos.X;
|
||||
double lightY = cur_node->lightsource->Y() - Thread->Viewport->viewpoint.Pos.Y;
|
||||
double lightZ = cur_node->lightsource->Z() - Thread->Viewport->viewpoint.Pos.Z;
|
||||
|
||||
float lx = (float)(lightX * Thread->Viewport->viewpoint.Sin - lightY * Thread->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 lz = (float)lightZ;
|
||||
|
||||
// Precalculate the constant part of the dot here so the drawer doesn't have to.
|
||||
bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
float lconstant = lx * lx + ly * ly;
|
||||
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
|
||||
|
||||
// Include light only if it touches this column
|
||||
float radius = cur_node->lightsource->GetRadius();
|
||||
if (radius * radius >= lconstant && nlconstant >= 0.0f)
|
||||
{
|
||||
uint32_t red = cur_node->lightsource->GetRed();
|
||||
uint32_t green = cur_node->lightsource->GetGreen();
|
||||
uint32_t blue = cur_node->lightsource->GetBlue();
|
||||
|
||||
auto &light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
|
||||
light.x = lconstant;
|
||||
light.y = nlconstant;
|
||||
light.z = lz;
|
||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||
light.color = (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
||||
{
|
||||
if (rw_pic == nullptr)
|
||||
return;
|
||||
|
@ -344,54 +67,347 @@ namespace swrenderer
|
|||
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)
|
||||
{
|
||||
drawerargs.SetStyle(true, false, OPAQUE, basecolormap);
|
||||
drawerargs.SetStyle(true, false, OPAQUE, mLight.GetBaseColormap());
|
||||
}
|
||||
else
|
||||
{
|
||||
drawerargs.SetStyle(mask, additive, alpha, basecolormap);
|
||||
drawerargs.SetStyle(mask, additive, alpha, mLight.GetBaseColormap());
|
||||
}
|
||||
|
||||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
bool fixed = (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0);
|
||||
RenderViewport *viewport = Thread->Viewport.get();
|
||||
|
||||
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;
|
||||
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 = light;
|
||||
for (int x = x1; x < x2; x++, curlight += lightstep)
|
||||
float curlight = mLight.GetLightPos(x1);
|
||||
float lightstep = mLight.GetLightStep();
|
||||
|
||||
if (viewport->RenderTarget->IsBgra())
|
||||
{
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 <= y1)
|
||||
continue;
|
||||
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 (!fixed)
|
||||
drawerargs.SetLight(curlight, mLight.GetLightLevel(), mLight.GetFoggy(), viewport);
|
||||
|
||||
if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(lwal[x + 1]) - FIXED2DBL(lwal[x]));
|
||||
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);
|
||||
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)
|
||||
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.
|
||||
// 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[x] * yrepeat;
|
||||
double v = (texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight();
|
||||
v = v - floor(v);
|
||||
v *= height;
|
||||
v *= (1 << uv_fracbits);
|
||||
|
||||
uv_pos = (uint32_t)(int64_t)v;
|
||||
uv_step = xs_ToFixed(uv_fracbits, uv_stepd * rw_pic->GetPhysicalScale());
|
||||
if (uv_step == 0) // To prevent divide by zero elsewhere
|
||||
uv_step = 1;
|
||||
}
|
||||
else
|
||||
{ // Hack for one pixel tall textures
|
||||
uv_pos = 0;
|
||||
uv_step = 0;
|
||||
uv_max = 1;
|
||||
}
|
||||
|
||||
int col = xxoffset >> FRACBITS;
|
||||
|
||||
// If the texture's width isn't a power of 2, then we need to make it a
|
||||
// positive offset for proper clamping.
|
||||
int width;
|
||||
if (col < 0 && (width = rw_pic->GetPhysicalWidth()) != (1 << rw_pic->GetWidthBits()))
|
||||
{
|
||||
col = width + (col % width);
|
||||
}
|
||||
|
||||
drawerargs.SetTexture(rw_pic->GetColumn(DefaultRenderStyle(), col, nullptr), nullptr, height);
|
||||
|
||||
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
|
||||
{
|
||||
uint32_t left = y2 - y1;
|
||||
int y = y1;
|
||||
while (left > 0)
|
||||
{
|
||||
uint32_t available = uv_max - uv_pos;
|
||||
uint32_t next_uv_wrap = available / uv_step;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Thread->MainThread)
|
||||
NetUpdate();
|
||||
if (r_modelscene)
|
||||
{
|
||||
for (int x = x1; x < x2; x++)
|
||||
{
|
||||
int y1 = uwal[x];
|
||||
int y2 = dwal[x];
|
||||
if (y2 > y1)
|
||||
{
|
||||
int count = y2 - y1;
|
||||
|
||||
float w1 = 1.0f / WallC.sz1;
|
||||
float w2 = 1.0f / WallC.sz2;
|
||||
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal)
|
||||
void RenderWallPart::SetLights(WallDrawerArgs &drawerargs, int x, int y1)
|
||||
{
|
||||
ProcessWallWorker(uwal, dwal, texturemid, swal, lwal);
|
||||
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
|
||||
float w1 = 1.0f / WallC.sz1;
|
||||
float w2 = 1.0f / WallC.sz2;
|
||||
float t = (x - WallC.sx1 + 0.5f) / (WallC.sx2 - WallC.sx1);
|
||||
float wcol = w1 * (1.0f - t) + w2 * t;
|
||||
float zcol = 1.0f / wcol;
|
||||
|
||||
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
|
||||
drawerargs.dc_viewpos.Y = zcol;
|
||||
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol);
|
||||
drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale);
|
||||
|
||||
// Calculate max lights that can touch column so we can allocate memory for the list
|
||||
int max_lights = 0;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
drawerargs.dc_num_lights = 0;
|
||||
drawerargs.dc_lights = Thread->FrameMemory->AllocMemory<DrawerLight>(max_lights);
|
||||
|
||||
// Setup lights for column
|
||||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
{
|
||||
double lightX = cur_node->lightsource->X() - viewport->viewpoint.Pos.X;
|
||||
double lightY = cur_node->lightsource->Y() - viewport->viewpoint.Pos.Y;
|
||||
double lightZ = cur_node->lightsource->Z() - viewport->viewpoint.Pos.Z;
|
||||
|
||||
float lx = (float)(lightX * viewport->viewpoint.Sin - lightY * viewport->viewpoint.Cos) - drawerargs.dc_viewpos.X;
|
||||
float ly = (float)(lightX * viewport->viewpoint.TanCos + lightY * viewport->viewpoint.TanSin) - drawerargs.dc_viewpos.Y;
|
||||
float lz = (float)lightZ;
|
||||
|
||||
// Precalculate the constant part of the dot here so the drawer doesn't have to.
|
||||
bool is_point_light = (cur_node->lightsource->lightflags & LF_ATTENUATE) != 0;
|
||||
float lconstant = lx * lx + ly * ly;
|
||||
float nlconstant = is_point_light ? lx * drawerargs.dc_normal.X + ly * drawerargs.dc_normal.Y : 0.0f;
|
||||
|
||||
// Include light only if it touches this column
|
||||
float radius = cur_node->lightsource->GetRadius();
|
||||
if (radius * radius >= lconstant && nlconstant >= 0.0f)
|
||||
{
|
||||
uint32_t red = cur_node->lightsource->GetRed();
|
||||
uint32_t green = cur_node->lightsource->GetGreen();
|
||||
uint32_t blue = cur_node->lightsource->GetBlue();
|
||||
|
||||
auto &light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
|
||||
light.x = lconstant;
|
||||
light.y = nlconstant;
|
||||
light.z = lz;
|
||||
light.radius = 256.0f / cur_node->lightsource->GetRadius();
|
||||
light.color = (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
}
|
||||
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
lightlist_t *lit = &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);
|
||||
mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]);
|
||||
}
|
||||
|
||||
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->x2 = x2;
|
||||
|
@ -524,18 +538,17 @@ namespace swrenderer
|
|||
this->curline = curline;
|
||||
this->WallC = WallC;
|
||||
this->yrepeat = yscale;
|
||||
this->lightlevel = lightlevel;
|
||||
this->mLight = light;
|
||||
this->xoffset = xoffset;
|
||||
this->light = light;
|
||||
this->lightstep = lightstep;
|
||||
this->foggy = foggy;
|
||||
this->basecolormap = basecolormap;
|
||||
this->light_list = light_list;
|
||||
this->rw_pic = pic;
|
||||
this->mask = mask;
|
||||
this->additive = additive;
|
||||
this->alpha = alpha;
|
||||
|
||||
if (Thread->MainThread)
|
||||
NetUpdate();
|
||||
|
||||
Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here.
|
||||
|
||||
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
|
||||
|
|
|
@ -63,13 +63,9 @@ namespace swrenderer
|
|||
bool mask,
|
||||
bool additive,
|
||||
fixed_t alpha,
|
||||
int lightlevel,
|
||||
fixed_t xoffset,
|
||||
float light,
|
||||
float lightstep,
|
||||
FLightNode *light_list,
|
||||
bool foggy,
|
||||
FDynamicColormap *basecolormap);
|
||||
const ProjectedWallLight &light,
|
||||
FLightNode *light_list);
|
||||
|
||||
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 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 ProcessWallWorker(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal);
|
||||
void Draw1Column(int x, int y1, int y2, WallSampler &sampler);
|
||||
void SetLights(WallDrawerArgs &drawerargs, int x, int y1);
|
||||
|
||||
int x1 = 0;
|
||||
int x2 = 0;
|
||||
|
@ -88,33 +83,13 @@ namespace swrenderer
|
|||
seg_t *curline = nullptr;
|
||||
FWallCoords WallC;
|
||||
|
||||
ProjectedWallLight mLight;
|
||||
|
||||
double yrepeat = 0.0;
|
||||
int lightlevel = 0;
|
||||
fixed_t xoffset = 0;
|
||||
float light = 0.0f;
|
||||
float lightstep = 0.0f;
|
||||
bool foggy = false;
|
||||
FDynamicColormap *basecolormap = nullptr;
|
||||
FLightNode *light_list = nullptr;
|
||||
bool mask = false;
|
||||
bool additive = false;
|
||||
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 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
|
||||
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;
|
||||
seg_t* line;
|
||||
|
@ -463,7 +463,7 @@ namespace swrenderer
|
|||
{
|
||||
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++;
|
||||
}
|
||||
|
@ -622,8 +622,6 @@ namespace swrenderer
|
|||
|
||||
DVector2 viewpointPos = Thread->Viewport->viewpoint.Pos.XY();
|
||||
|
||||
basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
|
||||
seg_t *line = sub->firstline;
|
||||
int count = sub->numlines;
|
||||
while (count--)
|
||||
|
@ -637,8 +635,8 @@ namespace swrenderer
|
|||
}
|
||||
else if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
|
||||
{
|
||||
Add3DFloorLine(line, frontsector, basecolormap, foggy);
|
||||
renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, foggy, basecolormap, Fake3DOpaque::Normal); // now real
|
||||
Add3DFloorLine(line, frontsector);
|
||||
renderline.Render(line, InSubsector, frontsector, nullptr, floorplane, ceilingplane, Fake3DOpaque::Normal); // now real
|
||||
}
|
||||
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
|
||||
if (r_3dfloors && line->backsector && frontsector->e && line->backsector->e->XFloor.ffloors.Size())
|
||||
|
@ -669,7 +667,7 @@ namespace swrenderer
|
|||
clip3d->fakeFloor->validcount = validcount;
|
||||
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;
|
||||
}
|
||||
|
@ -744,7 +742,7 @@ namespace swrenderer
|
|||
|
||||
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
|
||||
|
@ -812,7 +810,7 @@ namespace swrenderer
|
|||
|
||||
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;
|
||||
|
|
|
@ -86,8 +86,8 @@ namespace swrenderer
|
|||
void AddPolyobjs(subsector_t *sub);
|
||||
|
||||
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 Add3DFloorLine(seg_t *line, sector_t *frontsector, FDynamicColormap *basecolormap, bool foggy);
|
||||
void FakeDrawLoop(subsector_t *sub, sector_t *frontsector, VisiblePlane *floorplane, VisiblePlane *ceilingplane, Fake3DOpaque opaque3dfloor);
|
||||
void Add3DFloorLine(seg_t *line, sector_t *frontsector);
|
||||
|
||||
void AddSprites(sector_t *sec, int lightlevel, WaterFakeSide fakeside, bool foggy, FDynamicColormap *basecolormap);
|
||||
bool IsPotentiallyVisible(AActor *thing);
|
||||
|
|
|
@ -206,10 +206,8 @@ namespace swrenderer
|
|||
// Create a drawseg to clip sprites to the sky plane
|
||||
DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
|
||||
draw_segment->CurrentPortalUniq = CurrentPortalUniq;
|
||||
draw_segment->siz1 = INT_MAX;
|
||||
draw_segment->siz2 = INT_MAX;
|
||||
draw_segment->sz1 = 0;
|
||||
draw_segment->sz2 = 0;
|
||||
draw_segment->WallC.sz1 = 0;
|
||||
draw_segment->WallC.sz2 = 0;
|
||||
draw_segment->x1 = pl->left;
|
||||
draw_segment->x2 = pl->right;
|
||||
draw_segment->silhouette = SIL_BOTH;
|
||||
|
@ -219,7 +217,6 @@ namespace swrenderer
|
|||
draw_segment->swall = nullptr;
|
||||
draw_segment->bFogBoundary = false;
|
||||
draw_segment->curline = nullptr;
|
||||
draw_segment->foggy = false;
|
||||
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));
|
||||
drawseglist->Push(draw_segment);
|
||||
|
|
|
@ -107,18 +107,18 @@ namespace swrenderer
|
|||
group.EndIndex = MIN(index + groupSize, SegmentsCount());
|
||||
group.x1 = ds->x1;
|
||||
group.x2 = ds->x2;
|
||||
group.neardepth = MIN(ds->sz1, ds->sz2);
|
||||
group.fardepth = MAX(ds->sz1, ds->sz2);
|
||||
group.neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2);
|
||||
group.fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2);
|
||||
|
||||
for (unsigned int groupIndex = group.BeginIndex + 1; groupIndex < group.EndIndex; groupIndex++)
|
||||
{
|
||||
ds = Segment(groupIndex);
|
||||
group.x1 = MIN(group.x1, ds->x1);
|
||||
group.x2 = MAX(group.x2, ds->x2);
|
||||
group.neardepth = MIN(group.neardepth, ds->sz1);
|
||||
group.neardepth = MIN(group.neardepth, ds->sz2);
|
||||
group.fardepth = MAX(ds->sz1, group.fardepth);
|
||||
group.fardepth = MAX(ds->sz2, group.fardepth);
|
||||
group.neardepth = MIN(group.neardepth, ds->WallC.sz1);
|
||||
group.neardepth = MIN(group.neardepth, ds->WallC.sz2);
|
||||
group.fardepth = MAX(ds->WallC.sz1, group.fardepth);
|
||||
group.fardepth = MAX(ds->WallC.sz2, group.fardepth);
|
||||
}
|
||||
|
||||
for (int x = group.x1; x < group.x2; x++)
|
||||
|
|
|
@ -31,15 +31,10 @@ namespace swrenderer
|
|||
float light, lightstep;
|
||||
float iscale, iscalestep;
|
||||
short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg
|
||||
short sx1, sx2; // left, right of parent seg on screen
|
||||
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;
|
||||
FWallCoords WallC;
|
||||
float yscale;
|
||||
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
||||
bool bFogBoundary = false;
|
||||
int lightlevel = 0;
|
||||
bool foggy = false;
|
||||
|
||||
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
|
||||
short *sprtopclip = nullptr;
|
||||
|
|
|
@ -57,15 +57,15 @@ EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
|||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
int x1, x2;
|
||||
|
@ -75,7 +75,6 @@ namespace swrenderer
|
|||
int needrepeat = 0;
|
||||
sector_t *back;
|
||||
FDynamicColormap *usecolormap;
|
||||
float light = 0;
|
||||
const short *mfloorclip;
|
||||
const short *mceilingclip;
|
||||
|
||||
|
@ -257,7 +256,7 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
// Prepare lighting
|
||||
usecolormap = basecolormap;
|
||||
usecolormap = light.GetBaseColormap();
|
||||
|
||||
// Decals that are added to the scene must fade to black.
|
||||
if (decal->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0)
|
||||
|
@ -265,7 +264,7 @@ namespace swrenderer
|
|||
usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate);
|
||||
}
|
||||
|
||||
light = lightleft + (x1 - savecoord.sx1) * lightstep;
|
||||
float lightpos = light.GetLightPos(x1);
|
||||
|
||||
cameraLight = CameraLight::Instance();
|
||||
|
||||
|
@ -288,7 +287,7 @@ namespace swrenderer
|
|||
int x = x1;
|
||||
|
||||
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;
|
||||
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)
|
||||
{ // 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);
|
||||
light += lightstep;
|
||||
lightpos += light.GetLightStep();
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@ namespace swrenderer
|
|||
class RenderDecal
|
||||
{
|
||||
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:
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -291,7 +291,9 @@ namespace swrenderer
|
|||
{
|
||||
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
|
||||
if (ds->CurrentPortalUniq == CurrentPortalUniq)
|
||||
|
|
|
@ -340,8 +340,8 @@ namespace swrenderer
|
|||
continue;
|
||||
}
|
||||
|
||||
float neardepth = MIN(ds->sz1, ds->sz2);
|
||||
float fardepth = MAX(ds->sz1, ds->sz2);
|
||||
float neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2);
|
||||
float fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2);
|
||||
|
||||
// Check if sprite is in front of draw seg:
|
||||
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 r2 = MIN<int>(ds->x2, x2);
|
||||
|
||||
float neardepth = MIN(ds->sz1, ds->sz2);
|
||||
float fardepth = MAX(ds->sz1, ds->sz2);
|
||||
float neardepth = MIN(ds->WallC.sz1, ds->WallC.sz2);
|
||||
float fardepth = MAX(ds->WallC.sz1, ds->WallC.sz2);
|
||||
|
||||
// Check if sprite is in front of draw seg:
|
||||
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
|
||||
|
|
|
@ -48,16 +48,16 @@ const char *GetVersionString();
|
|||
#ifdef GIT_DESCRIPTION
|
||||
#define VERSIONSTR GIT_DESCRIPTION
|
||||
#else
|
||||
#define VERSIONSTR "3.7pre"
|
||||
#define VERSIONSTR "3.8pre"
|
||||
#endif
|
||||
|
||||
// The version as seen in the Windows resource
|
||||
#define RC_FILEVERSION 3,6,9999,0
|
||||
#define RC_PRODUCTVERSION 3,6,9999,0
|
||||
#define RC_FILEVERSION 3,7,9999,0
|
||||
#define RC_PRODUCTVERSION 3,7,9999,0
|
||||
#define RC_PRODUCTVERSION2 VERSIONSTR
|
||||
// These are for content versioning.
|
||||
#define VER_MAJOR 3
|
||||
#define VER_MINOR 7
|
||||
#define VER_MINOR 8
|
||||
#define VER_REVISION 0
|
||||
|
||||
// Version identifier for network games.
|
||||
|
|
|
@ -146,6 +146,12 @@ class LevelCompatibility native play
|
|||
SetLineActivation(959, SPAC_Cross);
|
||||
SetLineSpecial(960, Floor_RaiseToNearest, 16, 32);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -179,6 +185,7 @@ class LevelCompatibility native play
|
|||
}
|
||||
|
||||
case 'A53AE580A4AF2B5D0B0893F86914781E': // TNT: Evilution map31
|
||||
case '55192065F7FAA7D161767145DA008293': // TNT Anthology/GOG MAP31
|
||||
{
|
||||
// The famous missing yellow key...
|
||||
SetThingFlags(470, 2016);
|
||||
|
@ -234,6 +241,15 @@ class LevelCompatibility native play
|
|||
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
|
||||
{
|
||||
// Missing texture at level exit.
|
||||
|
|
Loading…
Reference in a new issue