Add plane clipping to the triangle drawer

This commit is contained in:
Magnus Norddahl 2016-11-26 10:49:29 +01:00
parent 8bbb63e913
commit c37ce1fdbc
19 changed files with 146 additions and 99 deletions

View File

@ -191,26 +191,6 @@ struct TriVertex
float varying[NumVarying];
};
struct TriMatrix
{
static TriMatrix null();
static TriMatrix identity();
static TriMatrix translate(float x, float y, float z);
static TriMatrix scale(float x, float y, float z);
static TriMatrix rotate(float angle, float x, float y, float z);
static TriMatrix swapYZ();
static TriMatrix perspective(float fovy, float aspect, float near, float far);
static TriMatrix frustum(float left, float right, float bottom, float top, float near, float far);
static TriMatrix worldToView(); // Software renderer world to view space transform
static TriMatrix viewToClip(); // Software renderer shearing projection
TriVertex operator*(TriVertex v) const;
TriMatrix operator*(const TriMatrix &m) const;
float matrix[16];
};
struct TriUniforms
{
uint32_t light;

View File

@ -44,7 +44,7 @@ void RenderPolyScene::Render()
ClearBuffers();
SetSceneViewport();
SetupPerspectiveMatrix();
MainPortal.SetViewpoint(WorldToClip, Vec4f(0.0f), GetNextStencilValue());
MainPortal.SetViewpoint(WorldToClip, Vec4f(0.0f, 0.0f, 0.0f, 1.0f), GetNextStencilValue());
MainPortal.Render(0);
Skydome.Render(WorldToClip);
MainPortal.RenderTranslucent(0);

View File

@ -177,7 +177,7 @@ bool PolyCull::CheckBBox(float *bspcoord)
// Skip if its in front of the portal:
if (PortalClipPlane != Vec4f(0.0f) && IntersectionTest::plane_aabb(PortalClipPlane, aabb) == IntersectionTest::outside)
if (IntersectionTest::plane_aabb(PortalClipPlane, aabb) == IntersectionTest::outside)
return false;
// Occlusion test using solid segments:

View File

@ -29,7 +29,7 @@
#include "r_poly.h"
#include "a_sharedglobal.h"
void RenderPolyDecal::RenderWallDecals(const TriMatrix &worldToClip, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue)
void RenderPolyDecal::RenderWallDecals(const TriMatrix &worldToClip, const Vec4f &clipPlane, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue)
{
if (line->linedef == nullptr && line->sidedef == nullptr)
return;
@ -37,11 +37,11 @@ void RenderPolyDecal::RenderWallDecals(const TriMatrix &worldToClip, const seg_t
for (DBaseDecal *decal = line->sidedef->AttachedDecals; decal != nullptr; decal = decal->WallNext)
{
RenderPolyDecal render;
render.Render(worldToClip, decal, line, subsectorDepth, stencilValue);
render.Render(worldToClip, clipPlane, decal, line, subsectorDepth, stencilValue);
}
}
void RenderPolyDecal::Render(const TriMatrix &worldToClip, DBaseDecal *decal, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue)
void RenderPolyDecal::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue)
{
if (decal->RenderFlags & RF_INVISIBLE || !viewactive || !decal->PicNum.isValid())
return;
@ -166,5 +166,6 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, DBaseDecal *decal, co
args.stenciltestvalue = stencilValue;
args.stencilwritevalue = stencilValue;
//mode = R_SetPatchStyle (decal->RenderStyle, (float)decal->Alpha, decal->Translation, decal->AlphaColor);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Shaded);
}

View File

@ -24,11 +24,13 @@
#include "r_poly_triangle.h"
class Vec4f;
class RenderPolyDecal
{
public:
static void RenderWallDecals(const TriMatrix &worldToClip, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue);
static void RenderWallDecals(const TriMatrix &worldToClip, const Vec4f &clipPlane, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue);
private:
void Render(const TriMatrix &worldToClip, DBaseDecal *decal, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, DBaseDecal *decal, const seg_t *line, uint32_t subsectorDepth, uint32_t stencilValue);
};

View File

@ -28,7 +28,7 @@
#include "r_poly_particle.h"
#include "r_poly.h"
void RenderPolyParticle::Render(const TriMatrix &worldToClip, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
void RenderPolyParticle::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
{
DVector3 pos = particle->Pos;
double psize = particle->size / 8.0;
@ -104,5 +104,6 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, particle_t *partic
args.stenciltestvalue = stencilValue;
args.stencilwritevalue = stencilValue;
args.SetColormap(sub->sector->ColorMap);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
PolyTriangleDrawer::draw(args, TriDrawVariant::FillSubsector, TriBlendMode::AlphaBlend);
}

View File

@ -25,8 +25,10 @@
#include "r_poly_triangle.h"
#include "p_effect.h"
class Vec4f;
class RenderPolyParticle
{
public:
void Render(const TriMatrix &worldToClip, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, particle_t *particle, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue);
};

View File

@ -32,7 +32,7 @@
EXTERN_CVAR(Int, r_3dfloors)
void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, const Vec4f &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
RenderPolyPlane plane;
@ -58,7 +58,7 @@ void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, subsector_t *su
double fakeHeight = fakeFloor->top.plane->ZatPoint(frontsector->centerspot);
if (fakeHeight < ViewPos.Z && fakeHeight > frontsector->floorplane.ZatPoint(frontsector->centerspot))
{
plane.Render3DFloor(worldToClip, sub, subsectorDepth, stencilValue, false, fakeFloor);
plane.Render3DFloor(worldToClip, clipPlane, sub, subsectorDepth, stencilValue, false, fakeFloor);
}
}
@ -79,16 +79,16 @@ void RenderPolyPlane::RenderPlanes(const TriMatrix &worldToClip, subsector_t *su
double fakeHeight = fakeFloor->bottom.plane->ZatPoint(frontsector->centerspot);
if (fakeHeight > ViewPos.Z && fakeHeight < frontsector->ceilingplane.ZatPoint(frontsector->centerspot))
{
plane.Render3DFloor(worldToClip, sub, subsectorDepth, stencilValue, true, fakeFloor);
plane.Render3DFloor(worldToClip, clipPlane, sub, subsectorDepth, stencilValue, true, fakeFloor);
}
}
}
plane.Render(worldToClip, sub, subsectorDepth, stencilValue, true, skyCeilingHeight, sectorPortals);
plane.Render(worldToClip, sub, subsectorDepth, stencilValue, false, skyFloorHeight, sectorPortals);
plane.Render(worldToClip, clipPlane, sub, subsectorDepth, stencilValue, true, skyCeilingHeight, sectorPortals);
plane.Render(worldToClip, clipPlane, sub, subsectorDepth, stencilValue, false, skyFloorHeight, sectorPortals);
}
void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, F3DFloor *fakeFloor)
void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const Vec4f &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, F3DFloor *fakeFloor)
{
FTextureID picnum = ceiling ? *fakeFloor->bottom.texture : *fakeFloor->top.texture;
FTexture *tex = TexMan(picnum);
@ -140,11 +140,12 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, subsector_t *s
args.stencilwritevalue = stencilValue + 1;
args.SetTexture(tex);
args.SetColormap(sub->sector->ColorMap);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawNormal, TriBlendMode::Copy);
PolyTriangleDrawer::draw(args, TriDrawVariant::Stencil, TriBlendMode::Copy);
}
void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
void RenderPolyPlane::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals)
{
FSectorPortal *portal = sub->sector->ValidatePortal(ceiling ? sector_t::ceiling : sector_t::floor);
PolyDrawSectorPortal *polyportal = nullptr;
@ -251,6 +252,7 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, subsector_t *sub, uin
args.stenciltestvalue = stencilValue;
args.stencilwritevalue = stencilValue + 1;
args.SetColormap(frontsector->ColorMap);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
if (!isSky)
{

View File

@ -25,14 +25,15 @@
#include "r_poly_triangle.h"
class PolyDrawSectorPortal;
class Vec4f;
class RenderPolyPlane
{
public:
static void RenderPlanes(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
static void RenderPlanes(const TriMatrix &worldToClip, const Vec4f &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, double skyCeilingHeight, double skyFloorHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
private:
void Render3DFloor(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, F3DFloor *fakefloor);
void Render(const TriMatrix &worldToClip, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
void Render3DFloor(const TriMatrix &worldToClip, const Vec4f &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, F3DFloor *fakefloor);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue, bool ceiling, double skyHeight, std::vector<std::unique_ptr<PolyDrawSectorPortal>> &sectorPortals);
TriVertex PlaneVertex(vertex_t *v1, double height);
};

View File

@ -94,7 +94,7 @@ void RenderPolyPortal::RenderSubsector(subsector_t *sub)
if (sub->sector->CenterFloor() != sub->sector->CenterCeiling())
{
RenderPolyPlane::RenderPlanes(WorldToClip, sub, subsectorDepth, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals);
RenderPolyPlane::RenderPlanes(WorldToClip, PortalPlane, sub, subsectorDepth, StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, SectorPortals);
}
for (uint32_t i = 0; i < sub->numlines; i++)
@ -178,12 +178,12 @@ void RenderPolyPortal::RenderLine(subsector_t *sub, seg_t *line, sector_t *front
if (!(fakeFloor->flags & FF_EXISTS)) continue;
if (!(fakeFloor->flags & FF_RENDERPLANES)) continue;
if (!fakeFloor->model) continue;
RenderPolyWall::Render3DFloorLine(WorldToClip, line, frontsector, subsectorDepth, StencilValue, fakeFloor, SubsectorTranslucentWalls);
RenderPolyWall::Render3DFloorLine(WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, fakeFloor, SubsectorTranslucentWalls);
}
}
// Render wall, and update culling info if its an occlusion blocker
if (RenderPolyWall::RenderLine(WorldToClip, line, frontsector, subsectorDepth, StencilValue, SubsectorTranslucentWalls, LinePortals))
if (RenderPolyWall::RenderLine(WorldToClip, PortalPlane, line, frontsector, subsectorDepth, StencilValue, SubsectorTranslucentWalls, LinePortals))
{
if (hasSegmentRange)
Cull.MarkSegmentCulled(sx1, sx2);
@ -208,6 +208,7 @@ void RenderPolyPortal::RenderPortals(int portalDepth)
args.uniforms.color = 0;
args.uniforms.light = 256;
args.uniforms.flags = TriUniforms::fixed_light;
args.SetClipPlane(PortalPlane.x, PortalPlane.y, PortalPlane.z, PortalPlane.w);
for (auto &portal : SectorPortals)
{
@ -253,6 +254,7 @@ void RenderPolyPortal::RenderTranslucent(int portalDepth)
args.mode = TriangleDrawMode::Fan;
args.stenciltestvalue = portal->StencilValue + 1;
args.stencilwritevalue = StencilValue;
args.SetClipPlane(PortalPlane.x, PortalPlane.y, PortalPlane.z, PortalPlane.w);
for (const auto &verts : portal->Shape)
{
args.vinput = verts.Vertices;
@ -273,6 +275,7 @@ void RenderPolyPortal::RenderTranslucent(int portalDepth)
args.mode = TriangleDrawMode::Fan;
args.stenciltestvalue = portal->StencilValue + 1;
args.stencilwritevalue = StencilValue;
args.SetClipPlane(PortalPlane.x, PortalPlane.y, PortalPlane.z, PortalPlane.w);
for (const auto &verts : portal->Shape)
{
args.vinput = verts.Vertices;
@ -290,21 +293,21 @@ void RenderPolyPortal::RenderTranslucent(int portalDepth)
if (obj.particle)
{
RenderPolyParticle spr;
spr.Render(WorldToClip, obj.particle, obj.sub, obj.subsectorDepth, StencilValue + 1);
spr.Render(WorldToClip, PortalPlane, obj.particle, obj.sub, obj.subsectorDepth, StencilValue + 1);
}
else if (!obj.thing)
{
obj.wall.Render(WorldToClip);
obj.wall.Render(WorldToClip, PortalPlane);
}
else if ((obj.thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE)
{
RenderPolyWallSprite wallspr;
wallspr.Render(WorldToClip, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1);
wallspr.Render(WorldToClip, PortalPlane, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1);
}
else
{
RenderPolySprite spr;
spr.Render(WorldToClip, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1);
spr.Render(WorldToClip, PortalPlane, obj.thing, obj.sub, obj.subsectorDepth, StencilValue + 1);
}
}
}
@ -341,7 +344,7 @@ void PolyDrawSectorPortal::Render(int portalDepth)
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
RenderPortal.SetViewpoint(worldToClip, Vec4f(0.0f), StencilValue);
RenderPortal.SetViewpoint(worldToClip, Vec4f(0.0f, 0.0f, 0.0f, 1.0f), StencilValue);
RenderPortal.Render(portalDepth);
RestoreGlobals();
@ -445,7 +448,7 @@ void PolyDrawLinePortal::Render(int portalDepth)
DVector2 planePos = Portal->mDestination->v1->fPos();
DVector2 planeNormal = (Portal->mDestination->v2->fPos() - Portal->mDestination->v1->fPos()).Rotated90CW();
planeNormal.MakeUnit();
double planeD = -(planeNormal | (planePos + planeNormal * 5.0));
double planeD = -(planeNormal | (planePos + planeNormal * 0.001));
Vec4f portalPlane((float)planeNormal.X, (float)planeNormal.Y, 0.0f, (float)planeD);
RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue);

View File

@ -61,6 +61,7 @@ void PolySkyDome::Render(const TriMatrix &worldToClip)
args.stencilwritevalue = 255;
args.SetTexture(frontskytex);
args.SetColormap(&NormalLight);
args.SetClipPlane(0.0f, 0.0f, 0.0f, 0.0f);
RenderCapColorRow(args, frontskytex, 0, false);
RenderCapColorRow(args, frontskytex, rc, true);

View File

@ -27,11 +27,12 @@
#include "r_data/r_translate.h"
#include "r_poly_sprite.h"
#include "r_poly.h"
#include "r_poly_intersection.h"
EXTERN_CVAR(Float, transsouls)
EXTERN_CVAR(Int, r_drawfuzz)
void RenderPolySprite::Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
void RenderPolySprite::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
{
if (IsThingCulled(thing))
return;
@ -138,6 +139,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, AActor *thing, subse
args.stencilwritevalue = stencilValue;
args.SetTexture(tex, thing->Translation);
args.SetColormap(sub->sector->ColorMap);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
TriBlendMode blendmode;

View File

@ -24,10 +24,12 @@
#include "r_poly_triangle.h"
class Vec4f;
class RenderPolySprite
{
public:
void Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue);
static bool IsThingCulled(AActor *thing);
static FTexture *GetSpriteTexture(AActor *thing, /*out*/ bool &flipX);

View File

@ -119,34 +119,34 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, TriDrawVarian
const TriVertex *vinput = drawargs.vinput;
int vcount = drawargs.vcount;
TriVertex vert[3];
ShadedTriVertex vert[3];
if (drawargs.mode == TriangleDrawMode::Normal)
{
for (int i = 0; i < vcount / 3; i++)
{
for (int j = 0; j < 3; j++)
vert[j] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[j] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread, drawfunc);
}
}
else if (drawargs.mode == TriangleDrawMode::Fan)
{
vert[0] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[1] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[0] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
vert[1] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[2] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread, drawfunc);
vert[1] = vert[2];
}
}
else // TriangleDrawMode::Strip
{
vert[0] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[1] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[0] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
vert[1] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(*drawargs.objectToClip, *(vinput++));
vert[2] = shade_vertex(*drawargs.objectToClip, drawargs.clipPlane, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread, drawfunc);
vert[0] = vert[1];
vert[1] = vert[2];
@ -155,13 +155,18 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, TriDrawVarian
}
}
TriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip, TriVertex v)
ShadedTriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v)
{
// Apply transform to get clip coordinates:
return objectToClip * v;
ShadedTriVertex sv = objectToClip * v;
// Calculate gl_ClipDistance[0]
sv.clipDistance0 = v.x * clipPlane[0] + v.y * clipPlane[1] + v.z * clipPlane[2] + v.w * clipPlane[3];
return sv;
}
void PolyTriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread, void(*drawfunc)(const TriDrawTriangleArgs *, WorkerThreadData *))
void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread, void(*drawfunc)(const TriDrawTriangleArgs *, WorkerThreadData *))
{
// Cull, clip and generate additional vertices as needed
TriVertex clippedvert[max_additional_vertices];
@ -225,7 +230,7 @@ bool PolyTriangleDrawer::cullhalfspace(float clipdistance1, float clipdistance2,
return false;
}
void PolyTriangleDrawer::clipedge(const TriVertex *verts, TriVertex *clippedvert, int &numclipvert)
void PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert, int &numclipvert)
{
// Clip and cull so that the following is true for all vertices:
// -v.w <= v.x <= v.w
@ -243,16 +248,18 @@ void PolyTriangleDrawer::clipedge(const TriVertex *verts, TriVertex *clippedvert
}
// halfspace clip distances
float clipdistance[6 * 3];
static const int numclipdistances = 7;
float clipdistance[numclipdistances * 3];
for (int i = 0; i < 3; i++)
{
const auto &v = verts[i];
clipdistance[i * 6 + 0] = v.x + v.w;
clipdistance[i * 6 + 1] = v.w - v.x;
clipdistance[i * 6 + 2] = v.y + v.w;
clipdistance[i * 6 + 3] = v.w - v.y;
clipdistance[i * 6 + 4] = v.z + v.w;
clipdistance[i * 6 + 5] = v.w - v.z;
clipdistance[i * numclipdistances + 0] = v.x + v.w;
clipdistance[i * numclipdistances + 1] = v.w - v.x;
clipdistance[i * numclipdistances + 2] = v.y + v.w;
clipdistance[i * numclipdistances + 3] = v.w - v.y;
clipdistance[i * numclipdistances + 4] = v.z + v.w;
clipdistance[i * numclipdistances + 5] = v.w - v.z;
clipdistance[i * numclipdistances + 6] = v.clipDistance0;
}
// Clip against each halfspace
@ -260,7 +267,7 @@ void PolyTriangleDrawer::clipedge(const TriVertex *verts, TriVertex *clippedvert
float *output = weights + max_additional_vertices * 3;
int inputverts = 3;
int outputverts = 0;
for (int p = 0; p < 6; p++)
for (int p = 0; p < numclipdistances; p++)
{
// Clip each edge
outputverts = 0;
@ -268,14 +275,14 @@ void PolyTriangleDrawer::clipedge(const TriVertex *verts, TriVertex *clippedvert
{
int j = (i + 1) % inputverts;
float clipdistance1 =
clipdistance[0 * 6 + p] * input[i * 3 + 0] +
clipdistance[1 * 6 + p] * input[i * 3 + 1] +
clipdistance[2 * 6 + p] * input[i * 3 + 2];
clipdistance[0 * numclipdistances + p] * input[i * 3 + 0] +
clipdistance[1 * numclipdistances + p] * input[i * 3 + 1] +
clipdistance[2 * numclipdistances + p] * input[i * 3 + 2];
float clipdistance2 =
clipdistance[0 * 6 + p] * input[j * 3 + 0] +
clipdistance[1 * 6 + p] * input[j * 3 + 1] +
clipdistance[2 * 6 + p] * input[j * 3 + 2];
clipdistance[0 * numclipdistances + p] * input[j * 3 + 0] +
clipdistance[1 * numclipdistances + p] * input[j * 3 + 1] +
clipdistance[2 * numclipdistances + p] * input[j * 3 + 2];
float t1, t2;
if (!cullhalfspace(clipdistance1, clipdistance2, t1, t2) && outputverts + 1 < max_additional_vertices)
@ -512,17 +519,20 @@ TriMatrix TriMatrix::operator*(const TriMatrix &mult) const
return result;
}
TriVertex TriMatrix::operator*(TriVertex v) const
ShadedTriVertex TriMatrix::operator*(TriVertex v) const
{
float vx = matrix[0 * 4 + 0] * v.x + matrix[1 * 4 + 0] * v.y + matrix[2 * 4 + 0] * v.z + matrix[3 * 4 + 0] * v.w;
float vy = matrix[0 * 4 + 1] * v.x + matrix[1 * 4 + 1] * v.y + matrix[2 * 4 + 1] * v.z + matrix[3 * 4 + 1] * v.w;
float vz = matrix[0 * 4 + 2] * v.x + matrix[1 * 4 + 2] * v.y + matrix[2 * 4 + 2] * v.z + matrix[3 * 4 + 2] * v.w;
float vw = matrix[0 * 4 + 3] * v.x + matrix[1 * 4 + 3] * v.y + matrix[2 * 4 + 3] * v.z + matrix[3 * 4 + 3] * v.w;
v.x = vx;
v.y = vy;
v.z = vz;
v.w = vw;
return v;
ShadedTriVertex sv;
sv.x = vx;
sv.y = vy;
sv.z = vz;
sv.w = vw;
for (int i = 0; i < TriVertex::NumVarying; i++)
sv.varying[i] = v.varying[i];
return sv;
}
/////////////////////////////////////////////////////////////////////////////

View File

@ -38,6 +38,7 @@ enum class TriangleDrawMode
};
struct TriDrawTriangleArgs;
struct TriMatrix;
class PolyDrawArgs
{
@ -55,6 +56,15 @@ public:
uint8_t stenciltestvalue = 0;
uint8_t stencilwritevalue = 0;
const uint8_t *colormaps = nullptr;
float clipPlane[4];
void SetClipPlane(float a, float b, float c, float d)
{
clipPlane[0] = a;
clipPlane[1] = b;
clipPlane[2] = c;
clipPlane[3] = d;
}
void SetTexture(FTexture *texture)
{
@ -118,6 +128,31 @@ public:
}
};
struct ShadedTriVertex : public TriVertex
{
float clipDistance0;
};
struct TriMatrix
{
static TriMatrix null();
static TriMatrix identity();
static TriMatrix translate(float x, float y, float z);
static TriMatrix scale(float x, float y, float z);
static TriMatrix rotate(float angle, float x, float y, float z);
static TriMatrix swapYZ();
static TriMatrix perspective(float fovy, float aspect, float near, float far);
static TriMatrix frustum(float left, float right, float bottom, float top, float near, float far);
static TriMatrix worldToView(); // Software renderer world to view space transform
static TriMatrix viewToClip(); // Software renderer shearing projection
ShadedTriVertex operator*(TriVertex v) const;
TriMatrix operator*(const TriMatrix &m) const;
float matrix[16];
};
class PolyTriangleDrawer
{
public:
@ -125,11 +160,11 @@ public:
static void draw(const PolyDrawArgs &args, TriDrawVariant variant, TriBlendMode blendmode);
private:
static TriVertex shade_vertex(const TriMatrix &objectToClip, TriVertex v);
static ShadedTriVertex shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v);
static void draw_arrays(const PolyDrawArgs &args, TriDrawVariant variant, TriBlendMode blendmode, WorkerThreadData *thread);
static void draw_shaded_triangle(const TriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread, void(*drawfunc)(const TriDrawTriangleArgs *, WorkerThreadData *));
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread, void(*drawfunc)(const TriDrawTriangleArgs *, WorkerThreadData *));
static bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2);
static void clipedge(const TriVertex *verts, TriVertex *clippedvert, int &numclipvert);
static void clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert, int &numclipvert);
static int viewport_x, viewport_y, viewport_width, viewport_height, dest_pitch, dest_width, dest_height;
static bool dest_bgra;

View File

@ -35,7 +35,7 @@
EXTERN_CVAR(Bool, r_drawmirrors)
bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals)
bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals)
{
PolyDrawLinePortal *polyportal = nullptr;
if (line->backsector == nullptr && line->sidedef == line->linedef->sidedef[0] && (line->linedef->special == Line_Mirror && r_drawmirrors))
@ -85,7 +85,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, seg_t *line, secto
wall.UnpeggedCeil = frontceilz1;
wall.Texpart = side_t::mid;
wall.Polyportal = polyportal;
wall.Render(worldToClip);
wall.Render(worldToClip, clipPlane);
return true;
}
}
@ -120,7 +120,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, seg_t *line, secto
wall.BottomZ = topfloorz1;
wall.UnpeggedCeil = topceilz1;
wall.Texpart = side_t::top;
wall.Render(worldToClip);
wall.Render(worldToClip, clipPlane);
}
if ((bottomfloorz1 < bottomceilz1 || bottomfloorz2 < bottomceilz2) && line->sidedef)
@ -130,7 +130,7 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, seg_t *line, secto
wall.BottomZ = bottomfloorz2;
wall.UnpeggedCeil = topceilz1;
wall.Texpart = side_t::bottom;
wall.Render(worldToClip);
wall.Render(worldToClip, clipPlane);
}
if (line->sidedef)
@ -149,14 +149,14 @@ bool RenderPolyWall::RenderLine(const TriMatrix &worldToClip, seg_t *line, secto
if (polyportal)
{
wall.Polyportal = polyportal;
wall.Render(worldToClip);
wall.Render(worldToClip, clipPlane);
}
}
}
return polyportal != nullptr;
}
void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject> &translucentWallsOutput)
void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject> &translucentWallsOutput)
{
double frontceilz1 = fakeFloor->top.plane->ZatPoint(line->v1);
double frontfloorz1 = fakeFloor->bottom.plane->ZatPoint(line->v1);
@ -176,7 +176,7 @@ void RenderPolyWall::Render3DFloorLine(const TriMatrix &worldToClip, seg_t *line
wall.BottomZ = frontfloorz1;
wall.UnpeggedCeil = frontceilz1;
wall.Texpart = side_t::mid;
wall.Render(worldToClip);
wall.Render(worldToClip, clipPlane);
}
void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2)
@ -189,7 +189,7 @@ void RenderPolyWall::SetCoords(const DVector2 &v1, const DVector2 &v2, double ce
this->floor2 = floor2;
}
void RenderPolyWall::Render(const TriMatrix &worldToClip)
void RenderPolyWall::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane)
{
FTexture *tex = GetTexture();
if (!tex && !Polyportal)
@ -253,6 +253,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip)
if (tex)
args.SetTexture(tex);
args.SetColormap(Line->frontsector->ColorMap);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
if (Polyportal)
{
@ -275,7 +276,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip)
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::Add);
}
RenderPolyDecal::RenderWallDecals(worldToClip, LineSeg, SubsectorDepth, StencilValue);
RenderPolyDecal::RenderWallDecals(worldToClip, clipPlane, LineSeg, SubsectorDepth, StencilValue);
}
void RenderPolyWall::ClampHeight(TriVertex &v1, TriVertex &v2)

View File

@ -26,15 +26,16 @@
class PolyTranslucentObject;
class PolyDrawLinePortal;
class Vec4f;
class RenderPolyWall
{
public:
static bool RenderLine(const TriMatrix &worldToClip, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals);
static void Render3DFloorLine(const TriMatrix &worldToClip, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject> &translucentWallsOutput);
static bool RenderLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, std::vector<PolyTranslucentObject> &translucentWallsOutput, std::vector<std::unique_ptr<PolyDrawLinePortal>> &linePortals);
static void Render3DFloorLine(const TriMatrix &worldToClip, const Vec4f &clipPlane, seg_t *line, sector_t *frontsector, uint32_t subsectorDepth, uint32_t stencilValue, F3DFloor *fakeFloor, std::vector<PolyTranslucentObject> &translucentWallsOutput);
void SetCoords(const DVector2 &v1, const DVector2 &v2, double ceil1, double floor1, double ceil2, double floor2);
void Render(const TriMatrix &worldToClip);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane);
DVector2 v1;
DVector2 v2;

View File

@ -28,7 +28,7 @@
#include "r_poly_wallsprite.h"
#include "r_poly.h"
void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue)
{
if (RenderPolySprite::IsThingCulled(thing))
return;
@ -120,5 +120,6 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, AActor *thing, s
args.stencilwritevalue = stencilValue;
args.SetTexture(tex);
args.SetColormap(sub->sector->ColorMap);
args.SetClipPlane(clipPlane.x, clipPlane.y, clipPlane.z, clipPlane.w);
PolyTriangleDrawer::draw(args, TriDrawVariant::DrawSubsector, TriBlendMode::AlphaBlend);
}

View File

@ -24,8 +24,10 @@
#include "r_poly_triangle.h"
class Vec4f;
class RenderPolyWallSprite
{
public:
void Render(const TriMatrix &worldToClip, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue);
void Render(const TriMatrix &worldToClip, const Vec4f &clipPlane, AActor *thing, subsector_t *sub, uint32_t subsectorDepth, uint32_t stencilValue);
};