This document consolidates the current and intended rendering architecture, clarifying responsibilities, data flow, and lifecycle across Scene Nodes, CPU render data, GPU render objects, and the render cycle.
It reflects:
Application Assets (basePath): Example-specific assets
| Build | Location | Set By | |
| Debug | Example source directory | ASSETS_ROOT_DIR CMake define |
<example_dir>/assets/ (source) |
| Release | Executable dir | getExecutablePath() at runtime |
<exe>/assets/ (deployed) |
2. Engine Library Resource Paths (resourceRoot)
| Build | resourceRoot Value |
Determined By | Engine Resources Location |
|---|---|---|---|
| Debug | Project root + /resources/ |
DEBUG_ROOT_DIR + /resources/ |
<project>/resources/ (source) |
| Release | Library dir + /resources/ |
getEnginePath() + /resources/ |
<lib>/resources/ (deployed) |
Usage:
// Application assets
auto appTexture = PathProvider::getTextures("brick.png");
// Engine resources
auto engineShader = PathProvider::getResource("PBR_Lit_Shader.wgsl");
Key Rules:
PathProvider for all paths (never hardcode)assets/ = example-specific, resources/ = engine-wideProject Root/
├── build/
│ └── Windows/
│ ├── Debug/ # Engine library + dependencies
│ └── Release/
├── examples/
│ └── build/
│ └── <example_name>/
│ └── Windows/
│ ├── Debug/ # Example executable + copied assets
│ └── Release/
└── resources/ # Source assets (Debug builds access directly)
Key Points:
resources/ directlyPathProvider to ensure path portabilityEach layer has a strict responsibility:
| Layer | Responsibility |
|---|---|
| Scene Nodes | Visibility, transforms, scene logic |
| CPU Render Data | Geometry, materials, submesh layout |
| GPU Render Objects | GPU buffers, bind groups, pipelines |
| RenderItem | One draw call |
| Renderer | Sorting, batching, issuing draws |
No layer reaches “up” or sideways.
Indented example:
Mesh
├─ vertices[]
└─ indices[]
Indented example:
struct Submesh
{
uint32_t indexOffset;
uint32_t indexCount;
MaterialHandle material;
};
Indented example:
Model
├─ MeshHandle
└─ Submesh[]
ObjGeometryData)ObjLoader does not create materials or GPU objects.
It outputs:
tinyobj::material_tIndented example:
ObjGeometryData
{
vertices
indices
materials // tinyobj materials
materialRanges[] // offset + count + materialId
}
This avoids:
Indented example:
WebGPUMesh
├─ vertexBuffer
├─ indexBuffer
└─ updateGPUResources()
Submeshes do not become separate GPU meshes.
Indented example:
WebGPUMaterial
├─ shaderType OR customShaderName
├─ textures[]
├─ bindGroup
└─ updateGPUResources()
Shader lookup happens via:
context.shaderRegistry()
WebGPUShaderInfoShaderType)Materials store identifiers, not shader objects.
RenderObject::getRenderItems() or similarpreRender()onRenderCollect(RenderCollector&)postRender()onRenderCollect():
RenderItems for each submeshRenderItems collected for batching / sortingRenderItemsdirty flag and CPU versionupdate():