From a8f3d86705ef4c4d8adc32ad3e89814fdb6d6126 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Tue, 2 Apr 2024 22:28:36 +0100 Subject: [PATCH 1/5] Start cleaning up the zclip code --- GL/platforms/sh4.c | 381 ++++++++++++++++----------------------------- 1 file changed, 133 insertions(+), 248 deletions(-) diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index 0aec03a..2a356f6 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -1,8 +1,10 @@ +#include + #include "../platform.h" #include "sh4.h" -#define CLIP_DEBUG 0 +#define CLIP_DEBUG 1 #define PVR_VERTEX_BUF_SIZE 2560 * 256 @@ -133,6 +135,7 @@ static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, V vout->xyz[0] = invt * v1->xyz[0] + t * v2->xyz[0]; vout->xyz[1] = invt * v1->xyz[1] + t * v2->xyz[1]; vout->xyz[2] = invt * v1->xyz[2] + t * v2->xyz[2]; + vout->xyz[2] = (vout->xyz[2] < FLT_EPSILON) ? FLT_EPSILON : vout->xyz[2]; vout->uv[0] = invt * v1->uv[0] + t * v2->uv[0]; vout->uv[1] = invt * v1->uv[1] + t * v2->uv[1]; @@ -153,7 +156,22 @@ static volatile uint32_t* PVR_LMMODE0 = (uint32_t*) 0xA05F6884; static volatile uint32_t *PVR_LMMODE1 = (uint32_t*) 0xA05F6888; static volatile uint32_t *QACR = (uint32_t*) 0xFF000038; -void SceneListSubmit(Vertex* v2, int n) { +enum Visible { + NONE_VISIBLE = 0, + FIRST_VISIBLE = 1, + SECOND_VISIBLE = 2, + THIRD_VISIBLE = 4, + FIRST_AND_SECOND_VISIBLE = FIRST_VISIBLE | SECOND_VISIBLE, + SECOND_AND_THIRD_VISIBLE = SECOND_VISIBLE | THIRD_VISIBLE, + FIRST_AND_THIRD_VISIBLE = FIRST_VISIBLE | THIRD_VISIBLE, + ALL_VISIBLE = 7 +}; + +static inline bool is_header(Vertex* v) { + return !(v->flags == GPU_CMD_VERTEX || v->flags == GPU_CMD_VERTEX_EOL); +} + +void SceneListSubmit(Vertex* vertices, int n) { TRACE(); /* You need at least a header, and 3 vertices to render anything */ @@ -173,12 +191,12 @@ void SceneListSubmit(Vertex* v2, int n) { QACR[1] = QACR[0] = 0x11; #if CLIP_DEBUG - Vertex* vertex = (Vertex*) v2; - for(int i = 0; i < n; ++i) { - fprintf(stderr, ">> {%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]); - } - fprintf(stderr, "----\n"); + + Vertex* vertex = (Vertex*) vertices; + for(int i = 0; i < n; ++i) { + fprintf(stderr, "IN: {%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]); + } #endif /* This is a bit cumbersome - in some cases (particularly case 2) @@ -189,7 +207,7 @@ void SceneListSubmit(Vertex* v2, int n) { case 2. To workaround this we may queue a vertex temporarily here, in the normal case it will be submitted by the next iteration with the same flags it had, but in the invisible case it will be overridden to submit with EOL */ - static Vertex qv; + static Vertex __attribute__((aligned(32))) qv; Vertex* queued_vertex = NULL; #define QUEUE_VERTEX(v) \ @@ -199,100 +217,49 @@ void SceneListSubmit(Vertex* v2, int n) { do { if(queued_vertex) { queued_vertex->flags = (sflags); _glPushHeaderOrVertex(queued_vertex); queued_vertex = NULL; } } while(0) uint8_t visible_mask = 0; - uint8_t counter = 0; sq = SQ_BASE_ADDRESS; - for(int i = 0; i < n; ++i, ++v2) { - PREFETCH(v2 + 1); - switch(v2->flags) { - case GPU_CMD_VERTEX_EOL: - if(counter < 2) { - continue; - } - counter = 0; - break; - case GPU_CMD_VERTEX: - ++counter; - if(counter < 3) { - continue; - } - break; - default: - _glPushHeaderOrVertex(v2); - counter = 0; + Vertex* v0 = vertices; + for(int i = 0; i < n - 2; ++i, v0++) { + if(is_header(v0)) { + _glPushHeaderOrVertex(v0); continue; - }; + } - Vertex* const v0 = v2 - 2; - Vertex* const v1 = v2 - 1; + Vertex* v1 = v0 + 1; + Vertex* v2 = v0 + 2; - visible_mask = ( + int visible_mask = ( (v0->xyz[2] >= -v0->w) << 0 | (v1->xyz[2] >= -v1->w) << 1 | - (v2->xyz[2] >= -v2->w) << 2 | - (counter == 0) << 3 + (v2->xyz[2] >= -v2->w) << 2 ); -#if CLIP_DEBUG - fprintf(stderr, "0x%x 0x%x 0x%x -> %d\n", v0, v1, v2, visible_mask); -#endif + /* If we've gone behind the plane, we finish the strip + otherwise we submit however it was */ + if(visible_mask == NONE_VISIBLE) { + SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL); + } else { + SUBMIT_QUEUED_VERTEX(qv.flags); + } + + #if CLIP_DEBUG + fprintf(stderr, "0x%x 0x%x 0x%x -> %d\n", v0, v1, v2, visible_mask); + #endif + + Vertex __attribute__((aligned(32))) scratch[4]; + Vertex* a = &scratch[0], *b = &scratch[1], *c = &scratch[2], *d = &scratch[3]; switch(visible_mask) { - case 15: /* All visible, but final vertex in strip */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); - - _glPerspectiveDivideVertex(v1, h); - _glPushHeaderOrVertex(v1); - - _glPerspectiveDivideVertex(v2, h); - _glPushHeaderOrVertex(v2); - } - break; - case 7: - SUBMIT_QUEUED_VERTEX(qv.flags); - /* All visible, push the first vertex and move on */ - _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); - break; - case 9: - /* First vertex was visible, last in strip */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[2]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - - _glClipEdge(v0, v1, a); - a->flags = GPU_CMD_VERTEX; - - _glClipEdge(v2, v0, b); - b->flags = GPU_CMD_VERTEX_EOL; - + case ALL_VISIBLE: _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); - - _glPerspectiveDivideVertex(a, h); - _glPushHeaderOrVertex(a); - - _glPerspectiveDivideVertex(b, h); - _glPushHeaderOrVertex(b); - } + QUEUE_VERTEX(v0); break; - case 1: - /* First vertex was visible, but not last in strip */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[2]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - + case NONE_VISIBLE: + break; + break; + case FIRST_VISIBLE: _glClipEdge(v0, v1, a); a->flags = GPU_CMD_VERTEX; @@ -309,20 +276,8 @@ void SceneListSubmit(Vertex* v2, int n) { _glPushHeaderOrVertex(b); QUEUE_VERTEX(b); - } break; - case 10: - case 2: - /* Second vertex was visible. In self case we need to create a triangle and produce - two new vertices: 1-2, and 2-3. */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[3]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - Vertex* c = &scratch[2]; - + case SECOND_VISIBLE: memcpy_vertex(c, v1); _glClipEdge(v0, v1, a); @@ -339,52 +294,8 @@ void SceneListSubmit(Vertex* v2, int n) { _glPerspectiveDivideVertex(b, h); QUEUE_VERTEX(b); - } break; - case 11: - case 3: /* First and second vertex were visible */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[3]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - Vertex* c = &scratch[2]; - - memcpy_vertex(c, v1); - - _glClipEdge(v2, v0, b); - b->flags = GPU_CMD_VERTEX; - - _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); - - _glClipEdge(v1, v2, a); - a->flags = v2->flags; - - _glPerspectiveDivideVertex(c, h); - _glPushHeaderOrVertex(c); - - _glPerspectiveDivideVertex(b, h); - _glPushHeaderOrVertex(b); - - _glPerspectiveDivideVertex(a, h); - _glPushHeaderOrVertex(c); - - QUEUE_VERTEX(a); - } - break; - case 12: - case 4: - /* Third vertex was visible. */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[3]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - Vertex* c = &scratch[2]; - + case THIRD_VISIBLE: memcpy_vertex(c, v2); _glClipEdge(v2, v0, a); @@ -394,123 +305,97 @@ void SceneListSubmit(Vertex* v2, int n) { b->flags = GPU_CMD_VERTEX; _glPerspectiveDivideVertex(a, h); + //_glPushHeaderOrVertex(a); _glPushHeaderOrVertex(a); - if(counter % 2 == 1) { - _glPushHeaderOrVertex(a); - } - _glPerspectiveDivideVertex(b, h); _glPushHeaderOrVertex(b); + _glPerspectiveDivideVertex(c, h); + QUEUE_VERTEX(c); + break; + case FIRST_AND_SECOND_VISIBLE: + memcpy_vertex(c, v1); + + _glClipEdge(v2, v0, b); + b->flags = GPU_CMD_VERTEX; + + _glPerspectiveDivideVertex(v0, h); + _glPushHeaderOrVertex(v0); + + _glClipEdge(v1, v2, a); + a->flags = v2->flags; + _glPerspectiveDivideVertex(c, h); _glPushHeaderOrVertex(c); - } + + _glPerspectiveDivideVertex(b, h); + _glPushHeaderOrVertex(b); + + _glPerspectiveDivideVertex(a, h); + _glPushHeaderOrVertex(c); + + QUEUE_VERTEX(a); break; - case 13: - { - SUBMIT_QUEUED_VERTEX(qv.flags); + case SECOND_AND_THIRD_VISIBLE: + memcpy_vertex(c, v1); + memcpy_vertex(d, v2); - Vertex __attribute__((aligned(32))) scratch[3]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - Vertex* c = &scratch[2]; + _glClipEdge(v0, v1, a); + a->flags = GPU_CMD_VERTEX; - memcpy_vertex(c, v2); - c->flags = GPU_CMD_VERTEX; + _glClipEdge(v2, v0, b); + b->flags = GPU_CMD_VERTEX; - _glClipEdge(v0, v1, a); - a->flags = GPU_CMD_VERTEX; + _glPerspectiveDivideVertex(a, h); + _glPushHeaderOrVertex(a); - _glClipEdge(v1, v2, b); - b->flags = GPU_CMD_VERTEX; + _glPerspectiveDivideVertex(c, h); + _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); + _glPerspectiveDivideVertex(b, h); + _glPushHeaderOrVertex(b); + _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(a, h); - _glPushHeaderOrVertex(a); - - _glPerspectiveDivideVertex(c, h); - _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); - _glPushHeaderOrVertex(b); - - c->flags = GPU_CMD_VERTEX_EOL; - _glPushHeaderOrVertex(c); - } - break; - case 5: /* First and third vertex were visible */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[3]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - Vertex* c = &scratch[2]; - - memcpy_vertex(c, v2); - c->flags = GPU_CMD_VERTEX; - - _glClipEdge(v0, v1, a); - a->flags = GPU_CMD_VERTEX; - - _glClipEdge(v1, v2, b); - b->flags = GPU_CMD_VERTEX; - - _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); - - _glPerspectiveDivideVertex(a, h); - _glPushHeaderOrVertex(a); - - _glPerspectiveDivideVertex(c, h); - _glPushHeaderOrVertex(c); - _glPerspectiveDivideVertex(b, h); - _glPushHeaderOrVertex(b); - QUEUE_VERTEX(c); - } - break; - case 14: - case 6: /* Second and third vertex were visible */ - { - SUBMIT_QUEUED_VERTEX(qv.flags); - - Vertex __attribute__((aligned(32))) scratch[4]; - Vertex* a = &scratch[0]; - Vertex* b = &scratch[1]; - Vertex* c = &scratch[2]; - Vertex* d = &scratch[3]; - - memcpy_vertex(c, v1); - memcpy_vertex(d, v2); - - _glClipEdge(v0, v1, a); - a->flags = GPU_CMD_VERTEX; - - _glClipEdge(v2, v0, b); - b->flags = GPU_CMD_VERTEX; - - _glPerspectiveDivideVertex(a, h); - _glPushHeaderOrVertex(a); - - _glPerspectiveDivideVertex(c, h); - _glPushHeaderOrVertex(c); - - _glPerspectiveDivideVertex(b, h); - _glPushHeaderOrVertex(b); - _glPushHeaderOrVertex(c); - - _glPerspectiveDivideVertex(d, h); - _glPushHeaderOrVertex(d); - } - break; - case 8: - default: - // Not visible, if there was a queued vertex, submit it with - // the EOL flag - SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL); + _glPerspectiveDivideVertex(d, h); + QUEUE_VERTEX(d); break; + case FIRST_AND_THIRD_VISIBLE: + memcpy_vertex(c, v2); + c->flags = GPU_CMD_VERTEX; + + _glClipEdge(v0, v1, a); + a->flags = GPU_CMD_VERTEX; + + _glClipEdge(v1, v2, b); + b->flags = GPU_CMD_VERTEX; + + _glPerspectiveDivideVertex(v0, h); + _glPushHeaderOrVertex(v0); + + _glPerspectiveDivideVertex(a, h); + _glPushHeaderOrVertex(a); + + _glPerspectiveDivideVertex(c, h); + _glPushHeaderOrVertex(c); + _glPerspectiveDivideVertex(b, h); + _glPushHeaderOrVertex(b); + QUEUE_VERTEX(c); + break; + default: + fprintf(stderr, "ERROR\n"); + } + + if(v2->flags == GPU_CMD_VERTEX_EOL && visible_mask == ALL_VISIBLE) { + SUBMIT_QUEUED_VERTEX(qv.flags); + + _glPerspectiveDivideVertex(v1, h); + _glPushHeaderOrVertex(v1); + + _glPerspectiveDivideVertex(v2, h); + _glPushHeaderOrVertex(v2); + + i += 2; } } From f8d1fa34399c25ea42068524aad2132fbc2e1496 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Wed, 3 Apr 2024 21:19:36 +0100 Subject: [PATCH 2/5] Fix some issues with clipping --- GL/platforms/sh4.c | 45 +++++++----- samples/zclip_trianglestrip/main.c | 112 ++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 52 deletions(-) diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index 2a356f6..8503136 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -4,7 +4,7 @@ #include "sh4.h" -#define CLIP_DEBUG 1 +#define CLIP_DEBUG 0 #define PVR_VERTEX_BUF_SIZE 2560 * 256 @@ -192,7 +192,7 @@ void SceneListSubmit(Vertex* vertices, int n) { #if CLIP_DEBUG fprintf(stderr, "----\n"); - + Vertex* vertex = (Vertex*) vertices; for(int i = 0; i < n; ++i) { fprintf(stderr, "IN: {%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]); @@ -230,6 +230,27 @@ void SceneListSubmit(Vertex* vertices, int n) { Vertex* v1 = v0 + 1; Vertex* v2 = v0 + 2; + assert(!is_header(v1)); + + if(is_header(v2)) { + // OK so we've hit a new context header + // we need to finalize this strip and move on + SUBMIT_QUEUED_VERTEX(qv.flags); + + _glPerspectiveDivideVertex(v0, h); + _glPushHeaderOrVertex(v0); + + _glPerspectiveDivideVertex(v1, h); + _glPushHeaderOrVertex(v1); + i += 2; + continue; + } + + assert(!is_header(v2)); + + // FIXME: What if v1 or v2 are headers? Should we handle that or just + // assume the user has done something weird and all bets are off? + int visible_mask = ( (v0->xyz[2] >= -v0->w) << 0 | (v1->xyz[2] >= -v1->w) << 1 | @@ -244,9 +265,9 @@ void SceneListSubmit(Vertex* vertices, int n) { SUBMIT_QUEUED_VERTEX(qv.flags); } - #if CLIP_DEBUG - fprintf(stderr, "0x%x 0x%x 0x%x -> %d\n", v0, v1, v2, visible_mask); - #endif +#if CLIP_DEBUG + fprintf(stderr, "0x%x 0x%x 0x%x -> %d\n", v0, v1, v2, visible_mask); +#endif Vertex __attribute__((aligned(32))) scratch[4]; Vertex* a = &scratch[0], *b = &scratch[1], *c = &scratch[2], *d = &scratch[3]; @@ -277,7 +298,7 @@ void SceneListSubmit(Vertex* vertices, int n) { QUEUE_VERTEX(b); break; - case SECOND_VISIBLE: + case SECOND_VISIBLE: memcpy_vertex(c, v1); _glClipEdge(v0, v1, a); @@ -385,18 +406,6 @@ void SceneListSubmit(Vertex* vertices, int n) { default: fprintf(stderr, "ERROR\n"); } - - if(v2->flags == GPU_CMD_VERTEX_EOL && visible_mask == ALL_VISIBLE) { - SUBMIT_QUEUED_VERTEX(qv.flags); - - _glPerspectiveDivideVertex(v1, h); - _glPushHeaderOrVertex(v1); - - _glPerspectiveDivideVertex(v2, h); - _glPushHeaderOrVertex(v2); - - i += 2; - } } SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL); diff --git a/samples/zclip_trianglestrip/main.c b/samples/zclip_trianglestrip/main.c index 7d4b698..4960c1c 100644 --- a/samples/zclip_trianglestrip/main.c +++ b/samples/zclip_trianglestrip/main.c @@ -20,7 +20,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG glEnable(GL_DEPTH_TEST); // Enables Depth Testing glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading glEnable(GL_TEXTURE_2D); - glEnable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Reset The Projection Matrix @@ -64,30 +64,38 @@ int check_start() { return 0; } +static GLfloat movement = 0.0f; +static GLfloat rotation = 0.0f; + +void update_movement() { +#ifdef __DREAMCAST__ + maple_device_t *cont; + cont_state_t *state; + + cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER); + + if(cont) { + state = (cont_state_t *)maple_dev_status(cont); + if(state) { + if(state->buttons & CONT_DPAD_UP) { + movement += 0.5f; + } else if(state->buttons & CONT_DPAD_DOWN) { + movement -= 0.5f; + } + + if(state->buttons & CONT_DPAD_LEFT) { + rotation += 0.5f; + } else if(state->buttons & CONT_DPAD_RIGHT) { + rotation -= 0.5f; + } + } + } +#endif +} + /* The main drawing function. */ void DrawGLScene() { - static GLfloat movement = 0.0f; - static GLfloat rotation = 0.0f; - static GLboolean increasing = GL_TRUE; - - if(movement > 10.0) { - increasing = GL_FALSE; - } else if(movement < -10.0f) { - increasing = GL_TRUE; - } - - if(increasing) { - movement += 0.05f; - } else { - movement -= 0.05f; - } - - rotation += 0.1f; - if(rotation > 360.0f) { - rotation -= 360.0f; - } - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glLoadIdentity(); // Reset The View @@ -95,24 +103,58 @@ void DrawGLScene() glTranslatef(0.0f, -1.0f, movement); glRotatef(rotation, 0.0f, 1.0, 0.0f); - glBegin(GL_TRIANGLE_STRIP); - glColor3f(1.0f, 1.0f, 0.0f); - glVertex3f(-2.5f, 0.0f, 5.0f); + /* We create a horseshoe shape tri-strip here because that allows for situations where a strip + leaves and re-enters the viewport */ - glColor3f(1.0f, 0.0f, 0.0f); - glVertex3f(2.5f, 0.0f, 5.0f); + glBegin(GL_TRIANGLE_STRIP); + // Left side + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-2.0f, 0.0f, 5.0f); + + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-1.0f, 0.0f, 5.0f); + + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-2.0f, 0.0f, 3.0f); + + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-1.0f, 0.0f, 3.0f); + + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-2.0f, 0.0f, 1.0f); + + glColor3f(1.0f, 1.0f, 0.0f); + glVertex3f(-1.0f, 0.0f, 1.0f); + + // Curve + glColor3f(0.0f, 1.0f, 0.0f); + glVertex3f(-1.0f, 0.0f, -1.0f); glColor3f(0.0f, 1.0f, 0.0f); - glVertex3f(-2.5f, 0.0f, -5.0f); + glVertex3f(1.0f, 0.0f, 1.0f); - glColor3f(0.0f, 0.0f, 1.0f); - glVertex3f(2.5f, 0.0f, -5.0f); + glColor3f(0.0f, 1.0f, 0.0f); + glVertex3f(1.0f, 0.0f, -1.0f); - glColor3f(0.0f, 1.0f, 1.0f); - glVertex3f(-2.5f, 0.0f, -10.0f); + // Right side + // Degenerate to reverse ordering + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(2.0f, 0.0f, 1.0f); - glColor3f(1.0f, 0.0f, 1.0f); - glVertex3f(2.5f, 0.0f, -10.0f); + glColor3f(0.0f, 1.0f, 0.0f); + glVertex3f(1.0f, 0.0f, 1.0f); + + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(1.0f, 0.0f, 3.0f); + + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(2.0f, 0.0f, 3.0f); + + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(1.0f, 0.0f, 5.0f); + + glColor3f(1.0f, 0.0f, 0.0f); + glVertex3f(2.0f, 0.0f, 5.0f); glEnd(); glPopMatrix(); @@ -131,6 +173,8 @@ int main(int argc, char **argv) if(check_start()) break; + update_movement(); + DrawGLScene(); } From 5299badf58fdc199d353e8f8070812df3e8b24ad Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Wed, 3 Apr 2024 22:09:35 +0100 Subject: [PATCH 3/5] Only submit trailing vertices if the previous triangle was visible --- GL/platforms/sh4.c | 24 ++++++++++++------------ samples/zclip_trianglestrip/main.c | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index 8503136..53227e4 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -216,7 +216,7 @@ void SceneListSubmit(Vertex* vertices, int n) { #define SUBMIT_QUEUED_VERTEX(sflags) \ do { if(queued_vertex) { queued_vertex->flags = (sflags); _glPushHeaderOrVertex(queued_vertex); queued_vertex = NULL; } } while(0) - uint8_t visible_mask = 0; + int visible_mask = 0; sq = SQ_BASE_ADDRESS; @@ -237,21 +237,21 @@ void SceneListSubmit(Vertex* vertices, int n) { // we need to finalize this strip and move on SUBMIT_QUEUED_VERTEX(qv.flags); - _glPerspectiveDivideVertex(v0, h); - _glPushHeaderOrVertex(v0); + // If the last triangle was all visible, we need + // to submit the last two vertices, any clipped triangles + // would've + if(visible_mask == ALL_VISIBLE) { + _glPerspectiveDivideVertex(v0, h); + _glPushHeaderOrVertex(v0); - _glPerspectiveDivideVertex(v1, h); - _glPushHeaderOrVertex(v1); - i += 2; + _glPerspectiveDivideVertex(v1, h); + _glPushHeaderOrVertex(v1); + i += 2; + } continue; } - assert(!is_header(v2)); - - // FIXME: What if v1 or v2 are headers? Should we handle that or just - // assume the user has done something weird and all bets are off? - - int visible_mask = ( + visible_mask = ( (v0->xyz[2] >= -v0->w) << 0 | (v1->xyz[2] >= -v1->w) << 1 | (v2->xyz[2] >= -v2->w) << 2 diff --git a/samples/zclip_trianglestrip/main.c b/samples/zclip_trianglestrip/main.c index 4960c1c..064add8 100644 --- a/samples/zclip_trianglestrip/main.c +++ b/samples/zclip_trianglestrip/main.c @@ -64,7 +64,7 @@ int check_start() { return 0; } -static GLfloat movement = 0.0f; +static GLfloat movement = -10.0f; static GLfloat rotation = 0.0f; void update_movement() { From 77f4b59aeaec744f61ba13ff78c4eeebaea201f6 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Wed, 3 Apr 2024 22:30:41 +0100 Subject: [PATCH 4/5] Fix off-by-one --- GL/platforms/sh4.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index 53227e4..ae19d8e 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -221,9 +221,10 @@ void SceneListSubmit(Vertex* vertices, int n) { sq = SQ_BASE_ADDRESS; Vertex* v0 = vertices; - for(int i = 0; i < n - 2; ++i, v0++) { + for(int i = 0; i < n - 2; ++i, ++v0) { if(is_header(v0)) { _glPushHeaderOrVertex(v0); + visible_mask = 0; continue; } @@ -235,19 +236,29 @@ void SceneListSubmit(Vertex* vertices, int n) { if(is_header(v2)) { // OK so we've hit a new context header // we need to finalize this strip and move on - SUBMIT_QUEUED_VERTEX(qv.flags); // If the last triangle was all visible, we need // to submit the last two vertices, any clipped triangles // would've if(visible_mask == ALL_VISIBLE) { + SUBMIT_QUEUED_VERTEX(qv.flags); + _glPerspectiveDivideVertex(v0, h); _glPushHeaderOrVertex(v0); + v1->flags = GPU_CMD_VERTEX_EOL; + _glPerspectiveDivideVertex(v1, h); _glPushHeaderOrVertex(v1); - i += 2; + } else { + // If the previous triangle wasn't all visible, and we + // queued a vertex - we force it to be EOL and submit + SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL); } + + i++; + v0++; + visible_mask = 0; continue; } From 6a6d229e4c9caa4696a83afe4b8d8d0627b5cc05 Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Thu, 4 Apr 2024 06:30:37 +0100 Subject: [PATCH 5/5] Fix bug with multiple strips --- GL/platforms/sh4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GL/platforms/sh4.c b/GL/platforms/sh4.c index ae19d8e..bfa8415 100644 --- a/GL/platforms/sh4.c +++ b/GL/platforms/sh4.c @@ -233,7 +233,9 @@ void SceneListSubmit(Vertex* vertices, int n) { assert(!is_header(v1)); - if(is_header(v2)) { + bool is_trailing = (v1->flags == GPU_CMD_VERTEX_EOL) || is_header(v2); + + if(is_trailing) { // OK so we've hit a new context header // we need to finalize this strip and move on