fix quad sorting + simplify quad rasterization part
This commit is contained in:
parent
dc9d2c90bc
commit
4928008e6d
233
src/external/rlsw.h
vendored
233
src/external/rlsw.h
vendored
|
|
@ -960,7 +960,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef void (*sw_blend_factor_t)(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst);
|
typedef void (*sw_blend_factor_t)(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst);
|
||||||
typedef void (*sw_raster_triangle_f)(const sw_vertex_t *v0, const sw_vertex_t *v1, const sw_vertex_t *v2);
|
typedef void (*sw_raster_triangle_f)(const sw_vertex_t *v0, const sw_vertex_t *v1, const sw_vertex_t *v2);
|
||||||
typedef void (*sw_raster_quad_f)(void);
|
typedef void (*sw_raster_quad_f)(const sw_vertex_t *v0, const sw_vertex_t *v1, const sw_vertex_t *v2, const sw_vertex_t *v3);
|
||||||
typedef void (*sw_raster_line_f)(const sw_vertex_t *v0, const sw_vertex_t *v1);
|
typedef void (*sw_raster_line_f)(const sw_vertex_t *v0, const sw_vertex_t *v1);
|
||||||
typedef void (*sw_raster_point_f)(const sw_vertex_t *v);
|
typedef void (*sw_raster_point_f)(const sw_vertex_t *v);
|
||||||
|
|
||||||
|
|
@ -3171,7 +3171,7 @@ static bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES]
|
||||||
// Forward declarations because clangd does not follow #include __FILE__ to avoid infinite recursion
|
// Forward declarations because clangd does not follow #include __FILE__ to avoid infinite recursion
|
||||||
// These declarations make all variants visible to static analysis tools without affecting compilation
|
// These declarations make all variants visible to static analysis tools without affecting compilation
|
||||||
#define SW_FWD_DECL(NAME, _FLAGS) \
|
#define SW_FWD_DECL(NAME, _FLAGS) \
|
||||||
static void sw_raster_quad_##NAME(void);
|
static void sw_raster_quad_##NAME(const sw_vertex_t *v0, const sw_vertex_t *v1, const sw_vertex_t *v2, const sw_vertex_t *v3);
|
||||||
SW_RASTER_VARIANTS(SW_FWD_DECL) // NOLINT
|
SW_RASTER_VARIANTS(SW_FWD_DECL) // NOLINT
|
||||||
#undef SW_FWD_DECL
|
#undef SW_FWD_DECL
|
||||||
|
|
||||||
|
|
@ -3625,7 +3625,12 @@ static void sw_quad_render(uint32_t state)
|
||||||
|
|
||||||
if ((RLSW.vertexCounter == 4) && sw_quad_is_axis_aligned())
|
if ((RLSW.vertexCounter == 4) && sw_quad_is_axis_aligned())
|
||||||
{
|
{
|
||||||
SW_RASTER_QUAD_FUNCS[state]();
|
SW_RASTER_QUAD_FUNCS[state](
|
||||||
|
&RLSW.vertexBuffer[0],
|
||||||
|
&RLSW.vertexBuffer[1],
|
||||||
|
&RLSW.vertexBuffer[2],
|
||||||
|
&RLSW.vertexBuffer[3]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -5531,164 +5536,107 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con
|
||||||
|
|
||||||
#define SW_RASTER_QUAD SW_CONCATX(sw_raster_quad_, RLSW_TEMPLATE_RASTER_QUAD)
|
#define SW_RASTER_QUAD SW_CONCATX(sw_raster_quad_, RLSW_TEMPLATE_RASTER_QUAD)
|
||||||
|
|
||||||
#ifndef RLSW_TEMPLATE_RASTER_QUAD_INTERNAL
|
|
||||||
#define RLSW_TEMPLATE_RASTER_QUAD_INTERNAL
|
|
||||||
static void sw_quad_sort_cw(const sw_vertex_t* *output)
|
|
||||||
{
|
|
||||||
const sw_vertex_t *input = RLSW.vertexBuffer;
|
|
||||||
|
|
||||||
// Calculate the centroid of the quad
|
|
||||||
float cx = (input[0].screen[0] + input[1].screen[0] +
|
|
||||||
input[2].screen[0] + input[3].screen[0])*0.25f;
|
|
||||||
float cy = (input[0].screen[1] + input[1].screen[1] +
|
|
||||||
input[2].screen[1] + input[3].screen[1])*0.25f;
|
|
||||||
|
|
||||||
// Calculate the angle of each vertex relative to the center
|
|
||||||
// and assign them directly to their correct position
|
|
||||||
const sw_vertex_t *corners[4] = { 0 };
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
float dx = input[i].screen[0] - cx;
|
|
||||||
float dy = input[i].screen[1] - cy;
|
|
||||||
|
|
||||||
// Determine the quadrant (clockwise from top-left)
|
|
||||||
// top-left: dx < 0, dy < 0
|
|
||||||
// top-right: dx >= 0, dy < 0
|
|
||||||
// bottom-right: dx >= 0, dy >= 0
|
|
||||||
// bottom-left: dx < 0, dy >= 0
|
|
||||||
|
|
||||||
int idx;
|
|
||||||
if (dy < 0) idx = (dx < 0)? 0 : 1; // Top row
|
|
||||||
else idx = (dx < 0)? 3 : 2; // Bottom row
|
|
||||||
|
|
||||||
corners[idx] = &input[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
output[0] = corners[0]; // top-left
|
|
||||||
output[1] = corners[1]; // top-right
|
|
||||||
output[2] = corners[2]; // bottom-right
|
|
||||||
output[3] = corners[3]; // bottom-left
|
|
||||||
}
|
|
||||||
#endif // RLSW_TEMPLATE_RASTER_QUAD_INTERNAL
|
|
||||||
|
|
||||||
// REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
|
// REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
|
||||||
// still appear perfectly aligned from a certain point of view?
|
// still appear perfectly aligned from a certain point of view?
|
||||||
// Because in that case, it's still needed to perform perspective division for textures and colors...
|
// Because in that case, it's still needed to perform perspective division for textures and colors...
|
||||||
|
|
||||||
static void SW_RASTER_QUAD(void)
|
static void SW_RASTER_QUAD(const sw_vertex_t *a, const sw_vertex_t *b,
|
||||||
|
const sw_vertex_t *c, const sw_vertex_t *d)
|
||||||
{
|
{
|
||||||
const sw_vertex_t *sortedVerts[4];
|
// Classify corners
|
||||||
sw_quad_sort_cw(sortedVerts);
|
// For axis-aligned quads x+y and x-y uniquely identify each corner
|
||||||
|
const sw_vertex_t *verts[4] = { a, b, c, d };
|
||||||
|
const sw_vertex_t *tl = verts[0], *tr = verts[0], *br = verts[0], *bl = verts[0];
|
||||||
|
for (int i = 1; i < 4; i++)
|
||||||
|
{
|
||||||
|
float sum = verts[i]->screen[0] + verts[i]->screen[1];
|
||||||
|
float diff = verts[i]->screen[0] - verts[i]->screen[1];
|
||||||
|
if (sum < tl->screen[0] + tl->screen[1]) tl = verts[i];
|
||||||
|
if (diff > tr->screen[0] - tr->screen[1]) tr = verts[i];
|
||||||
|
if (sum > br->screen[0] + br->screen[1]) br = verts[i];
|
||||||
|
if (diff < bl->screen[0] - bl->screen[1]) bl = verts[i];
|
||||||
|
}
|
||||||
|
|
||||||
const sw_vertex_t *v0 = sortedVerts[0];
|
int xMin = (int)tl->screen[0];
|
||||||
const sw_vertex_t *v1 = sortedVerts[1];
|
int yMin = (int)tl->screen[1];
|
||||||
const sw_vertex_t *v2 = sortedVerts[2];
|
int xMax = (int)br->screen[0];
|
||||||
const sw_vertex_t *v3 = sortedVerts[3];
|
int yMax = (int)br->screen[1];
|
||||||
|
|
||||||
/* Screen bounds (axis-aligned) */
|
float w = (float)(xMax - xMin);
|
||||||
int xMin = (int)v0->screen[0];
|
float h = (float)(yMax - yMin);
|
||||||
int yMin = (int)v0->screen[1];
|
if (w <= 0 || h <= 0) return;
|
||||||
int xMax = (int)v2->screen[0];
|
|
||||||
int yMax = (int)v2->screen[1];
|
|
||||||
|
|
||||||
float w = v2->screen[0] - v0->screen[0];
|
float wRcp = 1.0f / w;
|
||||||
float h = v2->screen[1] - v0->screen[1];
|
float hRcp = 1.0f / h;
|
||||||
|
|
||||||
if ((w == 0) || (h == 0)) return;
|
// Subpixel corrections
|
||||||
|
float xSubstep = 1.0f - sw_fract(tl->screen[0]);
|
||||||
|
float ySubstep = 1.0f - sw_fract(tl->screen[1]);
|
||||||
|
|
||||||
float wRcp = (w > 0.0f)? 1.0f/w : 0.0f;
|
// Gradients along X (tl->tr) and Y (tl->bl)
|
||||||
float hRcp = (h > 0.0f)? 1.0f/h : 0.0f;
|
float dCdx[4] = {
|
||||||
|
(tr->color[0] - tl->color[0]) * wRcp,
|
||||||
|
(tr->color[1] - tl->color[1]) * wRcp,
|
||||||
|
(tr->color[2] - tl->color[2]) * wRcp,
|
||||||
|
(tr->color[3] - tl->color[3]) * wRcp,
|
||||||
|
};
|
||||||
|
float dCdy[4] = {
|
||||||
|
(bl->color[0] - tl->color[0]) * hRcp,
|
||||||
|
(bl->color[1] - tl->color[1]) * hRcp,
|
||||||
|
(bl->color[2] - tl->color[2]) * hRcp,
|
||||||
|
(bl->color[3] - tl->color[3]) * hRcp,
|
||||||
|
};
|
||||||
|
|
||||||
/* Subpixel corrections */
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
float xSubstep = 1.0f - sw_fract(v0->screen[0]);
|
float dZdx = (tr->homogeneous[2] - tl->homogeneous[2]) * wRcp;
|
||||||
float ySubstep = 1.0f - sw_fract(v0->screen[1]);
|
float dZdy = (bl->homogeneous[2] - tl->homogeneous[2]) * hRcp;
|
||||||
|
float zRow = tl->homogeneous[2] + dZdx*xSubstep + dZdy*ySubstep;
|
||||||
/* Calculation of vertex gradients in X and Y */
|
|
||||||
#ifdef SW_ENABLE_TEXTURE
|
|
||||||
float dUdx = (v1->texcoord[0] - v0->texcoord[0])*wRcp;
|
|
||||||
float dVdx = (v1->texcoord[1] - v0->texcoord[1])*wRcp;
|
|
||||||
float dUdy = (v3->texcoord[0] - v0->texcoord[0])*hRcp;
|
|
||||||
float dVdy = (v3->texcoord[1] - v0->texcoord[1])*hRcp;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float dCdx[4], dCdy[4];
|
#ifdef SW_ENABLE_TEXTURE
|
||||||
dCdx[0] = (v1->color[0] - v0->color[0])*wRcp;
|
float dUdx = (tr->texcoord[0] - tl->texcoord[0]) * wRcp;
|
||||||
dCdx[1] = (v1->color[1] - v0->color[1])*wRcp;
|
float dVdx = (tr->texcoord[1] - tl->texcoord[1]) * wRcp;
|
||||||
dCdx[2] = (v1->color[2] - v0->color[2])*wRcp;
|
float dUdy = (bl->texcoord[0] - tl->texcoord[0]) * hRcp;
|
||||||
dCdx[3] = (v1->color[3] - v0->color[3])*wRcp;
|
float dVdy = (bl->texcoord[1] - tl->texcoord[1]) * hRcp;
|
||||||
dCdy[0] = (v3->color[0] - v0->color[0])*hRcp;
|
float uRow = tl->texcoord[0] + dUdx*xSubstep + dUdy*ySubstep;
|
||||||
dCdy[1] = (v3->color[1] - v0->color[1])*hRcp;
|
float vRow = tl->texcoord[1] + dVdx*xSubstep + dVdy*ySubstep;
|
||||||
dCdy[2] = (v3->color[2] - v0->color[2])*hRcp;
|
#endif
|
||||||
dCdy[3] = (v3->color[3] - v0->color[3])*hRcp;
|
|
||||||
|
|
||||||
float dZdx, dZdy;
|
float cRow[4] = {
|
||||||
dZdx = (v1->homogeneous[2] - v0->homogeneous[2])*wRcp;
|
tl->color[0] + dCdx[0]*xSubstep + dCdy[0]*ySubstep,
|
||||||
dZdy = (v3->homogeneous[2] - v0->homogeneous[2])*hRcp;
|
tl->color[1] + dCdx[1]*xSubstep + dCdy[1]*ySubstep,
|
||||||
|
tl->color[2] + dCdx[2]*xSubstep + dCdy[2]*ySubstep,
|
||||||
|
tl->color[3] + dCdx[3]*xSubstep + dCdy[3]*ySubstep,
|
||||||
|
};
|
||||||
|
|
||||||
int wDst = RLSW.colorBuffer->width;
|
int stride = RLSW.colorBuffer->width;
|
||||||
uint8_t *cPixels = RLSW.colorBuffer->pixels;
|
uint8_t *cPixels = RLSW.colorBuffer->pixels;
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
uint8_t *dPixels = RLSW.depthBuffer->pixels;
|
uint8_t *dPixels = RLSW.depthBuffer->pixels;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
|
||||||
float zScanline = v0->homogeneous[2] + dZdx*xSubstep + dZdy*ySubstep;
|
|
||||||
#endif
|
|
||||||
#ifdef SW_ENABLE_TEXTURE
|
|
||||||
float uScanline = v0->texcoord[0] + dUdx*xSubstep + dUdy*ySubstep;
|
|
||||||
float vScanline = v0->texcoord[1] + dVdx*xSubstep + dVdy*ySubstep;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float colorScanline[4] = {
|
|
||||||
v0->color[0] + dCdx[0]*xSubstep + dCdy[0]*ySubstep,
|
|
||||||
v0->color[1] + dCdx[1]*xSubstep + dCdy[1]*ySubstep,
|
|
||||||
v0->color[2] + dCdx[2]*xSubstep + dCdy[2]*ySubstep,
|
|
||||||
v0->color[3] + dCdx[3]*xSubstep + dCdy[3]*ySubstep
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int y = yMin; y < yMax; y++)
|
for (int y = yMin; y < yMax; y++)
|
||||||
{
|
{
|
||||||
int baseOffset = y*wDst + xMin;
|
int baseOffset = y*stride + xMin;
|
||||||
uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
|
uint8_t *cPtr = cPixels + baseOffset*SW_FRAMEBUFFER_COLOR_SIZE;
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
|
uint8_t *dPtr = dPixels + baseOffset*SW_FRAMEBUFFER_DEPTH_SIZE;
|
||||||
#endif
|
float z = zRow;
|
||||||
|
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
|
||||||
float z = zScanline;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef SW_ENABLE_TEXTURE
|
#ifdef SW_ENABLE_TEXTURE
|
||||||
float u = uScanline;
|
float u = uRow;
|
||||||
float v = vScanline;
|
float v = vRow;
|
||||||
#endif
|
#endif
|
||||||
|
float color[4] = { cRow[0], cRow[1], cRow[2], cRow[3] };
|
||||||
|
|
||||||
float color[4] = {
|
|
||||||
colorScanline[0],
|
|
||||||
colorScanline[1],
|
|
||||||
colorScanline[2],
|
|
||||||
colorScanline[3]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Span rasterization
|
|
||||||
for (int x = xMin; x < xMax; x++)
|
for (int x = xMin; x < xMax; x++)
|
||||||
{
|
{
|
||||||
// Pixel color computation
|
float srcColor[4] = { color[0], color[1], color[2], color[3] };
|
||||||
float srcColor[4] = {
|
|
||||||
color[0],
|
|
||||||
color[1],
|
|
||||||
color[2],
|
|
||||||
color[3]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test and write depth
|
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
{
|
{
|
||||||
/* TODO: Implement different depth funcs? */
|
|
||||||
float depth = SW_FRAMEBUFFER_DEPTH_GET(dPtr, 0);
|
float depth = SW_FRAMEBUFFER_DEPTH_GET(dPtr, 0);
|
||||||
if (z > depth) goto discard;
|
if (z > depth) goto discard;
|
||||||
|
|
||||||
/* TODO: Implement depth mask */
|
|
||||||
SW_FRAMEBUFFER_DEPTH_SET(dPtr, z, 0);
|
SW_FRAMEBUFFER_DEPTH_SET(dPtr, z, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -5718,17 +5666,18 @@ static void SW_RASTER_QUAD(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
discard:
|
discard:
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
|
||||||
{
|
|
||||||
z += dZdx;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
color[0] += dCdx[0];
|
color[0] += dCdx[0];
|
||||||
color[1] += dCdx[1];
|
color[1] += dCdx[1];
|
||||||
color[2] += dCdx[2];
|
color[2] += dCdx[2];
|
||||||
color[3] += dCdx[3];
|
color[3] += dCdx[3];
|
||||||
|
|
||||||
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
|
{
|
||||||
|
z += dZdx;
|
||||||
|
dPtr += SW_FRAMEBUFFER_DEPTH_SIZE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SW_ENABLE_TEXTURE
|
#ifdef SW_ENABLE_TEXTURE
|
||||||
{
|
{
|
||||||
u += dUdx;
|
u += dUdx;
|
||||||
|
|
@ -5737,29 +5686,23 @@ static void SW_RASTER_QUAD(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
|
cPtr += SW_FRAMEBUFFER_COLOR_SIZE;
|
||||||
|
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
|
||||||
{
|
|
||||||
dPtr += SW_FRAMEBUFFER_DEPTH_SIZE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cRow[0] += dCdy[0];
|
||||||
|
cRow[1] += dCdy[1];
|
||||||
|
cRow[2] += dCdy[2];
|
||||||
|
cRow[3] += dCdy[3];
|
||||||
|
|
||||||
#ifdef SW_ENABLE_DEPTH_TEST
|
#ifdef SW_ENABLE_DEPTH_TEST
|
||||||
{
|
{
|
||||||
zScanline += dZdy;
|
zRow += dZdy;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
colorScanline[0] += dCdy[0];
|
|
||||||
colorScanline[1] += dCdy[1];
|
|
||||||
colorScanline[2] += dCdy[2];
|
|
||||||
colorScanline[3] += dCdy[3];
|
|
||||||
|
|
||||||
#ifdef SW_ENABLE_TEXTURE
|
#ifdef SW_ENABLE_TEXTURE
|
||||||
{
|
{
|
||||||
uScanline += dUdy;
|
uRow += dUdy;
|
||||||
vScanline += dVdy;
|
vRow += dVdy;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user