c-ray: a small path tracer written in plain C
c-ray is a small, simple path tracer written in C
At a glance
- What is it?
- c-ray is a portable, hackable software path tracer whose core is plain C99, with a BVH accelerator, a node graph material system, a C API, Python bindings and a Blender add-on. It is built for learning, and the README says so directly, which shapes both what it does well and where it stops.
- Who is it for?
- c-ray is a good fit for a graphics programmer who wants to read a complete path tracer end to end, for a student who needs a renderer whose every line is legible, and for a tool team that wants to embed path tracing through the C API without adopting a large framework.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 35 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A renderer written to be read
c-ray describes itself as a portable, hackable, embeddable software path tracer, and the About section puts the intent plainly: it is a portable, hackable, offline CPU rendering engine built for learning. The core is in plain C99, with an emphasis on clarity and avoiding superfluous abstraction.
That last clause is the design constraint everything else follows from. There is no scene graph framework, no plugin registry, no job system with a configuration file. The source is organised into a library, a driver and a common set of files, which the Makefile reflects by compiling src/lib, src/driver and src/common into separate object sets before linking them into the binary.
The consequences are mostly positive for a learning project. You can read a function and know what it does, because it is plain C with no framework magic in the way. You can add a feature without first learning an abstraction you did not ask for. And because it is a CPU path tracer with no GPU dependency, it runs anywhere a C compiler runs, which the portability list takes advantage of in unusual ways.
The README invites contributions and points to a contributing section in the wiki for the details, and the author asks people to file an issue describing the improvements they plan, so that effort can be coordinated rather than duplicated.
What the renderer actually implements
The feature list is described as incomplete, which is a good sign, because it is specific.
The rendering core is a simple unidirectional Monte Carlo integrator with global illumination, accelerated by a performant BVH accelerator contributed by madmann92, who the README credits with an overall performance improvement of roughly 60 percent. Russian Roulette path optimisation is included, which is the standard way to cut the cost of paths that bounce too many times.
Materials are handled by a node graph system with more than 32 node types, including an approximation of the Principled BSDF rather than the real thing. On the list the author gives of things to implement are proper physically based materials to replace the current ad-hoc implementations, which is the clearest statement in the repository that material quality is the weak point.
Geometry is triangles and spheres, with object instancing available. Lighting uses HDR environment maps for realistic lighting. The camera is a thin lens approximation that gives depth of field. Multithreading is there, and there is real time render preview with state reporting through a callback mechanism, so an embedding application can show progress rather than a frozen window.
Beyond the renderer itself, the repository includes cluster rendering over TCP/IP, a C API in a public header, Python bindings, and a Blender add-on.
Building it with make, CMake or Visual Studio
The dependency list is short. At compile time you need a standard C99 compiler with common libraries, specifically libc, libm and pthreads. At runtime, CMake for the build system is optional because a basic makefile is provided for Unix-like systems, SDL2 is optional and enabled if it was found at runtime, and Python3 is optional, used for some utility scripts.
The Makefile shows what that means in practice, and the compiler flags are a good indication of the project's priorities.
CFLAGS=-I./include/ -I./src/ -Wall -Wextra -Wpedantic -Wno-missing-field-initializers -std=c99 -D_POSIX_C_SOURCE=200112L $(OPT) -g -ftree-vectorizeWarnings are turned on across the board with pedantic mode enabled, which is unusual in a hobby renderer and consistent with the claim of clarity. The standard is pinned to C99 and POSIX 2001.
The link step is equally plain:
@echo "LD $@"
@$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)The Makefile also pulls in ccache.mk for compiler caching, cosmo.mk, lib.mk and the test makefile, and it generates a C file containing the git hash of the checkout so a render can report which revision produced it.
For Windows the README documents the Visual Studio route: install the Build Tools, optionally fetch the SDL2 development libraries, set the SDL2DIR environment variable in a Developer Command Prompt, run cmake with the Visual Studio generator, build the generated solution with msbuild, and copy SDL2.dll into the output folder if you enabled it.
Running it standalone and feeding it scenes
On Linux the sequence is short: run make, and if the plain Makefile does not work on your system, run cmake . and then make again. The binary lands in bin, and a scene is a JSON file.
The driver is invoked with a scene path, for example bin/c-ray with one of the test scenes in the input directory. It also reads from standard input, which the README points out as useful for scripts that invoke c-ray, with the example of piping a scene file into the binary. There is a caveat with that mode: when the JSON comes from standard input, c-ray assumes the asset path is the current directory, and the asset path can be set explicitly with the --asset-path option.
All the .json files in the input directory are test scenes shipped with the project, and their assets are mostly bundled in the repository too, so you can render something meaningful immediately after building without authoring a scene.
macOS is covered by the same instructions, with the alternative of generating an Xcode project using mkdir build, cd build and cmake -G Xcode. If you have Python3 installed and you have made a scene worth keeping, the scripts directory has a bundle.py script that packages a scene into a portable zip file.
The output directory is part of the tree, alongside bin, input, include, src, tests, bindings, integrations and scripts, which is roughly the shape of a project that expects to be read as well as run.
The Blender add-on and the embedding APIs
The README says the easiest way to try out c-ray is not the standalone driver at all, but the Blender add-on, and it walks through the four steps.
First, check the BLENDER_ROOT setting in lib.mk and make sure it points at the version of Blender you have installed. Second, run make fullblsync, which compiles the Python bindings into a cray_wrap.so shared object and installs it under BLENDER_ROOT as an add-on. Third, enable the c-ray add-on in Blender Preferences and choose c-ray for Blender as the render engine. Fourth, report the bugs and missing features, of which the author says there are a lot, by filing an issue.
That path is what makes the project interesting for an artist rather than only for a programmer, because the scene description and the UI come from Blender while the rendering comes from c-ray.
For everything else there are two more doors. The include directory holds a public C header, so the renderer can be linked into another program, and the bindings directory holds Python bindings and the Blender add-on script. There is also cluster rendering support over TCP/IP, documented in the wiki, which is how a single scene can be spread across several machines.
The design implication is that c-ray is usable as a component. If your interest is in path tracing as a subject, the library is the part to read; if your interest is in producing images, the Blender add-on is the shortest path to a result.
Portability that goes further than expected
The portability section lists architectures the project has been verified to work on, and the list is unusual enough to be worth quoting.
x86 and x86_64 are listed as the primary development targets. Then there are ARMv6, ARMv7 and ARMv8 with AARCH64, described as various Raspberry Pi systems. PowerPC 7xx and 74xx, described as PowerPC G3 and G4 systems. MIPS R5000, with a link to a post about a 1996 SGI O2. SuperSPARC II, with a link about a 1992 Sun SparcStation 10. And WebAssembly with emscripten, hosted on a branch.
The last two entries are the interesting ones, because they are evidence rather than aspiration. Running a path tracer on a 1996 SGI O2 or a 1992 SparcStation 10 means the code stays inside what those machines can do, which is a decent proxy for keeping a renderer readable and dependency free. The Raspberry Pi entry means the same code is fast enough to be worth using on cheap hardware.
The emscripten branch is the one to note if you want c-ray in a browser, and the README points at it directly. Since the project is a CPU renderer with no GPU requirement, the browser is a natural target for it, and the fact that this exists as a separate branch rather than a mainline feature suggests it is maintained separately.
The image library and the other dependencies are also conservative: lodePNG for PNG compression, stb_image.h, SDL2 optionally, cJSON for parsing and the PCG random number generator. Nothing here needs a package manager to be present on the target.
Tests, licensing and the maintenance picture
There is an integrated test suite, and the README gives the three ways to run it. The test script compiles c-ray with the correct flags and then runs each test in a separate process. If you want them in one process, the binary has a test mode. And a single suite can be run by passing its name to the script, with mathnode given as the example.
The repository also carries a code of conduct, a contributing guide, git hooks that can be enabled through the Makefile, an editor config, and a count-lines script. The author is reachable on Discord and asks that improvements be filed as issues first.
On versions, the release list is thin and old: v0.6.1 in October 2019, described as the first GitHub release with binaries, and v0.6.2 in January 2020. The last push was on 2026-09-18, so the branch is being worked on, but there is no recent tagged release to pin. For a project meant to be read and hacked, that is a reasonable trade; for a project you intend to depend on in production, it is not.
The licence is the MIT licence, which permits use, modification and redistribution in commercial and non commercial work with attribution and no warranty.
Against alternatives, the honest comparison is with a full renderer such as the one bundled with Blender. That will produce an image faster, support physically based materials properly and run on a GPU. c-ray wins on a different axis: it is small enough to read in a weekend, it is a CPU renderer you can embed through a C API, and it has a node graph material system you can extend without learning a proprietary file format.
Editorial conclusion
c-ray is a good fit for a graphics programmer who wants to read a complete path tracer end to end, for a student who needs a renderer whose every line is legible, and for a tool team that wants to embed path tracing through the C API without adopting a large framework. It is the wrong choice for production rendering, where a maintained engine with GPU support will beat it on time to image, and it is the wrong choice if you need physically accurate materials, since the README lists proper physically based materials as work still to do. Verify first that the features you need are in the node graph, that the platform you target is on the verified architectures list, and that the latest commit still builds with your compiler before you build anything on top of it.
Frequently asked questions
What is c-ray and what language is it written in?
c-ray is a portable, hackable, embeddable software path tracer for learning, with its core written in plain C99 and an emphasis on clarity over abstraction.
How do I build c-ray on Linux?
Run make, and if the plain Makefile does not work on your system run cmake . and then make again. The result is the bin/c-ray binary, and you render a scene with something like bin/c-ray input/hdr.json.
How do I use c-ray with Blender?
Point BLENDER_ROOT in lib.mk at your Blender installation, run make fullblsync to compile the Python bindings and install the add-on, then enable the c-ray add-on in Blender Preferences and pick c-ray for Blender as the render engine.
Does c-ray run on a Raspberry Pi?
Yes. The README lists ARMv6, ARMv7 and ARMv8 with AARCH64, described as various Raspberry Pi systems, among the architectures the project has been verified to work on.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/vkoskiv-c-ray)Was this useful?