View Issue Details

IDProjectCategoryView StatusLast Update
0005183NoesisGUIUnitypublic2026-08-21 21:01
Reportersagzain Assigned Tojsantos  
PrioritynormalSeveritymajor 
Status assignedResolutionopen 
Product Version4.0 
Target Version4.0.1 
Summary0005183: HDRP issue with multiple viewports
Description

When rendering multiple Views in subrectangles of the screen, the viewport coordinates are not properly applied to the GPU before rendering noesis.

PlatformAny

Activities

jsantos

jsantos

2026-08-21 21:01

manager   ~0012559

Patch provided by EF games

HDRP.diff (5,478 bytes)   
index 1354f22..5f639f0 100644
--- a/NoesisGUIUnity/Runtime/NoesisView.cs
+++ b/NoesisGUIUnity/Runtime/NoesisView.cs
@@ -1140,15 +1140,43 @@ public class NoesisView: MonoBehaviour, ISerializationCallbackReceiver
                 if (ctx.hdCamera.camera.TryGetComponent(out NoesisView view))
                 {
                     if (InjectionPoint == view.InjectionPoint)
                     {
                         bool flipY = SystemInfo.graphicsUVStartsAtTop && !IsBackbuffer(ctx.cameraColorBuffer);
-                        view.OnExecuteCustomPass(ctx.cmd, flipY);
+                        view.OnExecuteCustomPass(ctx.cmd, flipY, NeedsExplicitViewport(ctx.cameraColorBuffer));
                     }
                 }
             }

+            // [RIVALS] PARCHE LOCAL — split-screen. Si se actualiza NoesisGUI hay que RE-APLICARLO.
+            // Lo defiende el tripwire de fuente Assets/1_Tests/EditMode/NoesisHdrpViewportTests.cs.
+            //
+            // Devuelve true cuando HDRP NO ha dejado atado el viewport de esta camara, asi que dibujar
+            // sin atarlo estira la pagina sobre TODO el render target.
+            //
+            // El mecanismo, de arriba abajo:
+            //   1. CustomPass.SetCustomPassTarget llama a CoreUtils.SetRenderTarget(cmd, color, depth, ...)
+            //      y ese cmd.SetRenderTarget deja el viewport cubriendo el target ENTERO.
+            //   2. CoreUtils.SetViewportAndClear intenta corregirlo con CoreUtils.SetViewport(cmd, color),
+            //      pero esa funcion es literalmente `if (target.useScaling) { ... }`: sobre un RTHandle
+            //      SIN escalado no hace NADA (CoreUtils.cs:899-906).
+            //   3. HDRP entrega el BACKBUFFER importado (useScaling == false) siempre que el post-proceso
+            //      sea el pase final, y eso lo decide HDUtils.PostProcessIsFinalPass:
+            //      `!aov && !Debug.isDebugBuild && !WillCustomPassBeExecuted(AfterPostProcess) && !hasCaptureActions`.
+            //      `Debug.isDebugBuild` es true en el EDITOR y en una development build, y false en una
+            //      build de RELEASE; y `WillCustomPassBeExecuted` solo mira los CustomPassVolume de la
+            //      escena, nunca la lista global donde vive este pase, asi que Noesis no se cuenta a si
+            //      mismo. Resultado: editor y dev build van por el buffer intermedio (viewport correcto)
+            //      y la build de release va por el backbuffer (viewport a pantalla completa).
+            //
+            // Con la camara a pantalla completa el viewport correcto y el completo COINCIDEN, y por eso
+            // esto no se habia visto nunca: solo se manifiesta con camaras de rect parcial (split-screen).
+            private static bool NeedsExplicitViewport(RTHandle buffer)
+            {
+                return !buffer.useScaling;
+            }
+
             private static bool IsBackbuffer(RTHandle buffer)
             {
                 var id = new RenderTargetIdentifier(buffer.nameID, 0, CubemapFace.Unknown, 0);
                 return id == BuiltinRenderTextureType.CameraTarget;
             }
@@ -1205,16 +1233,37 @@ public class NoesisView: MonoBehaviour, ISerializationCallbackReceiver
         }
     }

     public static readonly CustomSampler _customSampler = CustomSampler.Create("Noesis.RenderOnscreen", true);

-    private void OnExecuteCustomPass(CommandBuffer commands, bool flipY)
+    // [RIVALS] PARCHE LOCAL — split-screen. Si se actualiza NoesisGUI hay que RE-APLICARLO.
+    // `bindViewport` lo decide NoesisCustomPass.NeedsExplicitViewport (ver el porque completo alli).
+    private void OnExecuteCustomPass(CommandBuffer commands, bool flipY, bool bindViewport)
     {
         if (_uiView != null && _visible)
         {
             // In HDRP, the custom pass is configured to always clear the stencil buffer before execution
             commands.BeginSample(_customSampler);
+
+            // [RIVALS] Noesis dibuja con una proyeccion ortografica de su TAMANO LOGICO al NDC y no ata
+            // viewport en ninguna parte (ni aqui ni en el plugin nativo), asi que el mapeo a pixeles lo
+            // decide entero el viewport que este atado. Su tamano logico son exactamente
+            // `_camera.pixelWidth/pixelHeight` (ver UpdateSize), o sea que atar el rect de la camara con
+            // esos MISMOS dos enteros hace el mapeo 1:1 por construccion.
+            //
+            // La expresion es la misma que HDCamera.GetPixelRect() —origen de `pixelRect`, tamano de
+            // `pixelWidth/pixelHeight`— porque de ahi sale el `finalViewport` con el que HDRP acaba de
+            // pintar la ESCENA de esta camara en el backbuffer: asi el HUD cae exactamente sobre ella.
+            //
+            // Con la camara a pantalla completa esto es un no-op bit a bit, de modo que solo puede
+            // cambiar el render en el unico caso que estaba roto.
+            if (bindViewport && _camera != null)
+            {
+                commands.SetViewport(new UnityEngine.Rect(
+                    _camera.pixelRect.x, _camera.pixelRect.y, _camera.pixelWidth, _camera.pixelHeight));
+            }
+
             NoesisRenderer.RenderOnscreen(_uiView, flipY, commands, true, _clearStencil);
             commands.EndSample(_customSampler);
         }
     }
HDRP.diff (5,478 bytes)   

Issue History

Date Modified Username Field Change
2026-08-21 20:59 jsantos New Issue
2026-08-21 21:00 jsantos Reporter jsantos => sagzain
2026-08-21 21:00 jsantos Assigned To => jsantos
2026-08-21 21:00 jsantos Status new => assigned
2026-08-21 21:00 jsantos Target Version => 4.0.1
2026-08-21 21:01 jsantos Note Added: 0012559
2026-08-21 21:01 jsantos File Added: HDRP.diff