- The editor drives a RasterRender from the application GpuDevice and shows the
path-traced frame through a Canvas RGBA image instead of a GL texture.
- Sketch3D renders strokes with a geometry-shader pipeline on a shared
RenderTarget, caching one vertex buffer per stroke version, and splits the
renderer from the widgets so it can be tested headless.
- Both apps pass a device to the widget that renders into the Canvas.
3DScene:
- Scene::castRay is const and returns std::optional<RayHit>; RayTracer reuses it
instead of its own copy of the loop.
- Scene::loadLua throws SceneLoadError with the failing field; Lua stack values
are popped by scope guards and the state is closed on every path.
- Objects get a stable id and are added through addObject/findObject.
RasterRender:
- Replaces the OpenGL renderer with a Vulkan one on GpuDevice.
- RenderTarget: offscreen color/depth images with optional MSAA, registered in
the device RenderTargetRegistry for Canvas sampling, plus a pixel readback.
- GpuBuffer and GraphicsPipeline: reusable host-visible buffers and a
pipeline builder shared by the scene and sketch renderers.
- The scene holds no GPU state; RasterRender caches one mesh per object id and
drops meshes of removed objects. The highlight is drawn in the same pass so
it no longer clears the scene.
- Tests render headless and read back pixels to verify depth shading, row
orientation against Camera::project, the highlight, resize and mesh release.
- TrigCache::castRay returns std::optional<halnf> for the hit distance instead
of writing a static hit position through static scratch variables, so ray
casts are reentrant.
- TopologyCache::update takes its source Topology instead of holding a pointer
that dangled whenever a Buffer moved the objects it referred to.