Implement face culling modes
This commit is contained in:
parent
43dc1023d6
commit
43e9508f6a
|
@ -14,6 +14,9 @@ static Matrix4x4 MATRIX;
|
||||||
static SDL_Window* WINDOW = NULL;
|
static SDL_Window* WINDOW = NULL;
|
||||||
static SDL_Renderer* RENDERER = NULL;
|
static SDL_Renderer* RENDERER = NULL;
|
||||||
|
|
||||||
|
GPUCulling CULL_MODE = GPU_CULLING_CCW;
|
||||||
|
|
||||||
|
|
||||||
static VideoMode vid_mode = {
|
static VideoMode vid_mode = {
|
||||||
640, 480
|
640, 480
|
||||||
};
|
};
|
||||||
|
@ -33,7 +36,7 @@ typedef struct GPUVertex {
|
||||||
#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(const GPUVertex* v0, const GPUVertex* v1, const GPUVertex* v2) {
|
static void DrawTriangle(GPUVertex* v0, GPUVertex* v1, GPUVertex* v2) {
|
||||||
// Compute triangle bounding box.
|
// Compute triangle bounding box.
|
||||||
|
|
||||||
int minX = MIN(MIN(v0->x, v1->x), v2->x);
|
int minX = MIN(MIN(v0->x, v1->x), v2->x);
|
||||||
|
@ -57,10 +60,36 @@ static void DrawTriangle(const GPUVertex* v0, const GPUVertex* v1, const GPUVert
|
||||||
|
|
||||||
float area = 0.5 * (e0.c + e1.c + e2.c);
|
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() \
|
||||||
|
GPUVertex* tv = v0; \
|
||||||
|
v0 = v1; \
|
||||||
|
v1 = tv; \
|
||||||
|
EdgeEquationInit(&e0, &v0->x, &v1->x); \
|
||||||
|
EdgeEquationInit(&e1, &v1->x, &v2->x); \
|
||||||
|
EdgeEquationInit(&e2, &v2->x, &v0->x); \
|
||||||
|
area = 0.5f * (e0.c + e1.c + e2.c) \
|
||||||
|
|
||||||
// Check if triangle is backfacing.
|
// Check if triangle is backfacing.
|
||||||
if (area < 0) {
|
if(CULL_MODE == GPU_CULLING_CCW) {
|
||||||
|
if(area < 0) {
|
||||||
return;
|
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;
|
ParameterEquation r, g, b;
|
||||||
|
|
||||||
|
@ -116,6 +145,12 @@ void SceneListSubmit(void* src, int n) {
|
||||||
for(int i = 0; i < n; ++i, flags += step) {
|
for(int i = 0; i < n; ++i, flags += step) {
|
||||||
if((*flags & GPU_CMD_POLYHDR) == GPU_CMD_POLYHDR) {
|
if((*flags & GPU_CMD_POLYHDR) == GPU_CMD_POLYHDR) {
|
||||||
vertex_counter = 0;
|
vertex_counter = 0;
|
||||||
|
|
||||||
|
uint32_t mode1 = *(flags + 1);
|
||||||
|
// Extract culling mode
|
||||||
|
uint32_t mask = mode1 & GPU_TA_PM1_CULLING_MASK;
|
||||||
|
CULL_MODE = mask >> GPU_TA_PM1_CULLING_SHIFT;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch(*flags) {
|
switch(*flags) {
|
||||||
case GPU_CMD_VERTEX_EOL:
|
case GPU_CMD_VERTEX_EOL:
|
||||||
|
@ -128,9 +163,9 @@ void SceneListSubmit(void* src, int n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vertex_counter > 2) {
|
if(vertex_counter > 2) {
|
||||||
const GPUVertex* v0 = (const GPUVertex*) (flags - step - step);
|
GPUVertex* v0 = (GPUVertex*) (flags - step - step);
|
||||||
const GPUVertex* v1 = (const GPUVertex*) (flags - step);
|
GPUVertex* v1 = (GPUVertex*) (flags - step);
|
||||||
const GPUVertex* v2 = (const GPUVertex*) (flags);
|
GPUVertex* v2 = (GPUVertex*) (flags);
|
||||||
(vertex_counter % 2 == 0) ? DrawTriangle(v0, v1, v2) : DrawTriangle(v1, v0, v2);
|
(vertex_counter % 2 == 0) ? DrawTriangle(v0, v1, v2) : DrawTriangle(v1, v0, v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user