Package Exports
- ascii-raytracer
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ascii-raytracer) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
ascii-raytracer
Explore infinite 3d worlds from the comfort of your terminal!
Simple utility takes a signed distance function and lets you explore it with realtime raytracing (marching spheres) or alternatively by using a user-provided raytracing function. No GPU needed!
Why?
For retro fun, to experiment with distance functions / 3d algorithms / ray-tracing / data-stuctures / optimization without dealing with browser, GPU, ect.
Table of Contents
- Installation
- Controls
- Simple Example - Blob World
- With Custom Raytracer - Maze
- Polygon Mesh with Bounding Volume Hierarchy
- UV Texture Mapping
- 3D Texture Mapping
- Taking high-res screenshots
- See Also
Installation
npm i ascii-raytracer
Controls
A/S/W/D - move camera
Arrow Keys - rotate camera
Q/E - rise/fall
R/F - change field of view
C/X - change camera mode
H - Toggle fast anti-aliasing (EPX + anti-aliasing simultaneous)
V - Toggle naive anti-aliasing (2x render size, runs 4x slower)
U - Toggle EPX Upscaling (1/2 render size + 2x upscale)
P - Take screenshot (saves PNG with 4x resolution)
Hold shift to move/rotate faster
Simple Example - Blob World
//here just a distance function - raytracing is done with marching spheres
//distance function format:
//funtion(x,y,z){return signedDistanceToScene;}
//see src of dfBlobWorld for more details
var art = require('ascii-raytracer');
var config = {
distanceFunction: art.distanceFunctions.dfBlobWorld
}
art.runScene(config);
With Custom Raytracer - Maze
//here we additionally include a custom raytracing function [much faster than naive marching spheres]
//raytrace function format:
// function(ray) {
// var o = ray.point; //{x,y,z} origin of ray
// var v = ray.vector; //{x,y,z} direction of ray
// return distance;
// }
//example with a maze build from axis aligned bounding blocks
var art = require('ascii-raytracer');
var config = {
distanceFunction: art.distanceFunctions.dfMaze,
raytraceFunction: art.distanceFunctions.dfMazeTrace, //raytracer uses RTree
resolution: 64,
aspectRatio: 1.0
}
art.runScene(config);
Polygon Mesh with Bounding Volume Hierarchy
//example with polygon mesh, 5000 triangles
//raytracer uses bounding volume hierarchy
var art = require('ascii-raytracer');
var config = {
distanceFunction: art.distanceFunctions.dfSkull,
raytraceFunction: art.distanceFunctions.dfSkullTrace,
resolution: 64,
aspectRatio: 1.0
}
art.runScene(config);
UV Texture Mapping
specify config.uvFunction
and config.textureFunction
to render a 2D texture onto the scene.
uvFunction
takes (x,y,z) as input and returns[u,v]
texture coordinates in range 0...1textureFunction
takes (u,v) as inputs and returns[r,g,b]
color data in range 0...1
in this example we load a PNG file with the readimage
module and then specify textureFunction to pull color values from the image, and uvFunction for tiling the image.
the scene is the same maze from the earlier example.
var art = require('ascii-raytracer');
var fs = require("fs")
var readimage = require("readimage")
var filedata = fs.readFileSync("./cat.png")
readimage(filedata, function (err, image) {
var w = image.width;
var h = image.height;
var d = image.frames[0].data;
var myTextureFunction = function(u,v){ //pull colors from texture data
var xc = Math.floor(u*w);
var yc = Math.floor(v*h);
var o = (yc*h+xc)*4;
return [d[o]/255, d[o+1]/255, d[o+2]/255] //return [r,g,b] in range 0...1
}
var myUvFunction = function(x,y,z){ //tile texture across XZ plane
return [Math.abs(x/1.0)%1.0, Math.abs(z/1.0)%1.0]; //return u,v coords
}
var config = {
distanceFunction: art.distanceFunctions.dfMaze,
raytraceFunction: art.distanceFunctions.dfMazeTrace,
uvFunction: myUvFunction,
textureFunction: myTextureFunction,
resolution: 64,
aspectRatio: 1.0
}
art.runScene(config);
})
3D Texture Mapping
Specify textureFunction3d
instead of textureFunction
if you want to define surface colors directly from a 3D function.
In this example we apply 3D perlin noise [from the blob world example] as the surface texture for our maze.
Because the blob world distance function varies over time, the texture is animated!
var art = require('ascii-raytracer');
var my3dTextureFunction = function(x,y,z){
var d = Math.abs(art.distanceFunctions.dfBlobWorld(x*15,y*15,z*15))/2.0; //using 3d perlin noise to define color
return [d,d,d] //return [r,g,b]
}
var config = {
distanceFunction: art.distanceFunctions.dfMaze,
raytraceFunction: art.distanceFunctions.dfMazeTrace,
textureFunction3d: my3dTextureFunction,
resolution: 64,
aspectRatio: 1.0
}
art.runScene(config);
Taking high-res screenshots
Press P to save a screenshot [png file]. By default, screenshots are 4x higher resolution than the ascii render.
To make screenshots bigger or smaller, specify screenShotScaleUp
in the config [default 4]
Warning - depending on your scene, taking a screenshot may be very slow!
var art = require('ascii-raytracer');
var config = {
distanceFunction: art.distanceFunctions.dfSkull,
raytraceFunction: art.distanceFunctions.dfSkullTrace,
resolution: 64,
aspectRatio: 1.0,
screenShotScaleUp: 8 //default is 4
}
art.runScene(config);
See Also
- ascii-data-image - render data to ascii
- pixel-scale-epx - EPX scaling
- glsl-imager - render GLSL in terminal