Skip to content

GameGraph Transparent Picture-in-Picture ​

Use the direct Viewport route when a local 3D scene only needs to appear over the main scene. Use RenderToTexture when the result must enter GameUI, Canvas, a material, or later processing.

Direct Viewport Workflow ​

  1. Configure the main scene with Renderer.SetupMainViewport(scene, camera).
  2. Create a separate overlay SceneGraph; do not copy the main scene's ground, sky, or environment into it.
  3. Add an overlay camera, lights, and only the objects that should appear.
  4. Create a Viewport, set its pixel rect, and require SetRenderPath to succeed:
csharp
var overlayViewport = Renderer.CreateViewport(overlayScene, overlayCamera);
overlayViewport.SetRect(464, 24, 880, 304);

if (!overlayViewport.SetRenderPath(
        "EngineRes/RenderPaths/GameOverlay.xml"u8))
{
    throw new InvalidOperationException("GameOverlay RenderPath not found.");
}

var overlayIndex = Renderer.GetNextFreeViewportIndex();
Renderer.SetViewport(overlayIndex, overlayViewport);
  1. On cleanup, call Renderer.SetViewport(overlayIndex, null) before disposing the scene.

GameOverlay.xml must contain useLastRenderTarget="true" and clear depth without clearing color. Do not replace it with a normal scene RenderPath when transparency is required.

Never Rely on the Host Default RenderPath ​

Every additional Viewport and RenderToTexture Viewport must call SetRenderPath(...) explicitly. A new Viewport does not guarantee the same RenderPath behavior across hosts:

  • editor-embedded debug commonly defaults to EditorMapSSAOBloomHDR.xml, which currently does not present scene fog;
  • standalone and battle-platform clients commonly default to CEMapSSAO.xml, which does present scene fog;
  • a PIP or minimap that is clear in the editor may therefore be fogged out in the real client, especially when its camera is far above the terrain.

Choose by intent: use CEMapSSAO.xml for a normal camera that should match client atmosphere, EditorMapSSAOBloomHDR.xml for an intentionally fog-free technical/minimap view, and GameOverlay.xml for transparent direct composition. Never treat an accidentally fog-free editor result as the specification.

Always Add a Control Viewport While Diagnosing ​

Use the same scene content and camera parameters for two Viewports. They may share one Scene/Camera, or use two structurally identical independent SceneGraphs when clearer visual labeling is useful:

  • control: EngineRes/RenderPaths/CEMapSSAO.xml;
  • experiment: EngineRes/RenderPaths/GameOverlay.xml.

Interpret the result:

  • neither renders: Viewport/Scene/Camera/material problem;
  • only control renders: overlay RenderPath or resource-version problem;
  • both render but overlay has a background: overlay scene contains background geometry, or the wrong RenderPath was loaded.

The code_sample/src/RendererViewportSample/ example demonstrates this comparison.

Troubleshooting: Skeletal Tearing Across Views ​

If a skeletal character is correct in either View alone but tears or stretches when the main camera and a minimap / PIP camera render it together, treat it as a multi-View skinning-state issue first. The texture-skinning atlas and Compute-Skinning output Geometry are not fully View-local yet, so View visibility and update order can overwrite shared Drawable state.

Use this short-term client-side workaround on every model part that is visible in both Views:

csharp
var model = actor.GetAnimatedModel();
if (model != null)
{
    model.SimpleSkinning = true;
    model.ComputeShaderSkinning = false;
}

SimpleSkinning requires client capability version 3, is limited by the device bone / uniform capacity, and is a model-level choice rather than a per-View override. If the model is too large for ordinary hardware skinning, filter that character from the secondary View instead. Do not claim that this workaround fixes View isolation; the long-term renderer work is tracked separately. See docs/systems/GameGraphSkeletalAnimation.md for the full symptom check and three-path comparison.

RenderToTexture Workflow ​

Use an explicit alpha format:

csharp
var texture = Texture2D.CreateRenderTarget(
    256,
    192,
    RenderTargetFormat.Rgba8);

Use Rgba16F/Rgba32F only when HDR or extra precision is required. Do not use Rg11B10 or the legacy highDynamicRange: false overload for alpha-dependent composition.

Bind the viewport to texture.RenderSurface, set UpdateAlways, and use a project RenderPath that clears to color="0 0 0 0". Display through RuntimeTexture, .Image(texture, name), Canvas.DrawTexture, or a material that is known to load in the target runtime.

  • QueueUpdate() requests a later surface update. Let the configured RTT viewport actually render before GetImage; neither IsUpdateQueued nor an advanced UrhoCore.Time.FrameNumber alone proves that this RTT rendered, especially when rendering is paused or the viewport is invalid.
  • GetImage returns an 8-bit RGB/RGBA snapshot of the current GPU texture. It does not tone-map, does not automatically linearize sRGB, and clips HDR values above 1. The encoding depends on the RTT format/sRGB state and RenderPath. See docs/guides/TransparentPictureInPicture.md#更新时机与像素回读.

Resource-Version Integrity ​

Treat the installed editor/client directory and source workspaces as independent.

  • Do not assume -use_local_res reads an XML edited in a source checkout.
  • For unpublished experiments, copy the XML into the test map's res/ with a unique path such as RenderPaths/TransparentOverlayTest.xml.
  • Rebuild GameEntry when code changes and restart the pure client after code or resource changes.
  • Restore experiments before committing official EngineRes changes.

Readable reference copies are under resources/rendering-reference/. They are documentation assets, not runtime-loaded SDK resources.

Verification ​

Do not accept editor-embedded rendering as final evidence for multi-Viewport behavior. One reason is that the embedded editor and standalone client can select different default RenderPaths, including different fog behavior.

  1. Close the editor before pure-client debugging.
  2. Run the updated client/runtime.
  3. Place the transparent Viewport over a visibly colored main-scene object.
  4. Capture a real frame with Runtime MCP debug.capture_screenshot.
  5. Verify that the overlay object is visible and the main scene remains visible around it.
  6. For ordinary PIP, minimap, or RTT cameras, verify that fog matches the explicitly selected RenderPath and that distant terrain remains visible when required.
  7. Check logs for the expected markers and absence of WASM exceptions or RenderPath failures.
  8. Stop only the client PID owned by the current test.

References ​

  • docs/guides/TransparentPictureInPicture.md
  • docs/systems/GameGraphOverview.md
  • docs/systems/MaterialSystem.md
  • docs/guides/ClientOnlyDebug.md
  • docs/guides/RuntimeMcpDebugGuide.md
  • resources/rendering-reference/README.md