Search Unity

Question How to down-sample and rescale single object using specific shader?

Discussion in 'Shaders' started by SamKennedy, Jan 23, 2023.

  1. SamKennedy

    SamKennedy

    Joined:
    Apr 25, 2021
    Posts:
    12
    I've been stuck on this for a few days now so any help would be very greatly appreciated. I have made a custom volumetric ray marching shader, but it gets expensive to render at 1920x1080. I have experimented and found that if I ray-march at 1280x720, then upscale to 1920x1080, visually it looks very similar, but computationally is much quicker.

    The problem I have is how to perform this down-sampling and rescaling only on the ray marched volume and not the entire screen?

    I have tried setting up two separate cameras: one just to do the ray marching, and the other to render the rest of the scene. However, this then requires trying to pass the scene depth buffer from the scene camera to the camera doing the ray marching, so that the volume is properly occluded by scene objects. I haven't been successful in attempting this.

    I have managed to get only the camera rendering the ray marching to down-sample and rescale to full resolution, however as soon as I enable the scene camera the ray marching is performed at full resolution, since the target resolution changes.

    Here is my code that I attach to the camera displaying the ray marched volume, however I can't figure out how to composite this with the full resolution scene camera, with proper depth/occlusion:

    Code (CSharp):
    1. [ExecuteInEditMode]
    2. [RequireComponent(typeof(Camera))]
    3. public class DownUpSample : MonoBehaviour
    4. {
    5.  
    6.     private Camera cam;
    7.     [SerializeField] private RenderTexture rt;
    8.  
    9.     private void OnEnable()
    10.     {
    11.         cam = GetComponent<Camera>();
    12.     }
    13.  
    14.     private void OnPreRender()
    15.     {
    16.         cam.targetTexture = rt;
    17.     }
    18.  
    19.     private void OnRenderImage(RenderTexture source, RenderTexture destination)
    20.     {
    21.         Graphics.Blit(source, destination);
    22.     }
    23.  
    24.     private void OnPostRender()
    25.     {
    26.         cam.targetTexture = null;
    27.     }
    28.  
    29.  
    30. }
    The resolution of rendering is set by the 'rt' RenderTexture. Also, I'm using the built-in render pipeline, switching to URP isn't an option at this point in the project.

    If there is a way to do this without requiring two cameras that would be ideal, but I'm guessing that's not possible.

    Thank you!