Suckless PD 3D software rasterizer
Miloslav Ciz c986e9b025 Update readme | 1 year ago | |
---|---|---|
media | 5 years ago | |
programs | 2 years ago | |
tools | 1 year ago | |
Doxyfile | 4 years ago | |
LICENSE.txt | 5 years ago | |
README.md | 1 year ago | |
TODO.txt | 2 years ago | |
small3dlib.h | 2 years ago | |
todo.txt | 4 years ago |
Public domain 3D software rasterizer for (not only) resource-limited computers.
If you like this, you may also like my similar project: raycastlib. These two libraries can very easily be combined together -- here is a proof-of-concept gif (environment rendered with raycastlib, cubes with small3dlib):
Pokitto (32bit embedded console, 48 MHz, 36 kB RAM):
Gamebuino META (Arduino 32bit console, 48 MHz, 32 kB RAM):
PC (SDL, offline rendering, terminal):
NOTE: Backwards compatibility isn't a goal of this libraray. It is meant to be an as-is set of tools that the users is welcome to adjust for his specific project. So new features will be preferred to keeping the same interface.
You just need to make a small mini 3D game, quick 3D animation or visualization and don't want to go through the horror of learning and setting up OpenGL or Vulkan, installing drivers, learning complex APIs and libraries? Don't want to be tied to HW, 3rd party API or libraries and their dependencies? Don't want to install gigabytes of heavy super ultra graphics engines just to play around with a few low poly models? You need a simple software renderer as a fallback to your main renderer? You want to create extremely portable 3D graphics that will run on small obscure embedded platforms that don't have OpenGL, good specs, FPU unit or even standard C library? Want to just render something offline simply without caring about highest rendering speed? You want to toy around with modifying something in the rendering pipeline that you can't easily do or debug in big frameworks (such as the rasterization algorithm)? Want to hack around in the demo scene? Want to create something public domain and need a public domain renderer? Or just don't want to be bothered by conditions such as proper attribution or copyleft? You want to create an authentic retro wobbly PS1 style graphics? Then this library may help you.
And advantages at the same time :)
S3L_USE_WIDER_TYPES
.For start take a look at the helloWorld.c program, then terminalCube and then other examples (e.g. level.c
shows simple integration with SDL).
For more see the other examples and the library code itself, it is meant to be self-documenting, i.e. the source code IS the documentation -- you'll find the description of a lot of things at the start of the file. You can also use doxygen to generate an HTML documentation.
The basic philosophy is:
S3L_PIXEL_FUNCTION
to the name of a function you will use to
draw pixels. It is basically a fragment/pixel shader function that the library will call. You will
be passed info about the pixel and can decide what to do with it, so you can process it, discard it,
or simply write it to the screen.S3L_RESOLUTION_X
and S3L_RESOLUTION_Y
(before including the library) or by setting S3L_resolutionX
and S3L_resolutionY
variables.S3L_init*
), set the position of the camera.S3L_newFrame
to prepare for rendering, then call S3L_drawScene
on the scene to perform the frame rendering.
This will cause the library to start rendering and calling the S3L_PIXEL_FUNCTION
in order to draw the frame. You can of course
modify the function or write a similar one of your own using the more low-level functions which are
also provided.S3L_Unit
type). The space is considered to be a uniform dense grid of discrete points, and what would normally be
a 1.0 float value is an int value equal to S3L_FRACTIONS_PER_UNIT
units (aka S3L_F
). Numbers are normalized by this
constant, so e.g. the sin function returns a value from -S3L_FRACTIONS_PER_UNIT
to S3L_FRACTIONS_PER_UNIT
. You have to
pass numbers of this format to the library functions, but of course you may chooe to use floats in other places of your program.S3L_PIXEL_FUNCTION
) will mostly be the performance bottleneck, try to make it as fast as possible. The number of pixels is usually much higher than the number of triangles or vertices processed, so you should focus on pixels the most.S3L_PIXEL_FUNCTION
use a per-triangle cache! This saves a lot of CPU time. Basically make sure you don't compute per-triangle values per-pixel, but only once, with the first pixel of the triangle. You can do this by remembering the last triangleID
and only recompute the value when the ID changes. See the examples for how this is done.#define S3L_RESOLUTION_X 512
) to increase performance!S3L_USE_WIDER_TYPES
to 1
will likely help. Besides this you can try to scale down the scene. If you also don't mind it, set S3L_STRICT_NEAR_CULLING
to 1
. With a bit of work you can implement big scene rendering even without wider types by multipass rendering (first render the far away scene scaled down, then clear z-buffer and render the near part of the scene over it).S3L_STRICT_NEAR_CULLING == 0
, you may set it to correctly handle near plane culling for a cost of some performance, or you may try different things like subdividing your model to more triangles which may reduce the negative effect.S3L_MAX_TRIANGLES_DRAWN
.Everything in this repository is CC0 1.0 (public domain, https://creativecommons.org/publicdomain/zero/1.0/) + a waiver of all other IP rights (including patents and trademarks).
I've written the code completely myself, from scratch. The art used in demos is either my own released under CC0 or someone else's released under CC0.
This project is made out of love and to be truly helpful to everyone, not for any self interest. I want it to forever stay completely in the public domain, not owned by anyone.
This is not mandatory but please consider supporting free software and free culture by using free licenses and/or waivers.
If you'd like to support me or just read something about me and my projects, visit my site: www.tastyfish.cz.
You can also choose to use this under the following waiver which is here to just ensure more legal safety and waiving of additional IP such as patents:
The intent of this waiver is to ensure that this work will never be encumbered by any exclusive intellectual property rights and will always be in the public domain world-wide, i.e. not putting any restrictions on its use.
Each contributor to this work agrees that they waive any exclusive rights, including but not limited to copyright, patents, trademark, trade dress, industrial design, plant varieties and trade secrets, to any and all ideas, concepts, processes, discoveries, improvements and inventions conceived, discovered, made, designed, researched or developed by the contributor either solely or jointly with others, which relate to this work or result from this work. Should any waiver of such right be judged legally invalid or ineffective under applicable law, the contributor hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to this right.