I have a bunch of voxels, lets just say 64x64x64, that I use to create a sphere/planet. This works very well, but once I try to apply noise to create a more interesting terrain things go wrong.
3D noise works fine, but I don't always want to create terrain with caves, overhangs etc, so I figured in those cases 2D noise would be a good solution, but I can't figure out how to use it correctly.
I tried this, where pos (world position) is a float3 and x and y are the input values for the noise function:
float x = math.acos(pos.z / math.length(pos));
float y = math.atan(pos.y / pos.x);
That results in a very noticeable seam along one axis and pinching at the poles though.
Is there any way I can convert my 3D world position into 2D coordinates, so that the noise function (Perlin or Simplex) will produce a seamless result without pinching? I don't mind in the least if this causes symmetry or repeating features.
Answer
There is no perfect way to map the surface of a sphere to a flat plane - you always get seams or stretching/pinching somewhere. This is why map projections are such a rich subject - every one offers different trade-offs that are good for some uses and less good for others.
A better route for your purposes is probably to continue using your 3D noise, but sample just a 2D manifold out of it:
GetSphereSurfaceNoise(float3 worldPosition, float3 center) {
float3 surfacePosition = normalize(worldPosition - center) * noiseRadius;
return GetNoise(surfacePosition);
}
This ensures all samples along a ray radiating out from the center of your sphere get the same noise value, so you can raise/lower whole columns of terrain without creating caves/overhangs, and the result will be continuous & seamless all around your sphere.
Tuning the noiseRadius
parameter lets you control the density of the noise (scaling up or down the 2D shell you're sampling from in noise space)
No comments:
Post a Comment