JSFiddle - React, Tailwind, and code Playground

HTML

<a id="anchor" download="3dplot.chr">3dplot.chr</a><br>
<canvas id="canvas" width="128" height="120"></canvas>

CSS

canvas {
	width: 256px;
	image-rendering: pixelated;
}

JavaScript

"use strict";

let ctx;

onload = function() {
	draw();
	chrgen();
};

function draw() {
	ctx = canvas.getContext("2d");
	ctx.fillStyle = "#000000";
	ctx.fillRect(0, 0, canvas.width, canvas.height);

	let yt = new Array(128).fill(120);
	let yb = new Array(128).fill(0);

	ctx.fillStyle = "#00ff00";
	for (let y = -180; y <= 180; y += 8) {
		for (let x = -180; x <= 180; x += 8) {
			let rad = Math.sqrt(x ** 2 + y ** 2) * Math.PI / 180;
			let z = Math.cos(rad) * 100 - Math.cos(3 * rad) * 30;
			let sx = Math.floor(64.5 + x / 4 - y / 8);
			let sy = Math.floor(56.5 - (y / 8 + z / 4));
			if (sx < 0 || 128 <= sx) continue;
			let draw = false;
			if (yt[sx] > sy) {
				yt[sx] = sy;
				draw = true;
			}
			if (yb[sx] < sy) {
				yb[sx] = sy;
				draw = true;
			}
			if (draw) {
				ctx.fillRect(sx, sy, 1, 1);
			}
		}
	}
}

function chrgen() {
	let chr = new Uint8Array(8192);
	for (let i = 0; i < 256; i++) {
		let imgData = ctx.getImageData((i & 0xf) * 8, (i >> 4) * 8, 8, 8);
		let data = imgData.data;
		let p = 1;	// G
		for (let y = 0; y < 8; y++) {
			let c = 0;
			for (let x = 0; x < 8; x++) {
				c = (c << 1) | (data[p] >= 0x80 ? 1 : 0);
				p += 4;
			}
			chr[i * 16 + y] = c;
		}
	}

	let blob = new Blob([chr.buffer]);
	let url = URL.createObjectURL(blob);
	anchor.href = url;
}