├── .gitignore ├── README.md ├── Effects ├── hsv_header.metal ├── place_header.metal ├── blend_header.metal ├── place.metal ├── hsv.metal └── blend.metal └── Content ├── gradient_header.metal ├── random_header.metal ├── random.metal ├── gradient.metal ├── noise_header.metal └── noise.metal /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Metal Shaders 3 | 4 | Additional shaders can be found in [**PixelKit**](https://github.com/heestand-xyz/PixelKit/). 5 | -------------------------------------------------------------------------------- /Effects/hsv_header.metal: -------------------------------------------------------------------------------- 1 | // 2 | // hsv_header.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Hexagons on 2018-08-23. 6 | // Open Source - MIT License 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #ifndef HSV 13 | #define HSV 14 | 15 | float3 rgb2hsv(float r, float g, float b); 16 | float3 hsv2rgb(float h, float s, float v); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Effects/place_header.metal: -------------------------------------------------------------------------------- 1 | // 2 | // place_header.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Anton Heestand on 2019-10-07. 6 | // Copyright © 2019 Hexagons. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #ifndef PLACE 13 | #define PLACE 14 | 15 | float2 place(int place, float2 uv, uint aw, uint ah, uint bw, uint bh); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /Effects/blend_header.metal: -------------------------------------------------------------------------------- 1 | // 2 | // blend_header.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Anton Heestand on 2019-10-07. 6 | // Copyright © 2019 Hexagons. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #ifndef BLEND 13 | #define BLEND 14 | 15 | float4 blend(int mode, float4 ca, float4 cb); 16 | float4 blendOver(float4 ca, float4 cb); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Content/gradient_header.metal: -------------------------------------------------------------------------------- 1 | // 2 | // gradient_header.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Anton Heestand on 2019-10-02. 6 | // Copyright © 2019 Hexagons. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #ifndef GRADIENT 13 | #define GRADIENT 14 | 15 | // Hardcoded at 128 16 | // Defined as uniformArrayMaxLimit in source 17 | constant int ARRMAX = 128; 18 | 19 | struct FractionAndZero { 20 | float fraction; 21 | bool zero; 22 | }; 23 | 24 | struct ColorStop { 25 | bool enabled; 26 | float position; 27 | float4 color; 28 | }; 29 | 30 | struct ColorStopArray { 31 | float fraction; 32 | float cr; 33 | float cg; 34 | float cb; 35 | float ca; 36 | }; 37 | 38 | FractionAndZero fractionAndZero(float fraction, int extend); 39 | float4 gradient(float fraction, array inArr, array inArrActive); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Effects/place.metal: -------------------------------------------------------------------------------- 1 | // 2 | // place.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Anton Heestand on 2019-10-07. 6 | // Copyright © 2019 Hexagons. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #include "place_header.metal" 13 | 14 | float2 place(int place, float2 uv, uint aw, uint ah, uint bw, uint bh) { 15 | 16 | float aspect_a = float(aw) / float(ah); 17 | float aspect_b = float(bw) / float(bh); 18 | float bu = uv.x; 19 | float bv = uv.y; 20 | switch (place) { 21 | case 1: // Aspect Fit 22 | if (aspect_b > aspect_a) { 23 | bv /= aspect_a; 24 | bv *= aspect_b; 25 | bv += ((aspect_a - aspect_b) / 2) / aspect_a; 26 | } else if (aspect_b < aspect_a) { 27 | bu /= aspect_b; 28 | bu *= aspect_a; 29 | bu += ((aspect_b - aspect_a) / 2) / aspect_b; 30 | } 31 | break; 32 | case 2: // Aspect Fill 33 | if (aspect_b > aspect_a) { 34 | bu *= aspect_a; 35 | bu /= aspect_b; 36 | bu += ((1.0 / aspect_a - 1.0 / aspect_b) / 2) * aspect_a; 37 | } else if (aspect_b < aspect_a) { 38 | bv *= aspect_b; 39 | bv /= aspect_a; 40 | bv += ((1.0 / aspect_b - 1.0 / aspect_a) / 2) * aspect_b; 41 | } 42 | break; 43 | case 3: // Center 44 | bu = 0.5 + ((uv.x - 0.5) * aw) / bw; 45 | bv = 0.5 + ((uv.y - 0.5) * ah) / bh; 46 | break; 47 | } 48 | 49 | return float2(bu, bv); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Content/random_header.metal: -------------------------------------------------------------------------------- 1 | /* 2 | * Loki Random Number Generator 3 | * Copyright (c) 2017 Youssef Victor All rights reserved. 4 | * 5 | * Function Result 6 | * ------------------------------------------------------------------ 7 | * 8 | * TausStep Combined Tausworthe Generator or 9 | * Linear Feedback Shift Register (LFSR) 10 | * random number generator. This is a 11 | * helper method for rng, which uses 12 | * a hybrid approach combining LFSR with 13 | * a Linear Congruential Generator (LCG) 14 | * in order to produce random numbers with 15 | * periods of well over 2^121 16 | * 17 | * rand A pseudo-random number based on the 18 | * method outlined in "Efficient 19 | * pseudo-random number generation 20 | * for monte-carlo simulations using 21 | * graphic processors" by Siddhant 22 | * Mohanty et al 2012. 23 | * 24 | */ 25 | 26 | #include 27 | using namespace metal; 28 | 29 | #ifndef LOKI 30 | #define LOKI 31 | 32 | 33 | class Loki { 34 | private: 35 | thread float seed; 36 | unsigned TausStep(const unsigned z, const int s1, const int s2, const int s3, const unsigned M); 37 | 38 | public: 39 | thread Loki(const unsigned seed1, const unsigned seed2 = 1, const unsigned seed3 = 1); 40 | 41 | thread float rand(); 42 | }; 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /Content/random.metal: -------------------------------------------------------------------------------- 1 | #include 2 | #include "random_header.metal" 3 | 4 | unsigned Loki::TausStep(const unsigned z, const int s1, const int s2, const int s3, const unsigned M) 5 | { 6 | unsigned b=(((z << s1) ^ z) >> s2); 7 | return (((z & M) << s3) ^ b); 8 | } 9 | 10 | thread Loki::Loki(const unsigned seed1, const unsigned seed2, const unsigned seed3) { 11 | unsigned seed = seed1 * 1099087573UL; 12 | unsigned seedb = seed2 * 1099087573UL; 13 | unsigned seedc = seed3 * 1099087573UL; 14 | 15 | // Round 1: Randomise seed 16 | unsigned z1 = TausStep(seed,13,19,12,429496729UL); 17 | unsigned z2 = TausStep(seed,2,25,4,4294967288UL); 18 | unsigned z3 = TausStep(seed,3,11,17,429496280UL); 19 | unsigned z4 = (1664525*seed + 1013904223UL); 20 | 21 | // Round 2: Randomise seed again using second seed 22 | unsigned r1 = (z1^z2^z3^z4^seedb); 23 | 24 | z1 = TausStep(r1,13,19,12,429496729UL); 25 | z2 = TausStep(r1,2,25,4,4294967288UL); 26 | z3 = TausStep(r1,3,11,17,429496280UL); 27 | z4 = (1664525*r1 + 1013904223UL); 28 | 29 | // Round 3: Randomise seed again using third seed 30 | r1 = (z1^z2^z3^z4^seedc); 31 | 32 | z1 = TausStep(r1,13,19,12,429496729UL); 33 | z2 = TausStep(r1,2,25,4,4294967288UL); 34 | z3 = TausStep(r1,3,11,17,429496280UL); 35 | z4 = (1664525*r1 + 1013904223UL); 36 | 37 | this->seed = (z1^z2^z3^z4) * 2.3283064365387e-10; 38 | } 39 | 40 | thread float Loki::rand() { 41 | unsigned hashed_seed = this->seed * 1099087573UL; 42 | 43 | unsigned z1 = TausStep(hashed_seed,13,19,12,429496729UL); 44 | unsigned z2 = TausStep(hashed_seed,2,25,4,4294967288UL); 45 | unsigned z3 = TausStep(hashed_seed,3,11,17,429496280UL); 46 | unsigned z4 = (1664525*hashed_seed + 1013904223UL); 47 | 48 | thread float old_seed = this->seed; 49 | 50 | this->seed = (z1^z2^z3^z4) * 2.3283064365387e-10; 51 | 52 | return old_seed; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /Effects/hsv.metal: -------------------------------------------------------------------------------- 1 | // 2 | // hsv.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Hexagons on 2018-08-23. 6 | // Open Source - MIT License 7 | // 8 | // https://stackoverflow.com/a/6930407/4586652 9 | // 10 | 11 | #include 12 | using namespace metal; 13 | 14 | #include "hsv_header.metal" 15 | 16 | float3 rgb2hsv(float r, float g, float b) { 17 | float h, s, v; 18 | float mn, mx, d; 19 | mn = r < g ? r : g; 20 | mn = mn < b ? mn : b; 21 | mx = r > g ? r : g; 22 | mx = mx > b ? mx : b; 23 | v = mx; 24 | d = mx - mn; 25 | if (d < 0.00001) { 26 | s = 0; 27 | h = 0; 28 | return float3(h, s, v); 29 | } 30 | if (mx > 0.0) { 31 | s = (d / mx); 32 | } else { 33 | s = 0.0; 34 | h = 0.0; 35 | return float3(h, s, v); 36 | } 37 | if (r >= mx) { 38 | h = (g - b ) / d; 39 | } else if (g >= mx) { 40 | h = 2.0 + ( b - r ) / d; 41 | } else { 42 | h = 4.0 + ( r - g ) / d; 43 | } 44 | h *= 60.0; 45 | if(h < 0.0) { 46 | h += 360.0; 47 | } 48 | return float3(h / 360, s, v); 49 | } 50 | 51 | float3 hsv2rgb(float h, float s, float v) { 52 | float hh, p, q, t, ff; 53 | int i; 54 | float3 c; 55 | if (s <= 0.0) { 56 | c.r = v; 57 | c.g = v; 58 | c.b = v; 59 | return c; 60 | } 61 | hh = (h - floor(h)) * 360; 62 | hh /= 60.0; 63 | i = int(hh); 64 | ff = hh - i; 65 | p = v * (1.0 - s); 66 | q = v * (1.0 - (s * ff)); 67 | t = v * (1.0 - (s * (1.0 - ff))); 68 | switch(i) { 69 | case 0: 70 | c.r = v; 71 | c.g = t; 72 | c.b = p; 73 | break; 74 | case 1: 75 | c.r = q; 76 | c.g = v; 77 | c.b = p; 78 | break; 79 | case 2: 80 | c.r = p; 81 | c.g = v; 82 | c.b = t; 83 | break; 84 | 85 | case 3: 86 | c.r = p; 87 | c.g = q; 88 | c.b = v; 89 | break; 90 | case 4: 91 | c.r = t; 92 | c.g = p; 93 | c.b = v; 94 | break; 95 | case 5: 96 | default: 97 | c.r = v; 98 | c.g = p; 99 | c.b = q; 100 | break; 101 | } 102 | return c; 103 | } 104 | -------------------------------------------------------------------------------- /Content/gradient.metal: -------------------------------------------------------------------------------- 1 | // 2 | // gradient.metal 3 | // Shaders 4 | // 5 | // Created by Anton Heestand on 2019-10-02. 6 | // Copyright © 2019 Hexagons. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #include "gradient_header.metal" 13 | 14 | FractionAndZero fractionAndZero(float fraction, int extend) { 15 | 16 | bool zero = false; 17 | switch (extend) { 18 | case 0: // Hold 19 | if (fraction < 0.0001) { 20 | fraction = 0.0001; 21 | } else if (fraction > 0.9999) { 22 | fraction = 0.9999; 23 | } 24 | break; 25 | case 1: // Zero 26 | if (fraction < 0) { 27 | zero = true; 28 | } else if (fraction > 1) { 29 | zero = true; 30 | } 31 | break; 32 | case 2: // Repeat 33 | fraction = fraction - floor(fraction); 34 | break; 35 | case 3: // Mirror 36 | bool mirror = false; 37 | if (fraction > 0 ? int(fraction) % 2 == 1 : int(fraction) % 2 == 0) { 38 | mirror = true; 39 | } 40 | fraction = fraction - floor(fraction); 41 | if (mirror) { 42 | fraction = 1.0 - fraction; 43 | } 44 | break; 45 | } 46 | 47 | FractionAndZero fz = FractionAndZero(); 48 | fz.zero = zero; 49 | fz.fraction = fraction; 50 | 51 | return fz; 52 | 53 | } 54 | 55 | float4 gradient(float fraction, array inArr, array inArrActive) { 56 | 57 | array color_stops; 58 | for (int i = 0; i < 7; ++i) { 59 | ColorStop color_stop = ColorStop(); 60 | color_stop.enabled = inArrActive[i]; 61 | color_stop.position = inArr[i].fraction; 62 | color_stop.color = float4(inArr[i].cr, inArr[i].cg, inArr[i].cb, inArr[i].ca); 63 | color_stops[i] = color_stop; 64 | } 65 | 66 | ColorStop low_color_stop; 67 | bool low_color_stop_set = false; 68 | ColorStop high_color_stop; 69 | bool high_color_stop_set = false; 70 | for (int i = 0; i < 7; ++i) { 71 | if (color_stops[i].enabled && color_stops[i].position <= fraction && (!low_color_stop_set || color_stops[i].position > low_color_stop.position)) { 72 | low_color_stop = color_stops[i]; 73 | low_color_stop_set = true; 74 | } 75 | if (color_stops[i].enabled && color_stops[i].position >= fraction && (!high_color_stop_set || color_stops[i].position < high_color_stop.position)) { 76 | high_color_stop = color_stops[i]; 77 | high_color_stop_set = true; 78 | } 79 | } 80 | 81 | float stop_fraction = (fraction - low_color_stop.position) / (high_color_stop.position - low_color_stop.position); 82 | 83 | if (stop_fraction < 0) { 84 | stop_fraction = 0.0; 85 | } else if (stop_fraction > 1) { 86 | stop_fraction = 1.0; 87 | } 88 | 89 | float4 c = mix(low_color_stop.color, high_color_stop.color, stop_fraction); 90 | 91 | return c; 92 | 93 | } 94 | -------------------------------------------------------------------------------- /Effects/blend.metal: -------------------------------------------------------------------------------- 1 | // 2 | // blend.metal 3 | // PixelKitShaders 4 | // 5 | // Created by Anton Heestand on 2019-10-07. 6 | // Copyright © 2019 Hexagons. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #include "blend_header.metal" 13 | 14 | float4 lerpColor(float4 fraction, float4 from, float4 to) { 15 | return from * (1.0 - fraction) + to * fraction; 16 | } 17 | 18 | float4 blendOver(float4 ca, float4 cb) { 19 | return blend(0, ca, cb); 20 | } 21 | 22 | float4 blend(int mode, float4 ca, float4 cb) { 23 | 24 | float pi = 3.14159265359; 25 | 26 | float4 c; 27 | float3 rgb_a = float3(ca); 28 | float3 rgb_b = float3(cb); 29 | float aa = max(ca.a, cb.a); 30 | float ia = min(ca.a, cb.a); 31 | float oa = ca.a - cb.a; 32 | float xa = abs(ca.a - cb.a); 33 | switch (mode) { 34 | case 0: // Over 35 | c = float4(rgb_a * (1.0 - cb.a) + rgb_b * cb.a, aa); 36 | break; 37 | case 1: // Under 38 | c = float4(rgb_a * ca.a + rgb_b * (1.0 - ca.a), aa); 39 | break; 40 | case 2: // Add Color 41 | c = float4(rgb_a + rgb_b, aa); 42 | break; 43 | case 3: // Add 44 | c = ca + cb; 45 | break; 46 | case 4: // Mult 47 | c = ca * cb; 48 | break; 49 | case 5: // Diff 50 | c = float4(abs(rgb_a - rgb_b), aa); 51 | break; 52 | case 6: // Sub Color 53 | c = float4(rgb_a - rgb_b, aa); 54 | break; 55 | case 7: // Sub 56 | c = ca - cb; 57 | break; 58 | case 8: // Max 59 | c = max(ca, cb); 60 | break; 61 | case 9: // Min 62 | c = min(ca, cb); 63 | break; 64 | case 10: // Gamma 65 | c = pow(ca, 1 / cb); 66 | break; 67 | case 11: // Power 68 | c = pow(ca, cb); 69 | break; 70 | case 12: // Divide 71 | c = ca / cb; 72 | break; 73 | case 13: // Average 74 | c = ca / 2 + cb / 2; 75 | break; 76 | case 14: // Cosine 77 | c = lerpColor(min(cb.r, 1.0), ca, cos(ca * pi + pi) / 2 + 0.5); 78 | for (int i = 1; i < int(ceil(cb.r)); i++) { 79 | c = lerpColor(min(max(cb.r - float(i), 0.0), 1.0), c, cos(c * pi + pi) / 2 + 0.5); 80 | } 81 | break; 82 | case 15: // Inside Source 83 | c = float4(rgb_a * ia, ia); 84 | break; 85 | // case 15: // Inside Destination 86 | // c = float4(rgb_b * ia, ia); 87 | // break; 88 | case 16: // Outside Source 89 | c = float4(rgb_a * oa, oa); 90 | break; 91 | // case 17: // Outside Destination 92 | // c = float4(rgb_b * oa, oa); 93 | // break; 94 | case 17: // XOR 95 | c = float4(rgb_a * (ca.a * xa) + rgb_b * (cb.a * xa), xa); 96 | break; 97 | } 98 | 99 | return c; 100 | 101 | } 102 | 103 | -------------------------------------------------------------------------------- /Content/noise_header.metal: -------------------------------------------------------------------------------- 1 | // 2 | // noise_header.metal 3 | // 4 | 5 | #include 6 | using namespace metal; 7 | 8 | #ifndef NOISE 9 | #define NOISE 10 | 11 | 12 | // Multi-octave Simplex noise 13 | // For each octave, a higher frequency/lower amplitude function will be added to the original. 14 | // The higher the persistence [0-1], the more of each succeeding octave will be added. 15 | float octave_noise_2d(const float octaves, 16 | const float persistence, 17 | const float scale, 18 | const float x, 19 | const float y); 20 | float octave_noise_3d(const float octaves, 21 | const float persistence, 22 | const float scale, 23 | const float x, 24 | const float y, 25 | const float z); 26 | float octave_noise_4d(const float octaves, 27 | const float persistence, 28 | const float scale, 29 | const float x, 30 | const float y, 31 | const float z, 32 | const float w); 33 | 34 | 35 | // Scaled Multi-octave Simplex noise 36 | // The result will be between the two parameters passed. 37 | float scaled_octave_noise_2d( const float octaves, 38 | const float persistence, 39 | const float scale, 40 | const float loBound, 41 | const float hiBound, 42 | const float x, 43 | const float y); 44 | float scaled_octave_noise_3d( const float octaves, 45 | const float persistence, 46 | const float scale, 47 | const float loBound, 48 | const float hiBound, 49 | const float x, 50 | const float y, 51 | const float z); 52 | float scaled_octave_noise_4d( const float octaves, 53 | const float persistence, 54 | const float scale, 55 | const float loBound, 56 | const float hiBound, 57 | const float x, 58 | const float y, 59 | const float z, 60 | const float w); 61 | 62 | // Scaled Raw Simplex noise 63 | // The result will be between the two parameters passed. 64 | float scaled_raw_noise_2d( const float loBound, 65 | const float hiBound, 66 | const float x, 67 | const float y); 68 | float scaled_raw_noise_3d( const float loBound, 69 | const float hiBound, 70 | const float x, 71 | const float y, 72 | const float z); 73 | float scaled_raw_noise_4d( const float loBound, 74 | const float hiBound, 75 | const float x, 76 | const float y, 77 | const float z, 78 | const float w); 79 | 80 | 81 | // Raw Simplex noise - a single noise value. 82 | float raw_noise_2d(const float x, const float y); 83 | float raw_noise_3d(const float x, const float y, const float z); 84 | float raw_noise_4d(const float x, const float y, const float, const float w); 85 | 86 | float dot(constant int g[2], const float x, const float y); 87 | float dot(constant int g[3], const float x, const float y, const float z); 88 | float dot(constant int g[4], const float x, const float y, const float z, const float w); 89 | 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /Content/noise.metal: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007-2012 Eliot Eshelman 2 | * 3 | * This program is free software: you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation, either version 3 of the License, or 6 | * (at your option) any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program. If not, see . 15 | * 16 | */ 17 | 18 | 19 | #include 20 | using namespace metal; 21 | 22 | 23 | #import "noise_header.metal" 24 | 25 | 26 | // 2D Multi-octave Simplex noise. 27 | // 28 | // For each octave, a higher frequency/lower amplitude function will be added to the original. 29 | // The higher the persistence [0-1], the more of each succeeding octave will be added. 30 | float octave_noise_2d( const float octaves, const float persistence, const float scale, const float x, const float y ) { 31 | float total = 0; 32 | float frequency = scale; 33 | float amplitude = 1; 34 | 35 | // We have to keep track of the largest possible amplitude, 36 | // because each octave adds more, and we need a value in [-1, 1]. 37 | float maxAmplitude = 0; 38 | 39 | for( int i=0; i < octaves; i++ ) { 40 | total += raw_noise_2d( x * frequency, y * frequency ) * amplitude; 41 | 42 | frequency *= 2; 43 | maxAmplitude += amplitude; 44 | amplitude *= persistence; 45 | } 46 | 47 | return total / maxAmplitude; 48 | } 49 | 50 | 51 | // 3D Multi-octave Simplex noise. 52 | // 53 | // For each octave, a higher frequency/lower amplitude function will be added to the original. 54 | // The higher the persistence [0-1], the more of each succeeding octave will be added. 55 | float octave_noise_3d( const float octaves, const float persistence, const float scale, const float x, const float y, const float z ) { 56 | float total = 0; 57 | float frequency = scale; 58 | float amplitude = 1; 59 | 60 | // We have to keep track of the largest possible amplitude, 61 | // because each octave adds more, and we need a value in [-1, 1]. 62 | float maxAmplitude = 0; 63 | 64 | for( int i=0; i < octaves; i++ ) { 65 | total += raw_noise_3d( x * frequency, y * frequency, z * frequency ) * amplitude; 66 | 67 | frequency *= 2; 68 | maxAmplitude += amplitude; 69 | amplitude *= persistence; 70 | } 71 | 72 | return total / maxAmplitude; 73 | } 74 | 75 | 76 | // 4D Multi-octave Simplex noise. 77 | // 78 | // For each octave, a higher frequency/lower amplitude function will be added to the original. 79 | // The higher the persistence [0-1], the more of each succeeding octave will be added. 80 | float octave_noise_4d( const float octaves, const float persistence, const float scale, const float x, const float y, const float z, const float w ) { 81 | float total = 0; 82 | float frequency = scale; 83 | float amplitude = 1; 84 | 85 | // We have to keep track of the largest possible amplitude, 86 | // because each octave adds more, and we need a value in [-1, 1]. 87 | float maxAmplitude = 0; 88 | 89 | for( int i=0; i < octaves; i++ ) { 90 | total += raw_noise_4d( x * frequency, y * frequency, z * frequency, w * frequency ) * amplitude; 91 | 92 | frequency *= 2; 93 | maxAmplitude += amplitude; 94 | amplitude *= persistence; 95 | } 96 | 97 | return total / maxAmplitude; 98 | } 99 | 100 | 101 | 102 | // 2D Scaled Multi-octave Simplex noise. 103 | // 104 | // Returned value will be between loBound and hiBound. 105 | float scaled_octave_noise_2d( const float octaves, const float persistence, const float scale, const float loBound, const float hiBound, const float x, const float y ) { 106 | return octave_noise_2d(octaves, persistence, scale, x, y) * (hiBound - loBound) / 2 + (hiBound + loBound) / 2; 107 | } 108 | 109 | 110 | // 3D Scaled Multi-octave Simplex noise. 111 | // 112 | // Returned value will be between loBound and hiBound. 113 | float scaled_octave_noise_3d( const float octaves, const float persistence, const float scale, const float loBound, const float hiBound, const float x, const float y, const float z ) { 114 | return octave_noise_3d(octaves, persistence, scale, x, y, z) * (hiBound - loBound) / 2 + (hiBound + loBound) / 2; 115 | } 116 | 117 | // 4D Scaled Multi-octave Simplex noise. 118 | // 119 | // Returned value will be between loBound and hiBound. 120 | float scaled_octave_noise_4d( const float octaves, const float persistence, const float scale, const float loBound, const float hiBound, const float x, const float y, const float z, const float w ) { 121 | return octave_noise_4d(octaves, persistence, scale, x, y, z, w) * (hiBound - loBound) / 2 + (hiBound + loBound) / 2; 122 | } 123 | 124 | 125 | 126 | // 2D Scaled Simplex raw noise. 127 | // 128 | // Returned value will be between loBound and hiBound. 129 | float scaled_raw_noise_2d( const float loBound, const float hiBound, const float x, const float y ) { 130 | return raw_noise_2d(x, y) * (hiBound - loBound) / 2 + (hiBound + loBound) / 2; 131 | } 132 | 133 | 134 | // 3D Scaled Simplex raw noise. 135 | // 136 | // Returned value will be between loBound and hiBound. 137 | float scaled_raw_noise_3d( const float loBound, const float hiBound, const float x, const float y, const float z ) { 138 | return raw_noise_3d(x, y, z) * (hiBound - loBound) / 2 + (hiBound + loBound) / 2; 139 | } 140 | 141 | // 4D Scaled Simplex raw noise. 142 | // 143 | // Returned value will be between loBound and hiBound. 144 | float scaled_raw_noise_4d( const float loBound, const float hiBound, const float x, const float y, const float z, const float w ) { 145 | return raw_noise_4d(x, y, z, w) * (hiBound - loBound) / 2 + (hiBound + loBound) / 2; 146 | } 147 | 148 | constant int perm[512] = { 149 | 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142, 150 | 8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117, 151 | 35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71, 152 | 134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41, 153 | 55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208, 89, 154 | 18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, 155 | 250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182, 156 | 189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43, 157 | 172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97, 158 | 228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239, 159 | 107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254, 160 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, 161 | 162 | 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142, 163 | 8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117, 164 | 35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71, 165 | 134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41, 166 | 55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208, 89, 167 | 18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, 168 | 250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182, 169 | 189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43, 170 | 172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97, 171 | 228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239, 172 | 107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254, 173 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 174 | }; 175 | 176 | constant int grad3[12][3] = { 177 | {1,1,0}, {-1,1,0}, {1,-1,0}, {-1,-1,0}, 178 | {1,0,1}, {-1,0,1}, {1,0,-1}, {-1,0,-1}, 179 | {0,1,1}, {0,-1,1}, {0,1,-1}, {0,-1,-1} 180 | }; 181 | constant int grad4[32][4] = { 182 | {0,1,1,1}, {0,1,1,-1}, {0,1,-1,1}, {0,1,-1,-1}, 183 | {0,-1,1,1}, {0,-1,1,-1}, {0,-1,-1,1}, {0,-1,-1,-1}, 184 | {1,0,1,1}, {1,0,1,-1}, {1,0,-1,1}, {1,0,-1,-1}, 185 | {-1,0,1,1}, {-1,0,1,-1}, {-1,0,-1,1}, {-1,0,-1,-1}, 186 | {1,1,0,1}, {1,1,0,-1}, {1,-1,0,1}, {1,-1,0,-1}, 187 | {-1,1,0,1}, {-1,1,0,-1}, {-1,-1,0,1}, {-1,-1,0,-1}, 188 | {1,1,1,0}, {1,1,-1,0}, {1,-1,1,0}, {1,-1,-1,0}, 189 | {-1,1,1,0}, {-1,1,-1,0}, {-1,-1,1,0}, {-1,-1,-1,0} 190 | }; 191 | 192 | constant int simplex[64][4] = { 193 | {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, 194 | {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, 195 | {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, 196 | {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, 197 | {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, 198 | {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, 199 | {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, 200 | {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0} 201 | }; 202 | 203 | // 2D raw Simplex noise 204 | float raw_noise_2d( const float x, const float y ) { 205 | // Noise contributions from the three corners 206 | float n0, n1, n2; 207 | 208 | // Skew the input space to determine which simplex cell we're in 209 | float F2 = 0.5 * (sqrt(3.0) - 1.0); 210 | // Hairy factor for 2D 211 | float s = (x + y) * F2; 212 | int i = floor( x + s ); 213 | int j = floor( y + s ); 214 | 215 | float G2 = (3.0 - sqrt(3.0)) / 6.0; 216 | float t = (i + j) * G2; 217 | // Unskew the cell origin back to (x,y) space 218 | float X0 = i-t; 219 | float Y0 = j-t; 220 | // The x,y distances from the cell origin 221 | float x0 = x-X0; 222 | float y0 = y-Y0; 223 | 224 | // For the 2D case, the simplex shape is an equilateral triangle. 225 | // Determine which simplex we are in. 226 | int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords 227 | if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) 228 | else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1) 229 | 230 | // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 231 | // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 232 | // c = (3-sqrt(3))/6 233 | float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 234 | float y1 = y0 - j1 + G2; 235 | float x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords 236 | float y2 = y0 - 1.0 + 2.0 * G2; 237 | 238 | // Work out the hashed gradient indices of the three simplex corners 239 | int ii = i & 255; 240 | int jj = j & 255; 241 | int gi0 = perm[ii+perm[jj]] % 12; 242 | int gi1 = perm[ii+i1+perm[jj+j1]] % 12; 243 | int gi2 = perm[ii+1+perm[jj+1]] % 12; 244 | 245 | // Calculate the contribution from the three corners 246 | float t0 = 0.5 - x0*x0-y0*y0; 247 | if(t0<0) n0 = 0.0; 248 | else { 249 | t0 *= t0; 250 | n0 = t0 * t0 * dot(grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient 251 | } 252 | 253 | float t1 = 0.5 - x1*x1-y1*y1; 254 | if(t1<0) n1 = 0.0; 255 | else { 256 | t1 *= t1; 257 | n1 = t1 * t1 * dot(grad3[gi1], x1, y1); 258 | } 259 | 260 | float t2 = 0.5 - x2*x2-y2*y2; 261 | if(t2<0) n2 = 0.0; 262 | else { 263 | t2 *= t2; 264 | n2 = t2 * t2 * dot(grad3[gi2], x2, y2); 265 | } 266 | 267 | // Add contributions from each corner to get the final noise value. 268 | // The result is scaled to return values in the interval [-1,1]. 269 | return 70.0 * (n0 + n1 + n2); 270 | } 271 | 272 | 273 | // 3D raw Simplex noise 274 | float raw_noise_3d( const float x, const float y, const float z ) { 275 | float n0, n1, n2, n3; // Noise contributions from the four corners 276 | 277 | // Skew the input space to determine which simplex cell we're in 278 | float F3 = 1.0/3.0; 279 | float s = (x+y+z)*F3; // Very nice and simple skew factor for 3D 280 | int i = floor(x+s); 281 | int j = floor(y+s); 282 | int k = floor(z+s); 283 | 284 | float G3 = 1.0/6.0; // Very nice and simple unskew factor, too 285 | float t = (i+j+k)*G3; 286 | float X0 = i-t; // Unskew the cell origin back to (x,y,z) space 287 | float Y0 = j-t; 288 | float Z0 = k-t; 289 | float x0 = x-X0; // The x,y,z distances from the cell origin 290 | float y0 = y-Y0; 291 | float z0 = z-Z0; 292 | 293 | // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 294 | // Determine which simplex we are in. 295 | int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 296 | int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 297 | 298 | if(x0>=y0) { 299 | if(y0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order 300 | else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order 301 | else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order 302 | } 303 | else { // x0 y0) ? 32 : 0; 400 | int c2 = (x0 > z0) ? 16 : 0; 401 | int c3 = (y0 > z0) ? 8 : 0; 402 | int c4 = (x0 > w0) ? 4 : 0; 403 | int c5 = (y0 > w0) ? 2 : 0; 404 | int c6 = (z0 > w0) ? 1 : 0; 405 | int c = c1 + c2 + c3 + c4 + c5 + c6; 406 | 407 | int i1, j1, k1, l1; // The integer offsets for the second simplex corner 408 | int i2, j2, k2, l2; // The integer offsets for the third simplex corner 409 | int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner 410 | 411 | // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. 412 | // Many values of c will never occur, since e.g. x>y>z>w makes x=3 ? 1 : 0; 417 | j1 = simplex[c][1]>=3 ? 1 : 0; 418 | k1 = simplex[c][2]>=3 ? 1 : 0; 419 | l1 = simplex[c][3]>=3 ? 1 : 0; 420 | // The number 2 in the "simplex" array is at the second largest coordinate. 421 | i2 = simplex[c][0]>=2 ? 1 : 0; 422 | j2 = simplex[c][1]>=2 ? 1 : 0; 423 | k2 = simplex[c][2]>=2 ? 1 : 0; 424 | l2 = simplex[c][3]>=2 ? 1 : 0; 425 | // The number 1 in the "simplex" array is at the second smallest coordinate. 426 | i3 = simplex[c][0]>=1 ? 1 : 0; 427 | j3 = simplex[c][1]>=1 ? 1 : 0; 428 | k3 = simplex[c][2]>=1 ? 1 : 0; 429 | l3 = simplex[c][3]>=1 ? 1 : 0; 430 | // The fifth corner has all coordinate offsets = 1, so no need to look that up. 431 | 432 | float x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords 433 | float y1 = y0 - j1 + G4; 434 | float z1 = z0 - k1 + G4; 435 | float w1 = w0 - l1 + G4; 436 | float x2 = x0 - i2 + 2.0*G4; // Offsets for third corner in (x,y,z,w) coords 437 | float y2 = y0 - j2 + 2.0*G4; 438 | float z2 = z0 - k2 + 2.0*G4; 439 | float w2 = w0 - l2 + 2.0*G4; 440 | float x3 = x0 - i3 + 3.0*G4; // Offsets for fourth corner in (x,y,z,w) coords 441 | float y3 = y0 - j3 + 3.0*G4; 442 | float z3 = z0 - k3 + 3.0*G4; 443 | float w3 = w0 - l3 + 3.0*G4; 444 | float x4 = x0 - 1.0 + 4.0*G4; // Offsets for last corner in (x,y,z,w) coords 445 | float y4 = y0 - 1.0 + 4.0*G4; 446 | float z4 = z0 - 1.0 + 4.0*G4; 447 | float w4 = w0 - 1.0 + 4.0*G4; 448 | 449 | // Work out the hashed gradient indices of the five simplex corners 450 | int ii = i & 255; 451 | int jj = j & 255; 452 | int kk = k & 255; 453 | int ll = l & 255; 454 | int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32; 455 | int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32; 456 | int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32; 457 | int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32; 458 | int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32; 459 | 460 | // Calculate the contribution from the five corners 461 | float t0 = 0.6 - x0*x0 - y0*y0 - z0*z0 - w0*w0; 462 | if(t0<0) n0 = 0.0; 463 | else { 464 | t0 *= t0; 465 | n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0); 466 | } 467 | 468 | float t1 = 0.6 - x1*x1 - y1*y1 - z1*z1 - w1*w1; 469 | if(t1<0) n1 = 0.0; 470 | else { 471 | t1 *= t1; 472 | n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1); 473 | } 474 | 475 | float t2 = 0.6 - x2*x2 - y2*y2 - z2*z2 - w2*w2; 476 | if(t2<0) n2 = 0.0; 477 | else { 478 | t2 *= t2; 479 | n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2); 480 | } 481 | 482 | float t3 = 0.6 - x3*x3 - y3*y3 - z3*z3 - w3*w3; 483 | if(t3<0) n3 = 0.0; 484 | else { 485 | t3 *= t3; 486 | n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3); 487 | } 488 | 489 | float t4 = 0.6 - x4*x4 - y4*y4 - z4*z4 - w4*w4; 490 | if(t4<0) n4 = 0.0; 491 | else { 492 | t4 *= t4; 493 | n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4); 494 | } 495 | 496 | // Sum up and scale the result to cover the range [-1,1] 497 | return 27.0 * (n0 + n1 + n2 + n3 + n4); 498 | } 499 | 500 | float dot( constant int g[2], const float x, const float y ) { return g[0]*x + g[1]*y; } 501 | float dot( constant int g[3], const float x, const float y, const float z ) { return g[0]*x + g[1]*y + g[2]*z; } 502 | float dot( constant int g[4], const float x, const float y, const float z, const float w ) { return g[0]*x + g[1]*y + g[2]*z + g[3]*w; } 503 | --------------------------------------------------------------------------------