Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Random Point/Vertex Distribution

Discussion in 'Shaders' started by hainkiwanki, Oct 15, 2018.

  1. hainkiwanki

    hainkiwanki

    Joined:
    Oct 23, 2017
    Posts:
    20
    Hello,

    My goal is to generates vertices equally distributed over any mesh. How do I plan on doing this? In a geometry shader with a triangle typology as input, I will generate x vertices based on the surface area of the triangle compared to the total surface area of the object.
    For example:
    Triangle 1 Surface Area = 2
    Total Object Surface Area = 100
    => ratio = 2/100 = 0.02
    Total amount of vertices to generate: 1000
    => vertices to generate in this triangle: 0.02 * 1000 => 20.

    Then I would need random values to apply the following equations to generate the points inside the triangle:
    https://adamswaab.wordpress.com/2009/12/11/random-point-in-a-triangle-barycentric-coordinates/
    https://stackoverflow.com/questions...erate-equally-distributed-points-in-a-polygon

    The problem lies with the random values. I know random isn't a thing in a geometry shader or at least not as easy to achieve as in C#.
    How can I get random numbers?
    I know I could perhaps use a noise map, but how does that exactly work then? I know I can use the UV coords from one of the 3 input vertices to get a value from it, but as in the example above, I need 20 different random values.
    Should I calculate my random values outside the shader, in C# code and then pass them to the shader?
    Perhaps use a custom buffer?

    What's the best way to get random numbers inside a geometry shader? Or should I do it another way?
     
  2. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    327
  3. hainkiwanki

    hainkiwanki

    Joined:
    Oct 23, 2017
    Posts:
    20
    This is good for 1 random value, but how do I get more than 1 random value in the geometry shader?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Is the question "more than one random value within each execution", or "a random value for each execution"?

    If you need a random number for each execution, @Przemyslaw_Zaworski answered that already.
    The primitive ID is unique for each execution of the geometry shader (ie: each triangle) per mesh.

    If you need multiple random numbers within each execution, just call your rand function multiple times, either with the output random value as the seed, or the original seed plus some arbitrary value.

    float n0 = rand(k);
    float n1 = rand(n0);
    float n2 = rand(k+1);
     
  5. hainkiwanki

    hainkiwanki

    Joined:
    Oct 23, 2017
    Posts:
    20
    It was multiple random values within each execution. It think your solution will do.
    I added the random position I created using the random in the next random function. But using the actual random as input seems easier.
    Thanks both :)
     
  6. hainkiwanki

    hainkiwanki

    Joined:
    Oct 23, 2017
    Posts:
    20
    This is the result of random vertex distribution used as hair roots:
    upload_2018-10-18_18-57-19.png

    Now I wanna figure out how to get the correct UV at the random point location, because there are white hair roots in black colored uv as shown in picture below:
    upload_2018-10-18_18-58-49.png

    Basically, I want white hair roots in white parts of the texture, and black hair roots in black parts of the texture. I did some googling first and found out I could perhaps interpolate between the UVs of the triangle the point is generated in:

    Code (CSharp):
    1.        
    2.         float4 rootB = mul(unity_ObjectToWorld, float4(root - vertices[1].pos, 1));
    3.         float4 rootC = mul(unity_ObjectToWorld, float4(root - vertices[2].pos, 1));
    4.         float4 rootA = mul(unity_ObjectToWorld, float4(root - vertices[0].pos, 1));
    5.  
    6.         float2 uv = vertices[0].texc * length(normalize(rootA)) + vertices[1].texc * length(normalize(rootB)) + vertices[2].texc * length(normalize(rootC));
    7.  
    I also found this:
    https://answers.unity.com/questions/383804/calculate-uv-coordinates-of-3d-point-on-plane-of-m.html
    I tried it, but still no good:
    upload_2018-10-18_19-9-23.png
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    So, I assume you're getting your random position using the technique of taking two random values to generate a barycentric coordinate, yes?

    float bx = rand(x);
    float by = rand(by);
    float bz = 1 - bx - by;

    float3 hairPos = verts[0].pos * bx + verts[1].pos * by + vertex[2].pos * bz;


    Getting the UV for that position is done exactly the same way.

    float2 hairUV = verts[0].uv * bx + verts[1].uv * by + verts[2].uv * bz;
     
  8. hainkiwanki

    hainkiwanki

    Joined:
    Oct 23, 2017
    Posts:
    20
    Aaaaah yes, I tried this method before but it didn't work because I messed up.
    What I had back then:

    Code (CSharp):
    1.        
    2.         float r1 = rand(x + OFFSET);
    3.         float r2 = rand(r1);
    4.         float r3 = 1 - r1 - r2;
    5.         x = r1;
    6.  
    7.         float3 root = vertices[0].pos + r1 * AB + r2 * AC;
    8.         float2 uv = vertices[0].texc * r1 + vertices[1].texc * r2 + vertices[2].texc * r3;
    What it had to be:

    Code (CSharp):
    1.        
    2.         float r1 = rand(x + OFFSET);
    3.         float r2 = rand(r1);
    4.         float r3 = 1 - r1 - r2;
    5.         x = r1;
    6.  
    7.         float3 root = vertices[0].pos + r1 * AB + r2 * AC;
    8.         float2 uv = vertices[0].texc * r3 + vertices[1].texc * r1 + vertices[2].texc * r2;
    Thank you, it works beautifully now
    upload_2018-10-18_23-24-9.png
     
    bzor likes this.