| name | orklev2-scenegraph |
| description | Answer questions about orkid's scene graph rendering system, Scene/Layer/Node hierarchy, drawables, cameras (CameraData, EzUiCam), lighting (point/directional/spot), probes, SceneGraphViewport, and Python scene composition. Use when the user asks about 3D scenes, models, cameras, lights, or rendering setup. |
| user-invocable | false |
Orkid Scene Graph Rendering Reference
When answering questions about scene graphs, 3D rendering, cameras, or lighting in orkid, consult these files. All under ork.lev2/.
Key Files
| Component | Header |
|---|
| Scene/Layer/Node | inc/ork/lev2/gfx/scenegraph/scenegraph.h |
| Drawable System | inc/ork/lev2/gfx/renderer/drawable.h |
| CameraData | inc/ork/lev2/gfx/camera/cameradata.h |
| EzUiCam | inc/ork/lev2/gfx/camera/uicam.h |
| Lighting | inc/ork/lev2/gfx/lighting/gfx_lighting.h |
| SceneGraphViewport | inc/ork/lev2/ui/viewport_scenegraph.h |
| Python Bindings | pyext/src/pyext_gfx_scenegraph.cpp |
Implementations: src/gfx/scenegraph/, src/gfx/camera/, src/gfx/lighting/
Hierarchy
Scene
├── Layer (named, sorted by _sortkey)
│ ├── DrawableNode (holds Drawable)
│ ├── LightNode (holds Light)
│ └── ProbeNode (holds LightProbe)
└── LightManager, CompositingData, CameraDataLut
Scene Creation (Python)
params = core.VarMap()
params.preset = "ForwardPBR"
params.SkyboxTexPathStr = "nebula"
params.clearcolor = fvec3(0.1, 0.1, 0.5)
scene = lev2.scenegraph.Scene(params)
layer = scene.createLayer("std_forward")
Drawable Types
| Type | Purpose |
|---|
ModelDrawableData | 3D model from file (glb/gltf) |
InstancedModelDrawableData | Instanced rendering (SSBO, up to 65536) |
CallbackDrawable | Custom procedural rendering |
StringDrawableData | 2D text |
BillboardStringDrawableData | Screen-facing text |
model_data = lev2.ModelDrawableData("data://tests/testcube.glb")
drawable = model_data.createDrawable()
node = layer.createDrawableNode("cube", drawable)
node.worldTransform = matrix
node.modcolor = fvec4(1, 1, 1, 1)
node.enabled = True
inst_data = lev2.InstancedModelDrawableData("data://models/sphere.glb")
inst_data.resize(1000)
inst_drawable = inst_data.createDrawable()
node = layer.createDrawableNode("spheres", inst_drawable)
Camera Setup
cam = lev2.CameraData()
cam.Lookat(eye=fvec3(0,3,8), tgt=fvec3(0,0,0), up=fvec3(0,1,0))
cam.Persp(near=0.1, far=1000.0, fov_degrees=45.0)
camera_lut = lev2.CameraDataLut()
camera_lut.create("main_cam")
from lev2utils.cameras import setupUiCameraX
cam_data, ui_cam = setupUiCameraX(
cameralut=camera_lut, camname="main_cam",
eye=fvec3(0,3,8), tgt=fvec3(0,0,0), up=fvec3(0,1,0), far=1000.0)
def on_cam_event(ev):
handled = ui_cam.uiEventHandler(ev)
if handled:
ui_cam.updateMatrices()
cam_data.copyFrom(ui_cam.cameradata)
return lev2.ui.HandlerResult()
Lighting
light_data = lev2.PointLightData()
light_data.mColor = fvec3(1, 1, 1)
light_data._intensity = 1.0
light_data.mbShadowCaster = True
light = light_data.createDrawable()
light_node = layer.createLightNode("main_light", light)
light_node.setMatrix(transform_matrix)
dir_data = lev2.DirectionalLightData()
dir_data.mColor = fvec3(1, 0.9, 0.8)
dir_data._intensity = 0.5
spot_data = lev2.SpotLightData()
spot_data.mFovy = 45.0
spot_data.mRange = 50.0
Light types: ELIGHTTYPE_POINT, ELIGHTTYPE_DIRECTIONAL, ELIGHTTYPE_SPOT, ELIGHTTYPE_AMBIENT
SceneGraphViewport Widget
item = layout_group.makeChild(
uiclass=lev2.ui.SceneGraphViewport, args=["viewport"])
sgvp = item.widget
sgvp.scenegraph = scene
sgvp.cameraName = "main_cam"
sgvp.camera_evhandler = on_cam_event
sgvp.forkDB()
lev2.ui.SceneGraphViewport.gpuUpdateAll(context)
Layer Conventions (PBR2 Phase 0)
The forward pipeline knows these layer roles (fwdnode_impl_top.cpp:k_roles[]):
| Layer | Purpose | Rendered in probe cubemap? |
|---|
depth_prepass | Depth prepass | yes |
std_forward | Main scene geometry | yes |
std_editor | Editor gizmos/grid | no (post-pass, gated on !_renderingPROBE) |
probe | Probe-only geometry | yes |
depth_probe | Probe depth | yes |
hud_overlay | HUD text / debug overlays | no (post-pass, gated on !_renderingPROBE) |
The probe cubemap CPD calls assignLayers(probe->renderLayer()) as a hard reset — only that one layer renders during a probe capture. Place HUD/debug content on hud_overlay, editor gizmos on std_editor, so neither appears in reflection probes.
Probe Nodes Register With LightManager
Layer::createProbeNode(name, probe) adds the probe to LightManager._lightprobes, making it discoverable via LightManager::findProbeByName(name). Non-lighting subsystems (e.g. ECS ParticlesGlobalSystem) resolve probes by entity name at _onActivateComponent time and cache the resolved lightprobe_ptr_t on the drawable (Drawable::_probeOverride) for per-draw cubemap selection.
Render Loop
scene.updateScene(camera_lut)
scene.renderOnContext(context)
Node Properties
node.worldTransform = fmtx4()
node.modcolor = fvec4(1,1,1,1)
node.enabled = True
node.pickable = True
node.view_relative = False
Thread Safety
Scene graph uses LockedResource<T> for all collections:
nodes = layer.drawable_nodes
layers = scene.layers
How to Answer
- For scene setup: read
scenegraph.h and pyext_gfx_scenegraph.cpp
- For drawables: read
drawable.h for all DrawableData types
- For cameras: read
cameradata.h and uicam.h for EzUiCam
- For lighting: read
gfx_lighting.h for all light types
- For examples: check
ork.lev2/pyext/tests/ui/sgui_emb_sg.py