v2026.9.4
All Bundles
Bundle OpenGL 3.3 core rendering on top of SDL2. Builds on sdl2.obl for the window and context; this bundle is the GL side. Compile with -lib sdl2. Targets the **3.3 core profile**, forward-compatible. That is the highest common denominator across the platforms Objeck ships: Windows, Linux and macOS desktop all reach it, and macOS caps at 4.1 core so nothing above 4.1 is portable there. GLES-only hardware (Raspberry Pi and similar) is out of scope by construction. Layers, from thinnest to friendliest -- all public, so nothing is capped: * GLWindow -- a window and a 3.3 core context, opened and paced for you. * GL -- static state operations. Thin, but never per-vertex. * Shader -- a linked program; Flat/Textured/TexturedFog/Normals built in, so the common cases need no GLSL at all. * Mesh -- geometry uploaded once into buffer objects, drawn many times, with Cube/Plane/Quad/Sphere built in, OBJ loading, and instancing. * Texture2D -- a texture, from a file or generated; Solid/Checker built in. * Light -- one directional light plus ambient, written into a shader. * RenderTarget -- draw into a texture instead of the window, then sample it. * Material -- a surface: its texture, tint and shininess. * Frustum -- the six planes of a view, for skipping what is off screen. * ShadowMap -- shadows from a directional or spot light, depth pass and all. * PointShadow -- shadows from a point light, in every direction, via a cube map. * Overlay -- text and rectangles over the scene, positioned in pixels. * Transform -- position, rotation and scale, with a cached matrix. * Box, Scene -- a world of boxes: draws itself, and answers collision. ## Why the API is shaped this way The native call boundary is expensive: the VM resolves each native symbol by string on EVERY call (GetProcAddress/dlsym) and boxes every argument into a fresh holder. A 1:1 mapping of OpenGL onto that would be thousands of lookups and allocations per frame. So each call here does real work -- 'compile a program from two sources' is one call, not the five GL calls it decomposes into -- and bulk data crosses as whole arrays, never element by element. This happens to be exactly what GL 3.3 core wants anyway: upload geometry once, then draw with few calls. ## Adding a call One `void fn(VMContext&)` in the OpenGL section of core/lib/sdl/sdl.cpp, and one method here that names it. See that file's header for the two rules that matter (positional slot indices, and keeping each call coarse).

Prop

A mesh, a material and a transform -- the thing Scene could not hold. Scene draws every Box with the ONE mesh it was given, which is what keeps a room of hundreds of boxes down to a single uploaded mesh. Anything that is a different mesh plus a transform therefore had no home, and every example that wanted one wrote the same five lines by hand: bind the texture, build the MVP, upload two matrices, draw. That sequence appears in gl_boing, 3d_gl_24, gl_model and gl_lantern. A Prop is that, as an object Scene can hold. ## Why this is not Box widened Box stays exactly what it was, and Scene keeps two lists. That is deliberate: - A Box is axis-aligned by construction, so it culls against a tight box test. A Prop has a rotation, so its mesh bounds are model-space and stop being axis-aligned the moment it turns -- it has to fall back to a bounding SPHERE, which is looser. Merging the two would have cost every wall and floor in every existing scene that accuracy. - Boxes share one mesh and one VAO. Props each bring their own, so a VAO rebind per prop is unavoidable -- but only for props. - Collision is a Box concept. OverlapsXZ is a plan-view test on a half-extent and means nothing for a rotated model, so Prop deliberately does not have it and Scene->Blocked still walks only the boxes. A prop that should block movement gets a Box beside it. ## Concrete, not abstract A class carrying a virtual method cannot be instantiated in Objeck, so an abstract Prop would need a subclass before anyone could use one. This is usable directly and can still be subclassed.

Operations

GetBoundsRadius #

Radius of a sphere that contains this prop wherever it is turned. Conservative on purpose: the mesh's own radius is measured from the mesh's CENTRE, which need not be the origin the transform rotates about, so the offset is added rather than assumed away. A bound that is slightly too large draws something that could have been culled; one that is too small makes geometry vanish at the edge of the screen.

method : public : GetBoundsRadius() ~ Float

Return

TypeDescription
Floatthe radius in world units

GetModelMatrix #

method : public : GetModelMatrix() ~ Float[]

Return

TypeDescription
Floatthe model matrix; BORROWED from the transform, do not write to it

GetTransform #

The prop's transform, to move, turn or scale it. Returned rather than copied, so changes take effect immediately.

method : public : GetTransform() ~ Transform

Return

TypeDescription
Transformthe transform

IsOpaque #

method : public : IsOpaque() ~ Bool

Return

TypeDescription
Booltrue when this prop needs no depth sorting

New # constructor

New(mesh:Mesh, material:Material)

Parameters

NameTypeDescription
meshMeshthe geometry; the prop does NOT own it, so a mesh shared between props is freed once
materialMaterialhow to draw it; may be Nil for the scene's current state

New # constructor

A prop at a position, with no material of its own.

New(mesh:Mesh, x:Float, y:Float, z:Float)

Parameters

NameTypeDescription
meshMeshthe geometry
xFloatwhere to put it
yFloatwhere to put it
zFloatwhere to put it