Firstborn/Library/PackageCache/com.unity.terrain-tools@4.0.3/Editor/TerrainTools/Compute/Thermal.compute

128 lines
4.2 KiB
Plaintext
Raw Normal View History

2023-03-28 13:24:16 -04:00
//
// conventions
// left = coord.x - 1
// right = coord.x + 1
// top = coord.y + 1
// bottom = coord.y - 1
//
//#include "../../../Shaders/NoiseLib/Noise.hlsl"
//Texture2D<float4> PrecipMask; //defines where rainfall will occur
Texture2D<float4> ReposeMask;
Texture2D<float> Collision;
Texture2D<float> TerrainHeightPrev; //previous frame
Texture2D<float> SedimentPrev;
Texture2D<float> Hardness;
//outputs
RWTexture2D<float> TerrainHeight; //terrain heightmap
RWTexture2D<float> Sediment; //suspended sediment concentration (being transported by the water)
float dt; //the time step for the simulation
float EffectScalar;
float4 texDim; //the dimensions of all of our textures (they must all be the same dimensions)
float3 terrainDim; //the dimensions of the terrain in world units
#define LEFT(C) C.y
#define RIGHT(C) C.x
#define TOP(C) C.z
#define BOTTOM(C) C.w
uint4 getSafeNeighbors(uint2 coord) {
return uint4(
(coord.x < (uint)texDim[0] - 1) ? coord.x + 1 : coord.x, //right index
(coord.x > 0) ? coord.x - 1 : coord.x, //left index
(coord.y < (uint)texDim[1] - 1) ? coord.y + 1 : coord.y, //top index
(coord.y > 0) ? coord.y - 1 : coord.y //bottom index
);
}
//
// Thermal Erosion
//
float4 angleOfRepose; //actually tan(theta), which is slope (m)
float4 dxdy; //<dx, dy, 1.0f / dx, 1.0f / dy>
float InvDiagMag;
void simulateThermalErosion(uint2 coord) {
uint4 neigh = getSafeNeighbors(coord);
float4 hCardinal = float4(TerrainHeightPrev[uint2(LEFT(neigh), coord.y)], //left
TerrainHeightPrev[uint2(RIGHT(neigh), coord.y)], //right
TerrainHeightPrev[uint2(coord.x, TOP(neigh))], //up
TerrainHeightPrev[uint2(coord.x, BOTTOM(neigh))]); //down
float4 hDiagonal = float4(TerrainHeightPrev[uint2(LEFT(neigh), TOP(neigh))], //top left
TerrainHeightPrev[uint2(RIGHT(neigh), TOP(neigh))], //top right
TerrainHeightPrev[uint2(LEFT(neigh), BOTTOM(neigh))], //bottom left
TerrainHeightPrev[uint2(RIGHT(neigh), BOTTOM(neigh))]); //bottom right
/*
float4 hardnessCardinal = saturate(float4(Hardness[uint2(neigh.y, coord.y)],
Hardness[uint2(neigh.x, coord.y)],
Hardness[uint2(coord.x, neigh.z)],
Hardness[uint2(coord.x, neigh.w)]));
float4 hardnessDiagonal = saturate(float4(Hardness[uint2(neigh.y, neigh.z)],
Hardness[uint2(neigh.x, neigh.z)],
Hardness[uint2(neigh.y, neigh.w)],
Hardness[uint2(neigh.x, neigh.w)]));
*/
float4 h = float4(TerrainHeightPrev[coord], TerrainHeightPrev[coord], TerrainHeightPrev[coord], TerrainHeightPrev[coord]);
float4 dhCardinal = terrainDim[1] * (h - hCardinal);
float4 dhDiagonal = terrainDim[1] * (h - hDiagonal);
float4 sCardinal = -1.0f * min(sign(dhCardinal), 0.0f);
float4 sDiagonal = -1.0f * min(sign(dhDiagonal), 0.0f);
/*
float4 cHardness = saturate(Hardness[coord]);
float4 hardness = lerp(cHardness, hardnessCardinal, sCardinal);
dhCardinal *= 1.0f - hardness;
hardness = lerp(cHardness, hardnessDiagonal, sDiagonal);
dhDiagonal *= 1.0f - hardness;
*/
//compute slopes
float4 mCardinal = abs(dhCardinal * float4(dxdy.z, dxdy.z, dxdy.w, dxdy.w));
float4 mDiagonal = abs(dhDiagonal * float4(InvDiagMag, InvDiagMag, InvDiagMag, InvDiagMag));
float tau = angleOfRepose.x;
float dv = 0.0f; //volume of sediment moved
//could probably vectorize this and eliminate the ifs...
if (mCardinal.x > tau) { dv += dhCardinal.x; }
if (mCardinal.y > tau) { dv += dhCardinal.y; }
if (mCardinal.z > tau) { dv += dhCardinal.z; }
if (mCardinal.w > tau) { dv += dhCardinal.w; }
if (mDiagonal.x > tau) { dv += 0.707f * dhDiagonal.x; }
if (mDiagonal.y > tau) { dv += 0.707f * dhDiagonal.y; }
if (mDiagonal.z > tau) { dv += 0.707f * dhDiagonal.z; }
if (mDiagonal.w > tau) { dv += 0.707f * dhDiagonal.w; }
float halfHeight = 0.5f * TerrainHeightPrev[coord];
dv = clamp(0.0625f * dt * dv, -halfHeight, halfHeight);
TerrainHeight[coord] = TerrainHeightPrev[coord] - dv;
Sediment[coord] += dv;
}
#pragma kernel ThermalErosion
[numthreads(8, 8, 1)]
void ThermalErosion(uint3 id : SV_DispatchThreadID)
{
simulateThermalErosion(id.xy);
}