mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-06-18 14:50:56 +00:00
Reduce number of erosion impulses
A reduction of impulse evaluations from 5^2 to 3^2, original algorithm used exponential falloff function which required evaluating impulses from further away to avoid artifacts. I've changed it to a parabolic falloff function which is exactly 0 at the largest possible distance from a cell origin, meaning any cells further than that will not have an effect, preventing said artifacting from occurring. The parabolic function could be replaced with an exponential function (or any other similar easing function) as long as it has an x-intercept at maxCellDistSq. In addition, an option to control whether averaging impulses has been added as it has more of a visual impact with the aforementioned changes.
This commit is contained in:
+9
-1
@@ -53,10 +53,18 @@ public class PseudoErosionTemplate extends SamplerTemplate<PseudoErosion> {
|
|||||||
@Default
|
@Default
|
||||||
private double slopeMaskFull = 1;
|
private double slopeMaskFull = 1;
|
||||||
|
|
||||||
|
@Value("jitter")
|
||||||
|
@Default
|
||||||
|
private double jitterModifier = 1;
|
||||||
|
|
||||||
|
@Value("average-impulses")
|
||||||
|
@Default
|
||||||
|
private boolean averageErosionImpulses = true;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PseudoErosion get() {
|
public PseudoErosion get() {
|
||||||
return new PseudoErosion(octaves, gain, lacunarity,
|
return new PseudoErosion(octaves, gain, lacunarity,
|
||||||
slopeStrength, branchStrength, strength,
|
slopeStrength, branchStrength, strength,
|
||||||
erosionFrequency, heightSampler, slopeMask, slopeMaskFull, slopeMaskNone);
|
erosionFrequency, heightSampler, slopeMask, slopeMaskFull, slopeMaskNone, jitterModifier, averageErosionImpulses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-17
@@ -21,9 +21,14 @@ public class PseudoErosion implements NoiseSampler {
|
|||||||
private final boolean slopeMask;
|
private final boolean slopeMask;
|
||||||
private final double slopeMaskFullSq;
|
private final double slopeMaskFullSq;
|
||||||
private final double slopeMaskNoneSq;
|
private final double slopeMaskNoneSq;
|
||||||
|
private final double jitter;
|
||||||
|
private final double maxCellDistSq;
|
||||||
|
private final double maxCellDistSqRecip;
|
||||||
|
private final boolean averageErosionImpulses;
|
||||||
|
|
||||||
public PseudoErosion(int octaves, double gain, double lacunarity, double slopeStrength, double branchStrength, double erosionStrength, double erosionFrequency, DerivativeNoiseSampler sampler,
|
public PseudoErosion(int octaves, double gain, double lacunarity, double slopeStrength, double branchStrength, double erosionStrength, double erosionFrequency, DerivativeNoiseSampler sampler,
|
||||||
boolean slopeMask, double slopeMaskFull, double slopeMaskNone) {
|
boolean slopeMask, double slopeMaskFull, double slopeMaskNone, double jitterModifier,
|
||||||
|
boolean averageErosionImpulses) {
|
||||||
this.octaves = octaves;
|
this.octaves = octaves;
|
||||||
this.gain = gain;
|
this.gain = gain;
|
||||||
this.lacunarity = lacunarity;
|
this.lacunarity = lacunarity;
|
||||||
@@ -37,6 +42,10 @@ public class PseudoErosion implements NoiseSampler {
|
|||||||
// squared value, otherwise a sqrt would need to be used
|
// squared value, otherwise a sqrt would need to be used
|
||||||
this.slopeMaskFullSq = slopeMaskFull * slopeMaskFull * Math.signum(slopeMaskFull);
|
this.slopeMaskFullSq = slopeMaskFull * slopeMaskFull * Math.signum(slopeMaskFull);
|
||||||
this.slopeMaskNoneSq = slopeMaskNone * slopeMaskNone * Math.signum((slopeMaskNone));
|
this.slopeMaskNoneSq = slopeMaskNone * slopeMaskNone * Math.signum((slopeMaskNone));
|
||||||
|
this.jitter = 0.43701595 * jitterModifier;
|
||||||
|
this.averageErosionImpulses = averageErosionImpulses;
|
||||||
|
this.maxCellDistSq = 1 + jitter * jitter;
|
||||||
|
this.maxCellDistSqRecip = 1 / maxCellDistSq;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float hash(float x, float y) {
|
public static float hash(float x, float y) {
|
||||||
@@ -62,26 +71,25 @@ public class PseudoErosion implements NoiseSampler {
|
|||||||
return (x - (float)Math.floor(x));
|
return (x - (float)Math.floor(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float[] erosion(float x, float y, float dirX, float dirY) {
|
public float[] erosion(float x, float y, float dirX, float dirY) {
|
||||||
float gridX = (float) Math.floor(x);
|
int gridX = Math.round(x);
|
||||||
float gridY = (float) Math.floor(y);
|
int gridY = Math.round(y);
|
||||||
float localX = x - gridX;
|
|
||||||
float localY = y - gridY;
|
|
||||||
float noise = 0.0f;
|
float noise = 0.0f;
|
||||||
float dirOutX = 0.0f;
|
float dirOutX = 0.0f;
|
||||||
float dirOutY = 0.0f;
|
float dirOutY = 0.0f;
|
||||||
float cumAmp = 0.0f;
|
float cumAmp = 0.0f;
|
||||||
|
|
||||||
for (int cellX = -2; cellX < 2; cellX++) {
|
for (int cellX = gridX - 1; cellX <= gridX + 1; cellX++) {
|
||||||
for (int cellY = -2; cellY < 2; cellY++) {
|
for (int cellY = gridY - 1; cellY <= gridY + 1; cellY++) {
|
||||||
// TODO - Make seed affect hashing
|
// TODO - Make seed affect hashing
|
||||||
float cellHash = hash(gridX - (float) cellX, gridY - (float) cellY);
|
float cellHash = hash(cellX, cellY);
|
||||||
float cellOffsetX = hashX(cellHash) * 0.5f;
|
float cellOffsetX = (float) (hashX(cellHash) * jitter);
|
||||||
float cellOffsetY = hashY(cellHash) * 0.5f;
|
float cellOffsetY = (float) (hashY(cellHash) * jitter);
|
||||||
float cellOriginDeltaX = cellX - cellOffsetX + localX;
|
float cellOriginDeltaX = (x - cellX) + cellOffsetX;
|
||||||
float cellOriginDeltaY = cellY - cellOffsetY + localY;
|
float cellOriginDeltaY = (y - cellY) + cellOffsetY;
|
||||||
float cellOriginDistSq = dot(cellOriginDeltaX, cellOriginDeltaY, cellOriginDeltaX, cellOriginDeltaY);
|
float cellOriginDistSq = cellOriginDeltaX * cellOriginDeltaX + cellOriginDeltaY * cellOriginDeltaY;
|
||||||
float amp = (float)exp(-cellOriginDistSq * 2.0); // Exponentially decrease amplitude further from cell center
|
if (cellOriginDistSq > maxCellDistSq) continue; // Skip calculating cells too far away
|
||||||
|
float ampTmp = (float) ((cellOriginDistSq * maxCellDistSqRecip) - 1); float amp = ampTmp * ampTmp; // Decrease cell amplitude further away
|
||||||
cumAmp += amp;
|
cumAmp += amp;
|
||||||
float directionalStrength = dot(cellOriginDeltaX, cellOriginDeltaY, dirX, dirY) * TAU;
|
float directionalStrength = dot(cellOriginDeltaX, cellOriginDeltaY, dirX, dirY) * TAU;
|
||||||
noise += (float) (MathUtil.cos(directionalStrength) * amp);
|
noise += (float) (MathUtil.cos(directionalStrength) * amp);
|
||||||
@@ -90,11 +98,11 @@ public class PseudoErosion implements NoiseSampler {
|
|||||||
dirOutY -= sinAngle * (cellOriginDeltaY + dirY);
|
dirOutY -= sinAngle * (cellOriginDeltaY + dirY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (averageErosionImpulses && cumAmp != 0) {
|
||||||
noise /= cumAmp;
|
noise /= cumAmp;
|
||||||
dirOutX /= cumAmp;
|
dirOutX /= cumAmp;
|
||||||
dirOutY /= cumAmp;
|
dirOutY /= cumAmp;
|
||||||
|
}
|
||||||
return new float[] {noise, dirOutX, dirOutY};
|
return new float[] {noise, dirOutX, dirOutY};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user