1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-23 20:59:58 +01:00

Add z-buffer

This commit is contained in:
Miloslav Číž 2019-05-22 17:32:34 +02:00
parent c11cc70238
commit 4c4ced2d77
2 changed files with 60 additions and 99 deletions

92
s3l.h
View file

@ -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

View file

@ -7,6 +7,8 @@
#include <stdio.h>
#include <math.h>
#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()