Speed up the software renderer
This commit is contained in:
parent
5865d57384
commit
f6713bc778
|
@ -30,81 +30,7 @@ static VideoMode vid_mode = {
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
static void DrawTriangle(Vertex* v0, Vertex* v1, Vertex* v2) {
|
AlignedVector vbuffer;
|
||||||
// Compute triangle bounding box.
|
|
||||||
|
|
||||||
int minX = MIN(MIN(v0->xyz[0], v1->xyz[0]), v2->xyz[0]);
|
|
||||||
int maxX = MAX(MAX(v0->xyz[0], v1->xyz[0]), v2->xyz[0]);
|
|
||||||
int minY = MIN(MIN(v0->xyz[1], v1->xyz[1]), v2->xyz[1]);
|
|
||||||
int maxY = MAX(MAX(v0->xyz[1], v1->xyz[1]), v2->xyz[1]);
|
|
||||||
|
|
||||||
// Clip to scissor rect.
|
|
||||||
|
|
||||||
minX = MAX(minX, 0);
|
|
||||||
maxX = MIN(maxX, vid_mode.width);
|
|
||||||
minY = MAX(minY, 0);
|
|
||||||
maxY = MIN(maxY, vid_mode.height);
|
|
||||||
|
|
||||||
// Compute edge equations.
|
|
||||||
|
|
||||||
EdgeEquation e0, e1, e2;
|
|
||||||
EdgeEquationInit(&e0, &v0->xyz[0], &v1->xyz[0]);
|
|
||||||
EdgeEquationInit(&e1, &v1->xyz[0], &v2->xyz[0]);
|
|
||||||
EdgeEquationInit(&e2, &v2->xyz[0], &v0->xyz[0]);
|
|
||||||
|
|
||||||
float area = 0.5 * (e0.c + e1.c + e2.c);
|
|
||||||
|
|
||||||
/* This is very ugly. I don't understand the math properly
|
|
||||||
* so I just swap the vertex order if something is back-facing
|
|
||||||
* and we want to render it. Patches welcome! */
|
|
||||||
#define REVERSE_WINDING() \
|
|
||||||
Vertex* tv = v0; \
|
|
||||||
v0 = v1; \
|
|
||||||
v1 = tv; \
|
|
||||||
EdgeEquationInit(&e0, &v0->xyz[0], &v1->xyz[0]); \
|
|
||||||
EdgeEquationInit(&e1, &v1->xyz[0], &v2->xyz[0]); \
|
|
||||||
EdgeEquationInit(&e2, &v2->xyz[0], &v0->xyz[0]); \
|
|
||||||
area = 0.5f * (e0.c + e1.c + e2.c) \
|
|
||||||
|
|
||||||
// Check if triangle is backfacing.
|
|
||||||
if(CULL_MODE == GPU_CULLING_CCW) {
|
|
||||||
if(area < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if(CULL_MODE == GPU_CULLING_CW) {
|
|
||||||
if(area < 0) {
|
|
||||||
// We only draw front-facing polygons, so swap
|
|
||||||
// the back to front and draw
|
|
||||||
REVERSE_WINDING();
|
|
||||||
} else {
|
|
||||||
// Front facing, so bail
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if(area < 0) {
|
|
||||||
/* We're not culling, but this is backfacing, so swap vertices and edges */
|
|
||||||
REVERSE_WINDING();
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterEquation r, g, b;
|
|
||||||
|
|
||||||
ParameterEquationInit(&r, v0->bgra[2], v1->bgra[2], v2->bgra[2], &e0, &e1, &e2, area);
|
|
||||||
ParameterEquationInit(&g, v0->bgra[1], v1->bgra[1], v2->bgra[1], &e0, &e1, &e2, area);
|
|
||||||
ParameterEquationInit(&b, v0->bgra[0], v1->bgra[0], v2->bgra[0], &e0, &e1, &e2, area);
|
|
||||||
|
|
||||||
// Add 0.5 to sample at pixel centers.
|
|
||||||
for (float x = minX + 0.5f, xm = maxX + 0.5f; x <= xm; x += 1.0f)
|
|
||||||
for (float y = minY + 0.5f, ym = maxY + 0.5f; y <= ym; y += 1.0f)
|
|
||||||
{
|
|
||||||
if (EdgeEquationTestPoint(&e0, x, y) && EdgeEquationTestPoint(&e1, x, y) && EdgeEquationTestPoint(&e2, x, y)) {
|
|
||||||
int rint = ParameterEquationEvaluate(&r, x, y);
|
|
||||||
int gint = ParameterEquationEvaluate(&g, x, y);
|
|
||||||
int bint = ParameterEquationEvaluate(&b, x, y);
|
|
||||||
SDL_SetRenderDrawColor(RENDERER, rint, gint, bint, 255);
|
|
||||||
SDL_RenderDrawPoint(RENDERER, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InitGPU(_Bool autosort, _Bool fsaa) {
|
void InitGPU(_Bool autosort, _Bool fsaa) {
|
||||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||||
|
@ -120,6 +46,8 @@ void InitGPU(_Bool autosort, _Bool fsaa) {
|
||||||
RENDERER = SDL_CreateRenderer(
|
RENDERER = SDL_CreateRenderer(
|
||||||
WINDOW, -1, SDL_RENDERER_ACCELERATED
|
WINDOW, -1, SDL_RENDERER_ACCELERATED
|
||||||
);
|
);
|
||||||
|
|
||||||
|
aligned_vector_init(&vbuffer, sizeof(SDL_Vertex));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneBegin() {
|
void SceneBegin() {
|
||||||
|
@ -531,13 +459,37 @@ void SceneListFinish() {
|
||||||
Vertex* v0 = (Vertex*) (flags - step - step);
|
Vertex* v0 = (Vertex*) (flags - step - step);
|
||||||
Vertex* v1 = (Vertex*) (flags - step);
|
Vertex* v1 = (Vertex*) (flags - step);
|
||||||
Vertex* v2 = (Vertex*) (flags);
|
Vertex* v2 = (Vertex*) (flags);
|
||||||
(vidx % 2 == 0) ? DrawTriangle(v0, v1, v2) : DrawTriangle(v1, v0, v2);
|
|
||||||
|
SDL_Vertex sv0 = {
|
||||||
|
{v0->xyz[0], v0->xyz[1]},
|
||||||
|
{v0->bgra[2], v0->bgra[1], v0->bgra[0], v0->bgra[3]},
|
||||||
|
{v0->uv[0], v0->uv[1]}
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_Vertex sv1 = {
|
||||||
|
{v1->xyz[0], v1->xyz[1]},
|
||||||
|
{v1->bgra[2], v1->bgra[1], v1->bgra[0], v1->bgra[3]},
|
||||||
|
{v1->uv[0], v1->uv[1]}
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_Vertex sv2 = {
|
||||||
|
{v2->xyz[0], v2->xyz[1]},
|
||||||
|
{v2->bgra[2], v2->bgra[1], v2->bgra[0], v2->bgra[3]},
|
||||||
|
{v2->uv[0], v2->uv[1]}
|
||||||
|
};
|
||||||
|
|
||||||
|
aligned_vector_push_back(&vbuffer, &sv0, 1);
|
||||||
|
aligned_vector_push_back(&vbuffer, &sv1, 1);
|
||||||
|
aligned_vector_push_back(&vbuffer, &sv2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if((*flags) == GPU_CMD_VERTEX_EOL) {
|
if((*flags) == GPU_CMD_VERTEX_EOL) {
|
||||||
vidx = 0;
|
vidx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(RENDERER, 255, 255, 255, 255);
|
||||||
|
SDL_RenderGeometry(RENDERER, NULL, aligned_vector_front(&vbuffer), aligned_vector_size(&vbuffer), NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneFinish() {
|
void SceneFinish() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user