分形/shadertoy
与 Shadertoy 相关的 GLSL ES 部分
Preprocessor: # #define #undef #if #ifdef #ifndef #else #elif #endif #error #pragma #extension #version #line Operators: () + - ! * / % << >> < > <= >= == != && || Comments: // /* */ Types: void bool int float vec2 vec3 vec4 bvec2 bvec3 bvec4 ivec2 ivec3 ivec4 mat2 mat3 mat4 sampler2D Function Parameter Qualifiers: [none], in, out, inout Global Variable Qualifiers: const Vector Components: .xyzw .rgba .stpq Flow Control: if else for return break continue Output: vec4 gl_FragColor Input: vec4 gl_FragCoord
主要有四种类型:[3]
- float
- int
- bool
- sampler
vec2, vec3, vec4 2D, 3D and 4D floating point vector ivec2, ivec3, ivec4 2D, 3D and 4D integer vector bvec2, bvec3, bvec4 2D, 3D and 4D boolean vectors \\ matrix types: mat2, mat3, mat4 2x2, 3x3, 4x4 floating point matrix \\ sampler1D, sampler2D, sampler3D 1D, 2D and 3D texture samplerCube Cube Map texture sampler1Dshadow, sampler2Dshadow 1D and 2D depth-component texture
type radians (type degrees) type degrees (type radians) type sin (type angle) type cos (type angle) type tan (type angle) type asin (type x) type acos (type x) type atan (type y, type x) type atan (type y_over_x) type pow (type x, type y) type exp (type x) type log (type x) type exp2 (type x) type log2 (type x) type sqrt (type x) type inversesqrt (type x) type abs (type x) type sign (type x) type floor (type x) type ceil (type x) type fract (type x) type mod (type x, float y) type mod (type x, type y) type min (type x, type y) type min (type x, float y) type max (type x, type y) type max (type x, float y) type clamp (type x, type minV, type maxV) type clamp (type x, float minV, float maxV) type mix (type x, type y, type a) type mix (type x, type y, float a) type step (type edge, type x) type step (float edge, type x) type smoothstep (type a, type b, type x) type smoothstep (float a, float b, type x) mat matrixCompMult (mat x, mat y) float length (type x) float distance (type p0, type p1) float dot (type x, type y) vec3 cross (vec3 x, vec3 y) type normalize (type x) type faceforward (type N, type I, type Nref) type reflect (type I, type N) type refract (type I, type N,float eta) bvec lessThan(vec x, vec y) bvec lessThan(ivec x, ivec y) bvec lessThanEqual(vec x, vec y) bvec lessThanEqual(ivec x, ivec y) bvec greaterThan(vec x, vec y) bvec greaterThan(ivec x, ivec y) bvec greaterThanEqual(vec x, vec y) bvec greaterThanEqual(ivec x, ivec y) bvec equal(vec x, vec y) bvec equal(ivec x, ivec y) bvec equal(bvec x, bvec y) bvec notEqual(vec x, vec y) bvec notEqual(ivec x, ivec y) bvec notEqual(bvec x, bvec y) bool any(bvec x) bool all(bvec x) bvec not(bvec x) vec4 texture2D(sampler2D sampler, vec2 coord ) vec4 texture2D(sampler2D sampler, vec2 coord, float bias) vec4 textureCube(samplerCube sampler, vec3 coord) vec4 texture2DProj(sampler2D sampler, vec3 coord ) vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias) vec4 texture2DProj(sampler2D sampler, vec4 coord) vec4 texture2DProj(sampler2D sampler, vec4 coord, float bias) type dFdx( type x ), dFdy( type x ) type fwidth( type p )
将 Shadertoy 着色器转换为
- GLSL Sandbox 代码[4]
"着色器是在 GPU 中执行的程序。一个着色器实际上包含两个程序:顶点着色器和片段(或像素)着色器。" [5]
着色器是一个“单个程序,作用于单个像素,但 Shadertoy 和 WebGL 将其(同时)运行在视窗中的每个像素上……这要归功于 GPU 加速的强大功能” [6]
Shadertoy 着色器的类型
- 图像着色器
- 声音着色器
- VR 着色器
图像着色器实现 mainImage() 函数,以便通过计算每个像素的颜色来生成过程图像。
预期此函数对每个像素调用一次,并且主机应用程序负责提供正确的输入并从中获取输出颜色并将其分配给屏幕像素。
原型是
void mainImage( out vec4 fragColor, in vec2 fragCoord );
"uniform 用于从着色器外部获取值,并将其输入到着色器中……uniform 可以是向量、浮点数、浮点数组、整数和整数数组。" [7]
可以使用以下 **uniform 变量**(Shadertoy 特定输入)为着色器提供不同类型的每帧静态信息
类型 | 名称 | 描述 |
---|---|---|
uniform vec3 | iResolution | 视窗分辨率。iResolution 的宽度/高度分别设置为 x 和 y。z 是像素纵横比,通常为 1.0 |
uniform float | iGlobalTime | 当前时间(以秒为单位) |
uniform float | iChannelTime[4] | 通道时间(如果为视频或音频),以秒为单位 |
uniform vec3 | iChannelResolution0..3 | 每个通道的输入纹理分辨率 |
uniform vec4 | iMouse | xy = 当前像素坐标(如果 LMB 已按下)。zw = 点击像素 |
uniform sampler2D | iChannel{i} | 输入纹理 i 的采样器 |
uniform vec4 | iDate | 年、月、日、时间(以秒为单位),分别存储在 .xyzw 中 |
uniform float | iSampleRate | 声音采样率(通常为 44100) |
类型
- 像素
- x 从 0 到宽度
- y 从 0 到高度
- 归一化:从 0.0 到 1.0
- 世界:任意范围
mainImage() 函数的输入变量是 **fragCoord**(= GLSL 中的 gl_FragCoord)
它包含当前像素位置(坐标)(以像素为单位),着色器需要为此计算颜色。我们可以访问它的 x 和 y 值
**坐标**以像素单位表示
分辨率通过 iResolution uniform 传递到着色器(参见上表)。
要**归一化**坐标(归一化设备坐标 = NDC),请执行以下操作
// Converting (x,y) to range [0,1] float x = gl_FragCoord.x / iResolution.x; // float y = gl_FragCoord.y / iResolution.y;
"现在我们的 x 和 y 在 0..1 范围内,我们不再关心(屏幕)分辨率、宽度或长度。" [8]
**纵横比**[9]
x *= iResolution.x / iResolution.y;
"对于图像着色器,常规的 gl_FragColor 用作输出通道。目前不是强制性的,但建议将 alpha 通道保留为 1.0;"
// This shader computes the same color ( red = 1.0,0.0,0.0 ) for every pixel
// static image
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// color = r,g,b,a
// every value is in range [0.0, 1.0]
fragColor = vec4(1.0,0.0,0.0,1.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float r = fragCoord.x / iResolution.x;
float g = fragCoord.y / iResolution.y;
float b = fragCoord.x / iResolution.y;
fragColor = vec4(r,g,b,1.0);
}
水平红色渐变
// based on the code by Omar Shehata
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float x = fragCoord.x; //We obtain our coordinates for the current pixel
x = x / iResolution.x; //We divide the coordinates by the screen size
// Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel
//Set its red component to the normalized x value = red gradient from left to right
fragColor = vec4(x, 0.0, 0.0, 1.0);
}
垂直绿色渐变
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float y = fragCoord.y; //We obtain our coordinates for the current pixel
y = y / iResolution.y; //We divide the coordinates by the screen size
// Now y is 0 for the bottom pixel, and 1 for the up pixel
//Set its red component to the normalized x value
fragColor = vec4( 0.0, y, 0.0, 1.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float x = fragCoord.x/iResolution.x; // 0.0 < x < 1.0
float y = fragCoord.y/iResolution.y; //
fragColor = vec4(0.0,1.0,0.0,1.0); // green = background
if( x > 0.5 && y > 0.5) {fragColor = vec4(1.0,0.0,0.0,1.0);} // red = upper right
if( x < 0.5 && y < 0.5) {fragColor = vec4(0.0,0.0,1.0,1.0);} // blue = lower left
}
// https://www.shadertoy.com/view/MssXWn
// bu Lukas Pukenis http://www.letsdive.in/2014/05/11/glsl-basics/
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
float thicknessH = 0.01;
float thicknessV = 0.01;
float y = fragCoord.y / iResolution.y;
float x = fragCoord.x / iResolution.x;
float diffY = abs(0.5 - y);
float diffX = abs(0.5 - x);
if ( diffY < thicknessH || diffX < thicknessV) {
fragColor = vec4(1.0, 0.0, 0.0, 1.0 );
} else {
fragColor = vec4(0.0, 0.0, 0.0, 1.0 );
}
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float x = fragCoord.x/iResolution.x; // 0.0 < x < 1.0
float y = fragCoord.y/iResolution.y; //
vec2 center = vec2(0.5, 0.5); // center of the image
fragColor = vec4(0.0,1.0,0.0,1.0); // green = background
if( abs(center.x - x) < 0.2 && abs(center.y - y) < 0.2) {fragColor = vec4(1.0,0.0,0.0,1.0);} // red rectangle in center of image
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{ float ratio = iResolution.x / iResolution.y; // aspect ratio of the window : https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson3
float x = ratio*fragCoord.x/iResolution.x; // 0.0 < x < 1.0*ratio
float y = fragCoord.y/iResolution.y; // 0.0 < y < 1.0
vec2 center = vec2(ratio*0.5, 0.5); // center of the image
fragColor = vec4(0.0,1.0,0.0,1.0); // green = background
if( abs(center.x - x) < 0.2 && abs(center.y - y) < 0.2) {fragColor = vec4(1.0,0.0,0.0,1.0);} // red rectangle in center of image
}
使用像素坐标 的圆形
// https://www.shadertoy.com/view/Mdf3Df
// circle using pixel coordinate
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// the center of the texture
vec2 center = vec2(iResolution.x/2.0,iResolution.y/2.0);
// current pixel location
vec2 loc = fragCoord.xy;
// how far we are from the center
float radius=length(loc-center);
if (radius<100.0)
fragColor = vec4(1,0,0,1); // if we are within our circle, paint it red
else
fragColor = vec4(0,0,0,1); // black background
}
vec2 center = vec2(0.0,0.0); // center of the image in world units
float radius = 2.0; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
// from pixel to world coordinate
// start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top
float x = (fragCoord.x - iResolution.x/2.0)/ (iResolution.y/2.0);
float y = (fragCoord.y - iResolution.y/2.0)/ (iResolution.y/2.0);
vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;
return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
vec3 GiveColor ( vec2 c, vec2 circle_center, float circle_radius)
{
vec3 color = vec3(1.0, 0.0, 035); // background
// draws a circle centered at circle_center
if ( length(circle_center-c)< circle_radius) {color = vec3(0.0, 0.0, 0.0);}
return color;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{
vec2 c = GiveCoordinate(center, radius, fragCoord, iResolution);
vec3 color = GiveColor(c, vec2(0.0, 0.9), 1.5);
fragColor = vec4(color,1.0); //
}
Julia 集
- 整数逃逸时间和用于外部的水平集方法
- 内部的纯色(红色)
// based on the code by gltracy
// https://www.shadertoy.com/view/XsS3Rm
const int i_max = 2055;
vec2 c = vec2( -0.12256, 0.74486);
float er2 = 4.0; // er= er*er escape radius
vec2 complex_square( vec2 v ) {
return vec2(
v.x * v.x - v.y * v.y,
v.x * v.y * 2.0
);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// compute coordinate
vec2 z = fragCoord.xy - iResolution.xy * 0.5;
z *= 2.5 / min( iResolution.x, iResolution.y );
float scale = 0.1;
int count = 0;
// iterations
for ( int i = 0 ; i < i_max; i++ ) {
z = c + complex_square( z );
count = i;
if ( dot(z,z) > er2 ) { break; }
}
// color
if (count == i_max-1) {fragColor = vec4(1.0, 0.0,0.0,1.0);} // filled-in Julia set = red
else fragColor = vec4(1.0- float( count ) * scale ); // exterior
}
轨道陷阱,抛物线棋盘格
// https://www.shadertoy.com/view/4dy3RR
// Orbit trapped julia by maeln
#define MAXITER 128
vec2 cmul(vec2 i1, vec2 i2)
{
return vec2(i1.x*i2.x - i1.y*i2.y, i1.y*i2.x + i1.x*i2.y);
}
vec3 julia(vec2 z, vec2 c)
{
int i = 0;
vec2 zi = z;
float trap1 = 10e5;
float trap2 = 10e5;
for(int n=0; n < MAXITER; ++n)
{
if(dot(zi,zi) > 4.0)
break;
i++;
zi = cmul(zi,zi) + c;
// Orbit trap
trap1 = min(trap1, sqrt(zi.x*zi.y));
trap2 = min(trap2, sqrt(zi.y*zi.y));
}
return vec3(i,trap1,trap2);
}
vec4 gen_color(vec3 iter)
{
float t1 = 1.0+log(iter.y)/8.0;
float t2 = 1.0+log(iter.z)/16.0;
float t3 = t1/t2;
//vec3 comp = vec3(t1,t1,t1);
vec3 red = vec3(0.9,0.2,0.1);
vec3 black = vec3(1.0,1.0,1.0);
vec3 blue = vec3(0.1,0.2,0.9);
vec3 comp = mix(blue,black,vec3(t2));
comp = mix(red,comp,vec3(t1));
return vec4(comp, 1.0);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 z = 2.*(2.*fragCoord.xy - iResolution.xy) / iResolution.x;
// Display the julia fractal for C = (-0.8, [0.0;0.3]).
vec3 iter = julia(z, vec2(cos(iTime/5.0), mix(0.0, 0.3, sin(iTime))));
fragColor = gen_color(iter);
}
二次一维多项式 fc(z)=z²+c 的动力学
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
//
//-----------------https://www.shadertoy.com/view/MdX3zN-------------------------------------------
//
// Dynamics for quadratic 1D polynomials fc(z)=z²+c
//
// * Orange: the Fatou set Kc.
// * Black: the Julia set Jc.
// * Checkerboard distortion: the Boettcher map phi(z).
// * Checkerboard shadowing: the gradient of the Green's function, log|phi(z)|
// * Blue: the two fixed points.
// * Green, the period 2 fixed points.
// * White: c
// * Yellow: the Koening coordinates
//
// Some theory:
//
// * c (white) belongs to Kc (orange), for these are all connected Julia sets.
//
// * When both fixed points (blue) are in Jc but not in Kc, or in other words, when both points
// are repeling (derivative of fc(z) is bigger than one), c does not belong to the Mandelbrot
// set's main cardioid, but to bulbs of higher period. In that case Kc (orange) is made of several
// branches (as many as the period of the bul)
//
// * When one of the two fixed points (blue dots) is inside Kc, meanins it is attractive (derivative
// of fc(z) < 1), then c belongs to the main cardiod of the Mandelbrot set, and Kc is a single piece
// shape.
//
// * When the period 2 fixed points are always repelling (belong to Jc, not to Kc) except for the sets
// that have c belonging to the period-2 bulb of the Mandelbrot set. In those cases, the green dots
// become attrative and sit inside the orange area Kc.
//
// * The Koening coordinates can only been seen when c belongs to the main cariod of the Madelbrot set
//
//------------------------------------------------------------
// complex number operations
vec2 cadd( vec2 a, float s ) { return vec2( a.x+s, a.y ); }
vec2 cmul( vec2 a, vec2 b ) { return vec2( a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x ); }
vec2 cdiv( vec2 a, vec2 b ) { float d = dot(b,b); return vec2( dot(a,b), a.y*b.x - a.x*b.y ) / d; }
vec2 csqrt( vec2 z ) { float m = length(z); return sqrt( 0.5*vec2(m+z.x, m-z.x) ) * vec2( 1.0, sign(z.y) ); }
vec2 conj( vec2 z ) { return vec2(z.x,-z.y); }
vec2 cpow( vec2 z, float n ) { float r = length( z ); float a = atan( z.y, z.x ); return pow( r, n )*vec2( cos(a*n), sin(a*n) ); }
//------------------------------------------------------------
float argument( in vec2 p )
{
float f = atan( p.y, p.x );
if( f<0.0 ) f += 6.2831;
f = f/6.2831;
return f;
}
float grid( in vec2 p )
{
vec2 q = 16.0*p;
vec2 r = fract( q );
float fx = smoothstep( 0.05, 0.06, r.x ) - smoothstep( 0.94, 0.95, r.x );
float fy = smoothstep( 0.05, 0.06, r.y ) - smoothstep( 0.94, 0.95, r.y );
return 0.5 + 0.5*mod( floor(q.x)+floor(q.y), 2.0 );
}
float cross( vec2 a, vec2 b )
{
return a.x*b.y - a.y*b.x;
}
bool isInTriangle( in vec2 p, in vec2 a, in vec2 b, in vec2 c )
{
vec3 di = vec3( cross( b - a, p - a ),
cross( c - b, p - b ),
cross( a - c, p - c ) );
return all(greaterThan(di,vec3(0.0)));
}
float distanceToSegment( vec2 a, vec2 b, vec2 p )
{
vec2 pa = p - a;
vec2 ba = b - a;
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
return length( pa - ba*h );
}
vec3 circle( vec3 bcol, vec3 col, in vec2 a, in vec2 b )
{
float rr = 0.04;
vec3 res = mix( bcol, col, 1.0 - smoothstep( rr-0.01, rr, length(a-b) ) );
float f = smoothstep( rr-0.01, rr, length(a-b) ) - smoothstep( rr, rr+0.01, length(a-b) );
return mix( res, vec3(0.0), f );
}
//------------------------------------------------------------
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy/iResolution.xy;
vec2 p = -1.0 + 2.0*uv;
p.x *= iResolution.x/iResolution.y;
float at = mod( (iTime+.5)/5.0, 8.0 );
vec2 c = vec2(-0.800, 0.100);
c = mix( c, vec2( 0.280,-0.490), smoothstep(0.0,0.1,at) );
c = mix( c, vec2(-0.500,-0.500), smoothstep(1.0,1.1,at) );
c = mix( c, vec2(-0.160, 0.657), smoothstep(2.0,2.1,at) );
c = mix( c, vec2(-0.650, 0.100), smoothstep(3.0,3.1,at) );
c = mix( c, vec2(-0.114, 0.650), smoothstep(4.0,4.1,at) );
c = mix( c, vec2(-0.731, 0.166), smoothstep(5.0,5.1,at) );
c = mix( c, vec2(-0.100,-0.660), smoothstep(6.0,6.1,at) );
c = mix( c, vec2(-0.800, 0.100), smoothstep(7.0,7.1,at) );
// get the 2 fixed points
vec2 one = vec2( 1.0, 0.0 );
vec2 fix1_1 = 0.5*( one + csqrt( one - 4.0*c ) );
vec2 fix1_2 = 0.5*( one - csqrt( one - 4.0*c ) );
vec2 fix2_1 = -(csqrt(-4.0*c-3.0*one)+one)/2.0;
vec2 fix2_2 = (csqrt(-4.0*c-3.0*one)-one)/2.0;
vec2 fix2_3 = -(csqrt( one-4.0*c)-one)/2.0;
vec2 fix2_4 = (csqrt( one-4.0*c)+one)/2.0;
vec2 z = p;
vec2 dz = vec2( 1.0, 0.0 );
vec2 ph = z;
vec2 gr = vec2( log(length(z)), atan(z.y,z.x) );
float t = 0.0;
for( int i=0; i<512; i++ )
{
if( dot(z,z)>10000.0 ) continue;
t += 1.0;
// derivative
dz = 2.0*cmul( z, dz );
// point
z = cmul(z,z) + c;
vec2 a = cdiv(z,z-c);
float s = pow( 0.5, t );
// phi
ph = cmul( ph, cpow(a, s) );
// green
gr.x += log(length(a)) * s;
float aa = atan(a.y,a.x);
if( isInTriangle( z, vec2(0.0), fix1_2, c ) )
{
aa -= sign(aa)*2.0*3.14159;
}
gr.y += aa * s;
}
vec3 col = vec3(1.0,0.65,0.10);
if( t<511.0 )
{
float s = pow( 0.5, t );
vec2 phib = cpow( z, s );
float phiR = length( phib );
float greenR = log(length(z)) * s;
float greenI = argument(z*s);
float d = log( length(z) ) * length(z) / length(dz);
vec2 gradG = -conj(cmul( dz, conj(z) ));
float n = t/50.0;
float sn = -log2(abs(greenR))/50.0;
col = vec3( 0.6 + 0.4*dot(normalize(-gradG),vec2(0.707)) );
col *= vec3( grid( ph ) );
col *= vec3(1.0)*clamp(d*50.0,0.0,1.0);
}
else
{
z = p;
float t = 0.0;
for( int i=0; i<200; i++ )
{
if( length(z-fix1_2)>0.001 )
{
z = cmul(z,z) + c;
t += 1.0;
}
}
vec2 fix = fix1_2;
if( length(2.0*fix1_1)<1.0 ) fix=fix1_1;
if( length(2.0*fix)<1.0 )
{
vec2 ph = cdiv( z - fix, cpow(2.0*fix,t) );
float g = log(length(ph));
float l = 1.0 - 0.1*smoothstep( 0.7, 0.71, sin(48.0*g) );
col += 0.1*(abs(g));
ph = 1.0*vec2( length(ph), atan(ph.y,ph.x)/3.14 );
col *= l;
}
}
// color depending of attractive/repulsive fixed point
col = circle( col, vec3(1.0,1.0,1.0), p, c );
vec3 col2 = vec3(0.0,1.0,0.0);
col = circle( col, col2, p, fix2_1 );
col = circle( col, col2, p, fix2_2 );
col = circle( col, col2, p, fix2_3 );
col = circle( col, col2, p, fix2_4 );
vec3 col1 = vec3(0.0,0.7,1.0);
col = circle( col, col1, p, fix1_1 );
col = circle( col, col1, p, fix1_2 );
fragColor = vec4( col, 1.0 );
}
曼德勃罗集
- 布尔逃逸时间方法
- 外部的纯色 background_color = vec3(1.0, 0.0, 035);
- 内部的纯色 mandel_color = vec3(0.0, 0.0, 0.0);
使用 的平面描述
// https://www.shadertoy.com/view/4sVGWz
// Simple_Mandelbrot by Created by r1nat in 2016-Jan-29
//Based on explanation http://www.hiddendimension.com/fractalmath/Divergent_Fractals_Main.html
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 c = fragCoord.xy / iResolution.xy;
//scaling real axis to [-2.5, 1.5] and imaginary axis to [-1.5, 1.5]
c = c * vec2(4,3) - vec2(2.5, 1.5);
vec2 z = vec2(0);
fragColor = vec4(0);
for (int i=0;i<100;i++)
{
if (z.x * z.x + z.y * z.y >= 4.)
{
fragColor = vec4(1);
break;
}
z = vec2(z.x*z.x - z.y*z.y, 2.*z.x*z.y) + c;
}
}
// image parameters in world coordinate
vec2 center = vec2(-0.75,0.0); // center of the image in world units : http://mightymandel.mathr.co.uk/gallery.html
float radius = 1.25; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".
// escape time algorithm
float er2 = 40.0; // square of escape radius : er2 = er*er so er = 2.0
#define imax 1000
// rgb colors
vec3 background_color = vec3(1.0, 0.0, 035);
vec3 mandel_color = vec3(0.0, 0.0, 0.0);
// compute pixel coordinate in world units
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
// from pixel to world coordinate
// start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top
float x = (fragCoord.x - iResolution.x/2.0)/ (iResolution.y/2.0);
float y = (fragCoord.y - iResolution.y/2.0)/ (iResolution.y/2.0);
vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;
return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
// square of vector ( = complex number)
vec2 complex_square( vec2 v ) {
return vec2(
v.x * v.x - v.y * v.y,
v.x * v.y * 2.0
);
}
bool CheckIfIsInsideMandelbrot(vec2 c)
{
int count=0;
vec2 z = vec2(0.0, 0.0); // initial value is a critical point
// iterations
for ( int i = 0 ; i < imax; i++ ) {
z = c + complex_square( z ); // z = fc(z) = z^2+c
count = i;
if ( dot(z,z) > er2 ) { break; }
}
if (count==imax-1)
{return true;}
else return false;
}
vec3 GiveColor ( vec2 c )
{
bool IsInside = CheckIfIsInsideMandelbrot(c);
if ( IsInside) {return mandel_color; }
else return background_color;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{
vec2 c = GiveCoordinate(center, radius, fragCoord, iResolution);
vec3 color = GiveColor(c);
fragColor = vec4(color,1.0); //
}
曼德勃罗集
- 整数逃逸时间方法 = 水平集方法
- 外部的梯度
- 内部的纯色 vec3(0.0, 0.0, 0.0);
使用 的平面描述
// image parameters in world coordinate
//vec2 center = vec2(-0.75,0.0); // center of the image in world units : http://mightymandel.mathr.co.uk/gallery.html
//float radius = 1.25; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".
vec2 center = vec2(-0.771139525,-0.115216065);
float radius = 0.001;
// escape time algorithm
float er2 = 4.0; // square of escape radius : er2 = er*er so er = 2.0
#define imax 500
// compute pixel coordinate in world units
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
// from pixel to world coordinate
// start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top
float x = (fragCoord.x - iResolution.x/2.0)/ (iResolution.y/2.0);
float y = (fragCoord.y - iResolution.y/2.0)/ (iResolution.y/2.0);
vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;
return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
// based on the code by gltracy https://www.shadertoy.com/view/XsS3Rm
// square of vector ( = complex number)
vec2 complex_square( vec2 v ) {
return vec2(
v.x * v.x - v.y * v.y,
v.x * v.y * 2.0 );
}
// based on the code by gltracy https://www.shadertoy.com/view/XsS3Rm
int GiveLevel(vec2 c)
{
int final_i = 0; // level
vec2 z = vec2(0.0, 0.0); // initial value is a critical point
// iterations
for ( int i = 0 ; i < imax; i++ ) {
z = c + complex_square( z ); // z = fc(z) = z^2+c
final_i = i;
if ( dot(z,z) > er2 ) { break; }
}
return final_i;
}
vec3 GiveColor ( int i)
{
vec3 color;
if ( i < imax )
// level set method = LSM/M
// based on https://www.weheartswift.com/fractals-xcode-6/ by Silviu Pop
{ color.r = sin(float(i) / 3.0); // exterior of Mandelbrot set
color.g = cos(float(i) / 6.0);
color.b = cos(float(i) / 12.0 + 3.14 / 4.0);
}
else color= vec3(0.0, 0.0, 0.0); // interior of mandelbrot set
return color;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{
vec2 c = GiveCoordinate(center, radius, fragCoord, iResolution);
int level = GiveLevel(c );
vec3 color = GiveColor(level);
fragColor = vec4(color,1.0); //
}
// image parameters in world coordinate
vec2 center = vec2(-0.75,0.0); // center of the image in world units : http://mightymandel.mathr.co.uk/gallery.html
float radius = 1.5; // Radius is defined as "the difference in imaginary coordinate between the center and the top of the axis-aligned view rectangle".
// escape time algorithm
float er2 = 100000.0; // square of escape radius : er2 = er*er so er = 1000.0;
#define imax 1000
// rgba colors
vec4 up_color = vec4(1.0, 1.0, 1.0, 1.0);// target set up
vec4 down_color = vec4(0.0, 0.0, 0.0, 1.0); // target set down
vec4 mandel_color = vec4(0.0, 0.0, 0.0, 1.0); // inside
// compute pixel coordinate in world units
vec2 GiveCoordinate(vec2 center, float radius, vec2 fragCoord, vec3 iResolution)
{
// from pixel to world coordinate
// start with pixel coordinate : now point=(0,0) is left bottom and point=(iResolution.x, iResolution.y) is right top
float x = (fragCoord.x - iResolution.x/2.0)/ (iResolution.y/2.0);
float y = (fragCoord.y - iResolution.y/2.0)/ (iResolution.y/2.0);
vec2 c = vec2(center.x + radius*x, center.y + radius*y) ;
return c ; // now coordinate are measured in world units : from 0.0 t 1.0
}
// square of vector ( = complex number)
vec2 complex_square( vec2 v ) {
return vec2(
v.x * v.x - v.y * v.y,
v.x * v.y * 2.0
);
}
int CheckType(vec2 c)
{
int count=0;
vec2 z = vec2(0.0, 0.0); // initial value is a critical point
// iterations
for ( int i = 0 ; i < imax; i++ ) {
z = c + complex_square( z ); // z = fc(z) = z^2+c
count = i;
if ( dot(z,z) > er2 ) { break; }
}
if (count==imax-1)
{return 0;}
else
if (z.x>0.0) return 1;
else return 2;
}
vec4 GiveColor ( vec2 c )
{
int colorType = CheckType(c);
if ( colorType==0) {return mandel_color; }
if (colorType==1) return up_color;
return down_color;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord)
{
vec2 c = GiveCoordinate(center, radius, fragCoord, iResolution);
fragColor = GiveColor(c);
}
//see http://linas.org/art-gallery/escape/escape.html for more info on normalizing the Mandelbrot escape
// Smooth Mandelbrot Created by Justaway in 2015-Jan-2
// https://www.shadertoy.com/view/ltXGDN
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float e=100.0;
vec2 c = vec2(
(fragCoord.x-iResolution.x/2.0)/iResolution.y,
(fragCoord.y-iResolution.y/2.0)/iResolution.y);
c*=2.5;
int ic=0;
vec2 tz;
vec2 z=vec2(0.0);
for(int i=0;i<32;i++){
if(length(z)<e){
tz=z;
z.x=tz.x*tz.x-z.y*tz.y+c.x;
z.y=2.0*tz.x*tz.y+c.y;
ic++;
}
}
float m=float(ic)-(log(log(length(z))))/log(2.0);
fragColor=vec4(abs(sin(m/5.0)));
}
// Mandelbrot set zoom, with smooth coloring (Douady-Hubbard) by iq]
// https://www.shadertoy.com/view/lllGWH
// Created by inigo quilez - iq/2015
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
void mainImage( out vec4 f, in vec2 p )
{
float n = 0.;
vec2 c = vec2(-.745,.186) + 3. * (p.xy/iResolution.y-.5)*pow(.01,1.+cos(.2*iGlobalTime)), z=c*n;
for( int i=0; i<128; i++ )
{
z = vec2( z.x*z.x - z.y*z.y, 2.*z.x*z.y ) + c;
if( dot(z,z)>1e4 ) break;
n++;
}
f = .5 + .5*cos( vec4(3,4,11,0) + .05*(n - log2(log2(dot(z,z)))) );
}
// https://www.shadertoy.com/view/ldfSW4
// The trees are breathing Created by jld in 2014-May-24
#define M_PI 3.14159265358979323846
#define N 53
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 rth = fragCoord.xy / iResolution.xy * 2.0 * M_PI;
rth.y *= iResolution.y / iResolution.x;
rth.x += (iTime / 60.0) * 2.0 * M_PI;
vec2 z0 = (1.0 + rth.y) * vec2(cos(rth.x), sin(rth.x)) / 2.0;
vec2 z1 = vec2(1.0, 0.0) - z0;
vec2 c = vec2(z0.x * z1.x - z0.y * z1.y, z0.x * z1.y + z0.y * z1.x);
vec2 a = c;
float g = 1.0;
float thresh = 10.0 + 6.0 ;
vec3 color = vec3(1.0, 1.0, 1.0);
// color += (1.0 + cos (iTime)) * vec3(0.0, 0.007, 0.01) * clamp(z1.x - z0.x, -2.0, 3.0);
for (int i = 0; i < N; ++i) {
if (dot(a, a) > thresh) {
break;
}
g *= 0.9;
a = vec2(a.x * a.x - a.y * a.y, 2.0 * a.x * a.y) + c;
}
fragColor = vec4(g * color, 1.0);
}
// https://www.shadertoy.com/view/4st3Wn
// Filled Mandelbrot created by Kramin in 2015-Dec-1
#define AA 2
#define maxIteration 300
#define CX -0.75
#define CY 0.0
#define INVZOOM 2.5
#define T 20.0
float getColourValue(float mu, float s, float m, float e)
{
if (mu<s) {
return 0.0;
} else if (mu<m) {
return (mu - s)/(m-s);
} else if (mu<e) {
return 1.0 - (mu - m)/(e-m);
}
return 0.0;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
float modtime = iTime*1.5; //controls the slight pulsating
float sinsq1 = max(0.0,sin(modtime)); sinsq1 = sinsq1*sinsq1;
float sinsq2 = max(0.0,sin(modtime+0.75)); sinsq2 = sinsq2*sinsq2;
float sinsq3 = max(0.0,sin(modtime+1.5)); sinsq3 = sinsq3*sinsq3;
float sinsq4 = max(0.0,sin(modtime+2.25)); sinsq4 = sinsq4*sinsq4;
float izoom = INVZOOM;
vec3 colour = vec3(0.0,0.0,0.0);
#if AA>1
for( int m=0; m<AA; m++ )
for( int n=0; n<AA; n++ )
{
vec2 c = vec2(CX,CY) + (fragCoord+vec2(float(m),float(n))/float(AA)-iResolution.xy/2.0)*izoom/iResolution.y;
float w = float(AA*m+n);
#else
vec2 c = vec2(CX,CY) + (fragCoord-iResolution.xy/2.0)*izoom/iResolution.y;
#endif
vec2 z = c;
float iteration = float(maxIteration);
float zlen = length(z);
float minz = zlen;
int minziter = 0;
for (int i = 0; i<maxIteration; i++) {
if (zlen > 3000.0) {
iteration = float(i);
break;
}
if (zlen < minz){
minziter = i;
minz = zlen;
}
// do z = z^2 + c
z = mat2(z,-z.y,z.x)*z + c;
zlen = length(z);
}
if (iteration < float(maxIteration)){
//smooth colouring
float mu = float(iteration) - log(log(length(vec2(z))))/0.6931471805599453; //log(2.0) = 0.6931471805599453
mu = max(mu,0.0);
//transform to between 0 and 1
//mu/(mu+constant) goes to 1 as mu goes to infinity and to 0 as mu goes to 0.
//This transformation is much better than a simple mu = mu/maxIteration because it
//is independent of maxIteration
mu=mu/(mu+T);
//colour.x += getColourValue(mu,0.5,1.0,1.0) + getColourValue(mu,0.0,0.5,1.0)*0.9 + getColourValue(mu,-1.0,-0.5,0.5)*0.3;
//colour.y += getColourValue(mu,0.5,1.0,1.0) + getColourValue(mu,0.0,0.5,1.0)*0.1 + getColourValue(mu,-1.0,-0.5,0.5)*0.0;
//colour.z += getColourValue(mu,0.5,1.0,1.0) + getColourValue(mu,0.0,0.5,1.0)*0.1 + getColourValue(mu,-1.0,-0.5,0.5)*0.4;
colour += getColourValue(mu,0.5+0.05*(-0.5*sinsq2+0.5),1.0,1.0) + (0.2*sinsq2+0.8)*getColourValue(mu,0.0,0.5,1.0)*vec3(0.867,0.282,0.078) + (0.2*sinsq1+0.8)*getColourValue(mu,-1.0,-0.5,0.5)*vec3(0.302,0.114,0.208);
}
else {
float mu = float(minziter);
mu = (0.5+0.25*(-0.2*sinsq4+0.8))*10.0/(mu+10.0)+0.25*(-0.2*sinsq3+0.8)*sqrt(minz);//sqrt(minz) adds a little gradient to the interior
//colour.x += getColourValue(mu,0.0,0.7,1.0)*0.1 + getColourValue(mu,0.0,0.4,0.7)*0.0 + getColourValue(mu,0.0,0.1,0.5);
//colour.y += getColourValue(mu,0.0,0.7,1.0)*0.0 + getColourValue(mu,0.0,0.4,0.7)*0.6 + getColourValue(mu,0.0,0.1,0.5);
//colour.z += getColourValue(mu,0.0,0.7,1.0)*0.2 + getColourValue(mu,0.0,0.4,0.7)*0.8 + getColourValue(mu,0.0,0.1,0.5);
colour += getColourValue(mu,0.0,0.7,1.0)*vec3(0.302,0.114,0.208) + getColourValue(mu,0.0,0.4,0.7)*vec3(0.867,0.282,0.078) + getColourValue(mu,0.0,0.1,0.5);
}
#if AA>1
}
colour /= float(AA*AA);
#endif
fragColor = vec4( colour.x, colour.y, colour.z, 1.0 );
}