Skip to content

cedric-h/linear-webgl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EDIT: this started out with the lofty goals stated below, and quickly just became my scratchpad where I test out random ideas, only most of which are WebGL-related ...

webgl demos in a single file, the way god intended

If you ask me, any attempt to make an abstraction over WebGL ... only makes it more difficult to use.

But don't take it from me, let's look at the numbers:

WebGPU will be nice, but I've been waiting for it since 2018. It's only just been rolled out in a single browser, it will be forever before it makes it to low-end mobile devices, and that's where performance (and therefore clever graphics programming) matters the most.

So raw, unadulterated WebGL it is. Webglfundamentals.org is great, but it's just that: fundamentals. I want scrollbars and dropshadows and examples where those "fundamentals" are used to do real shit.

Ergo: flat, linear WebGL.

Other useful resources in the same vein:

simple

link desc
tri triangle; starting-off point; well, I tri-d.
lines shows how to do constant-screenspace-thickness 3D-based lines.
gazebo simple OBJ model
Screenshot 2024-03-08 at 2 54 01 PM

from cube to simple 3D editor

link desc
cube it's a cube.
cube grid this cube has a grid!
cube camera this cube has a grid AND mouse-based camera controls!
cube gizmos cube, grid, mouse-based camera controls, and "gizmos" (translate, rotate, scale
cube editor everything in gizmos + support for multiple things, undo/redo, etc.
Screenshot 2024-05-06 at 12 48 29 PM

reprojection (shadows and painting)

link desc
shadow super simple shadow with no PCF, etc. just reprojection
shadow_bake soft shadows + ambient occlusion + shadows dynamically from progressive lightmap
paint helpful to read alongside shadow code. also silly, messy, and fun!
scroll_thick the scroll scrolls, the paint paints. it's cool!
zen terrain painter click and hold to make mountains. it's cool!
Screenshot 2024-05-06 at 12 45 15 PM
ok.mov

nodes

interactive data thing with text, drop shadows, zooming, panning, scrollbars, etc. (yes, all from scratch in WebGL)

nodes, nodes-rpi

also: nodes-rpi, a WebGL 1 version that works (~25 fps) at low resolutions on a raspberry pi Model B that only supports WebGL 1

(this was a rewrite of an SVG-based application that got 200ms frametimes (5 fps) on a $3000 macbook)

Screenshot 2024-03-08 at 2 40 15 PM

Computational Geometry and Physics

I'm constantly exploring and improving my understanding of computational geometry.

Screenshot 2025-04-30 at 11 37 54 PM

These use canvas instead of WebGL because the rendering isn't really the point.

link desc
earclip minimal (~70 lines) earclipping implementation, with interactive visualization
z order curve helps you to develop an intuition for why z-order curve hashing is useful for spatial hashes
web finder solves a fun geometry puzzle where a bunch of lines need to turn into a tree
rope simple 2D verlet integration

Asset cookers

These turn animations, fonts, and SVGs into simple C headers so you can use them easily in WASM/native projects.

They use canvas instead of WebGL because the rendering isn't really the point.

Screenshot 2025-04-30 at 11 39 16 PM
link desc
guy.html turns mixamo animations into cool stick figures
svg cooker turns SVGs into geometry buffers (vertices and indices) - drag and drop the SVG on
font cooker turns fonts into SDF textures - why include stb_truetype for one font?

text

simple text demo, based on mapbox's TinySDF

I've tried a lot of different mechanisms for doing text and this one works the best by far with arbitrary zoom

link desc
text shows off tinysdf, arbitrarily zoomable text on an infinite canvas
text-dropin simpler text (no controls) you can just drop into an existing project
text-clipped example of how to clip text without scissor rects, useful for doing a lot of text with few drawcalls

also: example of how to clip text without scissor rects, useful for doing a lot of text with few drawcalls

Screenshot 2024-03-08 at 2 54 36 PM

quad squad

link desc
quad premultiplied alpha
quad-blur separable gaussian blur
quad-blur-depth separable gaussian blur + depth texture attached to rendertarget
quad-shadow demonstrates prebaking shadow for static geometry so you don't need to redo every frame -- can be easier for layering as well.
quad-woosh some fun with feedback transforms
Screenshot 2024-03-10 at 11 34 47 PM

✨ texture time ✨

link desc
image emoji -> canvas -> texture -> quad -> screen
image_atlas like "image," but demonstrates how to use several images on a single atlas.
galaxy see above + fun with gaussian blur
skybox all that, inside a spinning cube!
shadow has a one-shot function which adds a (customizable) shadow to a texture. pretty handy!
Screenshot 2024-06-04 at 2 32 42 PM Screenshot 2024-05-06 at 12 49 59 PM

🚀 instancing 🚀

link desc
pulling_texture useful when your instances need random access to a buffer of data (e.g. compute-type things)
pulling_buffer useful when your instances can use sequential data from a buffer; output looks just like pulling_texture
graph_slow just calls drawLine; naive, slow, CPU-bound graph
graph_fast exactly the same as graph_slow, but it does the slow part on the GPU.
graph_100k stress test; graphing 100k datapoints in red, and 2 million in blue. works well on M2 Max
graph where I keep the actual good up-to-date graph code.

super performant graph, outperforms chart.js, echarts, amcharts by about x100

Screenshot 2024-06-01 at 9 38 09 PM

errata

I'll fix these eventually, but

I say "high-retina" in almost every demo, where I should say "high-resolution retina" (one brain skip, copy/pasted a million times)

paint.html is the only demo which has a touchscreen rotatable camera, and almost the only demo where the camera doesn't skip if you rotate up too far. (That is just a one-line fix after yaw =.) More work is necessary for many demos to make sure they work on mobile. EDIT: some issues with the touch controls here, needs a rework. Probably need to completely separate this codepath from mouse controls.

On the topic of camera controls, scroll_thick.html and sphere_texture.html have much smoother camera controls than cube_camera, cube_grid, cube_editor, etc. Also probably some other demos which use that camera code outside of the cube family which I have forgotten.

I say "set up premultiplied alpha," then do gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_DST_ALPHA) but the way premultiplied alpha works, the color should be multiplied by ... nothing. gl.ONE. It's premultiplied. So I need to audit transparency in a lot of places. Alternatively, I could keep that "premultiplied alpha" blend func, and simply divide rgb by a in the shader, which may be preferable since premultiplication is lossy. Should note if so though because it's not obvious.

There are some places where things aren't especially "linear" or flat. I do have indirection/object orientation/etc. in some instances. I ought to audit myself to see if I'm doing so tastefully. Or perhaps it simply doesn't matter.

In several .htmls (cube family in particular) input.released is commented "true for a frame after up," when it is actually "true for a frame after down." Not as simple as just updating the comment, because _released shouldn't be the field name.

Pretty much all of the files have a let shaders; { } block, but they switch between vs_shader/fs_shader vs. shader_fs/shader_vs, and this should be homogenized.

errata - optimization

Plenty of matrices are allocated that don't need to be.

Plenty of buffers are recreated every frame when they could be created once at init, and almost everywhere buffers are created dynamically, the TypedArray is created on the fly every frame, and I would prefer to avoid the allocation if possible.

There are examples which do not perform well on my iPhone 8 (2017). Warrants investigation. I suspect the dampedEvent *= 0.8 could be exacerbating things, should probably use a framerate independent approach there.

About

WebGL demos, but flat. Because it's more hackable that way.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages