Skip to content

Design 3D

Randall C. O'Reilly edited this page Jan 25, 2024 · 1 revision

Overall design

The scenegraph is rooted at a gi3d.Scene node which is like gi.Viewport2D, where the scene is rendered, similar to the svg.SVG node for SVG drawings.

Children of the Scene are Node3D nodes, with Group and Solid as the main subtypes. Node3DBase is the base implementation, which has a Pose for the full matrix transform of relative position, scale, rotation, and bounding boxes at multiple levels.

  • Group is a container -- most discrete objects should be organized into a Group, with Groups of Solids underneath. For maximum efficiency it is important to organize large scenegraphs into hierarchical groups by location, so that regions can be pruned for rendering. The Pose on the Group is inherited by everything under it, so things can be transformed at different levels as well.

  • Solid has a Material to define the color / texture of the solid, and the name of a Mesh that defines the shape.

Objects that have uniform Material color properties on all surfaces can be a single Solid, but if you need e.g., different textures for each side of a box then that must be represented as a Group of Solids using Plane Mesh's, each of which can then bind to a different Texture via their Material settings.

Node bounding boxes are in both local and World reference frames, and are used for visibility and event selection.

All Meshes are stored directly on the Scene, and must have unique names, as they are referenced from Solids by name. The Mesh contains all the verticies, etc that define a shape, and are the major memory-consuming elements of the scene (along with textures). Thus, the Solid is very lightweight and just points to the Mesh, so Meshes can be reused across multiple Solids for efficiency.

Meshes are only indexed triangles, and there are standard shapes such as Box, Sphere, Cylinder, Capsule, and Line (rendered as a thin Box with end points specified).

Textures are also stored by unique names on the Scene, and the Material can optionally refer to a texture -- likewise allowing efficient re-use across different Solids.

The Scene also contains a Library of uniquely-named "objects" (Groups) which can be loaded from 3D object files, and then added into the scenegraph as needed. Thus, a typical, efficient workflow is to initialize a Library of such objects, and then configure the specific scene from these objects. The library objects are Cloned into the scenegraph -- because the Group and Solid nodes are lightweight, this is all very efficient.

The Scene also holds the Camera and Lights for rendering -- there is no point in putting these out in the scenegraph -- if you want to add a Solid representing one of these elements, you can easily do so.

The Scene is fully in charge of the rendering process by iterating over the scene elements and culling out-of-view elements, ordering opaque then transparent elements, etc.

There are standard Render types that manage the relevant GPU programs / Pipelines to do the actual rendering, depending on Material and Mesh properties (e.g., uniform vs per-vertex color vs. texture).

OpenGL design

Current strategy is to start with OpenGL and get stuff working, and then migrate to Vulkan in a second step. Key is to develop a good strategy overall that will be portable.

How to code opengl to be vulkan-friendly:

Program abstraction

  • each program deals with a particular case: opaque, transparent, shadows, etc -- most efficient to batch everything according to these factors. transparent comes last. and within that, faces need to be sorted.

  • shadows etc require multiple programs and steps and sorting..

  • Vertex and Fragment shaders need to use Uniform Buffer Objects (UBO) which can be shared across programs and more quickly updated.

Bounding boxes

Vulkan Notes

$ tar -xzf vulkan-sdk.tar.gz 
$ cd vulkansdk-macos-1.1.101.0/
$ sudo cp -av MoltenVK/macOS/framework/MoltenVK.framework /Library/Frameworks/
$ sudo cp -av macOS/Frameworks/vulkan.framework /Library/Frameworks/
Clone this wiki locally