SkillAgentSearch skills...

B3d

A a minimal software 3D renderer in C99, derived from bootleg3D

Install / Use

/learn @jserv/B3d
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

B3D

B3D is a minimal software 3D renderer in C99, derived from bootleg3D.

fps demo

Features

  • Triangle rasterization with depth buffering and clipping
  • Perspective projection with configurable FOV
  • Model transforms (translate, rotate, scale) and camera control
  • Zero heap allocations; depends only on <stdbool.h>, <stddef.h>, <stdint.h>, and <string.h>
  • Optional 16-bit depth buffer (B3D_DEPTH_16BIT)

Quick Start

#include "b3d.h"

#define W 320
#define H 240

int main(void) {
    static uint32_t pixels[W * H];
    static b3d_depth_t depth[W * H];

    b3d_init(pixels, depth, W, H, 60.0f);
    b3d_set_camera(&(b3d_camera_t){0, 0, -3, 0, 0, 0});

    b3d_clear();
    b3d_tri_t tri = {{{-1, -1, 0}, {1, -1, 0}, {0, 1, 0}}};
    b3d_triangle(&tri, 0xFF0000);  /* red triangle */

    /* pixels[] now contains rendered image */
    return 0;
}

Usage

#include "b3d.h"

Compile-time options:

  • B3D_DEPTH_32BIT - Default, 32-bit fixed-point depth (16.16)
  • B3D_DEPTH_16BIT - Use 16-bit depth buffer
  • B3D_FLOAT_POINT - Use floating-point math for comparisons

Examples

| Example | Description | |---------|-------------| | ball | Bouncing ball demo | | cubes | Benchmark: adds cubes until ~60 fps | | donut | Torus with directional lighting | | fps | First-person treasure hunt | | gears | Interlocking animated gears | | globe | Rotating Earth with Natural Earth country data | | lena3d | Image rendered as 3D heightfield | | lighting | Directional lighting showcase | | microcraft | Minecraft-style voxel terrain with procedural generation | | obj | OBJ viewer with auto-centering | | terrain | Animated sine/cosine heightmap | | voxel | Mesh voxelizer with cube rendering |

Build with make check to validate B3D implementation. Build with make all (requires SDL2). Run headlessly with --snapshot=PATH.

Globe Data Generation

The globe example uses Natural Earth country boundary data (public domain).

pip3 install pyshp requests   # one-time setup
make update-globe-data        # download and process data
make globe                    # build example

API

// Types
typedef struct { float x, y, z; } b3d_point_t;
typedef struct { b3d_point_t v[3]; } b3d_tri_t;
typedef struct { float x, y, z, yaw, pitch, roll; } b3d_camera_t;

// Setup
bool b3d_init(uint32_t *pixels, b3d_depth_t *depth, int w, int h, float fov);
void b3d_clear(void);
size_t b3d_buffer_size(int w, int h, size_t elem_size);  // 0 on overflow

// Transforms (angles in radians)
void b3d_reset(void);
void b3d_translate(float x, float y, float z);
void b3d_rotate_x(float angle);
void b3d_rotate_y(float angle);
void b3d_rotate_z(float angle);
void b3d_scale(float x, float y, float z);

// Matrix stack
bool b3d_push_matrix(void);  // false if stack full
bool b3d_pop_matrix(void);   // false if stack empty

// Direct matrix access (row-major 4x4)
void b3d_get_model_matrix(float out[16]);
void b3d_set_model_matrix(const float m[16]);

// Camera (yaw/pitch/roll in radians, FOV in degrees)
void b3d_set_camera(const b3d_camera_t *cam);
void b3d_get_camera(b3d_camera_t *out);
void b3d_look_at(float x, float y, float z);
void b3d_set_fov(float degrees);
float b3d_get_fov(void);
void b3d_get_view_matrix(float out[16]);
void b3d_get_proj_matrix(float out[16]);

// Rendering (returns false if culled/clipped)
bool b3d_triangle(const b3d_tri_t *tri, uint32_t color);
bool b3d_to_screen(float x, float y, float z, int *sx, int *sy);

// State queries
bool b3d_is_initialized(void);
int b3d_get_width(void);
int b3d_get_height(void);
size_t b3d_get_clip_drop_count(void);

Matrix Conventions

B3D uses DirectX-style matrix conventions, which differ from OpenGL:

| Aspect | B3D | OpenGL | |--------|-----|--------| | Coordinate system | Right-handed, Y-up, +Z forward | Right-handed, Y-up, -Z forward | | Memory layout | Row-major m[row][col] | Column-major m[col][row] | | Vector type | Row vectors | Column vectors | | Multiplication | v * M (vector on left) | M * v (vector on right) | | API multiply order | Post-multiply: M = M * T | Post-multiply: M = M * T | | Effect order | Transforms apply in call order | Transforms apply in reverse call order | | Translation storage | Row 3: m[3][0..2] | Column 3: m[12..14] in flat array |

Transform application order:

// B3D: transforms applied in code order (scale -> rotate -> translate)
b3d_scale(2, 2, 2);
b3d_rotate_y(angle);
b3d_translate(x, y, z);

// OpenGL: same API order, but effects apply in reverse (translate -> rotate -> scale)
// To match B3D's effect order, reverse the calls:
glTranslatef(x, y, z);
glRotatef(angle, 0, 1, 0);
glScalef(2, 2, 2);

Matrix layout comparison:

B3D (row-major):          OpenGL (column-major):
[ Xx Xy Xz 0 ]            [ Xx Yx Zx Tx ]
[ Yx Yy Yz 0 ]            [ Xy Yy Zy Ty ]
[ Zx Zy Zz 0 ]            [ Xz Yz Zz Tz ]
[ Tx Ty Tz 1 ]            [ 0  0  0  1  ]

When porting from OpenGL: transpose matrices and reverse transform order.

Color Format

Colors are 32-bit RGB (alpha channel ignored):

  • Format: 0xRRGGBB or 0xAARRGGBB
  • Examples: 0xFF0000 (red), 0x00FF00 (green), 0x0000FF (blue)

Per-face control flags use upper bits:

  • B3D_DRAW_BACKFACE (bit 31): Disable backface culling for this triangle
  • Usage: b3d_triangle(&tri, color | B3D_DRAW_BACKFACE)
  • Use case: Double-sided geometry (leaves, flags), skyboxes with outward normals

Coordinate System

| Property | Value | |----------|-------| | Handedness | Right-handed | | Up axis | +Y | | Forward axis | +Z (into screen) | | Screen origin | Top-left (0, 0) | | Winding order | Counter-clockwise = front face | | Near plane | 0.1 units | | Far plane | 100.0 units |

Return Values

| Function | Returns false when | |----------|---------------------| | b3d_init | NULL buffers, invalid size, overflow, or FOV ≤ 0 | | b3d_push_matrix | Stack full (16 levels max) | | b3d_pop_matrix | Stack empty | | b3d_triangle | Triangle culled or fully clipped | | b3d_to_screen | Point behind camera (w < epsilon) |

Note: b3d_look_at updates the view matrix but leaves b3d_get_camera orientation stale. Use b3d_get_view_matrix for accurate view state after b3d_look_at.

Thread Safety

B3D uses global state and is NOT thread-safe. Do not call B3D functions from multiple threads simultaneously. For multi-threaded rendering, serialize all B3D calls or use separate processes.

Performance

  • Depth buffer: 16-bit mode (B3D_DEPTH_16BIT) halves memory bandwidth
  • Fixed-point: Default Q15.16 is faster on systems without FPU
  • Culling: Back-face culling is enabled by default; use B3D_DRAW_BACKFACE per-face for skyboxes/particles, or B3D_NO_CULLING compile-time for all
  • Batching: Minimize b3d_push_matrix/b3d_pop_matrix pairs
  • Clipping: Use b3d_get_clip_drop_count() to detect buffer overflow

License

B3D is available under a permissive MIT-style license. Use of this source code is governed by a MIT license that can be found in the LICENSE file.

Related Skills

View on GitHub
GitHub Stars108
CategoryDevelopment
Updated12d ago
Forks10

Languages

C

Security Score

100/100

Audited on Mar 19, 2026

No findings