Skip to main content
add the context algorithm
Source Link

Updated 2

More detail about the algorithm which I had used.

Context:

  • The map is 2D, squared
  • The height map be stored in 1D float array
  • mapSize is the edge length of the 2D map, map squared size is mapSize * mapSize

The Compute Shader

// snoise is a function to calculate procedural (simplex?) noise
// long script here: https://github.com/SebLague/Hydraulic-Erosion/blob/master/Assets/Scripts/ComputeShaders/HeightMap.compute

RWStructuredBuffer<float> heightMap;//1D aray of height map
RWStructuredBuffer<int> minMax;// index 0 is min, index 1 is max
StructuredBuffer<float2> offsets;//octaves offsets
int floatToIntMultiplier;// 1000

int mapSize;// size of an edge of the 2D map
int octaves;
float lacunarity;
float persistence;
float scaleFactor;

[numthreads(1,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    // get 2D position,
    int x = id.x % mapSize;
    int y = id.x / mapSize;

    float scale = scaleFactor;
    float weight = 1;
    for (int i = 0; i < octaves; i ++) {
        heightMap[id.x] += snoise(float2(x,y)/mapSize * scale + offsets[i]) * weight;
        scale *= lacunarity;
        weight *= persistence;
    }
    int val = int(heightMap[id.x] * floatToIntMultiplier);
    InterlockedMin(minMax[0],val);// calculate min here
    InterlockedMax(minMax[1],val);// calculate max here
}

The C# script

int mapSize = 1000;
int floatToIntMultiplier = 1000;
float[] heightMap = new float[ mapSize * mapSize ];

...
// set stats and dispatch the compute shader
// get calculated data from the compute shader
...

float min = minMax[0] / (float)floatToIntMultiplier ;
float max = minMax[1] / (float)floatToIntMultiplier ;
for(int i = 0; i < heightMap.Length; ++i)
{
    heightMap[i] = Mathf.InverseLerp(min, max, heightMap[i])
}

Updated 2

More detail about the algorithm which I had used.

Context:

  • The map is 2D, squared
  • The height map be stored in 1D float array
  • mapSize is the edge length of the 2D map, map squared size is mapSize * mapSize

The Compute Shader

// snoise is a function to calculate procedural (simplex?) noise
// long script here: https://github.com/SebLague/Hydraulic-Erosion/blob/master/Assets/Scripts/ComputeShaders/HeightMap.compute

RWStructuredBuffer<float> heightMap;//1D aray of height map
RWStructuredBuffer<int> minMax;// index 0 is min, index 1 is max
StructuredBuffer<float2> offsets;//octaves offsets
int floatToIntMultiplier;// 1000

int mapSize;// size of an edge of the 2D map
int octaves;
float lacunarity;
float persistence;
float scaleFactor;

[numthreads(1,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    // get 2D position,
    int x = id.x % mapSize;
    int y = id.x / mapSize;

    float scale = scaleFactor;
    float weight = 1;
    for (int i = 0; i < octaves; i ++) {
        heightMap[id.x] += snoise(float2(x,y)/mapSize * scale + offsets[i]) * weight;
        scale *= lacunarity;
        weight *= persistence;
    }
    int val = int(heightMap[id.x] * floatToIntMultiplier);
    InterlockedMin(minMax[0],val);// calculate min here
    InterlockedMax(minMax[1],val);// calculate max here
}

The C# script

int mapSize = 1000;
int floatToIntMultiplier = 1000;
float[] heightMap = new float[ mapSize * mapSize ];

...
// set stats and dispatch the compute shader
// get calculated data from the compute shader
...

float min = minMax[0] / (float)floatToIntMultiplier ;
float max = minMax[1] / (float)floatToIntMultiplier ;
for(int i = 0; i < heightMap.Length; ++i)
{
    heightMap[i] = Mathf.InverseLerp(min, max, heightMap[i])
}
update a workaround
Source Link

I have a Compute Shader which uses InterlockedMin() and InterlockedMax().

The Compute Shader works very well on my PC (AMD Rx6600) but for Android (Google Pixel 5) it doesn't calculate the atomic Min/Max, just leaves it as the original value.
Know that the Android build always uses Vulkan API.
So, how to run atomic Min/Max in Android build?

Thank you very much!

preview image compare Compute Shader in PC and Android

P.S.: For more info, I am generating terrain. atomicMin/Max is required to ensure the same result in any game session.


Updated

The staffs of Unity3D confirmed InterlockedMin/Max still works for Android. So the problem may be devices's compatibility.
For a workaround, I quit using the atomic function and instead have fixed min/max as constants. I ran my code manytimes and decided min/max would be -1.8/1.8. If I make any change in the algorithm stats I have to pre-calculate the min/max again.

I have a Compute Shader which uses InterlockedMin() and InterlockedMax().

The Compute Shader works very well on my PC (AMD Rx6600) but for Android (Google Pixel 5) it doesn't calculate the atomic Min/Max, just leaves it as the original value.
Know that the Android build always uses Vulkan API.
So, how to run atomic Min/Max in Android build?

Thank you very much!

preview image compare Compute Shader in PC and Android

P.S.: For more info, I am generating terrain. atomicMin/Max is required to ensure the same result in any game session.

I have a Compute Shader which uses InterlockedMin() and InterlockedMax().

The Compute Shader works very well on my PC (AMD Rx6600) but for Android (Google Pixel 5) it doesn't calculate the atomic Min/Max, just leaves it as the original value.
Know that the Android build always uses Vulkan API.
So, how to run atomic Min/Max in Android build?

Thank you very much!

preview image compare Compute Shader in PC and Android

P.S.: For more info, I am generating terrain. atomicMin/Max is required to ensure the same result in any game session.


Updated

The staffs of Unity3D confirmed InterlockedMin/Max still works for Android. So the problem may be devices's compatibility.
For a workaround, I quit using the atomic function and instead have fixed min/max as constants. I ran my code manytimes and decided min/max would be -1.8/1.8. If I make any change in the algorithm stats I have to pre-calculate the min/max again.

Minor grammar fixes, markdown formatting
Source Link
liggiorgio
  • 5.5k
  • 6
  • 27
  • 38

I have a Compute Shader which useuses InterlockedMin() and InterlockedMax().

The Compute Shader workworks very well on my PC (AMD Rx6600) but for Android (Google Pixel 5) it doesn't calculate the atomic Min/Max, just leftleaves it as the original value.
Know that the Android build always uses Vulkan API.
So, how to run atomic Min/Max in Android build?

Thank you very much!

preview image compare Compute Shader in PC and Android
p/s

P.S.: forFor more info, I am generating terrain. atomicMin/Max is required to ensuranceensure the same result in any game session.

I have a Compute Shader which use InterlockedMin() and InterlockedMax().

The Compute Shader work very well on my PC (AMD Rx6600) but for Android (Google Pixel 5) it doesn't calculate the atomic Min/Max, just left it as the original value.
Know that the Android build always uses Vulkan API.
So, how to run atomic Min/Max in Android build?

Thank you very much!

preview image compare Compute Shader in PC and Android
p/s: for more info, I am generating terrain. atomicMin/Max is required to ensurance the same result in any game session.

I have a Compute Shader which uses InterlockedMin() and InterlockedMax().

The Compute Shader works very well on my PC (AMD Rx6600) but for Android (Google Pixel 5) it doesn't calculate the atomic Min/Max, just leaves it as the original value.
Know that the Android build always uses Vulkan API.
So, how to run atomic Min/Max in Android build?

Thank you very much!

preview image compare Compute Shader in PC and Android

P.S.: For more info, I am generating terrain. atomicMin/Max is required to ensure the same result in any game session.

Source Link
Loading