ascii3d

A text-based 3D rendering library for JavaScript and TypeScript

Usage no npm install needed!

<script type="module">
  import ascii3d from 'https://cdn.skypack.dev/ascii3d';
</script>

README

Ascii3D

Introduction

Ascii3D is a text-based 3D rendering library for JavaScript and TypeScript.

Demos

Installation

Install via npm:

npm install ascii3d

Render Buffers

A render buffer contains the result of draw calls. They have a width, height, and an array of character-codes, RGBA, and depth values. A render buffer is created like so:

import { RenderBuffer } from "ascii3d";

const width = 30, height = 30;
const renderBuffer = new RenderBuffer(width, height);

Vertex Arrays

A vertex array contains arbitrary numeric data about vertices. They normally contain spacial data (X, Y, Z), color (R, G, B, A), UV, and/or character codes.

const vertexArray = [
// 	X  	 Y    R    G    B    CharCode
    [-.5, -.5, 1.0, 1.0, 0.0, "#".charCodeAt(0)],
    [-.5, 0.5, 0.0, 1.0, 1.0, "#".charCodeAt(0)],
    [0.5, 0.5, 1.0, 0.0, 1.0, "#".charCodeAt(0)],
    [0.5, -.5, 1.0, 1.0, 0.0, "#".charCodeAt(0)]
];

A lot of 3D models are stored as vertex buffers and index buffers. You can convert them into a vertex array using the createVertexArray() function. For example:

import { createVertexArray } from "ascii3d";
    
const vertexBuffer = [ 1, 2, 3 ];
const vertexSize = 1;
const indexBuffer  = [ 1, 2, 3 ];
const vertexArray  = createVertexArray(vertexBuffer, vertexSize, indexBuffer);

Vertex Shaders and Fragment Shaders

A vertex shader accepts a vertex as an input and outputs a clipspace-position and a fragment.
The clipspace-position is 4-component vector.
The fragment is an array of arbitrary numeric values describing the pixel at the vertex. They are interpolated for every pixel and sent to the fragment shader.

function vertexShader([x, y, r, g, b, charCode]) {
    return {
        position: [x, y, 0, 1],
        fragment: [r, g, b, 1, charCode]
    }
}

A fragment shader accepts a fragment as an input (provided by the vertex shader), and outputs its color and character code.

function fragmentShader(fragment) {
    // output directly. ([r, g, b, a, charCode])
    return fragment;
}

Draw Calls

To make a draw call, use the renderBuffer.drawTriangles() method. If depth-testing is enabled, pixels with a greater depth will not be drawn over.

const doDepthTesting = true;
renderBuffer.drawTriangles(vertices, vertexShader, fragmentShader, doDepthTesting);

Rendering to a 2D canvas

One way to display a render buffer is through an HTML canvas element.

renderBuffer.renderToCanvas(
    ctx, 			// CanvasRenderingContext2D
    letterSpacing, 	// letter spacing
    0, 0 			// optional: start position (from bottom left)
);

Attribution

Special thanks to:

License

Licensed under MIT.

All files can be used for commercial or non-commercial purposes. Do not resell. Attribution is appreciated but not due.