- Make the relationship between TriMatrix, TriVertex and ShadedTriVertex more clean

This commit is contained in:
Magnus Norddahl 2017-09-21 01:21:21 +02:00
parent b6b78176d2
commit 59ee89b622
10 changed files with 82 additions and 74 deletions

View file

@ -46,6 +46,15 @@ public:
float A, B, C, D;
};
struct TriVertex
{
TriVertex() { }
TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w), u(u), v(v) { }
float x, y, z, w;
float u, v;
};
class PolyDrawArgs
{
public:

View file

@ -323,7 +323,7 @@ private:
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
// Calculate gradients
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
ScreenTriangleStepVariables gradientX = args->gradientX;
ScreenTriangleStepVariables gradientY = args->gradientY;
ScreenTriangleStepVariables blockPosY;

View file

@ -334,7 +334,7 @@ private:
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
// Calculate gradients
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
ScreenTriangleStepVariables gradientX = args->gradientX;
ScreenTriangleStepVariables gradientY = args->gradientY;
ScreenTriangleStepVariables blockPosY;

View file

@ -231,7 +231,7 @@ public:
int fuzzpos = (ScreenTriangle::FuzzStart + destX * 123 + destY) % FUZZTABLE;
// Calculate gradients
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
ScreenTriangleStepVariables gradientX = args->gradientX;
ScreenTriangleStepVariables gradientY = args->gradientY;
ScreenTriangleStepVariables blockPosY;

View file

@ -146,8 +146,15 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c
const TriMatrix &objectToClip = *drawargs.ObjectToClip();
// Apply transform to get clip coordinates:
FVector4 position = objectToClip * FVector4(v.x, v.y, v.z, v.w);
ShadedTriVertex sv;
sv.position = objectToClip * v;
sv.x = position.X;
sv.y = position.Y;
sv.z = position.Z;
sv.w = position.W;
sv.u = v.u;
sv.v = v.v;
// Calculate gl_ClipDistance[i]
for (int i = 0; i < 3; i++)
@ -162,12 +169,12 @@ ShadedTriVertex PolyTriangleDrawer::shade_vertex(const PolyDrawArgs &drawargs, c
bool PolyTriangleDrawer::is_degenerate(const ShadedTriVertex *vert)
{
// A degenerate triangle has a zero cross product for two of its sides.
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 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 crossx = ay * bz - az * by;
float crossy = az * bx - ax * bz;
float crossz = ax * by - ay * bx;
@ -182,7 +189,7 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
return;
// Cull, clip and generate additional vertices as needed
TriVertex clippedvert[max_additional_vertices];
ShadedTriVertex clippedvert[max_additional_vertices];
int numclipvert = clipedge(vert, clippedvert);
#ifdef NO_SSE
@ -273,7 +280,7 @@ void PolyTriangleDrawer::draw_shaded_triangle(const ShadedTriVertex *vert, bool
}
}
int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert)
int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert)
{
// Clip and cull so that the following is true for all vertices:
// -v.w <= v.x <= v.w
@ -288,16 +295,16 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
float *clipd = clipdistance;
for (int i = 0; i < 3; i++)
{
const auto &v = verts[i].position;
const auto &v = verts[i];
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] = verts[i].clipDistance[0];
clipd[7] = verts[i].clipDistance[1];
clipd[8] = verts[i].clipDistance[2];
clipd[6] = v.clipDistance[0];
clipd[7] = v.clipDistance[1];
clipd[8] = v.clipDistance[2];
for (int j = 0; j < 9; j++)
needsclipping = needsclipping || clipd[i];
clipd += numclipdistances;
@ -308,14 +315,14 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
{
for (int i = 0; i < 3; i++)
{
memcpy(clippedvert + i, &verts[i].position, sizeof(TriVertex));
memcpy(clippedvert + i, &verts[i], sizeof(ShadedTriVertex));
}
return 3;
}
#else
__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 mx = _mm_loadu_ps(&verts[0].x);
__m128 my = _mm_loadu_ps(&verts[1].x);
__m128 mz = _mm_loadu_ps(&verts[2].x);
__m128 mw = _mm_setzero_ps();
_MM_TRANSPOSE4_PS(mx, my, mz, mw);
__m128 clipd0 = _mm_add_ps(mx, mw);
@ -340,7 +347,7 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
{
for (int i = 0; i < 3; i++)
{
memcpy(clippedvert + i, &verts[i].position, sizeof(TriVertex));
memcpy(clippedvert + i, &verts[i], sizeof(ShadedTriVertex));
}
return 3;
}
@ -429,16 +436,16 @@ int PolyTriangleDrawer::clipedge(const ShadedTriVertex *verts, TriVertex *clippe
for (int i = 0; i < inputverts; i++)
{
auto &v = clippedvert[i];
memset(&v, 0, sizeof(TriVertex));
memset(&v, 0, sizeof(ShadedTriVertex));
for (int w = 0; w < 3; w++)
{
float weight = input[i * 3 + w];
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;
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;
}
}
return inputverts;

View file

@ -29,12 +29,6 @@
#include "polyrenderer/drawers/poly_buffer.h"
#include "polyrenderer/drawers/poly_draw_args.h"
struct ShadedTriVertex
{
TriVertex position;
float clipDistance[3];
};
typedef void(*PolyDrawFuncPtr)(const TriDrawTriangleArgs *, WorkerThreadData *);
class PolyTriangleDrawer
@ -50,7 +44,7 @@ private:
static void draw_shaded_triangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args, WorkerThreadData *thread);
static bool is_degenerate(const ShadedTriVertex *vertices);
static int clipedge(const ShadedTriVertex *verts, TriVertex *clippedvert);
static int clipedge(const ShadedTriVertex *verts, ShadedTriVertex *clippedvert);
static int viewport_x, viewport_y, viewport_width, viewport_height, dest_pitch, dest_width, dest_height;
static bool dest_bgra;

View file

@ -140,9 +140,9 @@ private:
TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread) : args(args), thread(thread)
{
const TriVertex &v1 = *args->v1;
const TriVertex &v2 = *args->v2;
const TriVertex &v3 = *args->v3;
const ShadedTriVertex &v1 = *args->v1;
const ShadedTriVertex &v2 = *args->v2;
const ShadedTriVertex &v3 = *args->v3;
clipright = args->clipright;
clipbottom = args->clipbottom;
@ -368,7 +368,7 @@ void TriangleBlock::DepthTest(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W;
@ -416,7 +416,7 @@ void TriangleBlock::DepthTest(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W;
@ -962,7 +962,7 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W;
@ -1023,7 +1023,7 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1;
const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W;
@ -1081,7 +1081,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thr
#else
static void SortVertices(const TriDrawTriangleArgs *args, TriVertex **sortedVertices)
static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices)
{
sortedVertices[0] = args->v1;
sortedVertices[1] = args->v2;
@ -1098,7 +1098,7 @@ static void SortVertices(const TriDrawTriangleArgs *args, TriVertex **sortedVert
void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread)
{
// Sort vertices by Y position
TriVertex *sortedVertices[3];
ShadedTriVertex *sortedVertices[3];
SortVertices(args, sortedVertices);
int clipright = args->clipright;

View file

@ -41,13 +41,11 @@ struct WorkerThreadData
}
};
struct TriVertex
struct ShadedTriVertex
{
TriVertex() { }
TriVertex(float x, float y, float z, float w, float u, float v) : x(x), y(y), z(z), w(w), u(u), v(v) { }
float x, y, z, w;
float u, v;
float clipDistance[3];
};
struct ScreenTriangleStepVariables
@ -59,9 +57,9 @@ struct TriDrawTriangleArgs
{
uint8_t *dest;
int32_t pitch;
TriVertex *v1;
TriVertex *v2;
TriVertex *v3;
ShadedTriVertex *v1;
ShadedTriVertex *v2;
ShadedTriVertex *v3;
int32_t clipright;
int32_t clipbottom;
uint8_t *stencilValues;
@ -80,23 +78,29 @@ struct TriDrawTriangleArgs
if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON))
return false;
gradientX.W = FindGradientX(bottomX, v1->w, v2->w, v3->w);
gradientY.W = FindGradientY(bottomY, v1->w, v2->w, v3->w);
gradientX.U = FindGradientX(bottomX, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w);
gradientY.U = FindGradientY(bottomY, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w);
gradientX.V = FindGradientX(bottomX, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w);
gradientY.V = FindGradientY(bottomY, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w);
gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f);
gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f);
gradientX.U = FindGradientX(bottomX, v1->u, v2->u, v3->u);
gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u);
gradientX.V = FindGradientX(bottomX, v1->v, v2->v, v3->v);
gradientY.V = FindGradientY(bottomY, v1->v, v2->v, v3->v);
return true;
}
private:
float FindGradientX(float bottomX, float c0, float c1, float c2)
{
c0 *= v1->w;
c1 *= v2->w;
c2 *= v3->w;
return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX;
}
float FindGradientY(float bottomY, float c0, float c1, float c2)
{
c0 *= v1->w;
c1 *= v2->w;
c2 *= v3->w;
return ((c1 - c2) * (v1->x - v3->x) - (c0 - c2) * (v2->x - v3->x)) / bottomY;
}
};

View file

@ -173,33 +173,27 @@ TriMatrix TriMatrix::operator*(const TriMatrix &mult) const
return result;
}
TriVertex TriMatrix::operator*(TriVertex v) const
FVector4 TriMatrix::operator*(const FVector4 &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;
TriVertex sv;
sv.x = vx;
sv.y = vy;
sv.z = vz;
sv.w = vw;
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;
return{ vx, vy, vz, vw };
#else
__m128 m0 = _mm_loadu_ps(matrix);
__m128 m1 = _mm_loadu_ps(matrix + 4);
__m128 m2 = _mm_loadu_ps(matrix + 8);
__m128 m3 = _mm_loadu_ps(matrix + 12);
__m128 mv = _mm_loadu_ps(&v.x);
__m128 mv = _mm_loadu_ps(&v.X);
m0 = _mm_mul_ps(m0, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(0, 0, 0, 0)));
m1 = _mm_mul_ps(m1, _mm_shuffle_ps(mv, mv, _MM_SHUFFLE(1, 1, 1, 1)));
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);
TriVertex sv;
_mm_storeu_ps(&sv.x, mv);
#endif
sv.u = v.u;
sv.v = v.v;
FVector4 sv;
_mm_storeu_ps(&sv.X, mv);
return sv;
#endif
}

View file

@ -39,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
TriVertex operator*(TriVertex v) const;
FVector4 operator*(const FVector4 &v) const;
TriMatrix operator*(const TriMatrix &m) const;
float matrix[16];