Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question How to draw pixelate normal edge in URP feature pass.

Discussion in 'Getting Started' started by Blueplane, Apr 11, 2024.

  1. Blueplane

    Blueplane

    Joined:
    Jun 4, 2019
    Posts:
    5
    Hi, I'm writing to ask for help because I feel limited..
    Please understand that I am not good at English. ..;)

    I'm doing pixelation in URP Feature Pass.

    Like this:

    Code (CSharp):
    1. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    2. {
    3.     SortingCriteria sortingCriteria = SortingCriteria.CommonOpaque;
    4.  
    5.     ScriptableRenderer renderer = renderingData.cameraData.renderer;
    6.     RenderTargetIdentifier colorHandle = renderer.cameraColorTargetHandle;
    7.     RenderTargetIdentifier depthHandle = renderer.cameraDepthTargetHandle;
    8.  
    9.     DrawingSettings drawingSettings = CreateDrawingSettings(m_ShaderTagIdList, ref renderingData, sortingCriteria);
    10.  
    11.     ref CameraData cameraData = ref renderingData.cameraData;
    12.     Camera camera = cameraData.camera;
    13.  
    14.     int pixelWidth = (int)(camera.pixelWidth / pixelDensity);
    15.     int pixelHeight = (int)(camera.pixelHeight / pixelDensity);
    16.  
    17.     CommandBuffer cmd = CommandBufferPool.Get("PixelateFeaturePass");
    18.     using (new ProfilingScope(cmd, m_ProfilingSampler))
    19.     {
    20.         cmd.ClearRenderTarget(true, true, Color.clear);
    21.  
    22.         // <!-- Pixelate render target --!>
    23.         cmd.GetTemporaryRT(pixelTexID, pixelWidth, pixelHeight, 0, FilterMode.Point);
    24.         cmd.GetTemporaryRT(pixelDepthID, pixelWidth, pixelHeight, 24, FilterMode.Point, RenderTextureFormat.Depth);
    25.         cmd.SetRenderTarget(pixelTexID, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, pixelDepthID, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
    26.  
    27.         cmd.ClearRenderTarget(true, true, Color.clear);
    28.         context.ExecuteCommandBuffer(cmd);
    29.         cmd.Clear();
    30.  
    31.         context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings, ref m_RenderStateBlock);
    32.         cmd.SetRenderTarget(colorHandle, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store, depthHandle, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store);
    33.         cmd.Blit(new RenderTargetIdentifier(pixelTexID), BuiltinRenderTextureType.CurrentActive, overrideMaterial);
    34.  
    35.         cmd.ReleaseTemporaryRT(pixelTexID);
    36.         cmd.ReleaseTemporaryRT(pixelDepthID);
    37.         cmd.ReleaseTemporaryRT(pixelNormalID);
    38.  
    39.         context.ExecuteCommandBuffer(cmd);
    40.         cmd.Clear();
    41.     }
    42.     context.ExecuteCommandBuffer(cmd);
    43.     CommandBufferPool.Release(cmd);
    44. }
    Original:
    upload_2024-4-11_16-12-40.png

    Result:
    upload_2024-4-11_16-14-23.png


    And I tried to draw edges using _CameraNormalsTexture in Shader, which corresponds to overrideMaterial

    Shader Code (Simplified):
    Code (CSharp):
    1. float NormalDiff(float3 center, float3 side)
    2. {
    3.     float normalDot = dot(center - side, float3(1.0, 1.0, 1.0));
    4.     normalDot = smooth_max(0.00000001, normalDot);
    5.     normalDot = (1.0 - dot(center, side)) * normalDot;
    6.     return normalDot;
    7. }
    8.  
    9. float3 GetNormal(float2 uv)
    10. {
    11.     float3 normal;
    12.     normal = _CameraNormalsTexture.SampleLevel(sampler_CameraNormalsTexture, uv, 0).rgb;
    13.     normal = TransformWorldToViewDir(normal, true);
    14.     return normal;
    15. }
    16.  
    17. float DiffNormalNeighbours(float2 uv)
    18. {
    19.     float2 delta = GetPixelSize();
    20.  
    21.     float3 up = GetNormal(uv + float2(0.0, 1.0) * delta);
    22.     float3 down = GetNormal(uv + float2(0.0, -1.0) * delta);
    23.     float3 left = GetNormal(uv + float2(-1.0, 0.0) * delta);
    24.     float3 right = GetNormal(uv + float2(1.0, 0.0) * delta);
    25.     float3 center = GetNormal(uv);
    26.  
    27.     float3 diff = NormalDiff(center, up);
    28.     diff += NormalDiff(center, down);
    29.     diff += NormalDiff(center, left);
    30.     diff += NormalDiff(center, right);
    31.  
    32.     return diff;
    33. }
    34.  
    35. half4 frag(Varyings input, out float depth : SV_Depth) : SV_Target
    36. {
    37.     // Do Something..
    38.  
    39.     float normalDiff = DiffNormalNeighbours(input.uv);
    40.     col.rgb = col.rgb * (1.0 + normalDiff);
    41.  
    42.     return col;
    43. }

    Result:
    upload_2024-4-11_17-2-3.png

    Primary pixelation was implemented in feature pass.
    However, draw the edge using _CameraNormalTexture in the shader of overrideMaterial, it was drawn based on the existing resolution as example.

    I tried visualizing the normal as shown below.
    I wondered what it would be like if the pixelation in the feature pass did the same in _CameraNormalTexture, but I couldn't find a way.

    Visualizing normals:
    upload_2024-4-11_17-10-25.png



    This is what i want (Example):
    upload_2024-4-11_17-5-31.png



    Thank you for reading the long article. Please help me just once..