mirror of
https://git.coom.tech/drummyfish/small3dlib.git
synced 2024-12-02 22:29:57 +01:00
Add ortho projection
This commit is contained in:
parent
63a241a0a5
commit
6a2cfb5ce6
3 changed files with 28 additions and 38 deletions
|
@ -55,6 +55,7 @@ PC (SDL, offline rendering, terminal):
|
|||
- **Extremely portable** due to no dependencies, no float, no build systems, low HW requirements, endian independence etc.
|
||||
- **Many compile-time options** to tune the performance vs quality.
|
||||
- **Similar to OpenGL** in principle, but simpler, easier to use, with higher-level features.
|
||||
- **Perspective and orthographic** projections.
|
||||
- **Tools** (Python scripts) for converting 3D models and textures to C array format used by the library.
|
||||
- **Well commented** and formatted code. Automatic documentation (comments + provided Doxyfile).
|
||||
- Completely **free of legal restrictions**, public domain, do literally anything you want.
|
||||
|
|
1
TODO.txt
1
TODO.txt
|
@ -1,4 +1,3 @@
|
|||
- orthographics projection - did I forget this lol?
|
||||
- Add option to compute sin with Bhaskaras approx instead of using a LUT.
|
||||
- camera's focallength attribute could really rather be stored in
|
||||
transformation.scale.z, while scale.x and scale.y could be used for
|
||||
|
|
64
small3dlib.h
64
small3dlib.h
|
@ -10,7 +10,7 @@
|
|||
license: CC0 1.0 (public domain)
|
||||
found at https://creativecommons.org/publicdomain/zero/1.0/
|
||||
+ additional waiver of all IP
|
||||
version: 0.904d
|
||||
version: 0.905d
|
||||
|
||||
Before including the library, define S3L_PIXEL_FUNCTION to the name of the
|
||||
function you'll be using to draw single pixels (this function will be called
|
||||
|
@ -166,7 +166,6 @@
|
|||
many rendering bugs and imprecisions happening due to overflows, but this will
|
||||
also consumer more RAM and may potentially be slower on computers with smaller
|
||||
native integer. */
|
||||
|
||||
#define S3L_USE_WIDER_TYPES 0
|
||||
#endif
|
||||
|
||||
|
@ -233,7 +232,6 @@ typedef
|
|||
3: Perform both geometrical and barycentric correction of triangle crossing
|
||||
the near plane. This is significantly more expensive but results in
|
||||
correct rendering. */
|
||||
|
||||
#define S3L_NEAR_CROSS_STRATEGY 0
|
||||
#endif
|
||||
|
||||
|
@ -243,8 +241,7 @@ typedef
|
|||
for the whole triangle. This can be used to create flat-shaded renders and
|
||||
will be a lot faster. With this option on you will probably want to use
|
||||
sorting instead of z-buffer. */
|
||||
|
||||
#define S3L_FLAT 0
|
||||
#define S3L_FLAT 0
|
||||
#endif
|
||||
|
||||
#if S3L_FLAT
|
||||
|
@ -262,7 +259,6 @@ typedef
|
|||
2: Approximation (computing only at every S3L_PC_APPROX_LENGTHth pixel).
|
||||
Quake-style approximation is used, which only computes the PC after
|
||||
S3L_PC_APPROX_LENGTH pixels. This is reasonably accurate and fast. */
|
||||
|
||||
#define S3L_PERSPECTIVE_CORRECTION 0
|
||||
#endif
|
||||
|
||||
|
@ -270,7 +266,6 @@ typedef
|
|||
/** For S3L_PERSPECTIVE_CORRECTION == 2, this specifies after how many pixels
|
||||
PC is recomputed. Should be a power of two to keep up the performance.
|
||||
Smaller is nicer but slower. */
|
||||
|
||||
#define S3L_PC_APPROX_LENGTH 32
|
||||
#endif
|
||||
|
||||
|
@ -300,13 +295,11 @@ typedef
|
|||
2: Use reduced-size z-buffer (of bytes). This is fast and somewhat accurate,
|
||||
but inaccuracies can occur and a considerable amount of memory is
|
||||
needed. */
|
||||
|
||||
#define S3L_Z_BUFFER 0
|
||||
#endif
|
||||
|
||||
#ifndef S3L_REDUCED_Z_BUFFER_GRANULARITY
|
||||
/** For S3L_Z_BUFFER == 2 this sets the reduced z-buffer granularity. */
|
||||
|
||||
#define S3L_REDUCED_Z_BUFFER_GRANULARITY 5
|
||||
#endif
|
||||
|
||||
|
@ -314,7 +307,6 @@ typedef
|
|||
/** Whether to use stencil buffer for drawing -- with this a pixel that would
|
||||
be resterized over an already rasterized pixel (within a frame) will be
|
||||
discarded. This is mostly for front-to-back sorted drawing. */
|
||||
|
||||
#define S3L_STENCIL_BUFFER 0
|
||||
#endif
|
||||
|
||||
|
@ -336,21 +328,18 @@ typedef
|
|||
because we prevent computing pixels that will be overwritten by nearer
|
||||
ones, but we need a 1b stencil buffer for this (enable S3L_STENCIL_BUFFER),
|
||||
so a bit more memory is needed. */
|
||||
|
||||
#define S3L_SORT 0
|
||||
#endif
|
||||
|
||||
#ifndef S3L_MAX_TRIANGES_DRAWN
|
||||
/** Maximum number of triangles that can be drawn in sorted modes. This
|
||||
affects the size of the cache used for triangle sorting. */
|
||||
|
||||
#define S3L_MAX_TRIANGES_DRAWN 128
|
||||
#endif
|
||||
|
||||
#ifndef S3L_NEAR
|
||||
/** Distance of the near clipping plane. Points in front or EXATLY ON this
|
||||
plane are considered outside the frustum. This must be >= 0. */
|
||||
|
||||
#define S3L_NEAR (S3L_F / 4)
|
||||
#endif
|
||||
|
||||
|
@ -361,7 +350,6 @@ typedef
|
|||
#ifndef S3L_NORMAL_COMPUTE_MAXIMUM_AVERAGE
|
||||
/** Affects the S3L_computeModelNormals function. See its description for
|
||||
details. */
|
||||
|
||||
#define S3L_NORMAL_COMPUTE_MAXIMUM_AVERAGE 6
|
||||
#endif
|
||||
|
||||
|
@ -371,7 +359,6 @@ typedef
|
|||
higher values can fix this -- in theory all higher values will have the same
|
||||
speed (it is a shift value), but it mustn't be too high to prevent
|
||||
overflow. */
|
||||
|
||||
#define S3L_FAST_LERP_QUALITY 11
|
||||
#endif
|
||||
|
||||
|
@ -524,7 +511,9 @@ void S3L_mat4Xmat4(S3L_Mat4 m1, S3L_Mat4 m2);
|
|||
|
||||
typedef struct
|
||||
{
|
||||
S3L_Unit focalLength; ///< Defines the field of view (FOV).
|
||||
S3L_Unit focalLength; /**< Defines the field of view (FOV). 0 sets an
|
||||
orthographics projection (scale is controlled
|
||||
with camera's scale in its transform). */
|
||||
S3L_Transform3D transform;
|
||||
} S3L_Camera;
|
||||
|
||||
|
@ -1669,6 +1658,9 @@ void S3L_transform3DInit(S3L_Transform3D *t)
|
|||
static inline void S3L_perspectiveDivide(S3L_Vec4 *vector,
|
||||
S3L_Unit focalLength)
|
||||
{
|
||||
if (focalLength == 0)
|
||||
return;
|
||||
|
||||
vector->x = (vector->x * focalLength) / vector->z;
|
||||
vector->y = (vector->y * focalLength) / vector->z;
|
||||
}
|
||||
|
@ -1719,8 +1711,10 @@ void S3L_project3DPointToScreen(
|
|||
result->w =
|
||||
(point.z <= 0) ? 0 :
|
||||
(
|
||||
camera.focalLength > 0 ?(
|
||||
(s * camera.focalLength * S3L_RESOLUTION_X) /
|
||||
(point.z * S3L_F)
|
||||
(point.z * S3L_F)) :
|
||||
((camera.transform.scale.x * S3L_RESOLUTION_X) / S3L_F)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1945,10 +1939,8 @@ void S3L_newFrame(void)
|
|||
S3L_stencilBufferClear();
|
||||
}
|
||||
|
||||
/*
|
||||
the following serves to communicate info about if the triangle has been split
|
||||
and how the barycentrics should be remapped.
|
||||
*/
|
||||
/* the following serves to communicate info about if the triangle has been split
|
||||
and how the barycentrics should be remapped. */
|
||||
uint8_t _S3L_projectedTriangleState = 0; // 0 = normal, 1 = cut, 2 = split
|
||||
|
||||
#if S3L_NEAR_CROSS_STRATEGY == 3
|
||||
|
@ -2585,7 +2577,15 @@ void S3L_makeCameraMatrix(S3L_Transform3D cameraTransform, S3L_Mat4 m)
|
|||
|
||||
S3L_mat4Transpose(r); // transposing creates an inverse transform
|
||||
|
||||
S3L_Mat4 s;
|
||||
|
||||
S3L_makeScaleMatrix(
|
||||
cameraTransform.scale.x,
|
||||
cameraTransform.scale.y,
|
||||
cameraTransform.scale.z,s);
|
||||
|
||||
S3L_mat4Xmat4(m,r);
|
||||
S3L_mat4Xmat4(m,s);
|
||||
}
|
||||
|
||||
int8_t S3L_triangleWinding(
|
||||
|
@ -2603,11 +2603,9 @@ int8_t S3L_triangleWinding(
|
|||
return winding > 0 ? 1 : (winding < 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if given triangle (in Screen Space) is at least partially visible,
|
||||
/** Checks if given triangle (in Screen 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.
|
||||
*/
|
||||
(left, right, top, bottom, near) or is invisible due to backface culling. */
|
||||
static inline int8_t S3L_triangleIsVisible(
|
||||
S3L_Vec4 p0,
|
||||
S3L_Vec4 p1,
|
||||
|
@ -2658,12 +2656,8 @@ _S3L_TriangleToSort S3L_sortArray[S3L_MAX_TRIANGES_DRAWN];
|
|||
uint16_t S3L_sortArrayLength;
|
||||
#endif
|
||||
|
||||
void _S3L_projectVertex(
|
||||
const S3L_Model3D *model,
|
||||
S3L_Index triangleIndex,
|
||||
uint8_t vertex,
|
||||
S3L_Mat4 projectionMatrix,
|
||||
S3L_Vec4 *result)
|
||||
void _S3L_projectVertex(const S3L_Model3D *model, S3L_Index triangleIndex,
|
||||
uint8_t vertex, S3L_Mat4 projectionMatrix, S3L_Vec4 *result)
|
||||
{
|
||||
uint32_t vertexIndex = model->triangles[triangleIndex * 3 + vertex] * 3;
|
||||
|
||||
|
@ -2696,12 +2690,10 @@ void _S3L_mapProjectedVertexToScreen(S3L_Vec4 *vertex, S3L_Unit focalLength)
|
|||
vertex->y = sY;
|
||||
}
|
||||
|
||||
/**
|
||||
Projects a triangle to the screen. If enabled, a triangle can be potentially
|
||||
/** Projects a triangle to the screen. If enabled, a triangle can be potentially
|
||||
subdivided into two if it crosses the near plane, in which case two projected
|
||||
triangles are returned (the info about splitting or cutting the triangle is
|
||||
passed in global variables, see above).
|
||||
*/
|
||||
passed in global variables, see above). */
|
||||
void _S3L_projectTriangle(
|
||||
const S3L_Model3D *model,
|
||||
S3L_Index triangleIndex,
|
||||
|
@ -2712,7 +2704,6 @@ void _S3L_projectTriangle(
|
|||
_S3L_projectVertex(model,triangleIndex,0,matrix,&(transformed[0]));
|
||||
_S3L_projectVertex(model,triangleIndex,1,matrix,&(transformed[1]));
|
||||
_S3L_projectVertex(model,triangleIndex,2,matrix,&(transformed[2]));
|
||||
|
||||
_S3L_projectedTriangleState = 0;
|
||||
|
||||
#if S3L_NEAR_CROSS_STRATEGY == 2 || S3L_NEAR_CROSS_STRATEGY == 3
|
||||
|
@ -2999,7 +2990,6 @@ void S3L_drawScene(S3L_Scene scene)
|
|||
S3L_drawTriangle(transformed[3],transformed[4],transformed[5],
|
||||
modelIndex, triangleIndex);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue