mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 15:22:15 +00:00
Add triangle fan and strip
This commit is contained in:
parent
a1ba371eed
commit
7a9c674f83
2 changed files with 130 additions and 88 deletions
|
@ -36,110 +36,143 @@
|
||||||
#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, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture)
|
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)
|
||||||
{
|
{
|
||||||
draw_any(objectToWorld, vinput, vcount, ccw, clipleft, clipright, cliptop, clipbottom, texture, 0, &ScreenTriangleDrawer::draw);
|
draw_arrays(objectToWorld, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, texture, 0, &ScreenTriangleDrawer::draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleDrawer::fill(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor)
|
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)
|
||||||
{
|
{
|
||||||
draw_any(objectToWorld, vinput, vcount, ccw, clipleft, clipright, cliptop, clipbottom, nullptr, solidcolor, &ScreenTriangleDrawer::fill);
|
draw_arrays(objectToWorld, vinput, vcount, mode, ccw, clipleft, clipright, cliptop, clipbottom, nullptr, solidcolor, &ScreenTriangleDrawer::fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleDrawer::draw_any(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, 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 &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 *))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < vcount / 3; i++)
|
if (vcount < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScreenTriangleDrawerArgs args;
|
||||||
|
args.dest = dc_destorg;
|
||||||
|
args.pitch = dc_pitch;
|
||||||
|
args.clipleft = clipleft;
|
||||||
|
args.clipright = clipright;
|
||||||
|
args.cliptop = cliptop;
|
||||||
|
args.clipbottom = clipbottom;
|
||||||
|
if (texture)
|
||||||
{
|
{
|
||||||
TriVertex vert[3];
|
args.textureWidth = texture->GetWidth();
|
||||||
|
args.textureHeight = texture->GetHeight();
|
||||||
|
args.texturePixels = texture->GetPixels();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args.textureWidth = 0;
|
||||||
|
args.textureHeight = 0;
|
||||||
|
args.texturePixels = nullptr;
|
||||||
|
}
|
||||||
|
args.solidcolor = solidcolor;
|
||||||
|
|
||||||
// Vertex shader stuff:
|
TriVertex vert[3];
|
||||||
for (int j = 0; j < 3; j++)
|
if (mode == TriangleDrawMode::Normal)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < vcount / 3; i++)
|
||||||
{
|
{
|
||||||
auto &v = vert[j];
|
for (int j = 0; j < 3; j++)
|
||||||
v = *(vinput++);
|
vert[j] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
|
draw_shaded_triangle(vert, ccw, &args, drawfunc);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Cull, clip and generate additional vertices as needed
|
else if (mode == TriangleDrawMode::Fan)
|
||||||
TriVertex clippedvert[6];
|
{
|
||||||
int numclipvert = 0;
|
vert[0] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
clipedge(vert[0], vert[1], clippedvert, numclipvert);
|
vert[1] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
clipedge(vert[1], vert[2], clippedvert, numclipvert);
|
for (int i = 2; i < vcount; i++)
|
||||||
clipedge(vert[2], vert[0], clippedvert, numclipvert);
|
|
||||||
|
|
||||||
// Map to 2D viewport:
|
|
||||||
for (int j = 0; j < numclipvert; j++)
|
|
||||||
{
|
{
|
||||||
auto &v = clippedvert[j];
|
vert[2] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
|
draw_shaded_triangle(vert, ccw, &args, drawfunc);
|
||||||
// Calculate normalized device coordinates:
|
vert[1] = vert[2];
|
||||||
v.w = 1.0f / v.w;
|
|
||||||
v.x *= v.w;
|
|
||||||
v.y *= v.w;
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Draw screen triangles
|
else // TriangleDrawMode::Strip
|
||||||
|
{
|
||||||
ScreenTriangleDrawerArgs args;
|
vert[0] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
args.dest = dc_destorg;
|
vert[1] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
args.pitch = dc_pitch;
|
for (int i = 2; i < vcount; i++)
|
||||||
args.clipleft = clipleft;
|
|
||||||
args.clipright = clipright;
|
|
||||||
args.cliptop = cliptop;
|
|
||||||
args.clipbottom = clipbottom;
|
|
||||||
if (texture)
|
|
||||||
{
|
{
|
||||||
args.textureWidth = texture->GetWidth();
|
vert[2] = shade_vertex(objectToWorld, *(vinput++));
|
||||||
args.textureHeight = texture->GetHeight();
|
draw_shaded_triangle(vert, ccw, &args, drawfunc);
|
||||||
args.texturePixels = texture->GetPixels();
|
vert[0] = vert[1];
|
||||||
|
vert[1] = vert[2];
|
||||||
|
ccw = !ccw;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
args.textureWidth = 0;
|
|
||||||
args.textureHeight = 0;
|
|
||||||
args.texturePixels = nullptr;
|
|
||||||
}
|
|
||||||
args.solidcolor = solidcolor;
|
|
||||||
|
|
||||||
if (ccw)
|
TriVertex TriangleDrawer::shade_vertex(const TriMatrix &objectToWorld, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriangleDrawer::draw_shaded_triangle(const TriVertex *vert, bool ccw, ScreenTriangleDrawerArgs *args, void(*drawfunc)(const ScreenTriangleDrawerArgs *))
|
||||||
|
{
|
||||||
|
// Cull, clip and generate additional vertices as needed
|
||||||
|
TriVertex clippedvert[6];
|
||||||
|
int numclipvert = 0;
|
||||||
|
clipedge(vert[0], vert[1], clippedvert, numclipvert);
|
||||||
|
clipedge(vert[1], vert[2], clippedvert, numclipvert);
|
||||||
|
clipedge(vert[2], vert[0], clippedvert, numclipvert);
|
||||||
|
|
||||||
|
// Map to 2D viewport:
|
||||||
|
for (int j = 0; j < numclipvert; j++)
|
||||||
|
{
|
||||||
|
auto &v = clippedvert[j];
|
||||||
|
|
||||||
|
// Calculate normalized device coordinates:
|
||||||
|
v.w = 1.0f / v.w;
|
||||||
|
v.x *= v.w;
|
||||||
|
v.y *= v.w;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw screen triangles
|
||||||
|
if (ccw)
|
||||||
|
{
|
||||||
|
for (int i = numclipvert; i > 1; i--)
|
||||||
{
|
{
|
||||||
for (int i = numclipvert; i > 1; i--)
|
args->v1 = &clippedvert[numclipvert - 1];
|
||||||
{
|
args->v2 = &clippedvert[i - 1];
|
||||||
args.v1 = &clippedvert[numclipvert - 1];
|
args->v3 = &clippedvert[i - 2];
|
||||||
args.v2 = &clippedvert[i - 1];
|
drawfunc(args);
|
||||||
args.v3 = &clippedvert[i - 2];
|
|
||||||
drawfunc(&args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 2; i < numclipvert; i++)
|
||||||
{
|
{
|
||||||
for (int i = 2; i < numclipvert; i++)
|
args->v1 = &clippedvert[0];
|
||||||
{
|
args->v2 = &clippedvert[i - 1];
|
||||||
args.v1 = &clippedvert[0];
|
args->v3 = &clippedvert[i];
|
||||||
args.v2 = &clippedvert[i - 1];
|
drawfunc(args);
|
||||||
args.v3 = &clippedvert[i];
|
|
||||||
drawfunc(&args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,14 +53,23 @@ struct TriMatrix
|
||||||
float matrix[16];
|
float matrix[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TriangleDrawMode
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Fan,
|
||||||
|
Strip
|
||||||
|
};
|
||||||
|
|
||||||
class TriangleDrawer
|
class TriangleDrawer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void draw(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, FTexture *texture);
|
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, bool ccw, int clipleft, int clipright, const short *cliptop, const short *clipbottom, int solidcolor);
|
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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void draw_any(const TriMatrix &objectToWorld, const TriVertex *vinput, int vcount, 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 &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 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);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue