Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How to access to neighbour pixels in compute shader?

Discussion in 'Shaders' started by mishazawa, Jul 22, 2023.

  1. mishazawa

    mishazawa

    Joined:
    Oct 4, 2019
    Posts:
    5
    Hello. I'm trying to generate simple 1D water surface line using compute shader and render texture. But I'm achieve strange scrolling of generated texture. I guess it is something related to GPU groups. My texture is 32 x 32 pixels.

    My approach is following:
    1. pick left pixel and right pixel
    2. make calculations for current pixel
    3. store results for the next frame
    Code (CSharp):
    1.  
    2. #pragma kernel ComputeFluid
    3.  
    4. #define DAMPING .9
    5.  
    6. Texture2D<float4> InputBuffer;
    7. SamplerState samplerInputBuffer;
    8. RWTexture2D<float4> OutputBuffer;
    9.  
    10. float2 mouse;
    11. float2 resolution;
    12.  
    13. [numthreads(8, 8, 1)]
    14. void ComputeFluid (uint3 id : SV_DispatchThreadID)
    15. {
    16.     // mouse position
    17.     float2 offset    = float2(1/resolution.x, 0) * .5;
    18.     float2 uv        = float2(id.xy) / resolution;
    19.     float2 cursor    = (mouse + .5);
    20.     float  dist      = distance(uv, cursor);
    21.  
    22.     // access to pixels and computations
    23.     float4 data      = InputBuffer.SampleLevel(samplerInputBuffer, uv, 0);
    24.     float4 dataLeft  = InputBuffer.SampleLevel(samplerInputBuffer, uv - offset, 0);
    25.     float4 dataRight = InputBuffer.SampleLevel(samplerInputBuffer, uv + offset, 0);
    26.     float  newValue  = dataLeft.x + dataRight.x - data.y + smoothstep(dist, 0, .1);
    27.  
    28.     OutputBuffer[id.xy] = float4(newValue * DAMPING, data.x, 0, 0);
    29. }
    30.  
    Dispatcher code:


    Code (CSharp):
    1.  
    2. void Start ()
    3.     {
    4.         ComputeFluid = shader.FindKernel ("ComputeFluid");
    5.  
    6.         data1.enableRandomWrite = true;
    7.         data1.Create ();
    8.      
    9.         shader.SetVector("resolution", new Vector2(width, heigth));
    10.         shader.SetTexture (ComputeFluid, "InputBuffer", data1);
    11.         shader.SetTexture (ComputeFluid, "OutputBuffer", data1);
    12.     }
    13.  
    14.     void Update()
    15.     {
    16.             shader.Dispatch (
    17.                ComputeFluid,
    18.                Mathf.CeilToInt(width / 8f),
    19.                Mathf.CeilToInt(heigth / 8f),
    20.                1);
    21.     }
    22.  
    23.     void FixedUpdate()
    24.     {
    25.         Vector2 npos = new Vector2(
    26.             cursor.position.x / transform.localScale.x,
    27.             cursor.position.y / transform.localScale.z
    28.         );
    29.  
    30.         shader.SetVector("mouse", npos);
    31.  
    32.     }
    33.  
     

    Attached Files:

    Last edited: Jul 22, 2023
  2. mishazawa

    mishazawa

    Joined:
    Oct 4, 2019
    Posts:
    5
  3. mishazawa

    mishazawa

    Joined:
    Oct 4, 2019
    Posts:
    5
    So basically I just not notice that my UVs multiplied by .5 and this cause this scrolling. Line 17
     
  4. mishazawa

    mishazawa

    Joined:
    Oct 4, 2019
    Posts:
    5
    Also Render texture that I use clamp values below 0.
    RenderTextureFormat.ARGBHalf format can fix it.
     
  5. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    466
    Just use
    float4 data = InputBuffer[id.xy];
    instead of
    float4 data = InputBuffer.SampleLevel(samplerInputBuffer, uv, 0);
    It's simple and direct access to texture without any uv/clamps. (and a little faster)
     
  6. mishazawa

    mishazawa

    Joined:
    Oct 4, 2019
    Posts:
    5
    Thank you for reply. It works perfectly.
    I didn't get how indices works, because I though id is limited to current processing group size. This concept is kind of hard to understand at the beginning.
     
  7. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    466
    SV_DispatchThreadID works like "dispatch size * numthreads"
    In your case (for example for texture size 1024 * 512) you will have SV_DispatchThreadID range x [0-1024] and y [0-512];
    For example you can use [numthreads 2, 2, 1] and dispatch(512, 256, 1)
    In this case you will have the same ID range (1024 and 512) but it will be slower (see the details about warps in nvidia/amd)
    https://anteru.net/blog/2018/intro-to-compute-shaders/
     
    mishazawa likes this.