Move software renderer transform to TriMatrix

This commit is contained in:
Magnus Norddahl 2016-11-07 03:34:59 +01:00
parent cdf8264dc3
commit 3ea9d7cf04
3 changed files with 74 additions and 41 deletions

View file

@ -966,6 +966,9 @@ static void R_DrawCubeSky(visplane_t *pl)
}; };
TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z) * TriMatrix::scale(1000.0f, 1000.0f, 1000.0f); TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z) * TriMatrix::scale(1000.0f, 1000.0f, 1000.0f);
TriMatrix objectToClip = TriMatrix::viewToClip() * TriMatrix::worldToView() * objectToWorld;
//TriMatrix objectToWorld = TriMatrix::scale(1000.0f, 1000.0f, 1000.0f);
//TriMatrix objectToClip = TriMatrix::viewToClip() * objectToWorld;
uint32_t solid_top = frontskytex->GetSkyCapColor(false); uint32_t solid_top = frontskytex->GetSkyCapColor(false);
uint32_t solid_bottom = frontskytex->GetSkyCapColor(true); uint32_t solid_bottom = frontskytex->GetSkyCapColor(true);
@ -973,9 +976,9 @@ static void R_DrawCubeSky(visplane_t *pl)
solid_top = RGB32k.RGB[(RPART(solid_top) >> 3)][(GPART(solid_top) >> 3)][(BPART(solid_top) >> 3)]; solid_top = RGB32k.RGB[(RPART(solid_top) >> 3)][(GPART(solid_top) >> 3)][(BPART(solid_top) >> 3)];
solid_bottom = RGB32k.RGB[(RPART(solid_bottom) >> 3)][(GPART(solid_bottom) >> 3)][(BPART(solid_bottom) >> 3)]; solid_bottom = RGB32k.RGB[(RPART(solid_bottom) >> 3)][(GPART(solid_bottom) >> 3)][(BPART(solid_bottom) >> 3)];
TriangleDrawer::fill(objectToWorld, cube, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_top); TriangleDrawer::fill(objectToClip, cube, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_top);
TriangleDrawer::fill(objectToWorld, cube + 6, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_bottom); TriangleDrawer::fill(objectToClip, cube + 6, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_bottom);
TriangleDrawer::draw(objectToWorld, cube + 2 * 6, 4 * 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, frontskytex); TriangleDrawer::draw(objectToClip, cube + 2 * 6, 4 * 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, frontskytex);
} }
namespace namespace
@ -1102,7 +1105,8 @@ namespace
short *uwal = (short *)pl->top; short *uwal = (short *)pl->top;
short *dwal = (short *)pl->bottom; short *dwal = (short *)pl->bottom;
TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z); TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z);
TriangleDrawer::draw(objectToWorld, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], TriangleDrawMode::Strip, false, x1, x2 - 1, uwal, dwal, frontskytex); TriMatrix objectToClip = TriMatrix::viewToClip() * TriMatrix::worldToView() * objectToWorld;
TriangleDrawer::draw(objectToClip, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], TriangleDrawMode::Strip, false, x1, x2 - 1, uwal, dwal, frontskytex);
} }
void SkyDome::RenderCapColorRow(int row, bool bottomCap, visplane_t *pl) void SkyDome::RenderCapColorRow(int row, bool bottomCap, visplane_t *pl)
@ -1115,7 +1119,8 @@ namespace
short *uwal = (short *)pl->top; short *uwal = (short *)pl->top;
short *dwal = (short *)pl->bottom; short *dwal = (short *)pl->bottom;
TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z); TriMatrix objectToWorld = TriMatrix::translate((float)ViewPos.X, (float)ViewPos.Y, (float)ViewPos.Z);
TriangleDrawer::fill(objectToWorld, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], TriangleDrawMode::Fan, bottomCap, x1, x2 - 1, uwal, dwal, solid); TriMatrix objectToClip = TriMatrix::viewToClip() * TriMatrix::worldToView() * objectToWorld;
TriangleDrawer::fill(objectToClip, &mVertices[mPrimStart[row]], mPrimStart[row + 1] - mPrimStart[row], TriangleDrawMode::Fan, bottomCap, x1, x2 - 1, uwal, dwal, solid);
} }
void SkyDome::Render(visplane_t *pl) void SkyDome::Render(visplane_t *pl)

View file

@ -36,17 +36,17 @@
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "r_triangle.h" #include "r_triangle.h"
void TriangleDrawer::draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture) void TriangleDrawer::draw(const TriMatrix &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture)
{ {
draw_arrays(objectToWorld, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, texture, 0, &ScreenTriangleDrawer::draw); draw_arrays(objectToClip, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, texture, 0, &ScreenTriangleDrawer::draw);
} }
void TriangleDrawer::fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor) void TriangleDrawer::fill(const TriMatrix &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor)
{ {
draw_arrays(objectToWorld, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, nullptr, solidcolor, &ScreenTriangleDrawer::fill); draw_arrays(objectToClip, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, nullptr, solidcolor, &ScreenTriangleDrawer::fill);
} }
void TriangleDrawer::draw_arrays(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *)) void TriangleDrawer::draw_arrays(const TriMatrix &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *))
{ {
if (vcount < 3) if (vcount < 3)
return; return;
@ -78,28 +78,28 @@ void TriangleDrawer::draw_arrays(const TriMatrix &objectToWorld, const TriVertex
for (int i = 0; i < vcount / 3; i++) for (int i = 0; i < vcount / 3; i++)
{ {
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++)
vert[j] = shade_vertex(objectToWorld, *(vinput++)); vert[j] = shade_vertex(objectToClip, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, drawfunc); draw_shaded_triangle(vert, ccw, &args, drawfunc);
} }
} }
else if (mode == TriangleDrawMode::Fan) else if (mode == TriangleDrawMode::Fan)
{ {
vert[0] = shade_vertex(objectToWorld, *(vinput++)); vert[0] = shade_vertex(objectToClip, *(vinput++));
vert[1] = shade_vertex(objectToWorld, *(vinput++)); vert[1] = shade_vertex(objectToClip, *(vinput++));
for (int i = 2; i < vcount; i++) for (int i = 2; i < vcount; i++)
{ {
vert[2] = shade_vertex(objectToWorld, *(vinput++)); vert[2] = shade_vertex(objectToClip, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, drawfunc); draw_shaded_triangle(vert, ccw, &args, drawfunc);
vert[1] = vert[2]; vert[1] = vert[2];
} }
} }
else // TriangleDrawMode::Strip else // TriangleDrawMode::Strip
{ {
vert[0] = shade_vertex(objectToWorld, *(vinput++)); vert[0] = shade_vertex(objectToClip, *(vinput++));
vert[1] = shade_vertex(objectToWorld, *(vinput++)); vert[1] = shade_vertex(objectToClip, *(vinput++));
for (int i = 2; i < vcount; i++) for (int i = 2; i < vcount; i++)
{ {
vert[2] = shade_vertex(objectToWorld, *(vinput++)); vert[2] = shade_vertex(objectToClip, *(vinput++));
draw_shaded_triangle(vert, ccw, &args, drawfunc); draw_shaded_triangle(vert, ccw, &args, drawfunc);
vert[0] = vert[1]; vert[0] = vert[1];
vert[1] = vert[2]; vert[1] = vert[2];
@ -108,25 +108,10 @@ void TriangleDrawer::draw_arrays(const TriMatrix &objectToWorld, const TriVertex
} }
} }
TriVertex TriangleDrawer::shade_vertex(const TriMatrix &objectToWorld, TriVertex v) TriVertex TriangleDrawer::shade_vertex(const TriMatrix &objectToClip, TriVertex v)
{ {
// Apply transform to get world coordinates: // Apply transform to get clip coordinates:
v = objectToWorld * v; return objectToClip * v;
// The software renderer world to clip transform:
double nearp = 5.0f;
double farp = 65536.f;
double tr_x = v.x - ViewPos.X;
double tr_y = v.y - ViewPos.Y;
double tr_z = v.z - ViewPos.Z;
double tx = tr_x * ViewSin - tr_y * ViewCos;
double tz = tr_x * ViewTanCos + tr_y * ViewTanSin;
v.x = (float)tx * 0.5f;
v.y = (float)tr_z * 0.5f;
v.z = (float)((-tz * (farp + nearp) / (nearp - farp) + (2.0f * farp * nearp) / (nearp - farp)));
v.w = (float)tz;
return v;
} }
void TriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *)) void TriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *))
@ -150,8 +135,8 @@ void TriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, Scree
v.z *= v.w; v.z *= v.w;
// Apply viewport scale to get screen coordinates: // Apply viewport scale to get screen coordinates:
v.x = (float)(CenterX + v.x * 2.0f * CenterX); v.x = viewwidth * (1.0f + v.x) * 0.5f;
v.y = (float)(CenterY - v.y * 2.0f * InvZtoScale); v.y = viewheight * (1.0f - v.y) * 0.5f;
} }
// Draw screen triangles // Draw screen triangles
@ -717,6 +702,45 @@ TriMatrix TriMatrix::rotate(float angle, float x, float y, float z)
return m; return m;
} }
TriMatrix TriMatrix::frustum(float left, float right, float bottom, float top, float near, float far)
{
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(far + near) / (far - near);
float d = -(2.0f * far) / (far - near);
TriMatrix m = null();
m.matrix[0 + 0 * 4] = 2.0f * near / (right - left);
m.matrix[1 + 1 * 4] = 2.0f * near / (top - bottom);
m.matrix[0 + 2 * 4] = a;
m.matrix[1 + 2 * 4] = b;
m.matrix[2 + 2 * 4] = c;
m.matrix[2 + 3 * 4] = d;
m.matrix[3 + 2 * 4] = -1;
return m;
}
TriMatrix TriMatrix::worldToView()
{
TriMatrix m = null();
m.matrix[0 + 0 * 4] = (float)ViewSin;
m.matrix[0 + 1 * 4] = (float)-ViewCos;
m.matrix[1 + 2 * 4] = 1.0f;
m.matrix[2 + 0 * 4] = (float)-ViewCos;
m.matrix[2 + 1 * 4] = (float)-ViewSin;
m.matrix[3 + 3 * 4] = 1.0f;
return m * translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
}
TriMatrix TriMatrix::viewToClip()
{
float near = 5.0f;
float far = 65536.0f;
float width = (float)(FocalTangent * near);
float top = (float)(CenterY / InvZtoScale * near);
float bottom = (float)(top - viewheight / InvZtoScale * near);
return frustum(-width, width, bottom, top, near, far);
}
TriMatrix TriMatrix::operator*(const TriMatrix &mult) const TriMatrix TriMatrix::operator*(const TriMatrix &mult) const
{ {
TriMatrix result; TriMatrix result;

View file

@ -46,6 +46,10 @@ struct TriMatrix
static TriMatrix translate(float x, float y, float z); static TriMatrix translate(float x, float y, float z);
static TriMatrix scale(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 rotate(float angle, float x, float y, float z);
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; TriVertex operator*(TriVertex v) const;
TriMatrix operator*(const TriMatrix &m) const; TriMatrix operator*(const TriMatrix &m) const;
@ -63,12 +67,12 @@ enum class TriangleDrawMode
class TriangleDrawer class TriangleDrawer
{ {
public: public:
static void draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture); static void draw(const TriMatrix &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture);
static void fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor); static void fill(const TriMatrix &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor);
private: private:
static TriVertex shade_vertex(const TriMatrix &objectToWorld, TriVertex v); static TriVertex shade_vertex(const TriMatrix &objectToClip, TriVertex v);
static void draw_arrays(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *)); static void draw_arrays(const TriMatrix &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture, int solidcolor, void(*drawfunc)(const ScreenTriangleDrawerArgs *));
static void draw_shaded_triangle(const TriVertex *vertices, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *)); static void draw_shaded_triangle(const TriVertex *vertices, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *));
static bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2); static bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2);
static void clipedge(const TriVertex &v1, const TriVertex &v2, TriVertex *clippedvert, int &numclipvert); static void clipedge(const TriVertex &v1, const TriVertex &v2, TriVertex *clippedvert, int &numclipvert);