Skip to content

Instantly share code, notes, and snippets.

@edom18
Last active June 27, 2024 14:34
Show Gist options
  • Save edom18/02d7e12d527335b8dfbeb31baf0eb19f to your computer and use it in GitHub Desktop.
Save edom18/02d7e12d527335b8dfbeb31baf0eb19f to your computer and use it in GitHub Desktop.
フラクタルブラウン運動とドメインワープ ref: https://qiita.com/edo_m18/items/e4d7a084cdbbfdc7863c
/**
* Fractal Brownian Motion
*
* Reference: https://thebookofshaders.com/13/
*
* See also: http://www.iquilezles.org/www/articles/morenoise/morenoise.htm
* : http://www.iquilezles.org/www/articles/warp/warp.htm
*/
const vec3 mixColor1 = vec3(0.8, 0.35, 0.12);
const vec3 mixColor2 = vec3(0.3, 0.75, 0.69);
#define NUM_OCTAVES 5
// Get random value
float random(in vec2 st)
{
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
// Get noise
float noise(in vec2 st)
{
// Splited integer and float values.
vec2 i = floor(st);
vec2 f = fract(st);
float a = random(i + vec2(0.0, 0.0));
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
// -2.0f^3 + 3.0f^2
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
// fractional brown motion
//
// Reduce amplitude multiplied by 0.5, and frequency multiplied by 2.
float fbm(in vec2 st)
{
float v = 0.0;
float a = 0.5;
for (int i = 0; i < NUM_OCTAVES; i++)
{
v += a * noise(st);
st = st * 2.0;
a *= 0.5;
}
return v;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Calculate normalized UV values.
vec2 st = fragCoord / iResolution.xy;
vec3 color = vec3(0.0);
vec2 q = vec2(0.0);
q.x = fbm(st + vec2(0.0));
q.y = fbm(st + vec2(1.0));
// These numbers(such as 1.7, 9.2, etc.) are not special meaning.
vec2 r = vec2(0.0);
r.x = fbm(st + (4.0 * q) + vec2(1.7, 9.2) + (0.15 * iTime));
r.y = fbm(st + (4.0 * q) + vec2(8.3, 2.8) + (0.12 * iTime));
// Mixed color by 'q' and 'r'.
color = mix(color, mixColor1, clamp(length(q), 0.0, 1.0));
color = mix(color, mixColor2, clamp(length(r), 0.0, 1.0));
// Calculate by 'r' is that getting domain warping.
float f = fbm(st + 4.0 * r);
// f^3 + 0.6f^2 + 0.5f
float coef = (f * f * f + (0.6 * f * f) + (0.5 * f));
color *= coef;
fragColor = vec4(color, 1.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// 解像度から、UV座標に変換(正規化)
vec2 st = fragCoord / iResolution.xy;
vec3 color = vec3(0, 0.745, 0.9);
// 最初の引数
vec2 q = vec2(0.0);
q.x = fbm(st + vec2(0.0));
q.y = fbm(st + vec2(1.0));
// 最初の引数をさらに加工。
// 1.7, 9.2などの数字は任意の数字。特別な意味はなし。
vec2 r = vec2(0.0);
r.x = fbm(st + (4.0 * q) + vec2(1.7, 9.2) + (0.15 * iTime));
r.y = fbm(st + (4.0 * q) + vec2(8.3, 2.8) + (0.12 * iTime));
// やっていることは以下と同義
// d1とd2は便宜上設定した追加パラメータ(上の例ではvec2(1.7, 9.2)などがそれ。
// fbm(st + fbm(st + fbm(st + d1) + d2))
// つまり、3段階のfbmで最後の係数を求めている
float f = fbm(st + 4.0 * r);
// f^3 + 0.6f^2 + 0.5f
float coef = (f * f * f + (0.6 * f * f) + (0.5 * f));
color *= coef;
fragColor = vec4(color, 1.0);
}
#define OCTAVES 5
float fbm(vec2 p)
{
float result = 0.0;
float amplitude = 1.0;
for (int i = 0; i < OCTAVES; i++)
{
result += amplitude * noise(p);
amplitude *= 0.5;
p *= 2.0;
}
return result;
}
\begin{eqnarray}
f &=& fbm(st + fbm(st + fbm(st + d_1) + d_2)) \\
result &=& f^3 + 0.6f^2 + 0.5f
\end{eqnarray}
// Get random value
float random(in vec2 st)
{
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
// Get noise
float noise(in vec2 st)
{
// Splited integer and float values.
vec2 i = floor(st);
vec2 f = fract(st);
float a = random(i + vec2(0.0, 0.0));
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));
// -2.0f^3 + 3.0f^2
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment