mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 16:41:09 +00:00
Add plane clipping to the triangle drawer
This commit is contained in:
parent
8bbb63e913
commit
c37ce1fdbc
19 changed files with 146 additions and 99 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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>> §orPortals)
|
||||
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>> §orPortals)
|
||||
{
|
||||
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>> §orPortals)
|
||||
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>> §orPortals)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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>> §orPortals);
|
||||
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>> §orPortals);
|
||||
|
||||
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>> §orPortals);
|
||||
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>> §orPortals);
|
||||
TriVertex PlaneVertex(vertex_t *v1, double height);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue