Compare commits

...

3 Commits

Author SHA1 Message Date
Luke Benstead
0f86adaf71 Start a better clipping algorithm for a triangle 2020-03-30 19:37:23 +01:00
Luke Benstead
0e26d8656d Fix rounding issues in _glClipLineToNearZ 2020-03-28 16:46:43 +00:00
Luke Benstead
9c47f3c3bb Start investigating and tweaking 2020-03-27 16:34:04 +00:00
4 changed files with 57 additions and 22 deletions

View File

@ -23,21 +23,30 @@ void _glEnableClipping(unsigned char v) {
ZCLIP_ENABLED = v;
}
void inline _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t) {
inline float _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout) {
const float d0 = v1->w + v1->xyz[2];
const float d1 = v2->w + v2->xyz[2];
*t = d0 / (d0 - d1);
/* We need to shift 't' a little, to avoid the possibility that a
* rounding error leaves the new vertex behind the near plane. We shift
* according to the direction we're clipping across the plane */
const float epsilon = (d0 < d1) ? -0.000001 : 0.000001;
const float vec [] = {
v2->xyz[0] - v1->xyz[0],
v2->xyz[1] - v1->xyz[1],
v2->xyz[2] - v1->xyz[2]
};
float t = MATH_Fast_Divide(d0, (d0 - d1)) + epsilon;
vout->xyz[0] = MATH_fmac(vec[0], (*t), v1->xyz[0]);
vout->xyz[1] = MATH_fmac(vec[1], (*t), v1->xyz[1]);
vout->xyz[2] = MATH_fmac(vec[2], (*t), v1->xyz[2]);
vout->xyz[0] = MATH_fmac(v2->xyz[0] - v1->xyz[0], t, v1->xyz[0]);
vout->xyz[1] = MATH_fmac(v2->xyz[1] - v1->xyz[1], t, v1->xyz[1]);
vout->xyz[2] = MATH_fmac(v2->xyz[2] - v1->xyz[2], t, v1->xyz[2]);
/*
printf(
"(%f, %f, %f, %f) -> %f -> (%f, %f, %f, %f) = (%f, %f, %f)\n",
v1->xyz[0], v1->xyz[1], v1->xyz[2], v1->w, t,
v2->xyz[0], v2->xyz[1], v2->xyz[2], v2->w,
vout->xyz[0], vout->xyz[1], vout->xyz[2]
);*/
return t;
}
GL_FORCE_INLINE void interpolateFloat(const float v1, const float v2, const float t, float* out) {
@ -78,7 +87,6 @@ typedef struct {
uint8_t visible;
} Triangle;
void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) __attribute__((optimize("fast-math")));
void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) {
uint8_t i, c = 0;
@ -94,6 +102,27 @@ void _glClipTriangle(const Triangle* triangle, const uint8_t visible, Submission
/* Used when flat shading is enabled */
uint32_t finalColour = *((uint32_t*) bgra);
for(i = 1; i <= 3; ++i) {
uint8_t thisIndex = (i == 3) ? 0 : i;
uint8_t lastIndex = i - 1;
uint8_t thisVisible = (visible & (1 << (2 - thisIndex))) > 0;
uint8_t lastVisible = (visible & (1 << (2 - lastIndex))) > 0;
if(thisVisible != lastVisible) {
/* We crossed a plane */
} else if(thisVisible) {
/* Our existing vertex is fine */
last = aligned_vector_push_back(&target->output->vector, &vertices[thisIndex], 1);
last->flags = VERTEX_CMD;
veLast = aligned_vector_push_back(target->extras, &extras[thisIndex], 1);
}
}
for(i = 0; i < 4; ++i) {
uint8_t thisIndex = (i == 3) ? 0 : i;
@ -106,16 +135,15 @@ void _glClipTriangle(const Triangle* triangle, const uint8_t visible, Submission
if(i > 0) {
uint8_t lastIndex = (i == 3) ? 2 : thisIndex - 1;
if(lastVisible < 255 && lastVisible != thisVisible) {
if(lastVisible != thisVisible) {
const Vertex* v1 = &vertices[lastIndex];
const Vertex* v2 = &vertices[thisIndex];
const VertexExtra* ve1 = &extras[lastIndex];
const VertexExtra* ve2 = &extras[thisIndex];
float t;
float t = _glClipLineToNearZ(v1, v2, &next);
_glClipLineToNearZ(v1, v2, &next, &t);
interpolateFloat(v1->w, v2->w, t, &next.w);
interpolateVec2(v1->uv, v2->uv, t, next.uv);
@ -260,6 +288,8 @@ void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade) {
((v3->w > 0 && v3->xyz[2] >= -v3->w) ? 1 : 0)
);
printf("Visible: %d\n", visible);
switch(visible) {
case B111:
/* All visible? Do nothing */

View File

@ -1219,7 +1219,7 @@ GL_FORCE_INLINE void push(PVRHeader* header, GLboolean multiTextureHeader, PolyL
*/
}
#define DEBUG_CLIPPING 0
#define DEBUG_CLIPPING 1
GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type, const GLvoid* indices) {
TRACE();
@ -1321,10 +1321,10 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL
uint32_t i = 0;
fprintf(stderr, "=========\n");
for(i = offset; i < activeList->vector.size; ++i) {
ClipVertex* v = aligned_vector_at(&activeList->vector, i);
for(i = 0; i < target->count; ++i) {
Vertex* v = aligned_vector_at(&target->output->vector, target->start_offset + i);
if(v->flags == 0xe0000000 || v->flags == 0xf0000000) {
fprintf(stderr, "(%f, %f, %f) -> %x\n", v->xyz[0], v->xyz[1], v->xyz[2], v->flags);
fprintf(stderr, "(%f, %f, %f, %f) -> %x\n", v->xyz[0], v->xyz[1], v->xyz[2], v->w, v->flags);
} else {
fprintf(stderr, "%x\n", *((uint32_t*)v));
}
@ -1337,10 +1337,10 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL
#if DEBUG_CLIPPING
fprintf(stderr, "--------\n");
for(i = offset; i < activeList->vector.size; ++i) {
ClipVertex* v = aligned_vector_at(&activeList->vector, i);
for(i = 0; i < target->count; ++i) {
Vertex* v = aligned_vector_at(&target->output->vector, target->start_offset + i);
if(v->flags == 0xe0000000 || v->flags == 0xf0000000) {
fprintf(stderr, "(%f, %f, %f) -> %x\n", v->xyz[0], v->xyz[1], v->xyz[2], v->flags);
fprintf(stderr, "(%f, %f, %f, %f) -> %x\n", v->xyz[0], v->xyz[1], v->xyz[2], v->w, v->flags);
} else {
fprintf(stderr, "%x\n", *((uint32_t*)v));
}

View File

@ -239,7 +239,7 @@ typedef enum {
struct SubmissionTarget;
void _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t);
float _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout);
void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade);
PolyList *_glActivePolyList();

View File

@ -44,6 +44,7 @@ void ReSizeGLScene(int Width, int Height)
/* The main drawing function. */
void DrawGLScene()
{
static GLfloat rotation = 0.0f;
static GLfloat movement = 0.0f;
static GLboolean increasing = GL_TRUE;
@ -59,6 +60,9 @@ void DrawGLScene()
movement -= 0.05f;
}
rotation += 0.5f;
rotation = (rotation > 360.0f) ? rotation - 360.0f : rotation;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
@ -66,6 +70,7 @@ void DrawGLScene()
glPushMatrix();
glTranslatef(0.0f, -1.0f, movement);
glRotatef(rotation, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);