Sprite Demo
App: apps/sprite_demo/
Demonstrates billboarded sprites: one PNG loaded with Texture.load, drawn as four
tinted, camera-facing quads at different depths. The sprites overlap, and because the
renderer sorts them back-to-front by view-space depth each frame, the nearest (blue) draws
over green over red. Runs unattended — there is no input; it takes a screenshot after
1.5 seconds and then just keeps drawing.
Run from root
Section titled “Run from root”% ./plume3d sprite_demoWhat it does
Section titled “What it does”- Loads a single texture with
Texture.load("textures/circle.png")and logs_tex.validplus_tex.width×_tex.heightviaLogger.info. The one texture is shared by all four sprites. - Builds the scene procedurally — no blend file.
Scene.new(), thenaddCamera()andaddNode("cam")at(0, 0.6, 6)withlookAt(0, 0, 0); FOV0.8rad, near0.1, far100. - Creates four
Sprite.new(_tex)instances, each with its ownsizeandcolor([r, g, b, a]tint, all at alpha0.95): red at z-3.0(farthest, size 2.4), green at z-1.0, blue at z1.0(nearest), and a yellow one off to the side at(1.4, 0.9, 0.0). - Sets
billboard = 0(spherical) on every sprite — this app only exercises the default mode, not cylindrical (1) or flat (2). - Keeps the sprites in a plain list of
[sprite, x, y, z]tuples and callsdrawAton each one every frame. Draw order does not decide occlusion — the renderer sorts the frame’s sprites by view-space depth, so the cascade reads correctly regardless. - In
draw, enables the 3D path withGraphics.setViewProjectionEnabled(true)and feeds it_cam.getViewMatrix()/_cam.getProjectionMatrix(aspect), where aspect comes fromWindow.getWidth() / Window.getHeight()(guarded to1if it degenerates below0.01). - In
update, counts down 1.5 s and then firesEngine.screenshot("sprite_demo.png")once, latching a_shotflag so it never repeats. - No lights and no shadow mapping — sprites are unlit, alpha-blended textured quads.
Key pattern
Section titled “Key pattern”// One texture, four sprites, each with its own size and tint._tex = Texture.load("textures/circle.png")
addSprite(-0.9, 0.0, -3.0, [1.0, 0.45, 0.45, 0.95], 2.4) // red, farthestaddSprite(-0.3, 0.0, -1.0, [0.5, 1.0, 0.5, 0.95], 2.2) // greenaddSprite( 0.3, 0.0, 1.0, [0.5, 0.7, 1.0, 0.95], 2.0) // blue, nearest
addSprite(x, y, z, color, size) { var s = Sprite.new(_tex) s.size = size // world-space height; width follows texture aspect s.color = color // [r, g, b, a] tint, multiplied with the texture s.billboard = 0 // spherical (camera-facing on every axis) _sprites.add([s, x, y, z])}
// Re-submitted every frame; the renderer depth-sorts them for you.for (e in _sprites) { e[0].drawAt(e[1], e[2], e[3])}- Sprite —
new,size,color,billboard,drawAt. - Texture —
load,valid,width,height. - Scene —
new,addCamera,addNode. - Camera —
setNode,setFovYRadians,setNearPlane,setFarPlane,getViewMatrix,getProjectionMatrix. - Graphics —
setViewProjectionEnabled,setViewMatrix,setProjectionMatrix. - Window —
getWidth,getHeight. - Engine —
screenshot. - Logger —
info.