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.

Here is the output from my msBuffer, as u can see it gaves me very weird results…
And this is the workflow:
- Fill an float array with the noise results = noiseComputer
- Check if noise results r greater then 0
- Fill the float3 array with the results XYZ = msComputer
- 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/
using UnityEngine;
using System.Collections;
using ImprovedPerlinNoiseProject;
public class Generator : MonoBehaviour
{
public ComputeShader noiseComputer, msComputer;
public int S;
public string seed;
public Vector3[] positions;
ComputeBuffer noiseBuffer, msBuffer;
ImprovedPerlinNoise noise;
int[,] map;
void Update()
{
if(Input.GetMouseButtonDown(0))
{
if (S % 8 != 0)
throw new System.ArgumentException("Size must be divisible be 8");
map = new int[S, S];
noiseBuffer = new ComputeBuffer(S * S, sizeof(float));
msBuffer = new ComputeBuffer(S * S, sizeof(float));
int newSeed = (seed == "") ? Random.Range(int.MinValue, int.MaxValue) : seed.GetHashCode();
noise = new ImprovedPerlinNoise(newSeed);
noise.LoadResourcesFor3DNoise();
noiseComputer.SetInt("_Width", S);
noiseComputer.SetInt("_Height", S);
noiseComputer.SetFloat("_Frequency", 0.02f);
noiseComputer.SetFloat("_Lacunarity", 2.0f);
noiseComputer.SetFloat("_Gain", 0.5f);
noiseComputer.SetTexture(0, "_PermTable2D", noise.GetPermutationTable2D());
noiseComputer.SetTexture(0, "_Gradient3D", noise.GetGradient3D());
noiseComputer.SetBuffer(0, "_Result", noiseBuffer);
noiseComputer.Dispatch(0, S / 8, S / 8, 1);
msComputer.SetInt("_Width", S);
msComputer.SetInt("_Height", S);
msComputer.SetBuffer(0, "_Map", noiseBuffer);
msComputer.SetBuffer(0, "_Result", msBuffer);
msComputer.Dispatch(0, S / 8, S / 8, 1);
positions = new Vector3[S * S];
msBuffer.GetData(positions);
Debug.Log(positions.Length);
}
}
void OnDrawGizmos()
{
if(positions != null)
{
Gizmos.color = Color.white;
for (int i = 0; i < positions.Length; i++)
if(positions[i].z == 1)
Gizmos.DrawWireCube(new Vector2(positions[i].x, positions[i].y), new Vector2(0.9f, 0.9f));
}
}
}
This is the noiseComputer.
#pragma kernel CSMain
SamplerState _PointRepeat;
Texture2D _PermTable1D, _Gradient2D;
float _Frequency, _Lacunarity, _Gain;
int _Width;
RWStructuredBuffer<float> _Result;
float2 fade(float2 t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
float perm(float x)
{
return _PermTable1D.SampleLevel(_PointRepeat, float2(x,0), 0).a;
}
float grad(float x, float2 p)
{
float2 g = _Gradient2D.SampleLevel(_PointRepeat, float2(x*8.0, 0), 0).rg * 2.0 - 1.0;
return dot(g, p);
}
float inoise(float2 p)
{
float2 P = fmod(floor(p), 256.0); // FIND UNIT SQUARE THAT CONTAINS POINT
p -= floor(p); // FIND RELATIVE X,Y OF POINT IN SQUARE.
float2 f = fade(p); // COMPUTE FADE CURVES FOR EACH OF X,Y.
P = P / 256.0;
const float one = 1.0 / 256.0;
// HASH COORDINATES OF THE 4 SQUARE CORNERS
float A = perm(P.x) + P.y;
float B = perm(P.x + one) + P.y;
// AND ADD BLENDED RESULTS FROM 4 CORNERS OF SQUARE
return lerp( lerp( grad(perm(A ), p ),
grad(perm(B ), p + float2(-1, 0) ), f.x),
lerp( grad(perm(A+one), p + float2(0, -1) ),
grad(perm(B+one), p + float2(-1, -1)), f.x), f.y);
}
// fractal sum, range -1.0 - 1.0
float fBm(float2 p, int octaves)
{
float freq = _Frequency, amp = 0.5;
float sum = 0;
for(int i = 0; i < octaves; i++)
{
sum += inoise(p * freq) * amp;
freq *= _Lacunarity;
amp *= _Gain;
}
return sum;
}
// fractal abs sum, range 0.0 - 1.0
float turbulence(float2 p, int octaves)
{
float sum = 0;
float freq = _Frequency, amp = 1.0;
for(int i = 0; i < octaves; i++)
{
sum += abs(inoise(p*freq))*amp;
freq *= _Lacunarity;
amp *= _Gain;
}
return sum;
}
// Ridged multifractal, range 0.0 - 1.0
// See "Texturing & Modeling, A Procedural Approach", Chapter 12
float ridge(float h, float offset)
{
h = abs(h);
h = offset - h;
h = h * h;
return h;
}
float ridgedmf(float2 p, int octaves, float offset)
{
float sum = 0;
float freq = _Frequency, amp = 0.5;
float prev = 1.0;
for(int i = 0; i < octaves; i++)
{
float n = ridge(inoise(p*freq), offset);
sum += n*amp*prev;
prev = n;
freq *= _Lacunarity;
amp *= _Gain;
}
return sum;
}
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float2 uv = float2(id.xy);
//uncomment this for fractal noise
float n = fBm(uv, 4);
//uncomment this for turbulent noise
//float n = turbulence(uv, 4);
//uncomment this for ridged multi fractal
//float n = ridgedmf(uv, 4, 1.0);
_Result[id.x + id.y * _Width] = n;
}
And finally the msComputer:
#pragma kernel CSMain
int _Width, _Height;
StructuredBuffer<float> _Map;
RWStructuredBuffer<float3> _Result;
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
if(id.x >= _Width - 1 - 1) return;
if(id.y >= _Height - 1 - 1) return;
int flagIndex = _Map[id.x + id.y * _Width];
if(flagIndex == 0) return;
_Result[id.x + id.y * _Width] = float3(id.x, id.y, 1);
}
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 ![]()


