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 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_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_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(objectToWorld, 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::fill(objectToClip, cube, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_top);
TriangleDrawer::fill(objectToClip, cube + 6, 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, solid_bottom);
TriangleDrawer::draw(objectToClip, cube + 2 * 6, 4 * 6, TriangleDrawMode::Normal, false, x1, x2 - 1, uwal, dwal, frontskytex);
}
namespace
@ -1102,7 +1105,8 @@ namespace
short *uwal = (short *)pl->top;
short *dwal = (short *)pl->bottom;
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)
@ -1115,7 +1119,8 @@ namespace
short *uwal = (short *)pl->top;
short *dwal = (short *)pl->bottom;
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)

View File

@ -36,17 +36,17 @@
#include "r_data/colormaps.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)
return;
@ -78,28 +78,28 @@ void TriangleDrawer::draw_arrays(const TriMatrix &objectToWorld, const TriVertex
for (int i = 0; i < vcount / 3; i++)
{
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);
}
}
else if (mode == TriangleDrawMode::Fan)
{
vert[0] = shade_vertex(objectToWorld, *(vinput++));
vert[1] = shade_vertex(objectToWorld, *(vinput++));
vert[0] = shade_vertex(objectToClip, *(vinput++));
vert[1] = shade_vertex(objectToClip, *(vinput++));
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);
vert[1] = vert[2];
}
}
else // TriangleDrawMode::Strip
{
vert[0] = shade_vertex(objectToWorld, *(vinput++));
vert[1] = shade_vertex(objectToWorld, *(vinput++));
vert[0] = shade_vertex(objectToClip, *(vinput++));
vert[1] = shade_vertex(objectToClip, *(vinput++));
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);
vert[0] = vert[1];
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:
v = objectToWorld * 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;
// Apply transform to get clip coordinates:
return objectToClip * v;
}
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;
// Apply viewport scale to get screen coordinates:
v.x = (float)(CenterX + v.x * 2.0f * CenterX);
v.y = (float)(CenterY - v.y * 2.0f * InvZtoScale);
v.x = viewwidth * (1.0f + v.x) * 0.5f;
v.y = viewheight * (1.0f - v.y) * 0.5f;
}
// Draw screen triangles
@ -717,6 +702,45 @@ TriMatrix TriMatrix::rotate(float angle, float x, float y, float z)
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 result;

View File

@ -46,6 +46,10 @@ struct TriMatrix
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 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;
@ -63,12 +67,12 @@ enum class TriangleDrawMode
class TriangleDrawer
{
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 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 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 &objectToClip, const TriVertex *vinput, int vcount, TriangleDrawMode mode, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor);
private:
static TriVertex shade_vertex(const TriMatrix &objectToWorld, 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 TriVertex shade_vertex(const TriMatrix &objectToClip, TriVertex v);
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 bool cullhalfspace(float clipdistance1, float clipdistance2, float &t1, float &t2);
static void clipedge(const TriVertex &v1, const TriVertex &v2, TriVertex *clippedvert, int &numclipvert);