CRT material
<CrtMaterial map> is the material of the mesh it sits in, inside a World: an old cathode-ray screen showing map. The glass bends the picture toward the corners, scanlines run across it, a phosphor grille splits it into red, green and blue stripes, a bright bar rolls up it, and it flickers. All of it runs on the world’s clock, as every Shader does, so a paused game holds the bar where it is.
Its props are in CrtMaterialProps.
Unity, Unreal and Godot ship a CRT look as a screen-wide pass over the whole game. This one is a material, so a terminal or a television can stand in the world, and the player walks up to it. A screen-wide pass is not in the engine yet.
The shader is ThreeUI’s CRT by Meng To, MIT, moved from the whole canvas onto a mesh’s UVs. Its source is crtFragment, an exported GLSL string with a comment per block: copy it, change a block and pass it to a Shader for a screen of your own.
Sample
Section titled “Sample”A terminal drawn on a canvas, standing on a plane in the meadow:
import { CrtMaterial, Entity, World } from "@daniel-zarinski/engine";import { useMemo } from "react";import { CanvasTexture } from "three";
function drawTerminal() { const canvas = document.createElement("canvas"); canvas.width = 640; canvas.height = 480; const context = canvas.getContext("2d"); if (!context) throw new Error("no 2d context"); context.fillStyle = "#03100a"; context.fillRect(0, 0, canvas.width, canvas.height); context.fillStyle = "#8dffb0"; context.font = "32px monospace"; context.fillText("> hello, world_", 40, 80); return new CanvasTexture(canvas);}
export function Terminal() { const map = useMemo(drawTerminal, []); return ( <World map="meadow"> <Entity position={[0, 1.2, -3]}> <mesh> <planeGeometry args={[1.6, 1.2]} /> <CrtMaterial map={map} /> </mesh> </Entity> </World> );}Where it runs
Section titled “Where it runs”Client. The screen changes nothing in the world; each player’s browser draws its own.