- 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; 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 class PolyDrawArgs
{ {
public: public:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -140,9 +140,9 @@ private:
TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread) : args(args), thread(thread) TriangleBlock::TriangleBlock(const TriDrawTriangleArgs *args, WorkerThreadData *thread) : args(args), thread(thread)
{ {
const TriVertex &v1 = *args->v1; const ShadedTriVertex &v1 = *args->v1;
const TriVertex &v2 = *args->v2; const ShadedTriVertex &v2 = *args->v2;
const TriVertex &v3 = *args->v3; const ShadedTriVertex &v3 = *args->v3;
clipright = args->clipright; clipright = args->clipright;
clipbottom = args->clipbottom; clipbottom = args->clipbottom;
@ -368,7 +368,7 @@ void TriangleBlock::DepthTest(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch; int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64; float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1; const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W; float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W; float stepYW = args->gradientY.W;
@ -416,7 +416,7 @@ void TriangleBlock::DepthTest(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch; int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64; float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1; const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W; float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W; float stepYW = args->gradientY.W;
@ -962,7 +962,7 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch; int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64; float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1; const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W; float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W; float stepYW = args->gradientY.W;
@ -1023,7 +1023,7 @@ void TriangleBlock::DepthWrite(const TriDrawTriangleArgs *args)
int block = (X >> 3) + (Y >> 3) * zbufferPitch; int block = (X >> 3) + (Y >> 3) * zbufferPitch;
float *depth = zbuffer + block * 64; float *depth = zbuffer + block * 64;
const TriVertex &v1 = *args->v1; const ShadedTriVertex &v1 = *args->v1;
float stepXW = args->gradientX.W; float stepXW = args->gradientX.W;
float stepYW = args->gradientY.W; float stepYW = args->gradientY.W;
@ -1081,7 +1081,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thr
#else #else
static void SortVertices(const TriDrawTriangleArgs *args, TriVertex **sortedVertices) static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sortedVertices)
{ {
sortedVertices[0] = args->v1; sortedVertices[0] = args->v1;
sortedVertices[1] = args->v2; sortedVertices[1] = args->v2;
@ -1098,7 +1098,7 @@ static void SortVertices(const TriDrawTriangleArgs *args, TriVertex **sortedVert
void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread) void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, WorkerThreadData *thread)
{ {
// Sort vertices by Y position // Sort vertices by Y position
TriVertex *sortedVertices[3]; ShadedTriVertex *sortedVertices[3];
SortVertices(args, sortedVertices); SortVertices(args, sortedVertices);
int clipright = args->clipright; 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 x, y, z, w;
float u, v; float u, v;
float clipDistance[3];
}; };
struct ScreenTriangleStepVariables struct ScreenTriangleStepVariables
@ -59,9 +57,9 @@ struct TriDrawTriangleArgs
{ {
uint8_t *dest; uint8_t *dest;
int32_t pitch; int32_t pitch;
TriVertex *v1; ShadedTriVertex *v1;
TriVertex *v2; ShadedTriVertex *v2;
TriVertex *v3; ShadedTriVertex *v3;
int32_t clipright; int32_t clipright;
int32_t clipbottom; int32_t clipbottom;
uint8_t *stencilValues; uint8_t *stencilValues;
@ -80,23 +78,29 @@ struct TriDrawTriangleArgs
if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON)) if ((bottomX >= -FLT_EPSILON && bottomX <= FLT_EPSILON) || (bottomY >= -FLT_EPSILON && bottomY <= FLT_EPSILON))
return false; return false;
gradientX.W = FindGradientX(bottomX, v1->w, v2->w, v3->w); gradientX.W = FindGradientX(bottomX, 1.0f, 1.0f, 1.0f);
gradientY.W = FindGradientY(bottomY, v1->w, v2->w, v3->w); gradientY.W = FindGradientY(bottomY, 1.0f, 1.0f, 1.0f);
gradientX.U = FindGradientX(bottomX, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); gradientX.U = FindGradientX(bottomX, v1->u, v2->u, v3->u);
gradientY.U = FindGradientY(bottomY, v1->u * v1->w, v2->u * v2->w, v3->u * v3->w); gradientY.U = FindGradientY(bottomY, v1->u, v2->u, v3->u);
gradientX.V = FindGradientX(bottomX, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); gradientX.V = FindGradientX(bottomX, v1->v, v2->v, v3->v);
gradientY.V = FindGradientY(bottomY, v1->v * v1->w, v2->v * v2->w, v3->v * v3->w); gradientY.V = FindGradientY(bottomY, v1->v, v2->v, v3->v);
return true; return true;
} }
private: private:
float FindGradientX(float bottomX, float c0, float c1, float c2) 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; return ((c1 - c2) * (v1->y - v3->y) - (c0 - c2) * (v2->y - v3->y)) / bottomX;
} }
float FindGradientY(float bottomY, float c0, float c1, float c2) 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; 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; return result;
} }
TriVertex TriMatrix::operator*(TriVertex v) const FVector4 TriMatrix::operator*(const FVector4 &v) const
{ {
#ifdef NO_SSE #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 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 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 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; 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; return{ vx, vy, vz, vw };
sv.x = vx;
sv.y = vy;
sv.z = vz;
sv.w = vw;
#else #else
__m128 m0 = _mm_loadu_ps(matrix); __m128 m0 = _mm_loadu_ps(matrix);
__m128 m1 = _mm_loadu_ps(matrix + 4); __m128 m1 = _mm_loadu_ps(matrix + 4);
__m128 m2 = _mm_loadu_ps(matrix + 8); __m128 m2 = _mm_loadu_ps(matrix + 8);
__m128 m3 = _mm_loadu_ps(matrix + 12); __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))); 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))); 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))); 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))); 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); mv = _mm_add_ps(_mm_add_ps(_mm_add_ps(m0, m1), m2), m3);
TriVertex sv; FVector4 sv;
_mm_storeu_ps(&sv.x, mv); _mm_storeu_ps(&sv.X, mv);
#endif
sv.u = v.u;
sv.v = v.v;
return sv; 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 worldToView(const FRenderViewpoint &viewpoint); // Software renderer world to view space transform
//static TriMatrix viewToClip(double focalTangent, double centerY, double invZtoScale); // Software renderer shearing projection //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; TriMatrix operator*(const TriMatrix &m) const;
float matrix[16]; float matrix[16];