Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

[7.3.1] RenderPassEvent.AfterRenderingPostProcessing is broken?

Discussion in 'Universal Render Pipeline' started by Elfstone, Apr 22, 2020.

  1. Elfstone

    Elfstone

    Joined:
    Apr 13, 2015
    Posts:
    26
    I want a custom render pass to be executed after integrated post processes.
    But it turns out there seems to be no way for me to access _AfterPostProcessTexture, not without modifying URP codes anyway. My pass is executed as expect after PPs but is overwritten by the final pass.
    Does this mean an AfterRenderingPostProcessing pass is officially broken for now?
     
    AlejMC likes this.
  2. Elfstone

    Elfstone

    Joined:
    Apr 13, 2015
    Posts:
    26
    And I'm not sure what RenderPassEvent.AfterRendering is for.
    Final Post Processing Pass is still after my custom pass.
     
  3. Elfstone

    Elfstone

    Joined:
    Apr 13, 2015
    Posts:
    26
    OK, it seems I'll have to expose ForwardRenderer.m_AfterPostProcessColor. And there isn't meant to be any pass after AfterRendering, or is there?
     
    Last edited: Apr 22, 2020
    daneobyrd likes this.
  4. StaggartCreations

    StaggartCreations

    Joined:
    Feb 18, 2015
    Posts:
    2,278
    I'm facing the same predicament. It's possible to declare _AfterPostProcessTexture and sample it in a shader, but there seems to be no way to write back to it from the C# side.

    This means I'm not able convert incoming HDR values to LDR, since this kills Tonemapping and Bloom otherwise.
     
  5. AxonGenesis

    AxonGenesis

    Joined:
    Jun 24, 2016
    Posts:
    91
    I've run into this issue as well. I created a URP render feature, but it only works if injected Before Render Post Processing or earlier. Setting it to after, the effect doesn't get rendered. All I'm doing is using blit between render textures to cameraColorTarget.

    Does anyone know if this is a limitation, bug, or needs to be a feature request? It would be useful in my effect to be able to process after everything else.

    It's also a bit unclear when to use an Image Effect, Custom Post Processing Effect, or Scriptable Render Pass. Seems the effect I'm implementing could be done with any, except I believe that CPP is not available in URP yet, and Image Effect cannot yet be created using Shader Graph.
     
  6. phil_lira

    phil_lira

    Unity Technologies

    Joined:
    Dec 17, 2014
    Posts:
    584
    Reading _CameraColorTexture after post is not yet supported in URP. You can still write to whatever target is bound after post. _AfterPostProcessing is an internal temp texture to avoid an extra blit due to a pipeline limitation. If we were to support this today, we would have to copy back the content of _AfterPostProcessing to _CameraColorTexture which is inneficient.

    What we have discussed doing is to support a "swap buffer" for URP and a way to access pipeline textures.
    This involves two part work.
    1) Supporting access to pipeline texture, similar to how built-in has https://docs.unity3d.com/ScriptReference/Rendering.BuiltinRenderTextureType.html we could have `UniversalRenderTextureType.CameraColorTexture` (or for that matter, depth, gbuffer, normals, motion vector etc).

    I'm prototyping this idea now and I have a PR open: https://github.com/Unity-Technologies/Graphics/pull/48

    2) When you do custom post-processing or (even the internal one), we want to sort of read and write to same texture, but that's not possible in hardware (unless you can do framebuffer fetch but that doesn't apply for most post-processing).

    Naive way is to blit back the result of post-processing to source texture:
    Blit(source, dest); // post-processing
    Blit(dest, source) // copy-back

    This is very inneficient though. However, you should not care about copy-back if you have a way to get the current camera color texture and have a swap chain.

    So, imaging you can do something like this:
    Blit(UniversalRenderTextureType.CameraColorTexture, UniversalRenderTextureType.CameraColorTextureBack);

    internally, this does:
    Blit(_CameraColorTexture[0], _CameraColorTexture[1]);
    Swap(_CameraColorTexture[0], _CameraColorTexture[1]);

    So next time you read from UniversalRenderTextureType.CameraColorTexture you are actually reading from _CameraColorTexture[1] that contains the result of post-processing.
     
  7. Elfstone

    Elfstone

    Joined:
    Apr 13, 2015
    Posts:
    26
    This looks great! Hope it will come to 2019 soon.
    What I have is really a simple pipeline of image effects with its own swap buffer in my custom pass. This does make it easier.
     
  8. AxonGenesis

    AxonGenesis

    Joined:
    Jun 24, 2016
    Posts:
    91
    I found a workaround which is a bit of a hack but gets the job done for my purposes. Maybe it will help others trying to do tricky things with the render pipeline. In my case I have been working on a high quality 360 VR capture that includes render features and post processing. Since I'm rendering frames to disk, speed isn't the main concern.

    The key is to use 2 cameras and a render texture as an intermediate buffer. The first camera uses a custom script to WaitForEndOfFrame to capture the frame into the render texture. The second camera then uses a custom ScriptableRenderPass (before post process) to blit the render texture into the 2nd camera for the final post process. I'm using shader graph to do some specialized processing with the render pass and allowing the 2nd camera to apply post processing afterward. Though one could configure the same setup so the 1st camera renders post processing and then the custom render pass does the extra post processing on the 2nd camera.

    This solution is working great as a method to render, but is slow due to the number of blits required. Not an ideal solution by any means, but is the only way I've found so far to do it.
     
  9. hiro_j

    hiro_j

    Joined:
    May 13, 2019
    Posts:
    16
    I'm having a problem with this issue as well.

    I tried the following simple method, but it flips upside down and copies it.

    commandBuffer.GetTemporaryRT(renderTextureId, w, h, 0, FilterMode.Point, RenderTextureFormat.Default);
    commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, renderTextureId);
    commandBuffer.Blit(renderTextureId, BuiltinRenderTextureType.CameraTarget);

    Once this problem is solved, everything should be fine.
     
  10. hiro_j

    hiro_j

    Joined:
    May 13, 2019
    Posts:
    16
    I have no problem with it in [scene] mode, but it flips when I'm in [game] mode.
    I think I can force a solution with [#if UNITY_EDITOR], but if you have any similar problems or solutions, please let me know.
     
  11. AlejMC

    AlejMC

    Joined:
    Oct 15, 2013
    Posts:
    149
    Ok, glad to hear that this is actually a limitation. Was pulling some hairs trying to understand how to make it work.
    My use case is:
    1. Rendering normally (camera renders 3d to a lower-res render texture)
    2. Compose it later with full-res canvas UI and all.
    Now, I wanted to do a downsize+blur after the whole 3D rendering to use as a blurred background for some of those UI elements that come after:
    1. Rendering normally (camera renders 3d to a lower-res render texture)
    2. Downsize+Blur the the previous result, store on a global shader variable.
    3. Compose it later with full-res canvas UI and all. UI elements custom shaders have access to that blurred outcome.
    I'm using the Kawase Blur sample from Sebastien Hein: https://github.com/sebastianhein/urp_kawase_blur

    It does work but for the sake of me I couldn't manage to get the FINAL after post rendering to go through that blur step.

    I like these swapping ideas... it would actually be great to expand it even more:
    • The swapped texture that it's left there for use could have 'downsize' options, similar to how the _OpaqueTexture is used.
    • On the double buffering idea: also sometimes the 'camera opaque' texture is ok if it is one frame late, could get the same treatment (if I'm understanding all of this right).
     
  12. LightJockey

    LightJockey

    Joined:
    Jan 24, 2014
    Posts:
    6
    Two years later and this is still an issue
     
  13. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,352
    Sorry for necroing this. It turned up in my search so here is an update from 2023.

    It seems if you Blit from the "cameraTargetHandle" (camera color target) then ..
    in URP 12 (haven't tested lower) the post pro texture is accessible via _MainTex (URP 12)
    in URP 13 via _BlitTexture [or _CameraColorTexture]

    However, in 2D URP it seems to not be accessible. Is there a way to get to it in the 2D renderer?

    upload_2023-7-27_9-8-24.png