// This is free and unencumbered software released into the public domain. // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. // In jurisdictions that recognize copyright laws, the author or authors // of this software dedicate any and all copyright interest in the // software to the public domain. We make this dedication for the benefit // of the public at large and to the detriment of our heirs and // successors. We intend this dedication to be an overt act of // relinquishment in perpetuity of all present and future rights to this // software under copyright law. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // For more information, please refer to import java.util.Random; // I can't stand arbitrary output // Image parameters: This is the stuff that's easy to change final int w = 1600, h = 900; final long seed = 0xDEADBEEF; final int noiseCount = 256; final float baser = 32, basey = 96; final float dist1 = .005, dist2 = .0005; final int nth = 0; // Other locals Worley worley = new Worley(seed, noiseCount); Worley orange = new Worley(seed + 1, noiseCount * 4); PImage img = createImage(w, h, RGB); // Generic setup code: Nothing of interest happens here, I promise. // This function just normalizes the x/y values to [0,1] and passes // them to colAt() one by one to populate the image. In a fragment // shader, this function would not exist. void setup() { size(w, h); img.loadPixels(); 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++] = colAt(x / (float)w, yf); } img.updatePixels(); image(img, 0, 0); save("worley-lava-tex.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; } // This is where the actual logic starts. // This is a class to sample one octave of worley noise. static class Worley { // These are the variables needed by the actual image logic double[][] points; // This creates our points, scattering them randomly according to the seed. public Worley(long seed, int npts) { Random worlrand = new Random(seed); points = new double[npts][2]; 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, final int k, double max, float clamp) { 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 min(clamp, (float)(d2[k] / max)); } } // This function samples a pixel and is called millions of times to draw your image color colAt(float x, float y) { color accum = color(x * 255, 0, y * 255); float wo = worley.get(x, y, nth, dist1, 2) + orange.get(x, y, nth, dist2, 1.5) / 12; accum = color(min(1, wo) * (255 - baser) + baser, basey * (wo - .25), 0); return accum; }