diff --git a/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java b/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java
index ec9d75887..508049f16 100644
--- a/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java
+++ b/src/main/java/com/volmit/iris/engine/object/NoiseStyle.java
@@ -20,6 +20,7 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.util.math.RNG;
+import com.volmit.iris.util.noise.BiasedCellularNoise;
import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.noise.CNGFactory;
import com.volmit.iris.util.noise.NoiseType;
@@ -447,6 +448,22 @@ public enum NoiseStyle {
@Desc("Vascular noise gets higher as the position nears a cell border. Cells are distorted using Iris styled wispy noise.")
VASCULAR_IRIS_HALF(rng -> CNG.signatureHalf(rng, NoiseType.VASCULAR)),
+ @Desc("White Noise is like static. Useful for block scattering but not terrain.")
+ SIMPLEX_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(),
+ SIMPLEX.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)),
+
+ @Desc("White Noise is like static. Useful for block scattering but not terrain.")
+ NOWHERE_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(),
+ NOWHERE.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)),
+
+ @Desc("White Noise is like static. Useful for block scattering but not terrain.")
+ IRIS_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(),
+ IRIS.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)),
+
+ @Desc("White Noise is like static. Useful for block scattering but not terrain.")
+ VASCULAR_BIASED_CELLULAR(rng -> new CNG(rng, new BiasedCellularNoise(rng.lmax(),
+ VASCULAR.stream(rng.nextParallelRNG(-23333666)).zoom(0.158)), 1D, 1)),
+
;
private final CNGFactory f;
diff --git a/src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java b/src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java
new file mode 100644
index 000000000..5742bb13b
--- /dev/null
+++ b/src/main/java/com/volmit/iris/util/noise/BiasedCellularNoise.java
@@ -0,0 +1,52 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 Arcane Arts (Volmit Software)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.volmit.iris.util.noise;
+
+import com.volmit.iris.engine.object.NoiseStyle;
+import com.volmit.iris.util.interpolation.IrisInterpolation;
+import com.volmit.iris.util.math.RNG;
+import com.volmit.iris.util.stream.ProceduralStream;
+
+public class BiasedCellularNoise implements NoiseGenerator {
+ private final FastNoise n;
+ private final ProceduralStream biasShape;
+
+ public BiasedCellularNoise(long seed, ProceduralStream biasShape) {
+ this.biasShape = biasShape.subtract(0.5).multiply(2);
+ this.n = new FastNoise(new RNG(seed).imax());
+ n.SetNoiseType(FastNoise.NoiseType.Cellular);
+ n.SetCellularReturnType(FastNoise.CellularReturnType.CellValue);
+ n.SetCellularDistanceFunction(FastNoise.CellularDistanceFunction.Natural);
+ }
+
+ @Override
+ public double noise(double x) {
+ return (n.GetCellular((float) x, (float) 0, biasShape) / 2D) + 0.5D;
+ }
+
+ @Override
+ public double noise(double x, double z) {
+ return (n.GetCellular((float) x, (float) z, biasShape) / 2D) + 0.5D;
+ }
+
+ @Override
+ public double noise(double x, double y, double z) {
+ return (n.GetCellular((float) x, (float) y, biasShape) / 2D) + 0.5D;
+ }
+}
diff --git a/src/main/java/com/volmit/iris/util/noise/FastNoise.java b/src/main/java/com/volmit/iris/util/noise/FastNoise.java
index 23e21deb7..548b4720d 100644
--- a/src/main/java/com/volmit/iris/util/noise/FastNoise.java
+++ b/src/main/java/com/volmit/iris/util/noise/FastNoise.java
@@ -20,6 +20,7 @@ package com.volmit.iris.util.noise;
import com.volmit.iris.util.math.Vector2f;
import com.volmit.iris.util.math.Vector3f;
+import com.volmit.iris.util.stream.ProceduralStream;
public class FastNoise {
private static final Float2[] GRAD_2D = {new Float2(-1, -1), new Float2(1, -1), new Float2(-1, 1), new Float2(1, 1), new Float2(0, -1), new Float2(-1, 0), new Float2(0, 1), new Float2(1, 0),
@@ -1728,6 +1729,19 @@ public class FastNoise {
return 0;
}
}
+ public float GetCellular(float x, float y, ProceduralStream sourceNoise) {
+ x *= m_frequency;
+ y *= m_frequency;
+
+ switch (m_cellularReturnType) {
+ case CellValue:
+ case NoiseLookup:
+ case Distance:
+ return SingleCellular(x, y, sourceNoise);
+ default:
+ return SingleCellular2Edge(x, y);
+ }
+ }
public float GetCellular(float x, float y) {
x *= m_frequency;
@@ -1823,6 +1837,86 @@ public class FastNoise {
}
}
+ private float SingleCellular(float x, float y, ProceduralStream sourceNoise) {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+
+ float distance = 999999;
+ int xc = 0, yc = 0;
+
+ switch (m_cellularDistanceFunction) {
+ default:
+ case Euclidean:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = vecX * vecX + vecY * vecY;
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ }
+ }
+ }
+ break;
+ case Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY));
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ }
+ }
+ }
+ break;
+ case Natural:
+ for (int xi = xr - 1; xi <= xr + 1; xi++) {
+ for (int yi = yr - 1; yi <= yr + 1; yi++) {
+ Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255];
+
+ float vecX = xi - x + vec.x;
+ float vecY = yi - y + vec.y;
+
+ float newDistance = (Math.abs(vecX) + Math.abs(vecY)) + (vecX * vecX + vecY * vecY);
+
+ if (newDistance < distance) {
+ distance = newDistance;
+ xc = xi;
+ yc = yi;
+ }
+ }
+ }
+ break;
+ }
+
+ switch (m_cellularReturnType) {
+ case CellValue:
+ return sourceNoise.get(xc, yc).floatValue();
+
+ case NoiseLookup:
+ Float2 vec = CELL_2D[Hash2D(m_seed, xc, yc) & 255];
+ return m_cellularNoiseLookup.GetNoise(xc + vec.x, yc + vec.y);
+
+ case Distance:
+ return distance - 1;
+ default:
+ return 0;
+ }
+ }
+
private float SingleCellular2Edge(float x, float y) {
int xr = FastRound(x);
int yr = FastRound(y);