Search Unity

Eliminating Raymarching Banding in Volume Shaders

Discussion in 'Shaders' started by Major, Jun 24, 2017.

  1. Major

    Major

    Joined:
    Jul 26, 2012
    Posts:
    69
    I recently started messing around with shaders in Unity and thought I'd try creating a raymarch volume shader. I found some success, but I've run into a rather ugly problem that I'm not really sure how to approach. As in the title, I am getting this banding in the render:

    Increasing the step count helps to a point, this was done at 256 steps, and it becomes such a drain on performance that I would like to decrease the steps rather than increase them.

    I would appreciate any insight into this issue. I would like to also understand any solutions as much as possible, so diagrams would also be greatly appreciated. Thanks!
     
  2. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    328
    Could you upload this broken shader or send me code in private message ? I will try to fix it.

    Have you used domain deformations in this shader ? Sometimes operations like bending / twisting can cause artifacts.
    Also you can visit my Git repository, where you can find some raymarch shaders for Unity3D....

    Here you have simple example:

    Code (CSharp):
    1. https://github.com/przemyslawzaworski/Unity3D-CG-programming/blob/master/raymarching_materials_integration.shader
     
    Last edited: Jul 3, 2017
  3. Major

    Major

    Joined:
    Jul 26, 2012
    Posts:
    69
    The code isn't broken, it's behaving exactly as it should. Here is a raymarch script that is heavily simplified to get to the root of the problem:

    Code (CSharp):
    1. Shader "Unlit/TestRayMarch"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.     }
    7.     SubShader {
    8.         Tags {
    9.             "Queue" = "Transparent"
    10.         }
    11.  
    12.         Pass {
    13.  
    14.             //Transparency Stuff
    15.                ZWrite Off
    16.             Cull Front
    17.                 Blend SrcAlpha OneMinusSrcAlpha
    18.  
    19.                 ZTest Off
    20.  
    21.                CGPROGRAM
    22.  
    23.                #include "UnityCG.cginc"
    24.                #include "Lighting.cginc"
    25.  
    26.             #pragma vertex vert          
    27.                 #pragma fragment frag
    28.  
    29.  
    30.                 //Check if the ray intersects with a sphere
    31.                 float checkSphere (float3 rayPosition, float3 _Center) {
    32.                     return distance (rayPosition, _Center);
    33.                 }
    34.  
    35.  
    36.                 float4 raymarch (float3 direction, float3 pixelWorldPos, float3 cameraPos) {
    37.                     float3 pos = cameraPos;
    38.                     float4 sampleValue = float4 (1, 1, 1, 0);
    39.  
    40.                     for (int i = 0; i < 128; i++) {
    41.                         if (checkSphere (pos, mul(unity_ObjectToWorld, float4 (0, 0, 0, 1)).xyz) <= 0.5){
    42.                         sampleValue.a += 0.1;        //This part here, having transparency, causes banding              
    43.                         }
    44.  
    45.                      pos += direction * 0.1;
    46.                     }
    47.  
    48.                     return float4 (sampleValue);
    49.                 }
    50.  
    51.             struct vertOutput {
    52.                     float4 pos : SV_POSITION;
    53.                     float3 wPos : TEXCOORD0;
    54.                };
    55.  
    56.             vertOutput vert(appdata_full v) {
    57.                    vertOutput o;
    58.  
    59.                 o.pos = UnityObjectToClipPos(v.vertex);
    60.                 o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    61.  
    62.                 return o;
    63.             }
    64.  
    65.  
    66.             half4 frag(vertOutput output) : COLOR {
    67.                 return raymarch ( normalize (output.wPos - _WorldSpaceCameraPos), output.wPos, _WorldSpaceCameraPos);
    68.                }
    69.  
    70.             ENDCG
    71.         }
    72.     }
    73. }

    The banding is noticeable because there is an alpha channel that is changing based on ray depth.

    I think another approach to solving this would be using a depth texture.
     
    Last edited: Jul 4, 2017
  4. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Looks like a precision issue as you have enough steps, or maybe you just need to process it further with dither or such?
     
  5. Major

    Major

    Joined:
    Jul 26, 2012
    Posts:
    69
    In a way, yes it is a precision problem. The step size can be changed and that can help reduce the effect, but it never quite goes away. I suppose one path may be that a dynamic system is needed to balance this out in real time, but it would be messy and kind of complicated.

    I've also found an academic paper in which this is avoided via a random depth offset. The problem is getting a random number, and it creates a static like effect which isn't very desirable.
     
  6. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    Jittering the ray depth can help a lot but it does created a "static" pattern. You should blur the volume then do a bilateral upsample to keep the sharp edges.

    Another option is using old school interleaved sampling. Basically render the volume 4 times at a (slices/4) count with a different initial ray offset.

    Then in your final composite pass use an interleaved pattern (dither pattern) to sample from those 4 previous samples.


    This will give you a better quality than if you had rendered all those passes together. It will give you a dither pattern but in either case you should do a blur pass.

    This is a good article even thought it deals with light all the techniques he uses can be applied.
    http://www.alexandre-pestana.com/volumetric-lights/
     
  7. Major

    Major

    Joined:
    Jul 26, 2012
    Posts:
    69
    Ah thanks! It never ceases to amaze me what I don't find in my own research.