From 4c4ced2d777190cb34a3b108bb7ae0235056e9e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Wed, 22 May 2019 17:32:34 +0200 Subject: [PATCH] Add z-buffer --- s3l.h | 92 ++++++++++++++++++++++++++++++++++--------------------- testSDL.c | 67 ++-------------------------------------- 2 files changed, 60 insertions(+), 99 deletions(-) diff --git a/s3l.h b/s3l.h index 1adcde5..1e65243 100644 --- a/s3l.h +++ b/s3l.h @@ -125,31 +125,6 @@ on. */ #endif -#ifndef S3L_RENDER_STRATEGY -#define S3L_RENDER_STRATEGY S3L_STRATEGY_Z_BUFFER /**< Strategy used for - visibility - determination -- see - S3L_STRATEGY_* - consts. */ -#endif - -#define S3L_STRATEGY_NONE 0 /**< No strategy -- can be sufficient in - some cases. */ -#define S3L_STRATEGY_Z_BUFFER 1 /**< Use z-buffer (depth buffer). - Accurate and fast, but requires a lot - of memory. */ -#define S3L_STRATEGY_BACK_TO_FRONT 2 /**< Sort and draw triangles from back to - front (painter's algorithm). Requires - less memory, but can be slower than - Z-buffer and can't handle - intersecting triangles. */ -#define S3L_STRATEGY_FRONT_TO_BACK 3 /**< Sort and draw triangles from front to - back (reverse painter's algorithm). - Requires a bit more memory than back - to front, but can also be faster - (doesn't draw over already drawn - pixels). */ - #ifndef S3L_MAX_TRIANGES_DRAWN #define S3L_MAX_TRIANGES_DRAWN 128 /**< Maximum number of triangles that can be drawn in sorted modes. This @@ -188,6 +163,20 @@ typedef int32_t S3L_Unit; /**< Units of measurement in 3D space. There is typedef int16_t S3L_ScreenCoord; typedef uint16_t S3L_Index; +#ifndef S3L_USE_Z_BUFFER +#define S3L_USE_Z_BUFFER 1 /**< Whether to use z-buffer (depth buffer) for + visibility determination. This is accurate + and can be fast, but requires a lot of + memory. */ +#endif + +#define S3L_MAX_DEPTH 2147483647 + +#if S3L_USE_Z_BUFFER +#define S3L_COMPUTE_DEPTH 1 +S3L_Unit S3L_zBuffer[S3L_RESOLUTION_X * S3L_RESOLUTION_Y]; +#endif + #ifndef S3L_NEAR #define S3L_NEAR (S3L_FRACTIONS_PER_UNIT / 4) /**< Distance of the near clipping plane. */ @@ -492,6 +481,8 @@ void S3L_drawTriangle( const S3L_Camera *camera, S3L_Index triangleID); +void S3L_zBufferClear(); + static inline void S3L_rotate2DPoint(S3L_Unit *x, S3L_Unit *y, S3L_Unit angle); //============================================================================= @@ -1149,6 +1140,30 @@ void S3L_mapProjectionPlaneToScreen( (point.y * S3L_HALF_RESOLUTION_X) / S3L_FRACTIONS_PER_UNIT; } +static inline int8_t S3L_zTest( + S3L_ScreenCoord x, + S3L_ScreenCoord y, + S3L_Unit depth) +{ + uint32_t index = y * S3L_RESOLUTION_X + x; + + if (depth < S3L_zBuffer[index]) + { + S3L_zBuffer[index] = depth; + return 1; + } + + return 0; +} + +void S3L_zBufferClear() +{ +#if S3L_USE_Z_BUFFER + for (uint32_t i = 0; i < S3L_RESOLUTION_X * S3L_RESOLUTION_Y; ++i) + S3L_zBuffer[i] = S3L_MAX_DEPTH; +#endif +} + void _S3L_drawFilledTriangle( S3L_Vec4 point0, S3L_Vec4 point1, @@ -1464,37 +1479,44 @@ void _S3L_drawFilledTriangle( for (S3L_ScreenCoord x = lXClipped; x < rXClipped; ++x) { + p->x = x; #if S3L_PERSPECTIVE_CORRECTION == 1 S3L_Unit rowT = S3L_correctPerspective(S3L_interpolateFrom0(S3L_FRACTIONS_PER_UNIT, x - lX,rowLength),&rowPC); +#endif +#if S3L_COMPUTE_DEPTH + #if S3L_PERSPECTIVE_CORRECTION == 1 + p->depth = S3L_interpolateByUnit(lDepth,rDepth,rowT); + #else + p->depth = S3L_getFastLerpValue(depthFLS); + S3L_stepFastLerp(depthFLS); + #endif +#endif + +#if S3L_USE_Z_BUFFER + if (!S3L_zTest(p->x,p->y,p->depth)) + continue; +#endif + +#if S3L_PERSPECTIVE_CORRECTION == 1 *barycentric0 = S3L_interpolateByUnitFrom0(rT,rowT); *barycentric1 = S3L_interpolateByUnitFrom0(lT,S3L_FRACTIONS_PER_UNIT - rowT); - - #if S3L_COMPUTE_DEPTH - p->depth = S3L_interpolateByUnit(lDepth,rDepth,rowT); - #endif #else *barycentric0 = S3L_getFastLerpValue(b0FLS); *barycentric1 = S3L_getFastLerpValue(b1FLS); S3L_stepFastLerp(b0FLS); S3L_stepFastLerp(b1FLS); - - #if S3L_COMPUTE_LERP_DEPTH - p->depth = S3L_getFastLerpValue(depthFLS); - S3L_stepFastLerp(depthFLS); - #endif #endif *barycentric2 = S3L_FRACTIONS_PER_UNIT - *barycentric0 - *barycentric1; - p->x = x; S3L_PIXEL_FUNCTION(p); } } // y clipping diff --git a/testSDL.c b/testSDL.c index a1722cd..f64d04d 100644 --- a/testSDL.c +++ b/testSDL.c @@ -7,6 +7,8 @@ #include #include +#define S3L_USE_Z_BUFFER 1 + #define S3L_PIXEL_FUNCTION drawPixel #define S3L_RESOLUTION_X 640 @@ -134,17 +136,7 @@ S3L_DrawConfig conf; void draw() { -/* - if (frame % 128 == 0) - { - printf("frame: %d\n",frame); - printf("scene.camera:\n"); - printf(" translation: "); - S3L_writeVec4(scene.camera.transform.translation); - printf(" rotation: "); - S3L_writeVec4(scene.camera.transform.rotation); - } -*/ + S3L_zBufferClear(); offScreenPixels = 0; @@ -155,63 +147,10 @@ void draw() scene.models[0].transform.rotation.z = f * 0.1; scene.models[0].transform.rotation.x = f * 0.3; -// modelTransform.translation.x = sin(f >> 7) * 700; -// modelTransform.translation.y = sin(f >> 8) * 600; - -/* - S3L_drawModelIndexed(ver,tri,12,modelTransform,&scene.camera,&conf); - - modelTransform.translation.x += 2 * S3L_FRACTIONS_PER_UNIT; - S3L_drawModelIndexed(ver,tri,12,modelTransform,&scene.camera,&conf); - modelTransform.translation.x -= 2 * S3L_FRACTIONS_PER_UNIT; -*/ - S3L_drawScene(scene); if (offScreenPixels > 0) printf("offscreen pixels: %d\n",offScreenPixels); - -// S3L_drawModelIndexed(ver,tri,1,modelTransform,&scene.camera,&conf); - -/* -conf.backfaceCulling = S3L_BACKFACE_CULLING_NONE; -conf.mode = S3L_MODE_TRIANGLES; - - for (int c = 0; c < 8; ++c) - { - int - x0 = test_coords[6 * c], - y0 = test_coords[6 * c + 1], - x1 = test_coords[6 * c + 2], - y1 = test_coords[6 * c + 3], - x2 = test_coords[6 * c + 4], - y2 = test_coords[6 * c + 5]; - -int cent = (x0 + x1 + x2) / 3.0; -x2 = cent + (x2 - cent) * sin(frame * 0.001) * 2; -//x2 = cent + (x2 - cent) * sin(600 * 0.001) * 2; - - S3L_drawTriangle(x0,y0,x1,y1,x2,y2,conf,0); - - setPixel(x0,y0,255,0,0); - setPixel(x1,y1,255,0,0); - setPixel(x2,y2,255,0,0); - - } - -float rotRate = 0.002; - -int16_t rotX0 = 200 + sin(frame * rotRate) * 100; -int16_t rotY0 = 200 + cos(frame * rotRate) * 100; - -int16_t rotX1 = 200 + sin((frame + 1500) * rotRate) * 100; -int16_t rotY1 = 200 + cos((frame + 1500) * rotRate) * 100; - -int16_t rotX2 = 200 + sin((frame + 500) * rotRate) * 100; -int16_t rotY2 = 200 + cos((frame + 500) * rotRate) * 100; - -S3L_drawTriangle(rotX0,rotY0,rotX1,rotY1,rotX2,rotY2,conf,0); - */ } int main()