mirror of
https://git.coom.tech/drummyfish/small3dlib.git
synced 2024-11-22 20:49:58 +01:00
Update tests
This commit is contained in:
parent
681503a703
commit
53d3c84fbf
3 changed files with 121 additions and 47 deletions
25
README.md
25
README.md
|
@ -39,7 +39,16 @@ PC (SDL, offline rendering, terminal):
|
||||||
- **Different drawing strategies** to choose from: none, z-buffer (none, full, reduced), triangle sorting (back-to-front, fron-to-back with stencil buffer).
|
- **Different drawing strategies** to choose from: none, z-buffer (none, full, reduced), triangle sorting (back-to-front, fron-to-back with stencil buffer).
|
||||||
- Triangles provide **barycentric coordinates**, thanks to which practically anything that can be achieved with OpenGL can be achieved (texturing, shading, normal-mapping, texture fitering, transparency, PBR, shadow mapping, MIP mapping, ...).
|
- Triangles provide **barycentric coordinates**, thanks to which practically anything that can be achieved with OpenGL can be achieved (texturing, shading, normal-mapping, texture fitering, transparency, PBR, shadow mapping, MIP mapping, ...).
|
||||||
- **Top-left rasterization rule**, pixels of adjacent triangles don't overlap or have holes (just like in OpenGL).
|
- **Top-left rasterization rule**, pixels of adjacent triangles don't overlap or have holes (just like in OpenGL).
|
||||||
- **Tested on multiple platforms** (PC, Pokitto, Gamebuino META).
|
- **Tested on many platforms**:
|
||||||
|
- PC (little endian, 64bit GNU)
|
||||||
|
- PowerPC emulator (big endian)
|
||||||
|
- compilers: gcc, clang
|
||||||
|
- Arduboy (only experimental)
|
||||||
|
- Gamebuino META (32bit resource-limited embedded ARM)
|
||||||
|
- TODO:
|
||||||
|
- Android
|
||||||
|
- Windows
|
||||||
|
- emscripten (web browser, JavaScript transpile)
|
||||||
- **Many compile-time options** to tune the performance vs quality.
|
- **Many compile-time options** to tune the performance vs quality.
|
||||||
- **Similar to OpenGL** in principle, but simpler, easier to use, with higher-level features.
|
- **Similar to OpenGL** in principle, but simpler, easier to use, with higher-level features.
|
||||||
- **Tools** (Python scripts) for converting 3D models and textures to C array format used by the library.
|
- **Tools** (Python scripts) for converting 3D models and textures to C array format used by the library.
|
||||||
|
@ -51,8 +60,22 @@ be an as-is set of tools that the users is welcome to adjust for their
|
||||||
specific project. So new features will be preferred to keeping the same
|
specific project. So new features will be preferred to keeping the same
|
||||||
interface.
|
interface.
|
||||||
|
|
||||||
|
## why?
|
||||||
|
|
||||||
|
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, installing drivers 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 for playing around with a few low poly models? You want to create extremely portable 3D
|
||||||
|
graphics that will run on small and obscure platforms that don't have OpenGL, good specs or even standard C library? Want to just render something
|
||||||
|
offline simply and not 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 OpenGL (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?
|
||||||
|
|
||||||
|
This library may help you.
|
||||||
|
|
||||||
## limitations
|
## limitations
|
||||||
|
|
||||||
|
And advantages at the same time :)
|
||||||
|
|
||||||
- **No scenegraph** (object parenting), just a scene list. Parenting can still be achieved by using cutom transform matrices.
|
- **No scenegraph** (object parenting), just a scene list. Parenting can still be achieved by using cutom transform matrices.
|
||||||
- Though performance is high, due to multiplatformness it **probably can't match platform-specific rasterizers written in assembly**.
|
- Though performance is high, due to multiplatformness it **probably can't match platform-specific rasterizers written in assembly**.
|
||||||
- There is **no far plane**.
|
- There is **no far plane**.
|
||||||
|
|
74
programs/helloWorld.c
Normal file
74
programs/helloWorld.c
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
Simple hello world for small3dlib. Renders a triangle in terminal as ASCII.
|
||||||
|
|
||||||
|
by drummyfish, released under CC0 1.0, public domain
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h> // for IO
|
||||||
|
|
||||||
|
// This tells the library the resolution of our ASCII screen.
|
||||||
|
#define S3L_RESOLUTION_X 64
|
||||||
|
#define S3L_RESOLUTION_Y 30
|
||||||
|
|
||||||
|
// This tells the library the name of a function we use to write pixels.
|
||||||
|
#define S3L_PIXEL_FUNCTION drawPixel
|
||||||
|
|
||||||
|
#include "../small3dlib.h" // now include the library
|
||||||
|
|
||||||
|
#define U S3L_FRACTIONS_PER_UNIT // this is the library unit, like e.g. 1 meter
|
||||||
|
|
||||||
|
S3L_Unit triangleVertices[] = { // x, y, z
|
||||||
|
U, 0, 0, // vertex 1
|
||||||
|
0, U, 0, // vertex 2
|
||||||
|
-U, U/2, 0 }; // vertex 3
|
||||||
|
|
||||||
|
S3L_Index triangleTriangles[] = { 0, 1, 2 }; // our single triangle
|
||||||
|
|
||||||
|
#undef U
|
||||||
|
|
||||||
|
#define SCREEN_SIZE (S3L_RESOLUTION_X * S3L_RESOLUTION_Y)
|
||||||
|
|
||||||
|
char screen[SCREEN_SIZE]; // our ASCII screen
|
||||||
|
|
||||||
|
/* This function will be called by the library to draw individual rasterized
|
||||||
|
pixels to our screen. We should try to make this function as fast as possible
|
||||||
|
as it tends to be the performance bottle neck. */
|
||||||
|
void drawPixel(S3L_PixelInfo *p)
|
||||||
|
{
|
||||||
|
screen[p->y * S3L_RESOLUTION_X + p->x] = 'X';
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < SCREEN_SIZE; ++i) // init the screen
|
||||||
|
screen[i] = '.';
|
||||||
|
|
||||||
|
S3L_Model3D triangleModel; // 3D model representing our triangle
|
||||||
|
S3L_initModel3D(triangleVertices,9,triangleTriangles,1,&triangleModel);
|
||||||
|
|
||||||
|
S3L_Scene scene; // scene of 3D models (we only have 1)
|
||||||
|
S3L_initScene(&triangleModel,1,&scene);
|
||||||
|
|
||||||
|
// shift the camera a little bit so that we can see the triangle
|
||||||
|
scene.camera.transform.translation.z = -2 * S3L_FRACTIONS_PER_UNIT;
|
||||||
|
scene.camera.transform.translation.y = S3L_FRACTIONS_PER_UNIT / 2;
|
||||||
|
|
||||||
|
S3L_newFrame(); // has to be called before each frame
|
||||||
|
S3L_drawScene(scene); /* this starts the scene rendering, the library
|
||||||
|
will now start calling our drawPixel function to
|
||||||
|
render the camera view */
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y < S3L_RESOLUTION_Y; ++y) // now display the screen
|
||||||
|
{
|
||||||
|
for (int x = 0; x < S3L_RESOLUTION_X; ++x)
|
||||||
|
{
|
||||||
|
putchar(screen[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // done!
|
||||||
|
}
|
|
@ -1,26 +1,22 @@
|
||||||
/*
|
/**
|
||||||
Simple example of small3dlib, rendering in terminal.
|
Simple example of small3dlib, rendering in terminal.
|
||||||
|
|
||||||
license: CC0 1.0
|
by drummyfish, released under CC0 1.0, public domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h> // for usleep
|
#include <unistd.h> // for usleep
|
||||||
|
|
||||||
// we need to define screen resolution before including the library:
|
// we need to define screen resolution before including the library:
|
||||||
|
|
||||||
#define S3L_RESOLUTION_X 80
|
#define S3L_RESOLUTION_X 80
|
||||||
#define S3L_RESOLUTION_Y 40
|
#define S3L_RESOLUTION_Y 40
|
||||||
|
|
||||||
// and a name of the function we'll be using to draw individual pixels:
|
// and a name of the function we'll be using to draw individual pixels:
|
||||||
|
|
||||||
#define S3L_PIXEL_FUNCTION drawPixel
|
#define S3L_PIXEL_FUNCTION drawPixel
|
||||||
|
|
||||||
// now include the library:
|
#include "../small3dlib.h" // now include the library
|
||||||
|
|
||||||
#include "../small3dlib.h"
|
// we'll use a predefined geometry of a cube from the library:
|
||||||
|
|
||||||
// we'll use a predefined geometry of a cube that's in the library:
|
|
||||||
|
|
||||||
S3L_Unit cubeVertices[] = { S3L_CUBE_VERTICES(S3L_FRACTIONS_PER_UNIT) };
|
S3L_Unit cubeVertices[] = { S3L_CUBE_VERTICES(S3L_FRACTIONS_PER_UNIT) };
|
||||||
S3L_Index cubeTriangles[] = { S3L_CUBE_TRIANGLES };
|
S3L_Index cubeTriangles[] = { S3L_CUBE_TRIANGLES };
|
||||||
|
@ -28,7 +24,10 @@ S3L_Index cubeTriangles[] = { S3L_CUBE_TRIANGLES };
|
||||||
S3L_Model3D cubeModel; // 3D model, has a geometry, position, rotation etc.
|
S3L_Model3D cubeModel; // 3D model, has a geometry, position, rotation etc.
|
||||||
S3L_Scene scene; // scene we'll be rendring (can have multiple models)
|
S3L_Scene scene; // scene we'll be rendring (can have multiple models)
|
||||||
|
|
||||||
uint8_t screen[S3L_RESOLUTION_X * S3L_RESOLUTION_Y]; // our screen
|
#define FRAME_OFFSET 20 // how many newlines will be printed before each frame
|
||||||
|
#define SCREEN_SIZE (FRAME_OFFSET + (S3L_RESOLUTION_X + 1) * S3L_RESOLUTION_Y + 1)
|
||||||
|
|
||||||
|
uint8_t screen[SCREEN_SIZE]; // ASCII screen
|
||||||
|
|
||||||
/* This function will be called by the library to draw individual rasterized
|
/* This function will be called by the library to draw individual rasterized
|
||||||
pixels to the screen. We should try to make this function as fast as possible
|
pixels to the screen. We should try to make this function as fast as possible
|
||||||
|
@ -50,34 +49,8 @@ void drawPixel(S3L_PixelInfo *p)
|
||||||
else
|
else
|
||||||
c = '.';
|
c = '.';
|
||||||
|
|
||||||
screen[p->y * S3L_RESOLUTION_X + p->x] = c; // draw the pixel to the screen
|
// draw to ASCII screen
|
||||||
}
|
screen[FRAME_OFFSET + p->y * (S3L_RESOLUTION_X + 1) + p->x] = c;
|
||||||
|
|
||||||
void clearScreen()
|
|
||||||
{
|
|
||||||
for (int j = 0; j < S3L_RESOLUTION_X * S3L_RESOLUTION_Y; ++j)
|
|
||||||
screen[j] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function prints out the content of the screen to the terminal.
|
|
||||||
|
|
||||||
void drawScreen()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 20; ++i)
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
for (int y = 0; y < S3L_RESOLUTION_Y; ++y)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < S3L_RESOLUTION_X; ++x)
|
|
||||||
{
|
|
||||||
printf("%c",screen[pos]);
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -90,8 +63,7 @@ int main()
|
||||||
&cubeModel);
|
&cubeModel);
|
||||||
|
|
||||||
S3L_initScene( // Initialize the scene we'll be rendering.
|
S3L_initScene( // Initialize the scene we'll be rendering.
|
||||||
&cubeModel, /* We only have one model (the cube), this is like an array
|
&cubeModel, // This is like an array with only one model in it.
|
||||||
with only one model in it. */
|
|
||||||
1,
|
1,
|
||||||
&scene);
|
&scene);
|
||||||
|
|
||||||
|
@ -101,18 +73,23 @@ int main()
|
||||||
|
|
||||||
for (int i = 0; i < 200; ++i) // render 200 frames
|
for (int i = 0; i < 200; ++i) // render 200 frames
|
||||||
{
|
{
|
||||||
clearScreen();
|
// clear the screen
|
||||||
|
for (int j = 0; j < FRAME_OFFSET; ++j)
|
||||||
|
screen[j] = '\n';
|
||||||
|
|
||||||
|
for (int j = FRAME_OFFSET; j < SCREEN_SIZE; ++j)
|
||||||
|
screen[j] = ((j - FRAME_OFFSET + 1) % (S3L_RESOLUTION_X + 1) ? ' ' : '\n');
|
||||||
|
|
||||||
|
screen[SCREEN_SIZE - 1] = 0; // terminate the string
|
||||||
|
|
||||||
S3L_newFrame(); // has to be called before each frame
|
S3L_newFrame(); // has to be called before each frame
|
||||||
|
|
||||||
S3L_drawScene(scene); /* This starts the scene rendering. The drawPixel
|
S3L_drawScene(scene); /* This starts the scene rendering. The drawPixel
|
||||||
function will be called to draw it. */
|
function will be called to draw it. */
|
||||||
drawScreen();
|
|
||||||
|
|
||||||
|
puts(screen); // display the frame
|
||||||
usleep(100000); // wait a bit to let the user see the frame
|
usleep(100000); // wait a bit to let the user see the frame
|
||||||
|
|
||||||
// now move and rotate the cube a little to see some movement:
|
// now move and rotate the cube a little to see some movement:
|
||||||
|
|
||||||
scene.models[0].transform.rotation.y += 10;
|
scene.models[0].transform.rotation.y += 10;
|
||||||
scene.models[0].transform.rotation.x += 4;
|
scene.models[0].transform.rotation.x += 4;
|
||||||
scene.models[0].transform.translation.x = S3L_sin(i * 4);
|
scene.models[0].transform.translation.x = S3L_sin(i * 4);
|
Loading…
Reference in a new issue