{"id":51179298,"url":"https://github.com/jackwthake/shader-works","last_synced_at":"2026-06-27T06:04:51.894Z","repository":{"id":296694836,"uuid":"994172533","full_name":"jackwthake/shader-works","owner":"jackwthake","description":"Pure C software 3D renderer with zero dependencies. Runs on desktop and ARM microcontrollers.","archived":false,"fork":false,"pushed_at":"2026-04-16T18:58:42.000Z","size":188533,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-16T20:23:50.674Z","etag":null,"topics":["3d-engine","3d-graphics","c","software-rendering"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jackwthake.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-01T11:26:58.000Z","updated_at":"2026-04-16T18:58:47.000Z","dependencies_parsed_at":"2025-06-01T20:21:46.072Z","dependency_job_id":"39693ae4-4f6f-4e83-afca-3e6af0f57915","html_url":"https://github.com/jackwthake/shader-works","commit_stats":null,"previous_names":["jackwthake/software-rasterizer","jackwthake/shader-works"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/jackwthake/shader-works","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackwthake%2Fshader-works","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackwthake%2Fshader-works/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackwthake%2Fshader-works/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackwthake%2Fshader-works/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jackwthake","download_url":"https://codeload.github.com/jackwthake/shader-works/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jackwthake%2Fshader-works/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34843149,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d-engine","3d-graphics","c","software-rendering"],"created_at":"2026-06-27T06:04:51.200Z","updated_at":"2026-06-27T06:04:51.884Z","avatar_url":"https://github.com/jackwthake.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eShader Works\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/jackwthake/shader-works/actions/workflows/linux-build.yml\"\u003e\n    \u003cimg src=\"https://github.com/jackwthake/shader-works/actions/workflows/linux-build.yml/badge.svg\" alt=\"Linux\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/jackwthake/shader-works/actions/workflows/macos-build.yml\"\u003e\n    \u003cimg src=\"https://github.com/jackwthake/shader-works/actions/workflows/macos-build.yml/badge.svg\" alt=\"macOS\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/jackwthake/shader-works/actions/workflows/windows-build.yml\"\u003e\n    \u003cimg src=\"https://github.com/jackwthake/shader-works/actions/workflows/windows-build.yml/badge.svg\" alt=\"Windows\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./demos/tundra/screenshots/ski.gif\" width=\"400\"/\u003e\n  \u003cimg src=\"./examples/screenshots/02_textured_scene.gif\" width=\"400\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./demos/zombies/screenshots/ss-3.png\" width=\"400\"/\u003e\n  \u003cimg src=\"./demos/microcraft/screenshots/embedded.jpeg\" width=\"400\"/\u003e\n\u003c/p\u003e\n\nA **portable software 3D renderer** written in pure C with zero external dependencies. Renders 2000-3000 triangles at 30-40 FPS on a 2019 MacBook Air without a GPU. Runs on everything from desktop computers to ARM Cortex-M4 microcontrollers.\n\n## Table of Contents\n- [Why This Matters](#why-this-matters)\n- [Performance](#performance)\n- [Key Features](#key-features)\n- [Technical Highlights](#technical-highlights)\n- [Quick Start](#quick-start)\n- [Demos](#demos)\n- [Building](#building)\n- [API Reference](#api-reference)\n\n# Why This Matters\n\n**Portability** — Zero dependencies in the core library. No OpenGL, Vulkan, DirectX, or GPU required. Runs identically on Linux, macOS, Windows, and ARM microcontrollers.\n\n**Performance** — Achieves 30-40 FPS rendering 2000-3000 triangles on a 2019 MacBook Air using multi-threaded CPU rasterization. Optimized barycentric coordinate triangle filling with perspective-correct texture mapping.\n\n**Real Applications** — Not just a toy. Powers [Tundra](#tundra), a demo with infinite procedural terrain, dynamic weather, and day/night cycles. [Microcraft](#microcraft) demonstrates the same renderer running on a SAMD51 microcontroller with a 160x128 display.\n\n# Performance\n\nBenchmarked on Intel Core i5-8210Y (4 cores @ 3.6GHz) at 800×600 resolution with threading enabled:\n\n![Performance Graph](./examples/screenshots/04_performance.png)\n\n| Scene Complexity | Triangles | FPS  | Triangles/sec |\n|-----------------|-----------|------|---------------|\n| Low             | 32        | 77   | 672           |\n| Medium          | 512       | 66   | 9,395         |\n| High            | 2,048     | 61   | 34,846        |\n| Very High       | 8,192     | 53   | 121,342       |\n\n**Note:** These measurements represent pure rendering performance without overhead from windowing systems (SDL), game logic, input handling, or vertical sync. Real-world applications will see lower FPS due to these additional costs. See `examples/04_benchmark` for details.\n\n![Planet](./demos/planets/screenshots/ss-1.png)\n\n# Key Features\n\n- **100% Software Rendering** — Complete 3D graphics pipeline from vertex transformation to pixel output with no GPU dependency\n- **Fully Portable** — Bring your own framebuffer and pixel format. Library handles the rest\n- **Programmable Shaders** — Custom vertex and fragment shaders via function pointers with rich context access\n- **Modern Graphics** — Perspective-correct texturing, multi-light support, depth testing, transparency, wireframe mode\n- **Multi-threaded** — Optional POSIX threads for parallel rasterization (configurable at build time)\n- **Built-in Geometry** — Generators for cubes, spheres, planes, and quads\n\n![Level](./demos/zombies/screenshots/ss-2.png)\n# Technical Highlights\n\n**Barycentric Rasterization** — Implements scanline-free triangle filling using barycentric coordinates for pixel-perfect coverage testing and smooth attribute interpolation.\n\n**Perspective-Correct Texturing** — Proper depth-aware UV interpolation using 1/w correction prevents texture warping on perspective-projected surfaces.\n\n**Pthread Parallelization** — Work-stealing multi-threaded architecture using atomic operations distributes triangle rasterization across CPU cores for near-linear performance scaling.\n\n**Compiler Optimization Support** — Strategic use of the `restrict` keyword on hot-path function parameters enables advanced compiler optimizations by guaranteeing pointer aliasing constraints, allowing better instruction scheduling and vectorization.\n\n**Embedded Systems Port** — Identical rendering code runs on SAMD51 ARM Cortex-M4 (200MHz, 192KB RAM) by abstracting platform-specific layers (framebuffer, display drivers) while maintaining zero external dependencies.\n\n# Quick Start\n```c\n#include \u003cshader-works/renderer.h\u003e\n#include \u003cshader-works/primitives.h\u003e\n\n// Required: implement color conversion for your target pixel format\nuint32_t rgb_to_u32(uint8_t r, uint8_t g, uint8_t b) {\n  return (r \u003c\u003c 24) | (g \u003c\u003c 16) | (b \u003c\u003c 8) | 0xFF; // RGBA8888 example\n}\n\nvoid u32_to_rgb(uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b) {\n  *r = (color \u003e\u003e 24) \u0026 0xFF; *g = (color \u003e\u003e 16) \u0026 0xFF; *b = (color \u003e\u003e 8) \u0026 0xFF;\n}\n\nint main() {\n  // Setup window and framebuffer...\n\n  uint32_t framebuffer[WIDTH * HEIGHT];\n  float depthbuffer[WIDTH * HEIGHT];\n  renderer_t renderer_state = {0};\n\n  init_renderer(\u0026renderer_state, WIDTH, HEIGHT, 0, 0,\n                framebuffer, depthbuffer, MAX_DEPTH);\n\n  transform_t camera = {0};\n  update_camera(\u0026renderer_state, \u0026camera);\n\n  model_t cube = {0};\n  generate_cube(\u0026cube, make_float3(0, 0, -5), make_float3(1, 1, 1));\n\n  while (running) {\n    // Clear buffers\n    for(int i = 0; i \u003c WIDTH * HEIGHT; ++i) {\n      framebuffer[i] = 0x000000;\n      depthbuffer[i] = FLT_MAX;\n    }\n\n    render_model(\u0026renderer_state, \u0026camera, \u0026cube, NULL, 0);\n\n    // Present framebuffer to screen...\n  }\n\n  delete_model(\u0026cube);\n  return 0;\n}\n```\n\n# Demos\n\n## Tundra\n![Tundra gameplay](./demos/tundra/screenshots/static-4.png)\n\nAn explorable infinite world featuring:\n- **Infinite procedural terrain** using Perlin noise\n- **Dynamic day/night cycle** with atmospheric color transitions\n- **Real-time snow particles** with physics simulation\n- **Chunk-based streaming** and an **FSM-driven architecture** for seamless exploration and state management\n\nDemonstrates the renderer's capability to handle complex scenes with thousands of triangles, dynamic lighting, and environmental effects.\n\n**Tech:** Uses cJSON for configuration. See [demos/tundra/](demos/tundra/) for details.\n\n## Microcraft\n![Microcraft running on hardware](./demos/microcraft/screenshots/screenshot.png)\n\nThe same 3D renderer **running on a SAMD51 ARM Cortex-M4 microcontroller** (200MHz, 192KB RAM) with a 160x128 LCD display.\n\nProves true portability — identical rendering code runs on both desktop and embedded hardware with zero GPU dependency. Features voxel-style world rendering at playable framerates on resource-constrained hardware.\n\n**Tech:** Custom SAMD51 drivers, UF2 bootloader deployment. See [demos/microcraft/](demos/microcraft/)\n\n# Building\n\n### Build Options\n- `SHADER_WORKS_USE_THREADS=ON/OFF` - Enable/disable multi-threaded rendering (default: ON)\n- `SHADER_WORKS_BUILD_EXAMPLES=ON/OFF` - Build example programs (default: ON)\n- `SHADER_WORKS_MULTI_CONFIG=ON/OFF` - Build multiple configurations (default: OFF)\n\n```bash\n# Configure with threading options\nmkdir build \u0026\u0026 cd build\ncmake -DCMAKE_BUILD_TYPE=Release -DSHADER_WORKS_USE_THREADS=ON ..\ncmake --build . -j 8 \u0026\u0026 ./bin/basic_demo\n\n# Library-only build (no examples - useful for integration)\ncmake -DCMAKE_BUILD_TYPE=Release -DSHADER_WORKS_BUILD_EXAMPLES=OFF ..\ncmake --build . -j 8\n```\n\n### Platform Support\nWorks on Linux, macOS, Windows (MinGW/MSVC), and ARM microcontrollers. Build requirements: C11 compiler, CMake 3.15+. Demos require SDL3 (included as submodule).\n\n# API Reference\n\n## renderer.h\n### Required Client Functions\n\n```c\nu32 rgb_to_u32(u8 r, u8 g, u8 b);\nvoid u32_to_rgb(u32 color, u8 *r, u8 *g, u8 *b);\n```\nClient must implement these for pixel format conversion. Allows renderer to be pixel-format agnostic.\n\n### Core Renderer Functions\n```c\nvoid init_renderer(renderer_t *state, u32 win_width, u32 win_height,\n                   u32 atlas_width, u32 atlas_height, u32 *framebuffer,\n                   f32 *depthbuffer, f32 max_depth);\n```\nInitialize renderer with client-provided buffers. Framebuffer and depthbuffer must be pre-allocated arrays of `win_width * win_height` elements.\n\n---\n```c\nvoid update_camera(renderer_t *state, transform_t *cam);\n```\nUpdate camera basis vectors based on transform (position + yaw/pitch). Call before rendering.\n\n---\n```c\nusize render_model(renderer_t *state, transform_t *cam, model_t *model,\n                   light_t *lights, usize light_count);\n```\nRender model with threading support. Returns number of triangles rendered. Handles vertex transformation, rasterization, and shading.\n\n---\n```c\nvoid apply_fog_to_screen(renderer_t *state, f32 fog_start, f32 fog_end,\n                         u8 fog_r, u8 fog_g, u8 fog_b);\n```\nApply depth-based fog effect to entire framebuffer. Fog interpolates between `fog_start` and `fog_end` distances.\n\n---\n## primitives.h\n\n### Data Structures\nUse the `model_t` structure to store model data for use with the renderer. Vertices must be in Counter-Clockwise Winding (CCW) order for proper back-face culling.\n```c\ntypedef struct {\n  vertex_data_t *vertex_data;     // Position, UV, normal per vertex\n  float3 *face_normals;           // Per-triangle normals for back-face culling\n  usize num_vertices, num_faces;\n\n  transform_t transform;          // Position, yaw, pitch\n  bool use_textures;              // If false, use flat shading\n\n  vertex_shader_t *vertex_shader;\n  fragment_shader_t *frag_shader;\n} model_t;\n```\n\n\n### Geometry Generation\n```c\n// Generator functions\nint generate_cube(model_t* model, float3 position, float3 size);\nint generate_sphere(model_t* model, f32 radius, int segments, int rings, float3 position);\nint generate_plane(model_t* model, float2 size, float2 segment_size, float3 position);\nint generate_quad(model_t* model, float2 size, float3 position);\nvoid delete_model(model_t* model);\n```\n\nAll generators allocate and populate model with vertices, normals, and UV coordinates. Return 0 on success. **cube**: axis-aligned box. **sphere**: UV sphere with configurable tessellation. **plane**: subdivided for displacement effects. **quad**: simple 2-triangle surface. Always call `delete_model()` to free memory.\n\n## shaders.h\n\n### Shader Creation\n\n```c\nvertex_shader_t make_vertex_shader(vertex_shader_func func, void *argv, usize argc);\nfragment_shader_t make_fragment_shader(fragment_shader_func func, void *argv, usize argc);\n```\nCreate custom shaders with user-defined arguments. Arguments are passed to shader function on every invocation.\n\n### Shader Function Signatures\n\n```c\ntypedef float3 (*vertex_shader_func)(vertex_context_t *context, void *args, usize argc);\ntypedef u32 (*fragment_shader_func)(u32 input_color, fragment_context_t *context, void *args, usize argc);\n```\n\n**Vertex shaders** transform vertices from model space and return modified position. Context provides camera data, original vertex info, and timing.\n\n**Fragment shaders** process pixels and return final color. Return `rgb_to_u32(255, 0, 255)` to discard pixel for transparency.\n\n### Built-in Shaders\n\n```c\nextern vertex_shader_t default_vertex_shader;           // Standard MVP transformation\nextern fragment_shader_t default_frag_shader;           // Textured\nextern fragment_shader_t default_lighting_frag_shader;  // Multi-light support\n```\n\n### Context Structures\nThe shader system provides extensive programmability through rich context structures and user-defined parameters. Context structures expose render pipeline data while custom parameter buffers enable dynamic effects with game data.\n**fragment_context_t** provides:\n- `world_pos`, `screen_pos`, `uv`, `depth` - spatial information\n- `normal`, `view_dir` - lighting vectors\n- `time` - for animations\n- `light`, `light_count` - scene lighting\n\n**vertex_context_t** provides:\n- Camera vectors (`cam_position`, `cam_forward`, `cam_right`, `cam_up`)\n- Projection parameters (`projection_scale`, `frustum_bound`, `screen_dim`)\n- Original vertex data (`original_vertex`, `original_uv`, `original_normal`)\n- Indices (`vertex_index`, `triangle_index`) and timing (`time`)\n\n### Lighting\nCan be used within fragment shaders to add lighting effects. Use `default_lighting_frag_shader` for basic diffuse lighting with no shadows.\n```c\ntypedef struct {\n  float3 position, direction;\n  u32 color;\n  bool is_directional;  // true = directional light, false = point light\n} light_t;\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackwthake%2Fshader-works","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjackwthake%2Fshader-works","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjackwthake%2Fshader-works/lists"}