Files
solvecraft/docs/render-workspace.md
T
Nathan Dane 85a60c1af6 Render output: Output editor, size presets, Check list, Copy, progress pill and result viewer (#6281) (#6433)
* Render output: size presets, Check list, Copy, progress pill, R and Esc, and the result viewer

* Complete Output GPU help translations and format choices

* Remove Output size labels already present in catalogs

* fix: compile the legacy finishing controls only for tests
2026-10-28 20:55:55 +00:00

29 KiB
Raw Blame History

Integrated Render workspace (R3)

The native image panel offers CPU raster, optional CPU ray tracing and GPU path tracing as explicit image methods. All three methods can be edited and saved offline. Check and Start are enabled only when the selected method has an installed supporting host; an unavailable method never falls back.

R4a builds on this viewport contract with a separately advertised CPU product-image executor and Check/Start/Cancel/Export controls. See render jobs for the asynchronous protocol, image limits, captured revisions and PNG export. The legacy ui.render snapshot remains a separate route.

Choose Render in the workspace switcher after finishing a modelling operation. The current integrated GPU renderer shows a separate product scene. Return to Design restores its camera, projection preference and existing viewport drawing policy. The live product preview remains independent of the selected image method.

Stage bar and floating docks

Render has no ribbon. A shared 88 pt two-row stage bar sits 8 pt to the right of the 104 × 88 pt workspace card, with matching top and bottom edges. The icon sits above the Render label and Workspace caption. The header is 36 pt; the remaining 52 pt contains the tools, centred vertically below a 1 pt divider. Numbered Look, Light, Frame and Output chips run view.render_stage {stage: look|light|frame|output}. The selection belongs to the open document tab's view state; it is not saved in the design. Opening a stage never applies or saves settings or starts an image job. It focuses the existing Inspector page, while every Inspector page and registered Render command remains reachable. The headless command validates and echoes the request without changing the document.

Render, Cancel and the shared command search (S) occupy the top row. The Pick control's icon-text Body/Face/Component segments, Paint/Pick Up actions and direct-light preview information chip occupy Look's second row with 8 pt side padding. Changing the light coordinate frame remains disabled with its reason in this checkout. Frame uses the existing explicit camera command for projection and the registered Save Shot action opens the shared naming confirmation; Output shows the current size/format and directs edits to the Output Inspector. No completion ticks are inferred.

The Browser and Inspector float in both shell layouts and share a top edge, 8 pt below the bar. Their default outer widths are 266 pt and 305 pt, with shared resize bounds. The Browser keeps the upper left card (up to ten compact scene rows); its stage panel fills the remaining height below it, ending 8 pt above the 48 pt Shots strip. Both cards share width and side preferences. Narrow windows shorten the Browser to reserve library space, then omit cards that cannot fit safely.

Look hosts Appearances: search with the actual catalog count, In Design / Library / Recent / favorites scopes, horizontally scrolling category chips and a three-column sphere grid or list. Resources used in the design or matching a selected look's finish family or category appear first. Clicking a look applies through appearance.assign to selected bodies, faces or components; with no target it only inspects. Favorites and recent history live in user preferences. Explicit catalog navigation from the Inspector retains the read-only resource browser.

Light hosts the existing native studios and HDR environments in the same tile grid. A click runs render.preset.apply or render.library.environment.apply, preserving those commands' validation and undo behavior. Studios require an explicitly selected GPU path setup; environments require CPU or GPU ray tracing. Frame shows a faded Frame presets placeholder with its Shot editor reason. Output hosts the Size presets card described below. Stage navigation itself never applies a resource.

The 110 pt compass uses the free canvas beside the Inspector; the navigation bar keeps its shared handler. The Shots strip's independent view.shots_strip preference is unchanged.

view.render_focus {on: true} hides the Browser, Inspector and Shots strip and releases their canvas reservations. Tab toggles focus while Render is active and no text field has focus; the Exit focus chip sits at the Browser's remembered side below the stage bar. The workspace card, stage bar, compass and view bar remain available. Focus belongs to the window, is never saved in a design or preferences, and retains the docks' sides, widths and folded state.

Below 1100 pt, or with view.layout {mode: compact}, the docks use their shared minimum width without overwriting the remembered width. Below 800 pt the Browser folds into a chip. Its floating card opens through view.render_browser {open: true} and closes through Fold Browser; it shields navigation beneath the card without reserving a canvas column. Neither command edits or evaluates the design, moves the camera or creates an undo step.

Image methods and controls

CPU raster produces the existing preview PNG with approximate transparency. CPU ray tracing requires a native worker and the raytrace-cpu build feature. Its panel offers Single image with 1, 4 or 16 spatial samples per pixel, or CPU progressive with 1–64 accumulated samples and a separate seed. Both use Neutral / Warm and cool / Key and rim lighting, cast shadows and exposure from −16 to +16 EV. Progressive sampling has a 1,048,576-pixel and 16,777,216 pixel × sample limit; the UI proposes a smaller size only as an explicit action. It requires an opaque background; the panel explains the incompatibility and lets the user clear Transparent background. Additional collapsible sections expose body reflections, captured HDR or constant environments, directional lights and point lights. Reflection bindings require explicit confirmation after a document change; reusing a name cannot redirect them to another body. Check and the current job display their separate HDR capture metadata. See CPU workspace controls for units, limits and the immutable capture contract. CPU glass, emission, surface effects, anisotropy, area lights and spot cones remain API capabilities without panel editors.

GPU path tracing preserves asynchronous shader preparation and its timing display. Its independent image device requires Vulkan; the live viewport may use another backend. When no compatible Vulkan device is available, GPU settings remain editable and saveable, while Check and Start explain why GPU execution is unavailable. The panel exposes progressive sample counts from 1 to 4096 and an Advanced section for maximum path depth (1–16), random seed and exposure (−32 to +32 EV). One setup exposure field controls the selected image method. Switching methods retains their local numeric drafts while submitting and saving only the active method. Reloading or choosing another setup replaces those drafts with the saved numeric intent. The live product preview keeps its fixed studio response and does not apply image exposure, environments, lens or material overrides.

The GPU Advanced section also exposes Reinhard / ACES fitted tone mapping, optional final edge-aware denoising, and a thin-lens depth-of-field control. Positive aperture requires a perspective product camera. Denoising preserves raw accumulation but can soften detail; glass and sharp specular first hits bypass its final spatial filter.

The Environment section selects no map, an original artistic sky gradient, or a local Radiance .hdr panorama. HDR input is bounded to 16 MiB, 2048 × 1024, 2:1, and linear sRGB/D65 primaries; unspecified primaries require the explicit interpretation checkbox. EXR is not supported. Rotation and intensity affect illumination, while the saved background remains the camera backplate. Selecting a file runs the bounded public render.hdr.inspect command; a typed path has an explicit Check HDR file action. The picker belongs to the originating document revision, setup, method and input selection. A cancelled or stale answer never replaces a newer selection.

The panel distinguishes a pending file, a checked file and HDR saved inside this design. It shows dimensions, declared colour primaries and intensity; the source digest is available in a collapsed details section. Check, Start and Save use the checked file's expected SHA-256, rejecting changed bytes until an explicit recheck. An already captured image retains its immutable source independently of later edits.

Custom studio lighting exposes constant linear-RGB environment radiance, a finite-radius sun, and up to four one-sided rectangular emitters. World-space centers and orthogonal half-edge vectors specify their geometry in millimetres; radiance is linear RGB. An environment map replaces the constant environment term. The path integrator uses the published emitter/BSDF MIS contract.

Appearance editor and body optics

Picking a face, body or component opens Appearance. Its kind chips, look card and Applies to scope lead to Edit: colour, finish, metallic, roughness, opacity and IOR. The look card's source tag opens the inheritance chain. Reset restores the picked target's values from when it was opened; Save to library uses the existing design library export flow.

Glass and absorption (GPU), Clear coat (GPU), Maps (GPU), Saved with this shot, and Reflections (CPU) follow in that order and start collapsed. Unsupported methods remain visible with an explanation; opening a section never changes the renderer. Optical bindings currently target one whole visible body, so face, component and multiple-body picks show the same controls disabled with a reason. The Browser command has no Wear selection kind yet, so no Open Wear link is shown.

The old Appearance page retains explicit target selection and the library/reference and wear controls awaiting their own editors. Its body optics use the same sections as the picked-body editor. Scene ordinal, exact name, stable target and document identity are checked; a document revision change requires Revalidate this body.

Six original glass recipes use linear transmittance over a reference distance to compute absorption per millimetre via -ln(T) / distance. Glass exposes boundary, IOR, thickness, RGB absorption, straight shadow transmission and closed-solid interior scattering. Thickness is disabled for closed glass, which uses geometric distance. Glass cannot share a body with coat or maps. Full topology, orientation, overlap and optical-boundary checks run during GPU preparation; Check does not certify those properties.

Clear coat retains weight, roughness and IOR. Maps retain the bounded PNG/JPEG picker flow for base colour, normal, metallic and roughness images, world-space origin and U/V repeat vectors, normal strength, V orientation and base replacement. The backend's map-size, encoded-byte, repeat and assignment limits still apply. File-picker completion checks the original document, revision and body identity.

These local overrides are temporary on the document tab. Save these optics uses render.optics.bind to save physical glass with the shot; replacement requires the explicit Replace this body's saved optics checkbox. Coat and local image maps remain temporary, and the save action explains that limit. Remove saved opens the shared Remove saved optics? confirmation before render.optics.unbind; stale confirmations cannot affect a changed document. Saved authored surface bindings remain manageable in Saved with this shot. Reflections retains this body's Off/Mirror/Rough CPU binding and explicit target confirmation.

Active GPU overrides still cause Check/Start to refuse a CPU request. Both buttons submit the same freshly validated runtime parameters and the engine captures file contents at that boundary.

Check and Start build the same request from the current product camera, size and selected method, including when Render Result is open. Every click revalidates host availability and scene readiness. The engine checks resource admission at Start; an earlier successful Check does not reserve a queue slot or memory.

Product scene

engine::product_scene::extract consumes authoritative evaluated geometry, reusing the document's world/occurrence placement and mesh Arcs. Body, component, material, face and imported appearances retain their existing precedence and opacity. Source geometry is never transformed a second time or altered to serve a renderer.

The shared L1 ProductScene/ProductMesh contract contains world-space meshes, resolved sRGB colours, opacity and face appearance overrides. Face indices are the existing mesh-to-B-rep mapping, resolved through document appearance references; they are not new persistent names or triangle-derived face identities.

There are no grid/axis/edge lines, sketches, construction objects, section cuts, analysis shading, active-component fading, canvases or decals in the product scene. Browser visibility still controls which bodies appear. The existing Design viewport and CPU snapshot routes keep their current policies.

Extraction refuses a stale live-drag model. The explicit model-reading render.scene {} command follows the normal engine evaluation boundary, then returns bounded metadata: body names, triangle counts, resolved colours/opacity, face-override counts and bounds. It does not return mesh payloads, change the document or add an undo step. Product extraction admits at most 16,384 visible bodies.

Image result canvas

The image panel switches between Live Preview (the product camera) and Render Result (the current CPU checkpoint or last completed PNG). Clicking the small image preview also opens the result on the main canvas. Check, Start, Cancel and Export remain available in the same panel. An empty result explains how to start a job; it never substitutes the live preview for an exported image.

Fit Image frames the complete image and follows window resizing. 100% maps one image pixel to one physical display pixel, including on high-DPI screens. Pan, wheel, trackpad and Space + drag use the shared Navigation preferences with orbit disabled. Ctrl + arrow keys pan the image; Fit/Home frame it. Image navigation does not move the product or Design camera and does not change the saved setup.

The canvas shows the image dimensions, executor, full job identity and captured model revision. A visible warning identifies an earlier captured revision when the document has changed. A CPU progressive checkpoint is explicitly provisional and shows its samples per pixel and sequence. Its texture is cached by job identity and sequence, separately from the last completed image. Export final PNG keeps using that completed image even while a checkpoint is shown. Cancelling or failing the active job clears its preview and returns to the retained final image. Transparency is shown over a checker background; display scaling and navigation never modify the PNG bytes.

Canvas selection, framing and pan/zoom are local to each open document tab. Switching tabs never displays another document's texture. A new image starts fitted; later checkpoints and transitions to final/cancelled state preserve pan/zoom. Final publication is checked directly after the preview read so a stale status reply cannot briefly select an older frame and reset the next frame's zoom. The canvas itself adds no document fields; CPU sampling intent is saved with the job below.

Settings and product camera

The right panel stages a named setup's camera, background, output and active image method. Save Setup records the complete numerical RenderSetup.job and the current product Camera through render.settings.set, with one undo step. A new checked HDR uses render.settings.capture_hdr to save both source bytes and setup in that same atomic step. Editing the name is Save As; choosing an existing name from the picker loads that setup. Reload Saved Settings replaces the numeric draft with the saved values. Drafts remain separate for each open document, and loading a setup preserves completed images and result framing.

Active method Saved numeric intent
CPU raster Transparency, with zero exposure
CPU ray tracing Single-image AA or progressive SPP/seed, preset or custom directional lights, point/spot lights, area lights and their samples/seed, shadows, constant RGB environment or embedded HDR with rotation/intensity/samples, setup exposure
GPU path tracing Transparency, samples/depth/seed, tone map, denoise, lens, RGB studio lighting/sun/area lights, procedural sky or embedded HDR with rotation/intensity/explicit colour assumption, setup exposure

The CPU panel preserves existing area-light and spot-cone fields even though it does not yet edit every field. Opening a GPU setup retains non-power-of-two sample counts, RGB environment values, exact sky gradients and radians. Explicit empty light lists, black environments and absent settings remain distinct. The only exposure authority is RenderSetup.exposure_ev: CPU requests lower it to their raytrace options with zero outer exposure; GPU jobs use the same value in their job options. Choosing raster explicitly selects its zero-exposure response.

Saving uses pure numeric validation and does not require an installed renderer or a current evaluated scene. New HDR capture reads and validates the bounded source through the engine; failure leaves the document, resource table and local file selection intact. After success, the draft changes to the embedded resource and contains no source path. Saving that setup again, Save As, Reload and design reopen use the included bytes, even when the original file has been removed. CPU/GPU setups may share the same immutable payload. The engine limits each source to 16 MiB and the design to 64 resources/64 MiB.

Check and Start use the same complete typed setup and then perform normal host, scene and capture admission. Temporary bindings can still use an embedded HDR through the runtime resource selector. GPU maps and all body bindings, including disabled assignments, cannot yet be saved as a complete job. The panel explains the limitation and refuses Save before changing the document. Those inputs can still execute through the existing transient request route. Older setups with nondefault legacy environment rotation/intensity are also retained and refused for full-job saving until explicitly converted; their values are never erased.

Restore Saved Camera runs render.settings.apply {name}, preserving target, distance, yaw, pitch, roll, FOV and up axis as view state. It neither edits the document nor settles a stale model. The UI honours its up axis in Render; the Design camera is restored when returning. The camera moves exactly as in Design: the navigation preset, Orbit around, zoom to the cursor, the SpaceMouse, the middle double-click, F6 and the axis view or navigation cube all work and Fit Product frames visible product bodies without including sketches or selection.

Preview drafts do not make the document dirty until saved. Unknown backend preferences and unsupported modes remain saved intent: the strict resolver reports the unsupported viewport request. Use Integrated Preview is an explicit draft change, never an automatic fallback. The method selector describes the desired image execution independently of the installed host. It does not claim support for a saved final-mode or external-engine preference. Saved image settings do not change the fixed live product preview.

Host capabilities and resources

render.backends always retains the built-in cpu-raster preview/PNG image executor. An installed CPU image host adds cpu-product; a native host with raytrace-cpu also advertises cpu-raytrace, with its bounded PBR/HDRI/refraction profile. Discovery does not select that method automatically or enable native workers in the browser. Only an installed UI GPU host adds gpu-viewport, advertising Preview / Viewport with no image formats or HDRI/refraction/progressive features. The installed opaque PBR consumer adds the pbr feature. The host reports effective limits from its created device and depth attachment: at most 4096 pixels per dimension and 4,194,304 pixels, within the 256 MiB pixel scratch admission policy. The estimate includes the selected MSAA colour/depth cost; it excludes scene geometry, driver overhead and cached source meshes. It is not a measurement of total GPU memory.

The preview never refuses a frame because of the screen size. When the viewport's physical size is past those limits (a maximised 4K or 5K window is 8–15 million pixels), the preview draws at the largest size of the same aspect the executor admits (RenderLimits::fit, both axes scaled by one factor, scratch included) and filters it up into the viewport. A viewport within the limits draws at full size.

PNG images keep the saved-setup limits above. A setup past them is refused with the limits and the largest size at its aspect (for example 4096 × 4096 → 2048 × 2048), and the image panel offers to use that size.

Pure capability metadata lives in the session/host, outside persistence and history, surviving document replacement, scratch sessions and document-tab switches. No wgpu types enter the engine or document crates. A host without an installed GPU/depth buffer reports that product viewport preview is unavailable, rather than silently using the opaque CPU snapshot path to approximate transparent appearances.

GPU product batches are separate from Design batches while sharing the installed device and pipelines. Model/visibility/appearance changes update the product scene; camera movement updates uniforms without rebuilding vertices. Selection and section state do not change the product buffers. Vertex uploads are bounded to 128 MiB and checked before allocation; malformed/non-finite triangles and invalid opacity fail. Reinstalling the host invalidates product uploads. This is not a general device-loss, render-job or cancellation protocol; those ownership mechanisms belong to R4.

Transparency uses the existing raster far/near alpha-blending approximation, without refraction or HDR illumination. Opaque PBR uses a separate surface batch in the same installed renderer. R3 itself added no export job; R4a supplies CPU product PNG jobs. There is no result gallery or Bevy dependency. Saved setups were added in format 21, alongside opt-in optical parameters on existing looks. ui.render remains the existing Design snapshot API, using its installed renderer; ui.screenshot captures the actual integrated Render workspace. Product-image export uses render.start and render.export, rather than the Design snapshot API.

Reproduce

Run the original procedural examples/render-studio.json through the engine/CLI and open its saved design in the app. Select Render, adjust its background or camera and save a setup. The fixture uses original boxes/cylinders and simple colour/opacity assignments; no commercial CAD files, artwork or materials are used. Actual Windows Vulkan/MSAA evidence is attached to #673.

Explicit Render camera and the Design view contract

render.camera.set {camera} applies a complete camera snapshot as transient view state. It uses the saved-render camera's strict decoder and finite mm/radian limits, preserves its explicit roll and up axis, and does not evaluate geometry, change a saved shot, modify the design or add an undo step. Omitted roll/up use zero/Z defaults; all other camera fields are required. Unknown fields, invalid axes, nonfinite values and out-of-bounds numbers refuse atomically.

The Render inspector uses this command for numerical edits and before Frame Subject. Design's view.apply retains upstream's independent policy: it accepts finite roll (clamped to +/-pi) and refuses an explicit up axis. Render does not reintroduce the former fork-specific extension to that Design command. Saving or restoring a shot still uses the existing render-settings commands.

The camera pitch label is explicitly Camera pitch, so the legacy English label adapter does not replace mechanical screw pitch translations. Material axis conventions have stable catalog IDs; the numerical/wood conventions and engineering data remain unchanged.

The legacy English-label adapter gives explicit catalog IDs precedence and, for an ambiguous source label, retains a translation already present in the chosen locale before falling back to English. Adding an untranslated Render alias no longer hides existing Library, Appearance or Checkpoint translations. Contextual Render labels still use their own stable IDs rather than borrowing a different feature's meaning.

Picking in the product view

The Look stage bar's second-row Pick control selects Body, Face or Component granularity, using Design’s selection filter state through the select.filter command. Component picks use the Browser’s exact occurrence path, including nested and repeated placements; a body at the design root retains its body identity. Face picks use the existing mesh-to-B-rep mapping and connected-surface selection rules.

Hover highlights the target; clicking selects it. Clicking empty space clears the selection. Shift and Ctrl/Cmd follow Design’s add/toggle behavior and the Shift add-only preference. Browser row selections and product picks share the same selection commands and state, retained across Design/Render switches. Picking works with the Shots strip shown or hidden. Render picking never starts a geometry edit.

Selection and hover use Design’s highlight drawing and theme tokens in a separate GPU overlay on the live product view. The product scene and its upload stay unchanged. CPU image jobs, exported PNGs, retained images and the Render Result canvas never contain this overlay; the Pick control is disabled on the result canvas.

Browser scene focus

The shared Browser lists Environment (with its source), Lights, saved Shots, Objects and Output (with image dimensions and format). Shots + opens the existing Shots manager; Lights +, Solo and Mute remain faded with an explicit reason until named light commands exist. Existing light entries describe the current numerical image setup, without inventing a saved rig.

ViewState.selection exposes RenderSelection for Nothing, Object (the existing engine selection), Environment, Light, Shot and Output. It belongs to each document view and is never saved in a design. view.render_select validates semantic focus requests without opening dialogs or editing/evaluating a design. Object picks and Browser selections keep the existing selection commands. Selecting Output opens the Output editor. Other focus types retain their existing Inspector routing for subsequent selection-following editor changes.

Look expands Objects, Light expands Lights and Environment, and Frame expands Shots. Output leaves expansion unchanged. Stages preserve selection and never lock rows or prevent manual expansion.

Appearance editor

Look shows one Appearance editor with scope, current look, the four-step look chain and Edit controls. There is no Inspector page strip. Applies to chooses the selected target or every exact user of the look; mixed values remain inert until edited. Edit contains colour/hex, finish and metallic/roughness/opacity sliders. Advanced reuses the existing surface library, optical bindings, glass, clear coat, texture-map, reflection and aging controls. The separate Textures disclosure is marked Soon. The shared footer exports the design library through library.export and resets the current target's override through appearance.assign. view.render_inspector {visible} controls transient per-document visibility; selecting a stage reopens the editor. Output selection routes to its dedicated editor; other semantic selection focus routing remains deferred.

Output editor

The Output stage offers size, format, quality and a Check summary in the stage bar's second row. Its lower-left Size presets card offers Preview (1280 × 720), Full HD, 4K, Square and Custom. Presets outside the selected executor's limits stay visible with a disabled explanation. Custom retains the current size and reveals its fields. Numerical size edits and presets use render.output.size; they never save a shot or start a job.

Selecting Output in the Browser shows one editor with Image, Effects and Check sections, without page navigation or pinned job actions. Image retains size/aspect, format, sampling, method, transparency and export destination controls. Effects owns tone, bloom, grading and regrade. Check retains the preflight list, freshness checks, installed backend/status metadata and expandable diagnostics. Named quality presets and EXR settings remain unavailable with their existing reasons. Destination selection uses the existing completed-image export picker.

Render and Cancel stay in the stage bar. Active jobs also show a single-row progress pill with Cancel. The result viewer retains Copy, export, close, Fit/100% and shared pan/zoom. R starts the active setup; Escape closes the image without cancelling its job.