Search Unity

Resolved Strange flickering from normals calculation in compute shader

Discussion in 'Shaders' started by Qleenie, Dec 27, 2020.

  1. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    867
    Hi there, I am trying to build some PBD cloth / softbody compute shaders, but am struggling with the part I thought would be the easiest: re-calculation of normals.
    My current approch: Send info about mesh triangles to compute shader, and do normals calculation in each timestep like this:
    Code (CSharp):
    1. #pragma kernel UpdateNormals
    2. [numthreads(32, 1, 1)] // TODO: play around with numthread size
    3. void UpdateNormals(uint3 id : SV_DispatchThreadID) {
    4.     if (id.x >= numTriangles) return;
    5.     uint3 indexes = triangles[id.x];
    6.  
    7.     float3 p0 = positions[indexes.x];
    8.     float3 p1 = positions[indexes.y];
    9.     float3 p2 = positions[indexes.z];
    10.  
    11.     //get normals
    12.     float3 n1 = cross(p1 - p0, p2 - p0);
    13.    
    14.     normals[indexes.x] += float4(n1,0);
    15.     normals[indexes.y] += float4(n1, 0);
    16.     normals[indexes.z] += float4(n1, 0);
    17. }
    "positions" are the calculated positions of vertices of the mesh; "triangles" stores the 3 vertex indexes of each triangle.
    Later in the code I do:
    Code (CSharp):
    1. float4 normal = normalize(normals[id.x]);
    The result goes into a RenderTexture, and get rendered by shader graph via vertex displacement. Normals look somehow correct, but are flickering a lot, especially in the darker areas. I have no clue what could cause this.
    Any help would be appreciated.
     
  2. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    867
    I did some more investigation; I can rule out that the shader graph part is the culprit, as when I pull the data from GPU on CPU and set the mesh normals every frame, same effect happens.
    I am really clueless about what's happening, as the normals seem to be correct, the triangles are only set once, but normal result seems to be different each frame. Can it be some sort of imprecision due to constant updates of vertex positions by PBD algorithm?

    Edit: Even if I don't update positions at all, flickering still occurs, so must be something else.
     
  3. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    867
    I found the reason; classic race condition, as I was updating the intermediate normal values in parallel, so some updates where overwritten by others. Solved it now with "InterlockedAdd" and using int internally. Wonder if there is a better method, but for now this works.