- Striped wall (lightlist) support

- Add two extra clipping planes to poly backend
- Make ShadedTriVertex internal to drawer backend
This commit is contained in:
Magnus Norddahl 2017-08-27 23:26:54 +02:00
parent 8c146e4e71
commit 293f62fcd2
15 changed files with 131 additions and 67 deletions

View file

@ -37,14 +37,6 @@
#include "poly_draw_args.h"
#include "swrenderer/viewport/r_viewport.h"
void PolyDrawArgs::SetClipPlane(const PolyClipPlane &plane)
{
mClipPlane[0] = plane.A;
mClipPlane[1] = plane.B;
mClipPlane[2] = plane.C;
mClipPlane[3] = plane.D;
}
void PolyDrawArgs::SetTexture(const uint8_t *texels, int width, int height)
{
mTexturePixels = texels;

View file

@ -48,7 +48,7 @@ public:
class PolyDrawArgs
{
public:
void SetClipPlane(const PolyClipPlane &plane);
void SetClipPlane(int index, const PolyClipPlane &plane) { mClipPlane[index] = plane; }
void SetTexture(const uint8_t *texels, int width, int height);
void SetTexture(FTexture *texture);
void SetTexture(FTexture *texture, uint32_t translationID, bool forcePal = false);
@ -66,7 +66,7 @@ public:
void DrawArray(const TriVertex *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles);
const TriMatrix *ObjectToClip() const { return mObjectToClip; }
const float *ClipPlane() const { return mClipPlane; }
const PolyClipPlane &ClipPlane(int index) const { return mClipPlane[index]; }
const TriVertex *Vertices() const { return mVertices; }
int VertexCount() const { return mVertexCount; }
@ -126,7 +126,7 @@ private:
uint8_t mStencilTestValue = 0;
uint8_t mStencilWriteValue = 0;
const uint8_t *mColormaps = nullptr;
float mClipPlane[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
PolyClipPlane mClipPlane[3];
TriBlendMode mBlendMode = TriBlendMode::FillOpaque;
uint32_t mLight = 0;
uint32_t mColor = 0;

View file

@ -111,28 +111,28 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD
for (int i = 0; i < vcount / 3; i++)
{
for (int j = 0; j < 3; j++)
vert[j] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[j] = shade_vertex(drawargs, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread);
}
}
else if (drawargs.DrawMode() == PolyDrawMode::TriangleFan)
{
vert[0] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[1] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[0] = shade_vertex(drawargs, *(vinput++));
vert[1] = shade_vertex(drawargs, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[2] = shade_vertex(drawargs, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread);
vert[1] = vert[2];
}
}
else // TriangleDrawMode::TriangleStrip
{
vert[0] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[1] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[0] = shade_vertex(drawargs, *(vinput++));
vert[1] = shade_vertex(drawargs, *(vinput++));
for (int i = 2; i < vcount; i++)
{
vert[2] = shade_vertex(*drawargs.ObjectToClip(), drawargs.ClipPlane(), *(vinput++));
vert[2] = shade_vertex(drawargs, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, thread);
vert[0] = vert[1];
vert[1] = vert[2];
@ -141,13 +141,20 @@ void PolyTriangleDrawer::draw_arrays(const PolyDrawArgs &drawargs, WorkerThreadD
}
}
ShadedTriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v)
ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v)
{
// Apply transform to get clip coordinates:
ShadedTriVertex sv = objectToClip * v;
const TriMatrix &objectToClip = *drawargs.ObjectToClip();
// Calculate gl_ClipDistance[0]
sv.clipDistance0 = v.x * clipPlane[0] + v.y * clipPlane[1] + v.z * clipPlane[2] + v.w * clipPlane[3];
// Apply transform to get clip coordinates:
ShadedTriVertex sv;
sv.position = objectToClip * v;
// Calculate gl_ClipDistance[i]
for (int i = 0; i < 3; i++)
{
const auto &clipPlane = drawargs.ClipPlane(i);
sv.clipDistance[i] = v.x * clipPlane.A + v.y * clipPlane.B + v.z * clipPlane.C + v.w * clipPlane.D;
}
return sv;
}
@ -155,12 +162,12 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const TriMatrix &objectToClip,
bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert)
{
// A degenerate triangle has a zero cross product for two of its sides.
float ax = vert[1].x - vert[0].x;
float ay = vert[1].y - vert[0].y;
float az = vert[1].w - vert[0].w;
float bx = vert[2].x - vert[0].x;
float by = vert[2].y - vert[0].y;
float bz = vert[2].w - vert[0].w;
float ax = vert[1].position.x - vert[0].position.x;
float ay = vert[1].position.y - vert[0].position.y;
float az = vert[1].position.w - vert[0].position.w;
float bx = vert[2].position.x - vert[0].position.x;
float by = vert[2].position.y - vert[0].position.y;
float bz = vert[2].position.w - vert[0].position.w;
float crossx = ay * bz - az * by;
float crossy = az * bx - ax * bz;
float crossz = ax * by - ay * bx;
@ -274,22 +281,25 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
// -v.w <= v.z <= v.w
// halfspace clip distances
static const int numclipdistances = 7;
static const int numclipdistances = 9;
#ifdef NO_SSE
float clipdistance[numclipdistances * 3];
bool needsclipping = false;
float *clipd = clipdistance;
for (int i = 0; i < 3; i++)
{
const auto &v = verts[i];
const auto &v = verts[i].position;
clipd[0] = v.x + v.w;
clipd[1] = v.w - v.x;
clipd[2] = v.y + v.w;
clipd[3] = v.w - v.y;
clipd[4] = v.z + v.w;
clipd[5] = v.w - v.z;
clipd[6] = v.clipDistance0;
needsclipping = needsclipping || clipd[0] < 0.0f || clipd[1] < 0.0f || clipd[2] < 0.0f || clipd[3] < 0.0f || clipd[4] < 0.0f || clipd[5] < 0.0f || clipd[6] < 0.0f;
clipd[6] = verts[i].clipDistance[0];
clipd[7] = verts[i].clipDistance[1];
clipd[8] = verts[i].clipDistance[2];
for (int j = 0; j < 9; j++)
needsclipping = needsclipping || clipd[i];
clipd += numclipdistances;
}
@ -298,14 +308,14 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
{
for (int i = 0; i < 3; i++)
{
memcpy(clippedvert + i, verts + i, sizeof(TriVertex));
memcpy(clippedvert + i, &verts[i].position, sizeof(TriVertex));
}
return 3;
}
#else
__m128 mx = _mm_loadu_ps(&verts[0].x);
__m128 my = _mm_loadu_ps(&verts[1].x);
__m128 mz = _mm_loadu_ps(&verts[2].x);
__m128 mx = _mm_loadu_ps(&verts[0].position.x);
__m128 my = _mm_loadu_ps(&verts[1].position.x);
__m128 mz = _mm_loadu_ps(&verts[2].position.x);
__m128 mw = _mm_setzero_ps();
_MM_TRANSPOSE4_PS(mx, my, mz, mw);
__m128 clipd0 = _mm_add_ps(mx, mw);
@ -314,7 +324,9 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
__m128 clipd3 = _mm_sub_ps(mw, my);
__m128 clipd4 = _mm_add_ps(mz, mw);
__m128 clipd5 = _mm_sub_ps(mw, mz);
__m128 clipd6 = _mm_setr_ps(verts[0].clipDistance0, verts[1].clipDistance0, verts[2].clipDistance0, 0.0f);
__m128 clipd6 = _mm_setr_ps(verts[0].clipDistance[0], verts[1].clipDistance[0], verts[2].clipDistance[0], 0.0f);
__m128 clipd7 = _mm_setr_ps(verts[0].clipDistance[1], verts[1].clipDistance[1], verts[2].clipDistance[1], 0.0f);
__m128 clipd8 = _mm_setr_ps(verts[0].clipDistance[2], verts[1].clipDistance[2], verts[2].clipDistance[2], 0.0f);
__m128 mneedsclipping = _mm_cmplt_ps(clipd0, _mm_setzero_ps());
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd1, _mm_setzero_ps()));
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd2, _mm_setzero_ps()));
@ -322,11 +334,13 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd4, _mm_setzero_ps()));
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd5, _mm_setzero_ps()));
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd6, _mm_setzero_ps()));
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd7, _mm_setzero_ps()));
mneedsclipping = _mm_or_ps(mneedsclipping, _mm_cmplt_ps(clipd8, _mm_setzero_ps()));
if (_mm_movemask_ps(mneedsclipping) == 0)
{
for (int i = 0; i < 3; i++)
{
memcpy(clippedvert + i, verts + i, sizeof(TriVertex));
memcpy(clippedvert + i, &verts[i].position, sizeof(TriVertex));
}
return 3;
}
@ -338,6 +352,8 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
_mm_storeu_ps(clipdistance + 16, clipd4);
_mm_storeu_ps(clipdistance + 20, clipd5);
_mm_storeu_ps(clipdistance + 24, clipd6);
_mm_storeu_ps(clipdistance + 28, clipd7);
_mm_storeu_ps(clipdistance + 32, clipd8);
#endif
// use barycentric weights while clipping vertices
@ -417,12 +433,12 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
for (int w = 0; w < 3; w++)
{
float weight = input[i * 3 + w];
v.x += verts[w].x * weight;
v.y += verts[w].y * weight;
v.z += verts[w].z * weight;
v.w += verts[w].w * weight;
v.u += verts[w].u * weight;
v.v += verts[w].v * weight;
v.x += verts[w].position.x * weight;
v.y += verts[w].position.y * weight;
v.z += verts[w].position.z * weight;
v.w += verts[w].position.w * weight;
v.u += verts[w].position.u * weight;
v.v += verts[w].position.v * weight;
}
}
return inputverts;

View file

@ -29,9 +29,10 @@
#include "polyrenderer/drawers/poly_buffer.h"
#include "polyrenderer/drawers/poly_draw_args.h"
struct ShadedTriVertex : public TriVertex
struct ShadedTriVertex
{
float clipDistance0;
TriVertex position;
float clipDistance[3];
};
typedef void(*PolyDrawFuncPtr)(const TriDrawTriangleArgs *, WorkerThreadData *);
@ -44,7 +45,7 @@ public:
static bool is_mirror();
private:
static ShadedTriVertex shade_vertex(const TriMatrix &objectToClip, const float *clipPlane, const TriVertex &v);
static ShadedTriVertex shade_vertex(const PolyDrawArgs &drawargs, const TriVertex &v);
static void draw_arrays(const PolyDrawArgs &args, WorkerThreadData *thread);
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread);
static bool is_degenerate(const ShadedTriVertex *vertices);

View file

@ -173,14 +173,14 @@ TriMatrix TriMatrix::operator*(const TriMatrix &mult) const
return result;
}
ShadedTriVertex TriMatrix::operator*(TriVertex v) const
TriVertex TriMatrix::operator*(TriVertex v) const
{
#ifdef NO_SSE
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;
ShadedTriVertex sv;
TriVertex sv;
sv.x = vx;
sv.y = vy;
sv.z = vz;
@ -196,7 +196,7 @@ ShadedTriVertex TriMatrix::operator*(TriVertex v) const
m2 = _mm_mul_ps(m2, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(2, 2, 2, 2)));
m3 = _mm_mul_ps(m3, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(3, 3, 3, 3)));
mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3);
ShadedTriVertex sv;
TriVertex sv;
_mm_storeu_ps(&sv.x, mv);
#endif
sv.u = v.u;

View file

@ -23,7 +23,6 @@
#pragma once
struct TriVertex;
struct ShadedTriVertex;
struct FRenderViewpoint;
struct TriMatrix
@ -40,7 +39,7 @@ struct TriMatrix
//static TriMatrix worldToView(const FRenderViewpoint &viewpoint); // Software renderer world to view space transform
//static TriMatrix viewToClip(double focalTangent, double centerY, double invZtoScale); // Software renderer shearing projection
ShadedTriVertex operator*(TriVertex v) const;
TriVertex operator*(TriVertex v) const;
TriMatrix operator*(const TriMatrix &m) const;
float matrix[16];

View file

@ -189,7 +189,7 @@ void RenderPolyDecal::Render(const TriMatrix &worldToClip, const PolyClipPlane &
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
args.SetDepthTest(true);
args.SetWriteStencil(false);
args.SetWriteDepth(false);

View file

@ -83,7 +83,7 @@ void RenderPolyParticle::Render(const TriMatrix &worldToClip, const PolyClipPlan
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(false);
args.SetWriteDepth(false);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
args.SetTexture(GetParticleTexture(), ParticleTextureSize, ParticleTextureSize);
args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
}

View file

@ -146,7 +146,7 @@ void RenderPolyPlane::Render3DFloor(const TriMatrix &worldToClip, const PolyClip
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetTexture(tex);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
args.DrawArray(vertices, sub->numlines, PolyDrawMode::TriangleFan);
}
@ -313,13 +313,13 @@ void RenderPolyPlane::Render(const TriMatrix &worldToClip, const PolyClipPlane &
lightlevel = clamp(lightlevel + actualextralight, 0, 255);
PolyDrawArgs args;
args.SetLight(GetColorTable(frontsector->Colormap, frontsector->SpecialColors[ceiling]), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
args.SetLight(GetColorTable(frontsector->Colormap, frontsector->SpecialColors[ceiling ? sector_t::ceiling : sector_t::floor]), lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
//args.SetSubsectorDepth(isSky ? RenderPolyScene::SkySubsectorDepth : subsectorDepth);
args.SetTransform(&worldToClip);
args.SetFaceCullCCW(ccw);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue + 1);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
if (!isSky)
{

View file

@ -376,7 +376,7 @@ void RenderPolyScene::RenderPortals(int portalDepth)
args.SetTransform(&WorldToClip);
args.SetLight(&NormalLight, 255, PolyRenderer::Instance()->Light.WallGlobVis(foggy), true);
args.SetColor(0, 0);
args.SetClipPlane(PortalPlane);
args.SetClipPlane(0, PortalPlane);
args.SetStyle(TriBlendMode::FillOpaque);
for (auto &portal : SectorPortals)
@ -416,7 +416,7 @@ void RenderPolyScene::RenderTranslucent(int portalDepth)
args.SetTransform(&WorldToClip);
args.SetStencilTestValue(portal->StencilValue + 1);
args.SetWriteStencil(true, StencilValue + 1);
args.SetClipPlane(PortalPlane);
args.SetClipPlane(0, PortalPlane);
for (const auto &verts : portal->Shape)
{
args.SetFaceCullCCW(verts.Ccw);
@ -434,7 +434,7 @@ void RenderPolyScene::RenderTranslucent(int portalDepth)
args.SetTransform(&WorldToClip);
args.SetStencilTestValue(portal->StencilValue + 1);
args.SetWriteStencil(true, StencilValue + 1);
args.SetClipPlane(PortalPlane);
args.SetClipPlane(0, PortalPlane);
for (const auto &verts : portal->Shape)
{
args.SetFaceCullCCW(verts.Ccw);

View file

@ -86,7 +86,7 @@ void PolySkyDome::Render(const TriMatrix &worldToClip)
args.SetTransform(&objectToClip);
args.SetStencilTestValue(255);
args.SetWriteStencil(true, 1);
args.SetClipPlane(PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f));
args.SetClipPlane(0, PolyClipPlane(0.0f, 0.0f, 0.0f, 1.0f));
RenderCapColorRow(args, mCurrentSetup.frontskytex, 0, false);
RenderCapColorRow(args, mCurrentSetup.frontskytex, rc, true);

View file

@ -158,7 +158,7 @@ void RenderPolySprite::Render(const TriMatrix &worldToClip, const PolyClipPlane
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetWriteStencil(true, stencilValue);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
if ((thing->renderflags & RF_ZDOOMTRANS) && r_UseVanillaTransparency)
args.SetStyle(LegacyRenderStyles[STYLE_Normal], 1.0f, thing->fillcolor, thing->Translation, tex, fullbrightSprite);
else

View file

@ -289,7 +289,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c
args.SetWriteStencil(true, StencilValue + 1);
if (tex && !Polyportal)
args.SetTexture(tex);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
if (FogBoundary)
{
@ -314,7 +314,7 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c
else if (!Masked)
{
args.SetStyle(TriBlendMode::TextureOpaque);
args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
DrawStripes(args, vertices);
}
else
{
@ -325,12 +325,66 @@ void RenderPolyWall::Render(const TriMatrix &worldToClip, const PolyClipPlane &c
args.SetDepthTest(true);
args.SetWriteDepth(true);
args.SetWriteStencil(false);
args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
DrawStripes(args, vertices);
}
RenderPolyDecal::RenderWallDecals(worldToClip, clipPlane, LineSeg, StencilValue);
}
void RenderPolyWall::DrawStripes(PolyDrawArgs &args, TriVertex *vertices)
{
const auto &lightlist = Line->frontsector->e->XFloor.lightlist;
if (lightlist.Size() > 0)
{
PolyClipPlane topPlane;
for (unsigned int i = 0; i < lightlist.Size(); i++)
{
lightlist_t *lit = &lightlist[i];
DVector3 normal = lit->plane.Normal();
double d = lit->plane.fD();
if (normal.Z < 0.0)
{
normal = -normal;
d = -d;
}
PolyClipPlane bottomPlane = { (float)normal.X, (float)normal.Y, (float)normal.Z, (float)d };
args.SetClipPlane(1, topPlane);
args.SetClipPlane(2, bottomPlane);
args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
FDynamicColormap *basecolormap = GetColorTable(lit->extra_colormap, Line->frontsector->SpecialColors[sector_t::walltop]);
bool foggy = false;
int lightlevel;
PolyCameraLight *cameraLight = PolyCameraLight::Instance();
if (cameraLight->FixedLightLevel() >= 0 || cameraLight->FixedColormap())
{
lightlevel = 255;
}
else
{
int actualextralight = foggy ? 0 : PolyRenderer::Instance()->Viewpoint.extralight << 4;
lightlevel = clamp(Side->GetLightLevel(foggy, *lit->p_lightlevel) + actualextralight, 0, 255);
}
args.SetLight(basecolormap, lightlevel, PolyRenderer::Instance()->Light.WallGlobVis(foggy), false);
topPlane = { (float)-normal.X, (float)-normal.Y, (float)-normal.Z, (float)-d };
}
args.SetClipPlane(1, topPlane);
args.SetClipPlane(2, PolyClipPlane());
args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
}
else
{
args.DrawArray(vertices, 4, PolyDrawMode::TriangleFan);
}
}
void RenderPolyWall::ClampHeight(TriVertex &v1, TriVertex &v2)
{
float top = v1.z;

View file

@ -65,6 +65,8 @@ private:
FTexture *GetTexture();
int GetLightLevel();
void DrawStripes(PolyDrawArgs &args, TriVertex *vertices);
static bool IsFogBoundary(sector_t *front, sector_t *back);
};

View file

@ -105,7 +105,7 @@ void RenderPolyWallSprite::Render(const TriMatrix &worldToClip, const PolyClipPl
args.SetFaceCullCCW(true);
args.SetStencilTestValue(stencilValue);
args.SetTexture(tex);
args.SetClipPlane(clipPlane);
args.SetClipPlane(0, clipPlane);
args.SetDepthTest(true);
args.SetWriteDepth(false);
args.SetWriteStencil(false);