More static demo images can be found here
PixelRay supports following tools for achieving pixel-themed look:
- low resolutions + nearest-neighbor upscaling for higher resolutions
- lighting quantization
- hard shadows + simple soft shadow logic with fixed disc offsets instead of sampling. Adjustable light radius and
shadow quantization bands
- soft shadows can look quite rough and out of place if light radius is even slightly larger, especially in animations
- ordered dithering
- keep reflection bounces low
- reflections + enough lighting are good for local use
- global illumination is not really possible as each ray follows just a single path. So even with high bounces and lot of reflective surfaces the end outcome is probably not that good. Of course this can still create interesting visuals
- diffused lighting can be used for additional dithering/flickering in animations
- custom color palettes
- not required, but can certainly change the aesthetics a lot
=> no anti-aliasing, resampling or realistic lighting (global illumination). Focus is on aliasing the initial output to achieve a stylistic look
- Executables for 64-bit Windows and Linux-x64 can be found in GitHub Releases page
- Otherwise you need to build from source
To produce an output image, paths for scene and output files are required:
./PixelRay -i <inputPath> -o <outputPath>If you want to automatically open the output after rendering, add the -p/--preview flag. This will attempt to
call default image opener program via shell execution:
./PixelRay -i scene.json -o output.png -pFor scripting e.g. animations, input static scene and Lua script files. This can be do
with -s/--script flag:
./PixelRay -i <inputPut> -s <scriptFile> <frames> {-g}Here frames is the total amount of frames + optional -g/--gif to produce a GIF from produced frames. For example
./PixelRay -i scene.json -s script.lua 60 -gTo avoid file path issues, just keep scene and script file in the same directory with executable.
-
-i <path>or--image <path>Scene file path. Scenes are stored in json files (see Scenes section below).
-
-o <path>or--output <path>Output file path. Image format is either .png or .ppm.
-
-por--preview:Attempts to open the output image after rendering by executing the image file, thus calling the default viewing tool in process. Only available for png images as basic editors seldom support ppm.
-
-s <luaScript> <frameCount> {gif}or--script <luaScript> <frameCount> {gif}Uses the static scene from
-icommand as a baseline then runs Lua script to produce output frames into./framesdirectory. Output format is always png, frame count defaults to 60 if frameCount is not a valid integer value.- script file uses Lua language and must there end in .lua
- cannot be used with output or preview flags
- automatically flushes
framesdirectory to remove old images - can optionally pass
-g/--gifflag to produce a GIF file from saved frames.
Example:
PixelRay -i scene.json -s script.lua 30 -g
produces files frame0.png to frame29.png in
./framesand then combines these into a gif file asoutputGif.gif -
--debug <mode>Renders image based on selected debug mode. These are:
normals= color objects based on normal directions. Red = x, Green = y, Blue = zdistance= color objects based on how far they're from camera. Uses gray scale: closer objects are white/light gray and distant objects become darker. Missed rays produce red pixels.id= each object gets a random color
Modes cannot be mixed, only first one gets applied.
Scenes use json format.
For all scene parameters and their explanations, see Scene.md
Scripts use Lua programming language embedded into C# via MoonSharp interpreter
Scripting can be applied to
- object transforms (translation/positioning, scaling, rotations)
- camera (position, forward/upward direction, fov, aspect ratio)
For scripting API, see Lua.md
Both third-party packages
- SixLabors.ImageSharp (png and gif generation)
- MoonSharp (Lua scripting)
are be well-supported on Windows, Linux and macOS.
To build the executable:
-
install .NET SDK version 10.0.
-
change working directory to project source i.e. the directory where Pixelray.csproj file is located.
-
Build with
dotnet publish -c Release -r <rid> <args>
There are generally two ways to build project:
- Self-contained executable
- larger size (almost 40 MB) but runs on its own, no .NET runtime installation required from end user
- minimal executable file + DLLs
- very small, but end user must have .NET 10.0 Runtime installed
Instead of modifying PixelRay.csproj for each, both can be done by passing additional args to build command.
- for args specification check this
- examples below use 64-bit Windows as runtime identifier; for other RIDs, see this
-
Self-contained:
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:EnableCompressionInSingleFile=true
-
minimal, but requires .NET runtime
dotnet publish -c Release -r win-x64 --self-contained false
No differences here, same commands work:
-
Self-contained
dotnet publish -c Release -r win-x64 \ --self-contained true \ -p:PublishSingleFile=true \ -p:EnableCompressionInSingleFile=true -
minimal, but requires .NET runtime
dotnet publish -c Release -r win-x64 \ --self-contained false
Release build can be found in "PixelRay/bin/Release/net10.0/win-x64/publish" or similar depending on which RID was used e.g. linux-x64 instead of win-x64
.NET SDK version 10.0 is required.
xUnit is used for testing. You don't need to download this manually, tests.csproj includes all dependencies which will be downloaded when test command is run.
To run tests: cd into "PixelRay/tests" then use command dotnet test
The goal of this project is not to become become a large, heavily optimized ray/path tracing tool yet it should still have a good amount of customization options. So here's a short list of what most likely gets added:
- build-in color palettes + read palettes from files
- this way scene.json palette field would only require the file path instead of listing all the colors
- depth of field/blur in some form
- materials/mediums: glass, matte, fog/gas etc.
- maybe simple emissive materials although current lighting is already good enough
- geometry:
- triangle meshes for custom shapes
- maybe some new primitives
- shared materials (and meshes): current system adds materials inside each object, preventing reusing them
- performance
- at least BVH when meshes get added
- so far only torus primitive uses something similar with a lazy bouncing sphere logic
- otherwise some smaller optimizations here and there
- at least BVH when meshes get added
- more tests
- meshes + BVH
- new materials/mediums
- the rest