diff --git a/houdini/CMakeLists.txt b/houdini/CMakeLists.txt index 35376d4..1130096 100644 --- a/houdini/CMakeLists.txt +++ b/houdini/CMakeLists.txt @@ -14,9 +14,10 @@ install(FILES install(DIRECTORY otls soho + toolbar python2.7libs python3.9libs + python3.11libs DESTINATION plugin/houdini ) - diff --git a/houdini/docs/moonray_render_settings_lop_audit.md b/houdini/docs/moonray_render_settings_lop_audit.md new file mode 100644 index 0000000..b4c1a30 --- /dev/null +++ b/houdini/docs/moonray_render_settings_lop_audit.md @@ -0,0 +1,990 @@ +# MoonRay Render Settings LOP Audit + +## Scope + +This is a technical development/audit note for the MoonRay Render Settings LOP work in Houdini Solaris. It is not a polished public user manual. + +- Validation target for this pass: Houdini 20.5 only. +- Custom node name: `moonrayrendersettings1`. +- Custom HDA/operator: `Lop::DW_MOONRAY::moonrayrendersettings::1`. +- Repo source path: `moonray/moonray_dcc_plugins/houdini/python3.11libs/moonray_render_settings.py`. +- HDA path: `moonray/moonray_dcc_plugins/houdini/otls/Lop::DW_MOONRAY::moonrayrendersettings::1.hda`. +- Installed runtime module path used by Houdini 20.5 validation: `/Applications/MoonRay/installs/openmoonray/plugin/houdini/python3.11libs/moonray_render_settings.py`. +- Houdini 21 evidence is out of scope for this pass and should not be mixed with the Houdini 20.5 results below. + +## Evidence-Gated Development Policy + +Every important Render Settings, AOV, viewport/IPR, render-buffer, or backend lifecycle claim must be classified as one of: + +- `PROVEN`: backed by exact source path/function, command output, exported USD/RDLA, log, installed-runtime provenance, render output, or EXR stats. +- `OBSERVED`: directly seen in Houdini/runtime behavior, but not fully explained. +- `HYPOTHESIS`: plausible explanation with a named test that can prove or disprove it. +- `UNKNOWN`: not enough evidence. +- `OUT OF SCOPE`: intentionally deferred. + +Rules: + +1. No claim without evidence. +2. No recommendation without a reproducer, source-path proof, exported USD proof, log proof, RDLA proof, render proof, or EXR proof. +3. Do not infer that something is working because a UI folder, parameter, channel, RenderVar, or SceneObject exists. +4. If the render is black, the path is functionally broken until render proof says otherwise. +5. Authored USD alone is not render proof. +6. RDLA/RenderOutput declaration alone is not image-buffer proof. +7. Debug renderer success is not production renderer success. +8. Houdini 21 behavior does not prove Houdini 20.5 behavior. +9. UI cleanup must not hide backend lifecycle, dirtying, render-buffer, AOV binding, or viewport/IPR refresh bugs. +10. If evidence conflicts, report the conflict instead of choosing the convenient explanation. + +Primary source-of-truth hierarchy: + +1. Local runtime behavior in the target Houdini version, currently H20.5. +2. Exported USD from the exact scene state being tested. +3. Installed hdMoonray source and binaries currently loaded by Houdini. +4. MoonRay native metadata: `/Applications/MoonRay/installs/openmoonray/coredata/SceneVariables.json` and `/Applications/MoonRay/installs/openmoonray/coredata/RenderOutput.json`. +5. MoonRay docs and source. +6. OpenUSD RenderSettings/Product/Var schemas. +7. SideFX Houdini/HDK docs and local Houdini headers. +8. Local project docs and prior audit notes. + +Track A is DCC/UI/USD-contract work: custom Render Settings LOP generator, regenerated HDA, validation scripts, docs, and installed/runtime source alignment. + +Track B is backend forensic work: backend source tracing, temporary diagnostics, logs, render proof, EXR stats, viewport/IPR lifecycle proof, and runtime symptom proof. + +Track A and Track B may run in parallel when UI/USD authoring and backend runtime behavior are coupled. Parallel work is allowed. Unsupported blending is not. DCC/USD evidence and backend/runtime evidence must be separated in reports. Commits should stay separate unless the backend root cause is proven, the fix is narrow, and the diff explains why UI/USD and backend behavior must change together. + +Backend files are not forbidden. They may be inspected or temporarily instrumented when runtime evidence points there, especially `RenderBuffer.cc`, `ArrasRenderer.cc`, `RenderPass.cc`, `RenderDelegate.cc`, `UsdRenderers.json`, Beauty/AOV binding lifecycle, render settings dirtying/versioning, and viewport/IPR refresh behavior. Backend behavioral changes require source-path proof, exported USD proof, log proof, and render/EXR or runtime symptom proof before implementation. + +Do not flip `aovsupport` because it appears related. Do not broaden non-beauty AOV transport. Do not ship UI-only cleanup as a substitute for backend/runtime proof. + +## References Consulted + +### OpenUSD RenderSettings / RenderProduct / RenderVar + +- [usdRender overview](https://openusd.org/dev/user_guides/schemas/usdRender/overview.html): Used for the RenderSettings, RenderProduct, and RenderVar schema relationship model. +- [RenderSettings schema](https://openusd.org/dev/user_guides/schemas/usdRender/RenderSettings.html): Used to confirm the render settings prim is the global render invocation/configuration prim. +- [RenderProduct schema](https://openusd.org/dev/user_guides/schemas/usdRender/RenderProduct.html): Used to confirm product/output path and ordered render variable ownership. +- [RenderVar schema](https://openusd.org/dev/user_guides/schemas/usdRender/RenderVar.html): Used to confirm output variable/AOV authoring expectations. +- [Render settings proposal](https://openusd.org/release/wp_render_settings.html): Used as background for the USD RenderSettings/Product/Var design. +- [USD render user guide](https://openusd.org/dev/user_guides/render_user_guide.html): Used for the broader USD rendering workflow context. + +### SideFX Solaris / USD Render ROP + +- [Render Settings LOP](https://www.sidefx.com/docs/houdini/nodes/lop/rendersettings.html): Primary Houdini/Solaris authoring reference. +- [Render Product LOP](https://www.sidefx.com/docs/houdini/nodes/lop/renderproduct.html): Used to compare productName/productType/orderedVars authoring. +- [Render Var LOP](https://www.sidefx.com/docs/houdini/nodes/lop/rendervar.html): Used to compare Beauty RenderVar authoring and driver parameter extras. +- [USD Render ROP](https://www.sidefx.com/docs/houdini/nodes/out/usdrender.html): Used to confirm the USD Render ROP execution/wiring model. + +### SideFX HOM / LOP Python + +- [hou.LopNode](https://www.sidefx.com/docs/houdini/hom/hou/LopNode.html): Used for Python LOP/HDA stage access and validation. +- [hou.lop](https://www.sidefx.com/docs/houdini/hom/hou/lop.html): Used for Solaris/HOM context. + +### SideFX HDK / USD / Hydra + +- [HDK USD Hydra customization](https://www.sidefx.com/docs/hdk/_h_d_k__u_s_d_hydra.html): Used for Houdini/Hydra integration context. +- [LOP_Node header/source](https://www.sidefx.com/docs/hdk/_l_o_p___node_8h_source.html): Used for LOP implementation and cooking context. + +### SideFX Houdini Digital Asset / UI References + +- [Asset UI](https://www.sidefx.com/docs/houdini/assets/asset_ui.html): Used for HDA parameter UI conventions. +- [Editing assets](https://www.sidefx.com/docs/houdini/assets/edit.html): Used for HDA/source-of-truth considerations. +- [Operator Type Properties](https://www.sidefx.com/docs/houdini/ref/windows/optype.html): Used for HDA operator definition behavior. +- [Edit Properties LOP](https://www.sidefx.com/docs/houdini/nodes/lop/editproperties.html): Used as context for Houdini's generic USD property authoring model. + +### OpenMoonRay / HdMoonRay + +- [HdMoonRay Render Settings](https://docs.openmoonray.org/user-reference/tools/hydra/render-settings/): Used for the MoonRay/Hydra render settings path. +- [HdMoonRay setup](https://docs.openmoonray.org/user-reference/tools/hydra/hdmoonray-setup/): Used for plugin/runtime environment context. +- [HdMoonRay commands](https://docs.openmoonray.org/user-reference/tools/hydra/commands/): Used for `husk`/Hydra command-line context. +- [HdMoonRay Houdini](https://docs.openmoonray.org/user-reference/tools/hydra/hdmoonray-houdini/): Used for Houdini integration context. +- [HdMoonRay features](https://docs.openmoonray.org/user-reference/tools/hydra/hdmoonray-features/): Used for feature support context. +- [MoonRay scene objects](https://docs.openmoonray.org/user-reference/scene-objects/): Used for RDL scene object context. +- [SceneVariables](https://docs.openmoonray.org/user-reference/scene-objects/scene-variables/SceneVariables/): Used to classify MoonRay SceneVariables. +- [RenderOutput](https://docs.openmoonray.org/user-reference/scene-objects/render-output/RenderOutput/): Used for MoonRay-side output/AOV realization. +- [Render outputs guide](https://docs.openmoonray.org/user-reference/how-to-guides/render-outputs/): Used for MoonRay RenderOutput workflow context. +- [OpenMoonRay developer reference](https://docs.openmoonray.org/developer-reference/): Used for developer-level source/library context. + +### Autodesk / Arnold AOV References + +These were treated only as practical renderer/AOV workflow references, not as MoonRay truth. + +- [arnold-usd](https://github.com/Autodesk/arnold-usd) +- [Arnold expression AOVs](https://help.autodesk.com/cloudhelp/ENU/AR-Core/files/ac-output-aovs/arnold_user_guide_ac_output_aovs_ac_expression_aovs_html.html) +- [Arnold AOV shaders](https://help.autodesk.com/cloudhelp/ENU/AR-Core/files/ac-shading/arnold_user_guide_ac_shading_ac_aov_shaders_html.html) +- [Arnold for Cinema 4D AOVs](https://help.autodesk.com/cloudhelp/JPN/AR-Cinema4D/files/ci-arnold-render-settings/arnold_for_cinema_4d_ci_Arnold_Render_Settings_ci_AOVs_html.html) +- [Arnold for 3ds Max AOVs](https://help.autodesk.com/view/3DSMAX/2024/ENU/?guid=arnold_for_3ds_max_ax_render_setup_ax_aovs_html) + +## Source of Truth and Runtime Import Rules + +The repo `moonray_render_settings.py` is the source of truth for the custom MoonRay Render Settings LOP. The HDA UI and cook-time Python must come from the same definition list. The generated HDA imports `moonray_render_settings` at cook time, so the module imported by Houdini must match the source used to generate the HDA. + +Runtime import path used by Houdini 20.5 validation: + +```text +/Applications/MoonRay/installs/openmoonray/plugin/houdini/python3.11libs/moonray_render_settings.py +``` + +Verification commands inside Houdini 20.5 `hython`: + +```python +import moonray_render_settings +print(moonray_render_settings.__file__) +print(len(moonray_render_settings.SCENE_VARIABLES)) +print(any(name == "enable_dof" for name, _ in moonray_render_settings.SCENE_VARIABLES)) +print(any(name == "light_sampling_mode" for name, _ in moonray_render_settings.SCENE_VARIABLES)) +``` + +The drift bug happened because the visible HDA UI was newer than the installed Python module that Houdini imported at cook time. The repo source and HDA contained newer settings, but Houdini 20.5 loaded the stale installed module from the plugin install tree. + +The local install-tree sync used during validation copied the repo source and regenerated HDA into the installed plugin tree. That was a validation step, not a final manual-install solution. Future repo/install tooling must keep the HDA and runtime Python module aligned reproducibly. + +## Proven Drift Bug + +Before the source/install sync: + +- HDA UI showed `Enable DOF`. +- Installed runtime module had only 18 SceneVariables. +- `enable_dof` was missing from the installed runtime module. +- Custom USD did not author `moonray:sceneVariable:enable_dof`. +- Custom RDLA kept camera `["dof"] = true`. + +After the source/install sync: + +- Installed runtime module has 50 SceneVariables. +- `enable_dof` is present. +- `light_sampling_mode` is present. +- Custom USD authors `custom bool moonray:sceneVariable:enable_dof = 0`. +- Custom RDLA contains `["enable_dof"] = false`. + +## USD RenderSettings / RenderProduct / RenderVar Contract + +The USD render contract is: + +- `RenderSettings` owns render invocation/global render settings. +- `RenderSettings` has the render camera relationship. +- `RenderSettings` has the products relationship. +- `RenderProduct` owns `productName`, `productType`, and `orderedVars`. +- `RenderVar` describes an AOV/output variable. +- AOVs flow through `RenderSettings -> RenderProduct -> orderedVars -> RenderVar`. +- The MoonRay backend realizes render outputs as MoonRay `RenderOutput` objects. + +Current custom authored paths: + +```text +/Render/rendersettings +/Render/Products/renderproduct +/Render/Products/Vars/beauty +``` + +## Render Product and Output Path Rules + +`RenderProduct.productName` is the USD fallback image output path authored by the custom LOP. `$HIP`, `$HIPNAME`, `$OS`, and `$F4` are valid Houdini path tokens, but plain `husk` does not have the same node/project context as a Houdini USD Render ROP. The default custom LOP path escapes the frame token as `\$F4` so the filename remains frame-expandable for husk/ROP execution without making the Render Settings LOP itself time-dependent on the current Houdini frame. + +For the owned MoonRay USD Render ROP, the ROP `outputimage` parameter is the primary output authority. It is linked to the LOP `product_name` parameter with a raw backtick HScript string expression so Houdini evaluates `$HIP`, `$HIPNAME`, and `$OS` in the ROP/HIP context while preserving the escaped frame token for husk frame expansion. + +When the USD Render ROP `outputimage` override is blank, the RenderProduct output path wins. A Houdini 20.5 smoke test wrote: + +```text +/tmp/moonray_render_settings_alignment_after/rop_product.0001.exr +``` + +That earlier smoke render was black, so it proved USD Render ROP wiring, RenderProduct output creation, and resolution/output path behavior only. The current H20.5 disk-output contract adds the default Beauty RenderVar/`orderedVars` path and has filled EXR proof; this evidence is scoped to Beauty and does not prove non-beauty AOV support. + +2026 output-path regression evidence: + +- Manual `husk -o /tmp/moonray_manual_husk_test2.exr` with `--settings /Render/rendersettings` writes a valid nonconstant 512x512 RGB float EXR. +- Manual `husk` with an absolute `RenderProduct.productName = "/tmp/moonray_product_abs.exr"` and no `-o` writes a valid nonconstant EXR. +- Manual `husk` with `RenderProduct.productName = "$HIP/render/$HIPNAME.$OS.$F4.exr"` and no `-o` writes `./render/untitled..0001.exr`, proving the fallback path is evaluated without the Houdini ROP/node context. +- A Houdini LOP `usdrender_rop` with blank `outputimage` and absolute `RenderProduct.productName = "/tmp/moonray_product_fallback.exr"` writes a valid nonconstant EXR, proving productName fallback still works when the path is concrete. +- The owned MoonRay ROP now links `outputimage` to the LOP `product_name`; a saved-HIP test wrote `/tmp/moonray_saved_hip_test/render/moonray_test.0001.exr`, not `untitled`. +- A later time-dependency audit showed that raw `$F4` in the custom LOP `product_name` makes the Render Settings LOP time-dependent. Escaping the default as `\$F4` keeps the frame placeholder for the ROP/husk filename but prevents unintended LOP time dependency. The owned ROP uses raw backtick strings such as `` `chs("/product_name")` `` rather than `parm.setExpression()`, so repair/creation does not create expression keyframes on the owned ROP parms. + +## Generic Houdini Render Settings Boundary + +The generic Houdini Render Settings LOP with a MoonRay folder is UI integration evidence only. It is not complete render proof. + +If flattened USDA has empty `rel products` and no `RenderProduct`, `productName`, or `productType`, generic Render Settings alone is not a complete MoonRay output setup. If it renders black, it is functionally broken until render proof says otherwise. + +Generic Render Settings may still be useful as raw/advanced reference UI, but it should not be advertised as the primary working workflow without product/output proof and filled render proof. + +## Resolution Behavior + +The custom MoonRay Render Settings LOP uses manual resolution only. + +Earlier prototypes mirrored Karma's computed camera-aperture modes: + +- Set Width, Compute Height from Camera. +- Set Height, Compute Width from Camera. + +Those computed modes were removed in the H20.5 UI/lifecycle cleanup pass to reduce callback and lifecycle complexity. The node now exposes a simple `Manual Resolution` note plus a directly editable `Resolution` integer pair. + +Validated dimensions: + +- Manual: `512 x 256`. + +The custom LOP authors final numeric resolution as `RenderSettings.resolution`. It must not author `moonray:sceneVariable:image_width` or `moonray:sceneVariable:image_height`. + +## SceneVariables and Render Settings + +MoonRay render settings that target RDL `SceneVariables` are authored as `moonray:sceneVariable:*` custom attributes on the `RenderSettings` prim where appropriate. + +`image_width` and `image_height` should not be authored by the custom LOP. They appear in RDLA from Hydra/render-pass framing, not from custom USD SceneVariable attributes. + +Current custom USD now authors: + +- `moonray:sceneVariable:enable_dof`. +- `moonray:sceneVariable:light_sampling_mode`. +- Tile order settings. +- `moonray:sceneVariable:roughness_clamping_factor`. +- `moonray:sceneVariable:target_adaptive_error`. + +RDLA proves MoonRay receives `enable_dof`, `light_sampling_mode`, `target_adaptive_error`, and `roughness_clamping_factor`. + +| UI label | USD attr | USD type | RDLA key | Current status | +|---------|----------|----------|----------|----------------| +| Enable DOF | `moonray:sceneVariable:enable_dof` | bool | `enable_dof` | working after drift fix | +| Light Sampling Mode | `moonray:sceneVariable:light_sampling_mode` | token/string | `light_sampling_mode` | working after drift fix | +| Target Adaptive Error | `moonray:sceneVariable:target_adaptive_error` | float | `target_adaptive_error` | working after drift fix | +| Roughness Clamping Factor | `moonray:sceneVariable:roughness_clamping_factor` | float | `roughness_clamping_factor` | working after drift fix | +| Image Width | do not author | n/a | `image_width` | render-pass-derived | +| Image Height | do not author | n/a | `image_height` | render-pass-derived | + +## Parameter Location Classification + +The Render Settings LOP must not absorb every MoonRay or USD setting. Not every `moonray:*` attribute belongs on `RenderSettings`. + +| Area | Example | Correct USD location | USD kind | MoonRay/RDL target | Should this Render Settings LOP author it? | Correct authoring path | Status | +|------|---------|----------------------|----------|--------------------|--------------------------------------------|------------------------|--------| +| Render settings | pixel samples | RenderSettings prim | `moonray:sceneVariable:*` attr | SceneVariables | yes | custom Render Settings LOP | verify/working | +| Render output/AOV | beauty/color | RenderProduct plus Beauty RenderVar by default for H20.5 disk output | UsdRenderProduct / UsdRenderVar | Hydra color AOV mapped to MoonRay beauty framebuffer | yes for disk output beauty; diagnostic disable path only | Output / Product | default Beauty RenderVar | +| Geometry settings | `moonray:mesh_resolution` | geometry prim | primvar or namespaced prim attr | RDL geometry setting | no | LOP wrangle / geometry settings node | document only | +| Camera/DOF settings | DOF enable/focus/aperture depending on native behavior | camera prim or RenderSettings depending on proven path | camera attr or SceneVariable | Camera / SceneVariables | only if native path proves it | match H20.5 generic/native | audit | +| Light settings | MoonRay light attrs | light prim | namespaced attrs | RDL light | no | light LOP / light-specific UI | document only | +| Material settings | material/shader attrs | material/shader prim | shader inputs | RDL material | no | material network | document only | +| Debug/RDLA output | RDLA dump path/options | RenderSettings/delegate setting if proven | renderer/debug setting | hdMoonRay/debug | yes, Advanced/Debug only | custom Render Settings LOP | verify | + +Do not expose `moonray:mesh_resolution` in the Render Settings LOP as a global render setting. Geometry, light, material, and camera prim-level settings belong on their own prims unless Houdini 20.5 native/generic behavior proves otherwise. + +### Sampling Mode Contract + +The current H20.5 source and documentation split sampling controls by mode: + +- MoonRay `sampling_mode` is a native SceneVariables enum. Local `SceneVariables.json` + and the public SceneVariables reference define `uniform = 0` and `adaptive = 2`. +- The custom LOP authors token strings, `uniform` and `adaptive`, as + `moonray:sceneVariable:sampling_mode`; `hdMoonray::ValueConverter` maps those + enum tokens to the native MoonRay enum values. +- MoonRay `pixel_samples` is the uniform sampling control. +- MoonRay `min_adaptive_samples`, `max_adaptive_samples`, and + `target_adaptive_error` are adaptive sampling controls. +- MoonRay `light_sampling_mode` uses `uniform = 0` and `adaptive = 1`; + `light_sampling_quality` is active only in adaptive light sampling mode. + +Houdini menu conditionals for this generated HDA use the custom LOP menu token +strings, not native MoonRay enum integer values. The HDA menu items are +`("uniform", "adaptive")`. The custom LOP therefore disables: + +- `Pixel Samples` when `sceneVariable_sampling_mode != "uniform"`. +- `Min Adaptive Samples`, `Max Adaptive Samples`, and `Target Adaptive Error` + when `sceneVariable_sampling_mode != "adaptive"`. +- `Light Sampling Quality` when `sceneVariable_light_sampling_mode != "adaptive"`. + +The installed hdMoonray viewport DS uses integer parameters and numeric +disable-when expressions for Display Options. Do not blindly copy those numeric +conditions into the generated custom HDA: the previous numeric-condition attempt +passed a headless HOM probe but regressed the graphical H20.5 custom LOP UI. + +Headless Hython validation can inspect the conditional strings, but it does not +prove the graphical disabled/greyed-out state. Fresh H20.5 GUI validation should +still be used before claiming viewport/UI parity with Solaris Display Options. + +The LOP currently authors the curated SceneVariables consistently even when a +control is inactive for the selected mode. Validation shows changing sampling +values and toggling `Sampling Mode` updates the exported USD without requiring a +manual dropdown refresh. The inactive values are retained as SceneVariables, but +the UI now communicates which controls are relevant for the selected mode. + +Do not add sampling `moonray:sceneVariable:*` keys to +`hdMoonray::RenderSettings::addDescriptors()` as a live-update workaround. +OpenUSD's `HdRenderSettingDescriptor` is a renderer-exported setting descriptor +used by hosts for UI/defaults, and adding these descriptors regressed Houdini +Display Options initialization. The custom LOP should author the USD +RenderSettings attrs; the viewport Display Options should continue to use the +existing DS-declared `sceneVariable_*` controls. + +## Native MoonRay SpotLight Toggle Time Dependency + +The Light LOP MoonRay tab exposes `Enable Native MoonRay SpotLight` from the +Houdini renderer-property DS files: + +```text +houdini/soho/parameters/HdMoonrayRendererPlugin_Light.ds +houdini/soho/parameters/moonray_Light.ds +``` + +That toggle is a convenience wrapper around the generated MoonRay class override +parameters: + +```text +xn__moonrayclass_control_o8a = set +xn__moonrayclass_nva = SpotLight +``` + +`xn__moonrayclass_nva` has a generated Python-expression default that derives the +MoonRay light class from the Houdini light type. The native-SpotLight callback +must replace that generated expression with a static `SpotLight` token without +leaving keyframes, expressions, helper user data, or USD time samples behind. +Earlier callback variants also wrote `moonray_native_spotlight_helper` node user +data; that bookkeeping was removed because Houdini can draw green network badges +for non-keyframe node data as well as for true time-dependency. H20.5 hython +validation executes the exact callback text and checks: + +- the Light LOP remains non-time-dependent; +- the native SpotLight toggle, class-control parm, and class parm have static + values after enable; +- `xn__moonrayclass_nva` has no expression and no keyframes after enable; +- no `moonray_native_spotlight_helper` user data is written; +- the flattened USD layer has no time-sampled attributes before or after enable. + +The static class value is ignored when the control parm is reset to `none`, so +disabling the helper does not author a MoonRay class override. + +## Beauty RenderVar and AOV Status + +The H20.5 USD Render ROP / husk disk-output workflow now authors a Beauty RenderVar by default. A +custom LOP export with `aov_beauty = 0`, `RenderProduct.productName`, `productType = "raster"`, and +empty `orderedVars` failed in production `husk` with `No orderedVars to specify channels for +/Render/Products/renderproduct`. The same scene with the Beauty RenderVar produced a filled, +nonconstant EXR. + +Current default custom LOP contract: + +- `aov_beauty = 1`. +- Beauty RenderVar authored by default for disk output. +- `UsdRender.Settings`. +- `UsdRender.Product`. +- `settings.products`. +- `settings.camera`. +- `settings.resolution`. +- `product.productName`. +- `product.productType = "raster"`. +- `orderedVars` targets `/Render/Products/Vars/beauty`. +- Curated `moonray:sceneVariable:*`. + +The Beauty control preserves the internal parameter name `aov_beauty` for compatibility. Its label is +`Beauty RenderVar / Disk Output Path`, and it belongs with Render Product/output controls. Disabling +it is a diagnostic viewport/default-framebuffer test path, not the production disk-output default. + +This Beauty/default-output contract is separate from non-beauty AOV support. It is the minimal proven +H20.5 disk-output beauty contract. + +Custom Beauty RenderVar when `aov_beauty` is enabled: + +```text +Path: /Render/Products/Vars/beauty +sourceName = color +sourceType = raw +dataType = color4f +driver:parameters:aov:name = color +driver:parameters:aov:format = color4f +driver:parameters:aov:multiSampled = 0 +driver:parameters:aov:clearValue = 0 +``` + +Generic Houdini 20.5 RenderVar extras now aligned: + +- `sourceType = raw`. +- `driver:parameters:aov:format = color4f` for the custom MoonRay Beauty RenderVar. +- `driver:parameters:aov:multiSampled = 0`. +- `driver:parameters:aov:clearValue = 0`. + +Houdini `customData` appears to be UI/editor metadata and should not be hand-copied unless the integration deliberately adopts the generic/Edit Properties infrastructure. + +Native non-beauty AOV status: + +- A first native AOV set is exposed as opt-in checkboxes under the `AOVs` tab. +- The exposed set is limited to existing hdMoonray `RenderBuffer.cc` mappings with production filled-pixel proof after the RenderBuffer allocation/channel-count fix: `alpha`, `depth`, `Z`, `N`, `Ng`, `P`, `Wp`, `St`, and `weight`. +- Product-facing depth outputs are `depth` and `Z`. +- The historical diagnostic depth token is not exposed by the custom MoonRay Render Settings LOP in this pass. +- Material AOVs, LPE/light AOVs, visibility AOVs, primitive-attribute AOVs, Cryptomatte, display filters, auxiliary adaptive buffers, and motion vectors remain deferred. +- Debug/local path filling is still not enough for artist UI exposure; future AOVs require production `HdMoonrayRendererPlugin` filled-pixel proof through USD Render ROP/husk or equivalent production path. +- If a production path produces zero-filled buffers again, classify that as backend payload unresolved, not UI-ready. + +Do not remove the default Beauty RenderVar for the custom LOP disk-output path unless fresh H20.5 +viewport/IPR, USD Render ROP/husk, and filled image/EXR output prove a replacement contract. Do not +extend this evidence to non-beauty AOVs. + +Do not claim AOV support from authored RenderVars, metadata, EXR channels, RDLA RenderOutput declarations, or debug renderer success alone. + +Current native AOV RenderVar contract: + +| UI toggle | RenderVar | sourceName | sourceType | dataType | Status | +|-----------|-----------|------------|------------|----------|--------| +| Beauty RenderVar / Disk Output Path | `beauty` | `color` | `raw` | `color4f` | default on; production Beauty/disk output | +| Alpha | `alpha` | `alpha` | `raw` | `float` | opt-in native AOV | +| Depth | `depth` | `depth` | `raw` | `float` | opt-in native AOV; follows hdMoonray depth mapping | +| Z | `Z` | `Z` | `raw` | `float` | opt-in native state-variable depth | +| N | `N` | `N` | `raw` | `normal3f` | opt-in native state variable | +| Ng | `Ng` | `Ng` | `raw` | `normal3f` | opt-in native state variable | +| P | `P` | `P` | `raw` | `point3f` | opt-in native state variable | +| Wp | `Wp` | `Wp` | `raw` | `point3f` | opt-in native state variable | +| St | `St` | `St` | `raw` | `float2` | opt-in native state variable | +| Weight | `weight` | `weight` | `raw` | `float` | opt-in native RenderOutput; simple fixture produced a constant sample-count value | + +All selected native AOVs also author matching `driver:parameters:aov:name`, `driver:parameters:aov:format`, `driver:parameters:aov:multiSampled = 0`, and `driver:parameters:aov:clearValue = 0` attrs. These attrs match the working Beauty path and the H20.5 RenderVar metadata shape, but the source of truth for renderer data remains the `sourceName`/`sourceType` pair consumed by hdMoonray. + +Manual H20.5 validation showed `color3f` Beauty output could produce vertical RGB/bayer-like EXR corruption in the explicit Beauty RenderVar path. Switching the custom Beauty RenderVar to `color4f` fixed that corruption by matching the RGBA beauty buffer contract. Copernicus and Nuke both read the resulting EXR channels correctly; an earlier Nuke channel-view issue was user selection error, not file corruption. + +## Material / Denoise AOV Contract + +Official MoonRay evidence: + +- The [moonray_gui documentation](https://docs.openmoonray.org/user-reference/tools/moonray-gui/) states that denoiser auxiliary buffers must be represented by `RenderOutput` objects tagged with `denoiser_input`; names and filenames are not important to the denoiser. +- The documented OIDN albedo auxiliary contract is `result = material aov`, `material aov = D.albedo`, and `denoiser_input = as albedo`. +- The documented OIDN normal auxiliary contract is `result = state variable`, `state variable = N`, `channel_suffix_mode = rgb`, and `denoiser_input = as normal`. +- The [Material AOV guide](https://docs.openmoonray.org/user-reference/how-to-guides/render-outputs/material-aovs/) defines material AOVs as diagnostic material-property outputs with syntax `[('