Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // 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 <http://www.gnu.org/licenses/>.
- import java.util.Random; // I can't stand arbitrary output
- import java.util.TreeMap; // FloorEntry/CeilEntry is needed for sampling
- // Image parameters: This is the stuff that's easy to change
- final int W = 2400, H = 1350;
- final int w = W, h = H;
- final long seed = 0x09f911029D74E35BL;
- final long seed2 = 0xD84156C5635688C0L;
- final long seed3 = 0xDECAFF;
- final int noiseCount = 512;
- final int cloudFreq = 16;
- final float baser = 32, basey = 96;
- final float dist1 = .002, dist2 = .0002;
- final int nth = 0;
- // Other locals
- PImage img = createImage(w, h, RGB);
- // Set up our noise and run it.
- void setup() {
- size(W, H);
- img.loadPixels();
- Combiner earth = new Combiner((new Octave())
- .addOctave(1.0, new Worley(seed, noiseCount, nth, dist1))
- .addOctave(1./12, new Worley(seed + 1, noiseCount * 4, nth, dist2))
- ).addLevel(0, new ColorSampler(0xFF0000FF))
- .addLevel(.6, new ColorSampler(0xFF00FFFF))
- .addLevel(.8, new ColorSampler(0xFFFFFEB4))
- .addLevel(1.4, new Combiner((new Octave())
- .addOctave(1./1, new Perlin(seed2, noiseCount / 4).square().square().square())
- .addOctave(1./2, new Perlin(seed2, noiseCount / 2))
- .addOctave(1./4, new Perlin(seed2, noiseCount * 1))
- .addOctave(1./8, new Perlin(seed2, noiseCount * 2))
- .addOctave(1./16, new Perlin(seed2, noiseCount * 4))
- ).addLevel(0, new ColorSampler(0xFF006000))
- .addLevel(.5, new ColorSampler(0xFF008000))
- .addLevel(1, new ColorSampler(0xFF00C000))
- );
- Combiner clouds = new Combiner((new Octave())
- .addOctave(2.0, new Perlin(seed3, cloudFreq * 1).square())
- .addOctave(1./2, new Perlin(seed3, cloudFreq * 2).square())
- .addOctave(1./4, new Perlin(seed3, cloudFreq * 4))
- .addOctave(1./8, new Perlin(seed3, cloudFreq * 8))
- ).addLevel(1, earth)
- .addLevel(2, new ColorSampler(0xFFFFFFFF))
- .addLevel(3, new ColorSampler(0xFFC0C0C0));
- Sampler pic = clouds;
- int ind = 0;
- for (int y = 0; y < h; ++y) {
- float yf = y / (float)h;
- for (int x = 0; x < w; ++x)
- img.pixels[ind++] = pic.get(x / (float)w, yf);
- }
- img.updatePixels();
- image(img, 0, 0, W, H);
- save("cloudy-world.png");
- }
- // Utility functions, boilerplate boilerplate boilerplate
- static double sqr(double x) { return x*x; }
- static void arrins(int[] arr, int x, int ind) {
- for (int i = arr.length - 1; i > ind; --i)
- arr[i] = arr[i-1];
- arr[ind] = x;
- } // This function exists because Java generics don't like primitives.
- // This will work in Java 7. OHWAITNOITWONT
- static void arrins(double[] arr, double x, int ind) {
- for (int i = arr.length - 1; i > ind; --i)
- arr[i] = arr[i-1];
- arr[ind] = x;
- }
- float clamp(float v, float min, float max) {
- return v < min? min : v > max? max : v;
- }
- float sigmoid(float a) {
- return 1 / (1 + exp(-4*a+2));
- }
- float slerp(float x, float y, float a) {
- return lerp(x, y, sin(a * PI/2));
- }
- color mergeColor2(color c1, color c2, float a) {
- int r1 = (c1 & 0xFF0000) >> 16, g1 = (c1 & 0xFF00) >> 8, b1 = (c1 & 0xFF);
- int r2 = (c2 & 0xFF0000) >> 16, g2 = (c2 & 0xFF00) >> 8, b2 = (c2 & 0xFF);
- if (a <= .5) {
- color m = color(max(r1, (r1 + r2)/2), max(g1, (g1 + g2)/2), max(b1, (b1 + b2)/2));
- return lerpColor(c1, m, 2 * a);
- }
- color m = color(max(r2, (r1 + r2)/2), max(g2, (g1 + g2)/2), max(b2, (b1 + b2)/2));
- return lerpColor(m, c2, a * 2 - 1);
- }
- color mergeColor(color c1, color c2, float a) {
- int r1 = (c1 & 0xFF0000) >> 16, g1 = (c1 & 0xFF00) >> 8, b1 = (c1 & 0xFF);
- int r2 = (c2 & 0xFF0000) >> 16, g2 = (c2 & 0xFF00) >> 8, b2 = (c2 & 0xFF);
- color m = color(max(r1, r2), max(g1, g2), max(b1, b2));
- return (a < .5)? lerpColor(c1, m, 2 * a) : lerpColor(m, c2, a * 2 - 1);
- }
- color slerpColor(color c1, color c2, float a) {
- return mergeColor(c1, c2, sigmoid(a));
- }
- // Interfaces, classes
- static interface Noise {
- public float get(float x, float y);
- }
- // This is where the actual logic starts.
- // This is a class to sample one octave of worley noise.
- static class Worley implements Noise {
- // These are the variables needed by the actual image logic
- double[][] points;
- int k;
- double max;
- // This creates our points, scattering them randomly according to the seed.
- public Worley(long seed, int npts, int k, double max) {
- Random worlrand = new Random(seed);
- points = new double[npts][2];
- this.k = k;
- this.max = max;
- for (int i = 0; i < points.length; ++i) {
- points[i][0] = worlrand.nextDouble();
- points[i][1] = worlrand.nextDouble();
- }
- }
- // This samples a point by computing the squared distance to the nearest k points,
- // then returning the kth closest
- public float get(float x, float y) {
- double[] d2 = new double[k + 1];
- int[] ptnum = new int[k + 1];
- for (int i = 0; i <= k; ++i) {
- d2[i] = Double.POSITIVE_INFINITY;
- ptnum[i] = 0;
- }
- for (int i = 0; i < points.length; ++i) {
- double d2i = sqr(x - points[i][0]) + sqr(y - points[i][1]);
- for (int j = 0; j <= k; ++j)
- if (d2i < d2[j]) {
- arrins(d2, d2i, j);
- arrins(ptnum, i, j);
- break;
- }
- }
- return (float)(d2[k] / max);
- }
- }
- class Perlin implements Noise {
- float[][] grid;
- int size;
- Perlin(long seed, int dim) {
- Random r = new Random(seed);
- grid = new float[dim][dim];
- size = dim;
- for (int i = 0; i < dim; ++i)
- for (int j = 0; j < dim; ++j)
- grid[i][j] = (float)r.nextDouble();
- }
- Perlin square() {
- for (int i = 0; i < size; ++i)
- for (int j = 0; j < size; ++j)
- grid[i][j] *= grid[i][j];
- return this;
- }
- float get(float x, float y) {
- float i = clamp(y, 0, 1) * (size - 1);
- float j = clamp(x, 0, 1) * (size - 1);
- int in = (int)floor(i), ix = (int)ceil(i);
- int jn = (int)floor(j), jx = (int)ceil(j);
- return slerp(
- slerp(grid[in][jn], grid[in][jx], (j - jn)),
- slerp(grid[ix][jn], grid[ix][jx], (j - jn)),
- (i - in)
- );
- }
- }
- class Octave implements Noise {
- ArrayList<Noise> octaves = new ArrayList<Noise>();
- ArrayList<Double> factors = new ArrayList<Double>();
- public Octave addOctave(double fac, Noise n) {
- octaves.add(n);
- factors.add(fac);
- return this;
- }
- float get(float x, float y) {
- double accum = 0;
- for (int i = 0; i < octaves.size(); ++i)
- accum += factors.get(i) * octaves.get(i).get(x, y);
- return (float)accum;
- }
- }
- interface Interpolator {
- color erp(color x, color y, float a);
- }
- class LinearInterpolator implements Interpolator {
- color erp(color x, color y, float a) {
- return lerpColor(x, y, a);
- }
- }
- interface Sampler {
- color get(float x, float y);
- }
- class ColorSampler implements Sampler {
- color c;
- public ColorSampler(color c) { this.c = c; }
- public color get(float x, float y) { return c; }
- }
- class Combiner implements Sampler {
- private class SampLerp {
- public Sampler s;
- public Interpolator i;
- public SampLerp(Sampler ss, Interpolator si) { s = ss; i = si; }
- }
- TreeMap<Float, SampLerp> subsamplers = new TreeMap<Float, SampLerp>();
- Noise sampleNoise;
- public Combiner(Noise n) { sampleNoise = n; }
- public Combiner addLevel(float threshold, Sampler s) { return addLevel(threshold, s, new LinearInterpolator()); }
- public Combiner addLevel(float threshold, Sampler s, Interpolator i) { subsamplers.put(threshold, new SampLerp(s, i)); return this; }
- public color get(float x, float y) {
- float noise = sampleNoise.get(x, y);
- Float less = subsamplers.floorKey(noise);
- Float more = subsamplers.ceilingKey(noise);
- if (less == null) less = more;
- if (less == more || more == null)
- return subsamplers.get(less).s.get(x, y);
- SampLerp sl = subsamplers.get(less);
- return sl.i.erp(sl.s.get(x, y), subsamplers.get(more).s.get(x, y), (noise - less)/(more - less));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment