diff --git a/s3l.h b/s3l.h index 171b9f4..9cbffed 100644 --- a/s3l.h +++ b/s3l.h @@ -1570,32 +1570,6 @@ void S3L_drawTriangle( S3L_Index modelID, S3L_Index triangleID) { - #define clipTest(c,cmp,v)\ - (point0.c cmp (v) && point1.c cmp (v) && point2.c cmp (v)) - - if ( // early clipping -- test if completely outside frustum - - clipTest(z,<=,S3L_NEAR) || - clipTest(x,<,-1 * S3L_FRACTIONS_PER_UNIT) || - clipTest(x,>,S3L_FRACTIONS_PER_UNIT) || - clipTest(y,<,-1 * S3L_PROJECTION_PLANE_HEIGHT / 2) || - clipTest(y,>,S3L_PROJECTION_PLANE_HEIGHT / 2) - ) - return; // completely behind the camera - - if (config->backfaceCulling != S3L_BACKFACE_CULLING_NONE) - { - int32_t winding = // determines CW or CCW - ( - (point1.y - point0.y) * (point2.x - point1.x) - - (point1.x - point0.x) * (point2.y - point1.y) - ); - - if ((config->backfaceCulling == S3L_BACKFACE_CULLING_CW && winding < 0) || - (config->backfaceCulling == S3L_BACKFACE_CULLING_CCW && winding >= 0)) - return; - } - S3L_PixelInfo p; S3L_initPixelInfo(&p); p.modelID = modelID; @@ -1754,6 +1728,45 @@ static inline void S3L_perspectiveDivide(S3L_Vec4 *vector, vector->y = (vector->y * focalLength) / divisor; } +/** + Checks if given triangle (in Projection Plane space) is at least partially + visible, i.e. returns false if the triangle is either completely outside + the frustum (left, right, top, bottom, near) or is invisible due to + backface culling. +*/ +static inline int8_t S3L_triangleIsVisible( + S3L_Vec4 p0, + S3L_Vec4 p1, + S3L_Vec4 p2, + uint8_t backfaceCulling) +{ + #define clipTest(c,cmp,v)\ + (p0.c cmp (v) && p1.c cmp (v) && p2.c cmp (v)) + + if ( // completely outside frustum? + clipTest(z,<=,S3L_NEAR) || + clipTest(x,<,-1 * S3L_FRACTIONS_PER_UNIT) || + clipTest(x,>,S3L_FRACTIONS_PER_UNIT) || + clipTest(y,<,-1 * S3L_PROJECTION_PLANE_HEIGHT / 2) || + clipTest(y,>,S3L_PROJECTION_PLANE_HEIGHT / 2) + ) + return 0; + + #undef clipTest + + if (backfaceCulling != S3L_BACKFACE_CULLING_NONE) + { + int32_t winding = // determines CW or CCW + (p1.y - p0.y) * (p2.x - p1.x) - (p1.x - p0.x) * (p2.y - p1.y); + + if ((backfaceCulling == S3L_BACKFACE_CULLING_CW && winding < 0) || + (backfaceCulling == S3L_BACKFACE_CULLING_CCW && winding >= 0)) + return 0; + } + + return 1; +} + void S3L_drawScene(S3L_Scene scene) { for (S3L_Index modelIndex; modelIndex < scene.modelCount; ++modelIndex) @@ -1804,9 +1817,14 @@ void S3L_drawScene(S3L_Scene scene) #undef project - S3L_drawTriangle(transformed0,transformed1,transformed2, - &(scene.models[modelIndex].config),&(scene.camera),modelIndex, - triangleIndex); + S3L_DrawConfig *config = &(scene.models[modelIndex].config); + + if (S3L_triangleIsVisible(transformed0,transformed1,transformed2, + config->backfaceCulling)) + { + S3L_drawTriangle(transformed0,transformed1,transformed2,config, + &(scene.camera),modelIndex,triangleIndex); + } ++triangleIndex; } diff --git a/testSDL.c b/testSDL.c index 00fd4ac..13142d0 100644 --- a/testSDL.c +++ b/testSDL.c @@ -7,7 +7,7 @@ #include #include -#define S3L_Z_BUFFER S3L_Z_BUFFER_BYTE +#define S3L_Z_BUFFER S3L_Z_BUFFER_FULL #define S3L_PIXEL_FUNCTION drawPixel @@ -122,13 +122,13 @@ void drawPixel(S3L_PixelInfo *p) uint8_t col = texturePixel(u,v); -// setPixel(p->x,p->y,col * 120,20,(2 - col) * 120); + setPixel(p->x,p->y,col * 120,20,(2 - col) * 120); uint8_t sss = (p->depth / 5000.0) * 255 ; //setPixel(p->x,p->y,sss,sss,sss); -setPixel(p->x,p->y,p->modelID * 64,p->modelID * 128,255); +//setPixel(p->x,p->y,p->modelID * 64,p->modelID * 128,255); // setPixel(p->x,p->y,p->barycentric0 / ((float) S3L_FRACTIONS_PER_UNIT) * 255,p->barycentric1 / ((float) S3L_FRACTIONS_PER_UNIT) * 255,p->barycentric2 / ((float) S3L_FRACTIONS_PER_UNIT) * 255); }