Brush Rosetta
This Rosetta demo is intended to give readers a starting point for porting the Brush VR app to three.js and WebGL2, highlighting some of the lower-level aspects of managing shaders. code let color, depth, brush, escorzo = true, fallback = [], points = [], record let basicShader function preload() { loadJSON('/cloud_500.json', json => fallback = json.map(entry => ({ worldPosition: createVector(entry.x, entry.y, entry.z), color: entry.color })) ) } function setup() { createCanvas(600, 400, WEBGL) colorMode(RGB, 1) document.oncontextmenu = () => false points = [...fallback] const o = parsePosition(Tree.ORIGIN, { from: Tree.WORLD, to: Tree.SCREEN }) depth = createSlider(0, 1, o.z, 0.001) depth.position(10, 10) depth.style('width', '580px') color = createColorPicker('#C7C08D') color.position(width - 70, 40) brush = sphereBrush basicShader = parseShader(`#version 300 es precision highp float; uniform vec4 uMaterialColor; out vec4 fragColor; void main() { fragColor = uMaterialColor; }`, Tree.pMatrix | Tree.vMatrix | Tree.mMatrix) } function draw() { (mouseY >= 30) && orbitControl() shader(basicShader) record && update() background('#222226') axes({ size: 50, bits: Tree.X | Tree.Y | Tree.Z }) for (const point of points) { push() translate(point.worldPosition) brush(point) pop() } } function keyPressed() { key === 'c' && (points = []) key === 'f' && focus() key === 'r' && (record = !record) key === 's' && saveCloud() } function update() { points.push({ worldPosition: parsePosition([mouseX, mouseY, depth.value()], { from: Tree.SCREEN, to: Tree.WORLD }), color: color.color(), }) } function focus() { const center = [0, 0, 0] const position = parsePosition() const up = parseDirection(Tree.j) camera(...position.array(), ...center, ...up.array()) const o = parsePosition(Tree.ORIGIN, { from: Tree.WORLD, to: Tree.SCREEN }) depth.value(o.z) } function sphereBrush(point) { push() noStroke() fill(point.color) sphere(1) pop() } function saveCloud() { const data = points.map(point => ({ x: point.worldPosition.x, y: point.worldPosition.y, z: point.worldPosition.z, color: [red(point.color) / 255, green(point.color) / 255, blue(point.color) / 255, alpha(point.color) / 255] })) saveJSON(data, 'custom_cloud.json') } Shader Declaration A key difference in this version is the use of parseShader, which defines a basic shader that handles color through the uMaterialColor uniform: ...