NakedNous

✨ Welcome to my blog! ✨

I’m Jean Pierre Charalambos, researcher & educator passionate about creating didactic tools through creative coding and visual computing. I build open-source tools to make learning more playful 🖥️📚.

🚀 Active Projects

nub p5.quadrille.js p5.platonic p5.tree

🧊 Inactive Projects

maku shaderbase proscene p5.treegl legacy p5.bitboard

🎓 Teaching Resources

Visual Computing Course OOP Course

📚 Recent Publications

nub JORS Paper p5.quadrille.js SoftwareX Paper
🧘 Yoga practitioner | 🏊 Open water swimmer | 📖 Science fiction | 🧠 Philosophy of mind

Streamlining Minesweeper Revisited

In object-oriented programming (OOP), maximizing API use streamlines development, leading to simpler and more concise code. This clarity not only improves readability but also eases debugging. Leveraging an API effectively in OOP thus ensures a blend of simplicity, efficiency and maintainability in software development. This demo (partially) implements the minesweeper video game using p5-v2 and the Quadrille API with a four-layer strategy. Each layer is one quadrille with a single responsibility: mines — the bombs. counts — the numbers next to bombs. cover — a two-tone internal layer (red over filled cells, green over empty cells) that distinguishes the two click zones and drives flood fill. mask — the uniformly magenta layer the player actually sees, derived from cover. As gameplay progresses, clicking on cells uncovers them by clearing either individual or connected cells from cover; mask is re-derived from cover after each click. ...

May 18, 2026 · 6 min · Theme PaperMod

Streamlining Minesweeper

ℹ️ See also A four-layer refinement of this design — splitting board into single-purpose mines and counts quadrilles, then using Quadrille.or to merge them into the two-tone cover in two lines — appears in Streamlining Minesweeper, revisited. Same game, each variable with one fixed meaning throughout. In object-oriented programming (OOP), maximizing API use streamlines development, leading to simpler and more concise code. This clarity not only improves readability but also eases debugging. Leveraging an API effectively in OOP thus ensures a blend of simplicity, efficiency and maintainability in software development. ...

May 13, 2026 · 6 min · Theme PaperMod

Visibility testing

Per-object frustum culling with visibility. Sixty mixed primitives drift around in a wide volume; each frame their bounds — AABBs for boxes, spheres for spheres — are tested against a fixed test camera’s frustum, with the six frustum planes pre-computed once per frame via bounds({ mat4Eye }). Three return states drive the render: solid lit material for VISIBLE, amber wireframe for SEMIVISIBLE (the bounds straddle a plane), faint grey for INVISIBLE. Toggle the test camera’s projection between perspective and orthographic with the gold checkbox; drag to orbit the observer and watch the cyan wireframe stay put while objects drift through it. ...

April 25, 2026 · 6 min · Theme PaperMod

CPU proximity picking

Zero-GPU hit testing with mouseHit. Ten waypoint nodes around a soft loop — each one tested every frame against the cursor by projecting its origin to screen space and comparing against a configurable radius. The hit zone is drawn explicitly with bullsEye, which takes the same size and shape parameters as mouseHit — the gizmo is the hit zone, no guessing where the click registers. Use the panel to tune the radius and switch between circular and square hit shapes. ...

April 25, 2026 · 4 min · Theme PaperMod

GPU color-ID picking

Pixel-perfect mouse picking with mousePick. Fifty mixed primitives — boxes, spheres, torii, cones, cylinders — drawn at random positions and tagged with a unique integer id encoded as a CSS hex colour by tag. Each frame the scene renders twice: once into a 1×1 framebuffer with each shape filled by its id, then gl.readPixels returns whichever id sits under the cursor; the visible pass renders normally and lights up the hit. Cost is one extra geometry submission per frame regardless of object count, and the answer is exactly the rendered pixel — through the hole of a torus, behind a partially-occluding box, anywhere a real fragment landed. ...

April 25, 2026 · 5 min · Theme PaperMod

Camera interpolation

Lookat-camera keyframe animation with createCameraTrack. A bound animCam plays a four-keyframe track; a separate viewCam orbits around the abstraction — eye polyline, gaze rays, per-keyframe mini-camera markers. A live frustum follows playback, and an FBO inset shows what animCam actually sees. Toggle TEX and that inset slides onto the live frustum’s near plane — the frustum becomes a window. Two createPanel instances drive the whole thing: one binds checkboxes to UI state, one binds transport controls to the track. ...

April 19, 2026 · 7 min · Theme PaperMod

Pose interpolation

TRS keyframe animation with createPoseTrack. Four { pos, rot } keyframes, cubic Hermite interpolation of position with auto-Catmull-Rom tangents, and slerp on rotations. A transport panel scrubs the track; a second panel toggles the trackPath overlay bits — PATH, CONTROLS, TANGENTS_IN, TANGENTS_OUT — and switches interpolation modes live. Unlike createCameraTrack, which applies its result to a camera automatically, PoseTrack produces an interpolated pose you fold into the transform stack yourself with applyPose(track.eval(out)). Four keyframes, one object createPoseTrack returns a PoseTrack — a renderer-agnostic state machine for { pos, rot, scl } keyframes. track.add(spec) appends one; adjacent duplicates are skipped by default: ...

April 19, 2026 · 5 min · Theme PaperMod

Depth-of-field blur with focal target

A depth-of-field blur effect where the focal plane is driven by a live world-space position. The scene is rendered into a p5.Framebuffer, then a p5.strands DOF pass is applied via pipe(). The magenta sphere is the focal target — its screen-space z is recomputed every frame with mapLocation() and fed directly into the shader, so the blur follows the sphere continuously. A first-person directional light tracks the viewer using mapDirection(). The shader as a strands callback The DOF pass is authored as a p5.strands callback on baseFilterShader().modify(). There is no raw GLSL string — the algorithm is expressed in JavaScript using the strands DSL, which compiles it to WebGL2 under the hood. ...

April 9, 2026 · 3 min · Theme PaperMod

Post-effects pipeline

Multi-pass post-processing with p5.strands and pipe(). Three filter passes — depth-of-field blur, value-noise warp, and pixelation — are chained over a scene framebuffer. Each pass is a baseFilterShader().modify() callback; createPanel wires their uniforms automatically. Press 1, 2, or 3 to rotate the pass ordering at runtime. Shader passes as strands callbacks Each post-processing pass is a baseFilterShader().modify() callback — a plain JavaScript function using the p5.strands DSL. The framework compiles each callback to WebGL2 at startup; no raw GLSL strings are needed. ...

April 9, 2026 · 2 min · Theme PaperMod

Toon shading

Toon shading, or cel shading, gives 3D geometry a flat, cartoon-like look by quantizing diffuse reflection into a finite number of discrete shades. In this p5.js v2 version the shader is written as a baseMaterialShader().modify() hook using the p5.strands DSL — no raw GLSL strings, no hand-written vertex shader. createPanel wires the color and shades controls to the shader automatically each frame. Toon shader The combineColors hook in baseMaterialShader().modify() receives the eye-space vNormal varying directly — no vertex shader boilerplate required. Diffuse intensity is the dot product of the surface normal and the (normalized) light direction; it is then snapped into discrete bands to produce the cel-shading look. ...

April 9, 2026 · 3 min · Theme PaperMod