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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Issue ComputeShader Noise Map

Discussion in 'Scripting' started by Shiikarii, Apr 13, 2016.

  1. Shiikarii

    Shiikarii

    Joined:
    Feb 6, 2014
    Posts:
    89
    Hello, it's me again..

    today i started with computeshaders and i wonder how they work... i wrote a little sample program that should hopefully output this:

    So it is a simple float3 array | XY = Position | Z = 1/0 Terrain or Air
    anyway this image below is not the compute shader, it should be the final output.

    mapFilled.PNG

    Here is the output from my msBuffer, as u can see it gaves me very weird results...

    positions.PNG

    And this is the workflow:
    1. Fill an float array with the noise results = noiseComputer
    2. Check if noise results r greater then 0
    3. Fill the float3 array with the results XYZ = msComputer
    4. Loop through this array and draw some gizmos

    Here r my scripts:

    This is the main script.
    The "ImprovedPerlinNoise" comes from this little blog: https://scrawkblog.com/category/procedural-mesh/
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using ImprovedPerlinNoiseProject;
    4.  
    5. public class Generator : MonoBehaviour
    6. {
    7.     public ComputeShader noiseComputer, msComputer;
    8.     public int S;
    9.     public string seed;
    10.  
    11.     public Vector3[] positions;
    12.  
    13.     ComputeBuffer noiseBuffer, msBuffer;
    14.     ImprovedPerlinNoise noise;
    15.  
    16.     int[,] map;
    17.  
    18.     void Update()
    19.     {
    20.         if(Input.GetMouseButtonDown(0))
    21.         {
    22.             if (S % 8 != 0)
    23.                 throw new System.ArgumentException("Size must be divisible be 8");
    24.  
    25.             map = new int[S, S];
    26.  
    27.             noiseBuffer = new ComputeBuffer(S * S, sizeof(float));
    28.             msBuffer = new ComputeBuffer(S * S, sizeof(float));
    29.  
    30.             int newSeed = (seed == "") ? Random.Range(int.MinValue, int.MaxValue) : seed.GetHashCode();
    31.             noise = new ImprovedPerlinNoise(newSeed);
    32.             noise.LoadResourcesFor3DNoise();
    33.  
    34.             noiseComputer.SetInt("_Width", S);
    35.             noiseComputer.SetInt("_Height", S);
    36.             noiseComputer.SetFloat("_Frequency", 0.02f);
    37.             noiseComputer.SetFloat("_Lacunarity", 2.0f);
    38.             noiseComputer.SetFloat("_Gain", 0.5f);
    39.             noiseComputer.SetTexture(0, "_PermTable2D", noise.GetPermutationTable2D());
    40.             noiseComputer.SetTexture(0, "_Gradient3D", noise.GetGradient3D());
    41.             noiseComputer.SetBuffer(0, "_Result", noiseBuffer);
    42.  
    43.             noiseComputer.Dispatch(0, S / 8, S / 8, 1);
    44.  
    45.             msComputer.SetInt("_Width", S);
    46.             msComputer.SetInt("_Height", S);
    47.             msComputer.SetBuffer(0, "_Map", noiseBuffer);
    48.             msComputer.SetBuffer(0, "_Result", msBuffer);
    49.  
    50.             msComputer.Dispatch(0, S / 8, S / 8, 1);
    51.  
    52.             positions = new Vector3[S * S];
    53.             msBuffer.GetData(positions);
    54.  
    55.             Debug.Log(positions.Length);
    56.         }
    57.     }
    58.  
    59.     void OnDrawGizmos()
    60.     {
    61.         if(positions != null)
    62.         {
    63.             Gizmos.color = Color.white;
    64.  
    65.             for (int i = 0; i < positions.Length; i++)
    66.                 if(positions[i].z == 1)
    67.                     Gizmos.DrawWireCube(new Vector2(positions[i].x, positions[i].y), new Vector2(0.9f, 0.9f));
    68.         }
    69.     }
    70. }
    71.  
    This is the noiseComputer.
    Code (CSharp):
    1.  
    2.  
    3. #pragma kernel CSMain
    4.  
    5. SamplerState _PointRepeat;
    6.  
    7. Texture2D _PermTable1D, _Gradient2D;
    8.  
    9. float _Frequency, _Lacunarity, _Gain;
    10.  
    11. int _Width;
    12.  
    13. RWStructuredBuffer<float> _Result;
    14.  
    15. float2 fade(float2 t)
    16. {
    17.     return t * t * t * (t * (t * 6 - 15) + 10);
    18. }
    19.  
    20. float perm(float x)
    21. {
    22.     return _PermTable1D.SampleLevel(_PointRepeat, float2(x,0), 0).a;
    23. }
    24.  
    25. float grad(float x, float2 p)
    26. {
    27.     float2 g = _Gradient2D.SampleLevel(_PointRepeat, float2(x*8.0, 0), 0).rg * 2.0 - 1.0;
    28.     return dot(g, p);
    29. }
    30.  
    31. float inoise(float2 p)
    32. {
    33.     float2 P = fmod(floor(p), 256.0);    // FIND UNIT SQUARE THAT CONTAINS POINT
    34.       p -= floor(p);                      // FIND RELATIVE X,Y OF POINT IN SQUARE.
    35.     float2 f = fade(p);                 // COMPUTE FADE CURVES FOR EACH OF X,Y.
    36.  
    37.     P = P / 256.0;
    38.     const float one = 1.0 / 256.0;
    39.  
    40.     // HASH COORDINATES OF THE 4 SQUARE CORNERS
    41.       float A = perm(P.x) + P.y;
    42.       float B = perm(P.x + one) + P.y;
    43.     // AND ADD BLENDED RESULTS FROM 4 CORNERS OF SQUARE
    44.       return lerp( lerp( grad(perm(A    ), p ),
    45.                        grad(perm(B    ), p + float2(-1, 0) ), f.x),
    46.                  lerp( grad(perm(A+one), p + float2(0, -1) ),
    47.                        grad(perm(B+one), p + float2(-1, -1)), f.x), f.y);
    48.                        
    49. }
    50.  
    51. // fractal sum, range -1.0 - 1.0
    52. float fBm(float2 p, int octaves)
    53. {
    54.     float freq = _Frequency, amp = 0.5;
    55.     float sum = 0;
    56.     for(int i = 0; i < octaves; i++)
    57.     {
    58.         sum += inoise(p * freq) * amp;
    59.         freq *= _Lacunarity;
    60.         amp *= _Gain;
    61.     }
    62.     return sum;
    63. }
    64.  
    65. // fractal abs sum, range 0.0 - 1.0
    66. float turbulence(float2 p, int octaves)
    67. {
    68.     float sum = 0;
    69.     float freq = _Frequency, amp = 1.0;
    70.     for(int i = 0; i < octaves; i++)
    71.     {
    72.         sum += abs(inoise(p*freq))*amp;
    73.         freq *= _Lacunarity;
    74.         amp *= _Gain;
    75.     }
    76.     return sum;
    77. }
    78.  
    79. // Ridged multifractal, range 0.0 - 1.0
    80. // See "Texturing & Modeling, A Procedural Approach", Chapter 12
    81. float ridge(float h, float offset)
    82. {
    83.     h = abs(h);
    84.     h = offset - h;
    85.     h = h * h;
    86.     return h;
    87. }
    88.  
    89. float ridgedmf(float2 p, int octaves, float offset)
    90. {
    91.     float sum = 0;
    92.     float freq = _Frequency, amp = 0.5;
    93.     float prev = 1.0;
    94.     for(int i = 0; i < octaves; i++)
    95.     {
    96.         float n = ridge(inoise(p*freq), offset);
    97.         sum += n*amp*prev;
    98.         prev = n;
    99.         freq *= _Lacunarity;
    100.         amp *= _Gain;
    101.     }
    102.     return sum;
    103. }
    104.  
    105. [numthreads(8,8,1)]
    106. void CSMain (uint3 id : SV_DispatchThreadID)
    107. {
    108.     float2 uv = float2(id.xy);
    109.  
    110.     //uncomment this for fractal noise
    111.     float n = fBm(uv, 4);
    112.  
    113.     //uncomment this for turbulent noise
    114.     //float n = turbulence(uv, 4);
    115.  
    116.     //uncomment this for ridged multi fractal
    117.     //float n = ridgedmf(uv, 4, 1.0);
    118.  
    119.     _Result[id.x + id.y * _Width] = n;
    120.  
    121. }
    122.  
    And finally the msComputer:
    Code (CSharp):
    1. #pragma kernel CSMain
    2.  
    3. int _Width, _Height;
    4.  
    5. StructuredBuffer<float> _Map;
    6. RWStructuredBuffer<float3> _Result;
    7.  
    8. [numthreads(8,8,1)]
    9. void CSMain (uint3 id : SV_DispatchThreadID)
    10. {
    11.     if(id.x >= _Width - 1 - 1) return;
    12.     if(id.y >= _Height - 1 - 1) return;
    13.  
    14.     int flagIndex = _Map[id.x + id.y * _Width];
    15.     if(flagIndex == 0) return;
    16.  
    17.     _Result[id.x + id.y * _Width] = float3(id.x, id.y, 1);
    18. }
    19.  
    I guess the problem could be the index of the linear float array coming from the noiseBuffer.. but im not sure because i can simulate a non linear array by doing this:

    int index = id.x + id.y * _Width;
    float value = noiseArray[index];

    Thanks to everyone who can help me with this tricky problem!
    Cheers :)
     
    Last edited: Apr 13, 2016
  2. Shiikarii

    Shiikarii

    Joined:
    Feb 6, 2014
    Posts:
    89
    ok i solved it myself.. anyway thanks for reading/watching my problems.

    here r some performance stats..

    noiseMap[2048, 2048] = 421ms
    noise.PNG

    noiseMap[64, 64] = 2ms
    noiseSmall.PNG

    Have a wonderful day ;)
    BR, Michael
     
  3. kumayu

    kumayu

    Joined:
    Oct 22, 2015
    Posts:
    4