I wanted to share a technical journey that spiraled completely out of hand. It started with one simple question: How do you draw an arbitrary, non-symmetrical triangle in Delightex Nova / Delightex Edu when the engine doesn’t offer a standard triangle primitive?
Here is the complete breakdown of what I’ve built so far and the theory I’m tackling next!
1. Solving the Primitive Problem [Already Done]
Delightex provides a Frustum4 primitive object, which can be manipulated into isosceles triangles. Through geometry and angle splitting, I realized any arbitrary triangle can be constructed using at most 4 isosceles triangles:
-
Isosceles: 1 primitive directly.
-
Right-angle: 2 primitives (split along the altitude line).
-
Acute: 3 primitives (decomposed from the interior).
-
Obtuse: 4 primitives (decomposed across the obtuse angle).
How to create arbitrary triangle ( a polygon ) in-game-time! - #4 by HenryHuy
2. Custom Meshes, CSG & Physics [Already Done]
Once you can construct arbitrary triangles, you can build custom polygon meshes. From there, I expanded the architecture:
-
Constructive Solid Geometry (CSG): Implemented Union, Difference, and Intersection operations to perform boolean geometry on custom models.
How to edit mesh in game time - CSG system -
Quadric Error Metrics (QEM): Built mesh decimation algorithms to simplify high-poly models dynamically.
-
Terrain & Physics: Integrated multi-octave Perlin noise for terrain generation, alongside a spring-mass constraint system for soft-body mesh physics.
Infinite map + Smooth terrain generation ( triangular terrain generation ) - #11 by HenryHuy
3. The Texturing Bottleneck & Asset Pipeline [Already Done]
Single-color models got old quickly, so I experimented with texturing and asset loading:
-
Asset Pipeline: Converted
.obj3D files and.ppmimage files into.txtdata, pasted them directly into.tsTypeScript files, and wrote custom parsers to deserialize and render them. -
Attempt 1 (Polygon Subdivision): Subdivided mesh faces into smaller fragments to color each vertex. It worked, but destroyed frame rates due to face inflation.
-
Attempt 2 (Surface Pixels): Mapped tiny 3D square primitives directly onto mesh surfaces like decals. This separated texture from mesh geometry, but broke under scale due to primitive count limits and severe Z-fighting.
4. Paradigm Shift: Bypassing the 3D Engine [Theory]
Since placing 3D primitives for textures hits engine bottlenecks, my next idea is a complete radical shift: stop fighting Delightex’s 3D engine constraints and treat it as a raw 2D pixel display canvas.
-
Software CPU/GPU Simulator: Instead of rendering 3D geometry inside Delightex’s native 3D world, use 2D square primitives as pixels on a 2D screen grid.
-
Decoupled Performance: By controlling the 2D grid programmatically, performance shifts entirely from 3D mesh complexity to 2D screen resolution.
-
Shading & 4D Projections: Running a custom software renderer inside Delightex opens the door to custom pixel shaders, software Z-buffering, custom texture mapping, and even projecting 4D dimensional objects onto the 2D display.
5. Octree Screen Optimization [Theory]
To make a 2D software screen performant inside Delightex:
-
Instead of rendering thousands of individual 1x1 screen pixels every frame, use an Octree/Quadtree spatial structure.
-
The tree will dynamically scan adjacent screen pixels of identical color and merge them into single, larger square primitives, drastically lowering draw calls.
Has anyone else attempted custom software rendering or primitive hacks in Delightex? Would love to swap ideas!