- Translucent 3d floor plane support

This commit is contained in:
Magnus Norddahl 2017-09-02 02:51:09 +02:00
parent 393373a661
commit b80bf6930a
4 changed files with 199 additions and 117 deletions

View file

@ -34,59 +34,6 @@
EXTERN_CVAR(Int, r_3dfloors)
void RenderPolyPlane::Render3DPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue)
{
if (!r_3dfloors || sub->sector->CenterFloor() == sub->sector->CenterCeiling())
return;
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
auto frontsector = sub->sector;
auto &ffloors = frontsector->e->XFloor.ffloors;
// 3D floor floors
for (int i = 0; i < (int)ffloors.Size(); i++)
{
F3DFloor *fakeFloor = ffloors[i];
if (!(fakeFloor->flags & FF_EXISTS)) continue;
if (!fakeFloor->model) continue;
//if (!(fakeFloor->flags & FF_NOSHADE) || (fakeFloor->flags & (FF_RENDERPLANES | FF_RENDERSIDES)))
// R_3D_AddHeight(fakeFloor->top.plane, frontsector);
if (!(fakeFloor->flags & FF_RENDERPLANES)) continue;
if (fakeFloor->alpha == 0) continue;
if (fakeFloor->flags & FF_THISINSIDE && fakeFloor->flags & FF_INVERTSECTOR) continue;
//fakeFloor->alpha
double fakeHeight = fakeFloor->top.plane->ZatPoint(frontsector->centerspot);
if (fakeFloor->bottom.plane->isSlope() || (fakeHeight < viewpoint.Pos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot)))
{
RenderPolyPlane plane;
plane.Render3DFloor(worldToClip, clipPlane, sub, stencilValue, false, fakeFloor);
}
}
// 3D floor ceilings
for (int i = 0; i < (int)ffloors.Size(); i++)
{
F3DFloor *fakeFloor = ffloors[i];
if (!(fakeFloor->flags & FF_EXISTS)) continue;
if (!fakeFloor->model) continue;
//if (!(fakeFloor->flags & FF_NOSHADE) || (fakeFloor->flags & (FF_RENDERPLANES | FF_RENDERSIDES)))
// R_3D_AddHeight(fakeFloor->bottom.plane, frontsector);
if (!(fakeFloor->flags & FF_RENDERPLANES)) continue;
if (fakeFloor->alpha == 0) continue;
if (!(fakeFloor->flags & FF_THISINSIDE) && (fakeFloor->flags & (FF_SWIMMABLE | FF_INVERTSECTOR)) == (FF_SWIMMABLE | FF_INVERTSECTOR)) continue;
//fakeFloor->alpha
double fakeHeight = fakeFloor->bottom.plane->ZatPoint(frontsector->centerspot);
if (fakeFloor->bottom.plane->isSlope() || (fakeHeight > viewpoint.Pos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot)))
{
RenderPolyPlane plane;
plane.Render3DFloor(worldToClip, clipPlane, sub, stencilValue, true, fakeFloor);
}
}
}
void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
if (sub->sector->CenterFloor() == sub->sector->CenterCeiling())
@ -97,59 +44,6 @@ void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipP
plane.Render(worldToClip, clipPlane, cull, sub, stencilValue, false, skyFloorHeight, sectorPortals);
}
void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, F3DFloor *fakeFloor)
{
FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture;
FTexture *tex = TexMan(picnum);
if (tex->UseType == FTexture::TEX_Null)
return;
PolyCameraLight *cameraLight = PolyCameraLight::Instance();
int lightlevel = 255;
bool foggy = false;
if (cameraLight->FixedLightLevel() < 0 && sub->sector->e->XFloor.lightlist.Size())
{
lightlist_t *light = P_GetPlaneLight(sub->sector, &sub->sector->ceilingplane, false);
//basecolormap = light->extra_colormap;
lightlevel = *light->p_lightlevel;
}
int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4;
lightlevel = clamp(lightlevel + actualextralight, 0, 255);
PolyPlaneUVTransform xform(ceiling ? fakeFloor->top.model->planes[sector_t::ceiling].xform : fakeFloor->top.model->planes[sector_t::floor].xform, tex);
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(sub->numlines);
if (ceiling)
{
for (uint32_t i = 0; i < sub->numlines; i++)
{
seg_t *line = &sub->firstline[i];
vertices[sub->numlines - 1 - i] = xform.GetVertex(line->v1, fakeFloor->bottom.plane->ZatPoint(line->v1));
}
}
else
{
for (uint32_t i = 0; i < sub->numlines; i++)
{
seg_t *line = &sub->firstline[i];
vertices[i] = xform.GetVertex(line->v1, fakeFloor->top.plane->ZatPoint(line->v1));
}
}
PolyDrawArgs args;
args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
args.SetTransform(&worldToClip);
args.SetStyle(TriBlendMode::TextureOpaque);
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetTexture(tex);
args.SetClipPlane(0, clipPlane);
args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan);
}
void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
@ -487,3 +381,161 @@ float PolyPlaneUVTransform::GetV(float x, float y) const
{
return (yOffs - x * sine - y * cosine) * yscale;
}
/////////////////////////////////////////////////////////////////////////////
void Render3DFloorPlane::RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector<PolyTranslucentObject *> &translucentObjects)
{
if (!r_3dfloors || sub->sector->CenterFloor() == sub->sector->CenterCeiling())
return;
const auto &viewpoint = PolyRenderer::Instance()->Viewpoint;
auto frontsector = sub->sector;
auto &ffloors = frontsector->e->XFloor.ffloors;
// 3D floor floors
for (int i = 0; i < (int)ffloors.Size(); i++)
{
F3DFloor *fakeFloor = ffloors[i];
if (!(fakeFloor->flags & FF_EXISTS)) continue;
if (!fakeFloor->model) continue;
//if (!(fakeFloor->flags & FF_NOSHADE) || (fakeFloor->flags & (FF_RENDERPLANES | FF_RENDERSIDES)))
// R_3D_AddHeight(fakeFloor->top.plane, frontsector);
if (!(fakeFloor->flags & FF_RENDERPLANES)) continue;
if (fakeFloor->alpha == 0) continue;
if (fakeFloor->flags & FF_THISINSIDE && fakeFloor->flags & FF_INVERTSECTOR) continue;
//fakeFloor->alpha
double fakeHeight = fakeFloor->top.plane->ZatPoint(frontsector->centerspot);
if (fakeFloor->bottom.plane->isSlope() || (fakeHeight < viewpoint.Pos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot)))
{
Render3DFloorPlane plane;
plane.sub = sub;
plane.stencilValue = stencilValue;
plane.ceiling = false;
plane.fakeFloor = fakeFloor;
plane.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS);
if (!plane.Additive && fakeFloor->alpha == 255)
{
plane.Masked = false;
plane.Alpha = 1.0;
}
else
{
plane.Masked = true;
plane.Alpha = fakeFloor->alpha / 255.0;
}
if (!plane.Masked)
plane.Render(worldToClip, clipPlane);
else
translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject<PolyTranslucentObject>(plane, subsectorDepth));
}
}
// 3D floor ceilings
for (int i = 0; i < (int)ffloors.Size(); i++)
{
F3DFloor *fakeFloor = ffloors[i];
if (!(fakeFloor->flags & FF_EXISTS)) continue;
if (!fakeFloor->model) continue;
//if (!(fakeFloor->flags & FF_NOSHADE) || (fakeFloor->flags & (FF_RENDERPLANES | FF_RENDERSIDES)))
// R_3D_AddHeight(fakeFloor->bottom.plane, frontsector);
if (!(fakeFloor->flags & FF_RENDERPLANES)) continue;
if (fakeFloor->alpha == 0) continue;
if (!(fakeFloor->flags & FF_THISINSIDE) && (fakeFloor->flags & (FF_SWIMMABLE | FF_INVERTSECTOR)) == (FF_SWIMMABLE | FF_INVERTSECTOR)) continue;
//fakeFloor->alpha
double fakeHeight = fakeFloor->bottom.plane->ZatPoint(frontsector->centerspot);
if (fakeFloor->bottom.plane->isSlope() || (fakeHeight > viewpoint.Pos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot)))
{
Render3DFloorPlane plane;
plane.sub = sub;
plane.stencilValue = stencilValue;
plane.ceiling = true;
plane.fakeFloor = fakeFloor;
plane.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS);
if (!plane.Additive && fakeFloor->alpha == 255)
{
plane.Masked = false;
plane.Alpha = 1.0;
}
else
{
plane.Masked = true;
plane.Alpha = fakeFloor->alpha / 255.0;
}
if (!plane.Masked)
plane.Render(worldToClip, clipPlane);
else
translucentObjects.push_back(PolyRenderer::Instance()->FrameMemory.NewObject<PolyTranslucentObject>(plane, subsectorDepth));
}
}
}
void Render3DFloorPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane)
{
FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture;
FTexture *tex = TexMan(picnum);
if (tex->UseType == FTexture::TEX_Null)
return;
PolyCameraLight *cameraLight = PolyCameraLight::Instance();
int lightlevel = 255;
bool foggy = false;
if (cameraLight->FixedLightLevel() < 0 && sub->sector->e->XFloor.lightlist.Size())
{
lightlist_t *light = P_GetPlaneLight(sub->sector, &sub->sector->ceilingplane, false);
//basecolormap = light->extra_colormap;
lightlevel = *light->p_lightlevel;
}
int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4;
lightlevel = clamp(lightlevel + actualextralight, 0, 255);
PolyPlaneUVTransform xform(ceiling ? fakeFloor->top.model->planes[sector_t::ceiling].xform : fakeFloor->top.model->planes[sector_t::floor].xform, tex);
TriVertex *vertices = PolyRenderer::Instance()->FrameMemory.AllocMemory<TriVertex>(sub->numlines);
if (ceiling)
{
for (uint32_t i = 0; i < sub->numlines; i++)
{
seg_t *line = &sub->firstline[i];
vertices[sub->numlines - 1 - i] = xform.GetVertex(line->v1, fakeFloor->bottom.plane->ZatPoint(line->v1));
}
}
else
{
for (uint32_t i = 0; i < sub->numlines; i++)
{
seg_t *line = &sub->firstline[i];
vertices[i] = xform.GetVertex(line->v1, fakeFloor->top.plane->ZatPoint(line->v1));
}
}
PolyDrawArgs args;
args.SetLight(GetColorTable(sub->sector->Colormap), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
args.SetTransform(&worldToClip);
if (!Masked)
{
args.SetStyle(TriBlendMode::TextureOpaque);
}
else
{
double srcalpha = MIN(Alpha, 1.0);
double destalpha = Additive ? 1.0 : 1.0 - srcalpha;
args.SetStyle(TriBlendMode::TextureAdd, srcalpha, destalpha);
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
}
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetTexture(tex);
args.SetClipPlane(0, clipPlane);
args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan);
}

View file

@ -49,10 +49,24 @@ class RenderPolyPlane
{
public:
static void RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
static void Render3DPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue);
private:
void Render3DFloor(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, bool ceiling, F3DFloor *fakefloor);
void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, PolyCull &cull, subsector_t *sub, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
void RenderSkyWalls(PolyDrawArgs &args, subsector_t *sub, sector_t *frontsector, FSectorPortal *portal, PolyDrawSectorPortal *polyportal, bool ceiling, double skyHeight, const PolyPlaneUVTransform &transform);
};
class Render3DFloorPlane
{
public:
static void RenderPlanes(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane, subsector_t *sub, uint32_t stencilValue, uint32_t subsectorDepth, std::vector<PolyTranslucentObject *> &translucentObjects);
void Render(const TriMatrix &worldToClip, const PolyClipPlane &clipPlane);
subsector_t *sub = nullptr;
uint32_t stencilValue = 0;
bool ceiling = false;
F3DFloor *fakeFloor = nullptr;
bool Masked = false;
bool Additive = false;
double Alpha = 1.0;
};

View file

@ -168,12 +168,12 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub, uint32_t ceilingSubsecto
RenderPolyNode(&sub->BSP->Nodes.Last(), subsectorDepth, frontsector);
}
RenderPolyPlane::Render3DPlanes(WorldToClip, PortalPlane, sub, StencilValue);
Render3DFloorPlane::RenderPlanes(WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects);
RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, Cull, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals);
}
else
{
RenderPolyPlane::Render3DPlanes(WorldToClip, PortalPlane, sub, StencilValue);
Render3DFloorPlane::RenderPlanes(WorldToClip, PortalPlane, sub, StencilValue, subsectorDepth, TranslucentObjects);
RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, Cull, sub, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals);
for (uint32_t i = 0; i < sub->numlines; i++)
@ -458,21 +458,26 @@ void RenderPolyScene::RenderTranslucent(int portalDepth)
for (auto it = TranslucentObjects.rbegin(); it != TranslucentObjects.rend(); ++it)
{
PolyTranslucentObject *obj = *it;
if (obj->particle)
// To do: convert PolyTranslucentObject to an interface with subclasses!
if (obj->type == PolyTranslucentObjectType::Particle)
{
RenderPolyParticle spr;
spr.Render(WorldToClip, PortalPlane, obj->particle, obj->sub, StencilValue + 1);
}
else if (!obj->thing)
else if (obj->type == PolyTranslucentObjectType::Wall)
{
obj->wall.Render(WorldToClip, PortalPlane);
}
else if ((obj->thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
else if (obj->type == PolyTranslucentObjectType::Plane)
{
obj->plane.Render(WorldToClip, PortalPlane);
}
else if (obj->type == PolyTranslucentObjectType::Thing && (obj->thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
{
RenderPolyWallSprite wallspr;
wallspr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, StencilValue + 1);
}
else
else if (obj->type == PolyTranslucentObjectType::Thing)
{
RenderPolySprite spr;
spr.Render(WorldToClip, PortalPlane, obj->thing, obj->sub, StencilValue + 1, obj->SpriteLeft, obj->SpriteRight);

View file

@ -39,23 +39,34 @@
#include <set>
#include <unordered_map>
enum class PolyTranslucentObjectType
{
Particle,
Thing,
Wall,
Plane
};
class PolyTranslucentObject
{
public:
PolyTranslucentObject(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth) : particle(particle), sub(sub), subsectorDepth(subsectorDepth) { }
PolyTranslucentObject(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2) : thing(thing), sub(sub), subsectorDepth(subsectorDepth), DistanceSquared(dist), SpriteLeft(t1), SpriteRight(t2) { }
PolyTranslucentObject(RenderPolyWall wall) : wall(wall), subsectorDepth(wall.SubsectorDepth), DistanceSquared(1.e6) { }
PolyTranslucentObject(particle_t *particle, subsector_t *sub, uint32_t subsectorDepth) : type(PolyTranslucentObjectType::Particle), particle(particle), sub(sub), subsectorDepth(subsectorDepth) { }
PolyTranslucentObject(AActor *thing, subsector_t *sub, uint32_t subsectorDepth, double dist, float t1, float t2) : type(PolyTranslucentObjectType::Thing), thing(thing), sub(sub), subsectorDepth(subsectorDepth), DistanceSquared(dist), SpriteLeft(t1), SpriteRight(t2) { }
PolyTranslucentObject(RenderPolyWall wall) : type(PolyTranslucentObjectType::Wall), wall(wall), subsectorDepth(wall.SubsectorDepth), DistanceSquared(1.e6) { }
PolyTranslucentObject(Render3DFloorPlane plane, uint32_t subsectorDepth) : type(PolyTranslucentObjectType::Plane), plane(plane), subsectorDepth(subsectorDepth), DistanceSquared(1.e7) { }
bool operator<(const PolyTranslucentObject &other) const
{
return subsectorDepth != other.subsectorDepth ? subsectorDepth < other.subsectorDepth : DistanceSquared < other.DistanceSquared;
}
PolyTranslucentObjectType type;
particle_t *particle = nullptr;
AActor *thing = nullptr;
subsector_t *sub = nullptr;
RenderPolyWall wall;
Render3DFloorPlane plane;
uint32_t subsectorDepth = 0;
double DistanceSquared = 0.0;