Opens a .pro3d scene without a window and renders the camera bookmarks prepared in
it: one PNG per bookmark, as the viewer shows that bookmark in a window of the requested
size. Surfaces, annotations and overlays are drawn by the same scene graph that
PRo3D.Snapshots uses.
You can also fix the OPC level of detail to one level everywhere. This is a test hook: renders of the same bookmark at different levels can be compared directly.
The same rendering is available as a library, PRo3D.SceneRender, for tests and
scripts that run in-process (below).
Phase 1 (#871) renders plain bookmarks (the bookmark panel). Sequenced bookmarks, which also carry scene state, frustum and SPICE observation time, come in phase 2.
pro3d-tool render-bookmarks --scene site.pro3d # every bookmark, 1920x1080
pro3d-tool render-bookmarks --scene site.pro3d --list # name and GUID of each bookmark
pro3d-tool render-bookmarks --scene site.pro3d --bookmarks "Crater rim" "Outcrop*" --width 1024 --height 768
pro3d-tool render-bookmarks --scene site.pro3d --bookmarks "*" --lod-level 3 --out lod3
pro3d-tool render-bookmarks --job render.json
| Option | Default | Meaning |
|---|---|---|
--scene <file> |
— | The scene to open. Required unless the job file names it. |
--bookmarks <p> … |
* |
Bookmarks to render, separated by spaces: names, names with * / ? wildcards, or GUIDs. Case-sensitive. Quote patterns in a shell, otherwise the shell expands * itself. |
--out <dir> |
<scene>-renders beside the scene |
Output directory. |
--width, --height |
1920, 1080 | Image size. The scene's field of view is kept and the aspect ratio follows the size, as in a viewer window of that size. |
--lod-level <n> |
the viewer's | Fix the OPC level of detail (below). |
--job <file> |
— | JSON job file (below). Options given on the command line override its top level. |
--list |
— | Only list the scene's bookmarks and exit. |
Every bookmark that a pattern selects is rendered once, in the order of the bookmark panel. A pattern that selects nothing is an error, and the error message lists the available bookmarks. This is deliberate: a typo should not quietly produce fewer images.
<bookmark name><suffix>.pngfor each bookmark and pass. Characters that a file system rejects, and whitespace, become_. When two bookmarks would get the same file name, the first 8 characters of each bookmark's GUID are appended.renders.json, a manifest of the images written:
{
"scene": "C:\\data\\site.pro3d",
"images": [
{ "bookmark": "Crater rim", "key": "…", "file": "Crater_rim_lod3.png", "width": 1920, "height": 1080, "lodLevel": 3 }
]
}The exit code is 0 on success and 1 on any error: a scene that won't load, a bookmark pattern that matches nothing, or a bad job file.
A job file holds the same settings as the command line, and optionally several passes. Each pass renders its own set of bookmarks with its own size and level.
- Precedence: command line, then the job file's top level, then the defaults. Each
pass inherits the top level and can override
bookmarks,width,height,lodLevelandsuffix. suffixis appended to every file name of the pass. It defaults to_lod<n>when the pass fixes a level, and to nothing otherwise. If two passes would write the same file, the job is refused before anything is rendered.- Comments and trailing commas are allowed. Unknown keys are errors, so a misspelt
lodlevelcannot silently fall back to the default. - Without
passes, the top level is a single pass.
OPC surfaces are quadtrees of patches. Level 0 is the root patch, and every refinement
adds one level. Normally the viewer chooses, patch by patch, how deep to go from the
patch's distance and screen size. --lod-level n replaces that choice: every hierarchy
is refined to exactly level n everywhere. Branches that are shallower than n end at
their leaves.
Typical uses:
- Testing a rendering override at a known, reproducible patch set, independent of the camera.
- Comparing levels: render the same bookmarks in several passes, one per level.
Two caveats:
- The fixed level ignores visibility. A deep level loads the whole surface at that resolution, including patches that are out of view. Large OPCs at their deepest levels can need a lot of memory and time.
- Patches load synchronously, so each image is complete when it is written. There is no settling time, and rendering the same bookmark twice gives the same image.
Implementation: LodOverride in src/PRo3D.Core/Surface/Surface.Sg.fs wraps the
viewer's level-of-detail decider. The wrapper reads the override with the adaptive
token, so switching levels re-filters the patch trees without rebuilding the scene graph.
open PRo3D.SceneRender
Aardvark.Init()
use app = new OpenGlApplication() // the host owns the GL runtime
use renderer = new SceneRenderer(app.Runtime, "site.pro3d")
for b in renderer.Bookmarks do
let image = renderer.Render(b, { size = V2i(1024, 768); lodLevel = Some 2 })
image.Save(sprintf "%s.png" b.name)
// or a whole job, exactly what the verb does
JobFile.load "render.json"
|> Result.bind JobFile.toJob
|> Result.bind (RenderJob.run (printfn "%s") renderer)SceneRenderer(runtime, signature, scene)loads the scene through the viewer's own update function.Renderputs the camera where clicking the bookmark in the bookmark panel ends up (the viewer flies there with an animation, which only a window drives), then renders one frame offscreen. The two-argument constructor uses the framebuffer signature ofPRo3D.Snapshots(RGBA8, depth-stencil, 8× MSAA). Tests pass their own runtime and signature (Render.context).Bookmarks.ofGroups,Bookmarks.selectandBookmarks.fileNameslist a scene's bookmarks, select them by pattern, and name their files.JobFileparses and merges job files.RenderJob.planandRenderJob.runresolve and render a job.- Render from the thread that owns the GL runtime. The level-of-detail override is
process-wide.
Rendersets it for every image, and disposing the renderer resets it.
Tests: src/Tests/SceneRenderTests.fs. They need PRO3D_TEST_DATA (the Dimorphos
projection scene) and a GL context.
PRo3D.Snapshots.exe --asnap also renders bookmarks, but only from a separate batch file
of copied bookmark records. It runs only as an executable, starts a web server, and waits
for a key press at the end. render-bookmarks reads the bookmarks from the scene itself,
and its library can be called in-process.
Phase 2 is meant to move the snapshot tool's bookmark path, and the tests that run
PRo3D.Snapshots.exe (SnapshotSunLightingTest), onto PRo3D.SceneRender.
{ "scene": "site.pro3d", // relative paths are relative to the job file "out": "renders", "bookmarks": [ "*" ], // a single string is fine too "width": 1280, "height": 720, "passes": [ { "lodLevel": 0 }, { "lodLevel": 2 }, { "lodLevel": 4, "bookmarks": [ "Crater rim" ], "width": 3840, "height": 2160 }, { "suffix": "_viewer" } // no lodLevel: the viewer's level of detail ] }