npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ascii-raytracer

v0.0.154

Published

Explore infinite 3d worlds from the comfort of your terminal

Downloads

25

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!

blob world

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

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

Example - Blob World

Simplest pre-built example, using only a distance function.

//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);

blob world blob world

Example - Custom Raycaster - Maze

It's usually a good idea to use a custom raytracing / raycasting function if you can organize your scene with an efficent data structure.

This pre-built example renders a maze which internally is stored in an R-Tree.

Note - the scene will still render if raytraceFunction is removed, but may be very slow!

You can also build scenes using just a list of boxes (see below).

//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);

maze maze

View STL file

By specifying stl in the config, the program will automatically produce a distance function and raycaster for your STL model.

You can also build scenes using just a list of triangles (see below).

//example with polygon mesh, 5000 triangles
//raycaster uses bounding volume hierarchy 

var art = require('ascii-raytracer');

var config = {
    stl: "./Bitey_Reconstructed_5k.stl"
}

art.runScene(config);

skull screenshot

Build a scene from boxes

Instead of dealing with distance functions, you can specify your scene with a list of axis-aligned bounding boxes.

The program will automatically create an appropriate distance function+raycaster.

In this example we create a bunch of random boxes and render them.

var art = require('ascii-raytracer');

//format of box: [lower-point-3d, upper-point-3d]

var randomBox3d = function(){
    var range = 32;
    var boxSizeMax = 8;
    var p0 = [Math.random()*range,Math.random()*range,Math.random()*range];
    var p1 = [p0[0]+Math.random()*boxSizeMax,p0[1]+Math.random()*boxSizeMax,p0[2]+Math.random()*boxSizeMax];
    return [p0,p1];
}

var randomBoxes = [];
for(var i=0; i<100; i++){
    randomBoxes.push(randomBox3d());
}

var config = {
    boxes: randomBoxes, //or bricks, or blocks
    resolution: 64,
    aspectRatio: 1.0
}

art.runScene(config);

boxes

Build a scene from triangles

Instead of dealing with distance functions, you can specify your scene with a list of triangles.

The program will automatically create an appropriate distance function+raycaster.

In this example we create a bunch of random triangles and render them.

var art = require('ascii-raytracer');

var randomPoint3d = function(){
    var S = 32;
    return [Math.random()*S,Math.random()*S,Math.random()*S];
}

var randomTriangles = [];

for(var i=0; i<100; i++){
    var randomTri = [ randomPoint3d(), randomPoint3d(), randomPoint3d() ];
    randomTriangles.push(randomTri);
}

var config = {
    triangles: randomTriangles,
    resolution: 64,
    aspectRatio: 1.0
}

art.runScene(config);

triangles

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...1
  • textureFunction 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 image = require('image-sync').read("./cat.png");

var w = image.width;
var h = image.height;
var d = image.data;  // [r,g,b,a,  r,g,b,a ...]

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);

texture texture cat

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);

maze with perlin noise maze with perlin noise

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 
    screenShotDir: '/Users/user/Desktop/' //default is ./
}

art.runScene(config);

screenshot

All Config Options

Note that the options distanceFunction,triangles, boxes, lines, points, stl are mutually exclusive - you should only declare one of these at a time.

{
    triangles: [], //list of tris [pt0,pt1,pt2]
    boxes: [], //list of aabb's [minPt,maxPt]
    lines: [], //list of line segments [startPt,endPt]
    points: [], //list of pts [x,y,z] -- rendered as small cubes 
    stl: "something.stl",
    distanceFunction: myDistFunc,
    raytraceFunction: myTraceFunc,
    uvFunction: myUvFunction,
    textureFunction: myTextureFunction,
    cameraPos: [-17.96,8.02,14.72], //camera position [x,y,z]
    cameraRot: [1.82,-0.40], //camera rotation, radians [phi, theta]
    aspectRatio: 4/3,
    screenShotScaleUp: 8, //default is 4 
    screenShotDir: '/Users/user/Desktop/' //default is ./
}

See Also

stonks