一、ShaderToy是什么?
ShaderToy是一个在线平台,允许用户创建、共享和浏览基于着色器(shaders)的实时图形效果。着色器是一种在图形编程中用于描述图形效果的程序,通常在图形处理器(GPU)上运行。ShaderToy专注于片元着色器(pixel shaders),这是一种用于处理屏幕上每个像素的着色器。
在ShaderToy上,用户可以使用OpenGL Shading Language(GLSL)编写着色器代码,以实时渲染各种视觉效果,包括抽象艺术、光影效果、模拟流体等等。用户可以通过简单的链接和分享来展示他们的作品,从而创建一个充满创意和艺术性的社区。
这个平台通常吸引着对图形编程、计算机图形学、计算机艺术等领域感兴趣的人们,他们可以通过ShaderToy分享他们的创意和学习经验。
二、ShaderToy链接
1.数学计算八卦阵_Yin Yang
ShaderToy内的源码与效果图如下:
ShaderToy中的代码如下:
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 p = 1.1 * (2.0*fragCoord-iResolution.xy)/min(iResolution.y,iResolution.x); float a = dot(p,p); float b = abs(p.y)-a; float c = (b>0.0) ? p.y : p.x; float d = (a-1.0)*(b-0.23)*c; float r = (a>1.0) ? 0.6 : (d>0.0) ? 1.0 : 0.0; fragColor = vec4( r, r, r, 1.0 ); }
下面是在Unity内的效果展示:
在代码中加入了一个旋转矩阵,让阴阳转动起来。
在片段着色器中输入下面的代码:
fixed4 frag(v2f i) : SV_Target { float2 uv = i.uv -0.5; fixed2 p = 1.1 * (2.0*uv); return fixed4(p.xxx, 1.0 ); }
输出效果如下:
实现画面对半的黑白效果
在片段着色器中输入下面的代码:
fixed4 frag(v2f i) : SV_Target { float2 uv = i.uv -0.5; fixed2 p = 1.1 * (2.0*uv); fixed h = dot(p,p); return fixed4(h.xxxx); }
fixed h = dot(p,p)解析
有点类似求 length 的最终效果,也就是说
fixed h = dot(p,p); fixed h = length(uv);//这两个最终表现的效果是一样的。
输出效果如下:
在片段着色器中输入下面的代码:
fixed4 frag(v2f i) : SV_Target { float2 uv = i.uv -0.5; fixed2 p = 1.1 * (2.0*uv); fixed h = length(uv); fixed d = abs(p.y)-h; return fixed4(d.xxxx); }
输出效果如下:
在片段着色器中输入下面的代码:
fixed4 frag(v2f i) : SV_Target { float2 uv = i.uv -0.5; fixed2 p = 1.1 * (2.0*uv); fixed h = dot(p,p); fixed d = abs(p.y)-h; fixed a = d-0.23; fixed b = h-1.00; return fixed4( a*b, a*b, a*b, 1.0 ); }
输出效果如下:
完整ShaderLab代码如下:
Shader"ShaderMan/Yin Yang" { Properties { } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenCoord : TEXCOORD1; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv ; o.screenCoord.xy = ComputeScreenPos(o.vertex); return o; } fixed4 frag(v2f i) : SV_Target { float2 uv = i.uv -0.5; float rad = _Time.y * 4; float2x2 RotationMatrix = float2x2 ( cos(rad), -sin(rad), sin(rad),cos(rad) ); uv = mul(RotationMatrix,uv); fixed2 p = 1.1 * (2.0*uv); fixed h = dot(p,p); fixed d = abs(p.y)-h; fixed a = d-0.23; fixed b = h-1.00; fixed c = sign(a*b*(p.y+p.x + (p.y-p.x)*sign(d))); c = lerp( c, 0.0, smoothstep(0.98,1.00,h) ); c = lerp( c, 0.6, smoothstep(1.00,1.02,h) ); return fixed4( c, c, c, 1.0 ); } ENDCG } } }
小总结:旋转计算
下面是以旋转度数为准的计算
void Unity_Rotate_Degrees_float(float2 UV, float2 Center, float Rotation, out float2 Out) { //rotation matrix Rotation = Rotation * (3.1415926f/180.0f); UV -= Center; float s = sin(Rotation); float c = cos(Rotation); //center rotation matrix float2x2 rMatrix = float2x2(c, -s, s, c); rMatrix *= 0.5; rMatrix += 0.5; rMatrix = rMatrix*2 - 1; //multiply the UVs by the rotation matrix UV.xy = mul(UV.xy, rMatrix); UV += Center; Out = UV; }
2.图形循环变换_Pattern
ShaderToy内的源码与效果图如下:
完整ShaderLab代码如下:
Shader"ShaderToy/Pattern" { Properties { _MainTex("_MainTex", 2D) = "white"{} } SubShader{ Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; sampler2D _MainTex; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenCoord : TEXCOORD1; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.screenCoord.xy = ComputeScreenPos(o.vertex); return o; } fixed noise( in fixed2 x ) { fixed2 p = floor(x); fixed2 f = frac(x); fixed2 uv = p.xy + f.xy*f.xy*(3.0-2.0*f.xy); return tex2Dlod( _MainTex,float4( (uv+118.4)/256.0, 0.0 ,0)).x; } fixed map( in fixed2 x, fixed t ) { return noise( 2.5*x - 1.5*t*fixed2(1.0,0.0) ); } fixed shapes( in fixed2 uv, in fixed r, in fixed e ) { fixed p = pow( 32.0, r - 0.5 ); fixed l = pow( pow(abs(uv.x),p) + pow(abs(uv.y),p), 1.0/p ); fixed d = l - pow(r,0.6) - e*0.2 + 0.05; fixed fw = fwidth( d )*0.5; fw *= 1.0 + 10.0*e; return (r)*smoothstep( fw, -fw, d ) * (1.0-0.2*e)*(0.4 + 0.6*smoothstep( -fw, fw, abs(l-r*0.8+0.05)-0.1 )); } fixed4 frag(v2f i) : SV_Target { fixed2 qq = i.uv.xy/1; fixed2 uv = (i.uv - 0.5) * 0.5 * (sin(_Time.y * 2)+2); fixed time = 11.0 + (_Time.y + 0.8*sin(_Time.y)) / 1.8; uv += 0.01*noise( 2.0*uv + 0.2*time ); fixed3 col = 0.1*fixed3(0.10,1.0,0.10) * 0.15 * abs(qq.y-0.5); fixed2 pq, st; fixed f; fixed3 coo; pq = floor( uv*9.0 ) / 9.0; st = frac( uv*9.0 )*2.0 - 1.0; coo = (fixed3(0.5,0.7,0.7) + 0.3*sin(10.0*pq.x)*sin(13.0*pq.y))*0.6; col += 1.0*coo*shapes( st, map(pq, time), 0.0 ); col += 0.6*coo*shapes( st, map(pq, time), 1.0 ); pq = floor( uv*9.0+0.5 ) / 9.0; st = frac( uv*9.0+0.5 )*2.0 - 1.0; coo = (fixed3(1.0,0.5,0.3) + 0.3*sin(10.0*pq.y)*cos(11.0*pq.x))*1.0; col += 1.0*coo*shapes( st, 1.0-map(pq, time), 0.0 ); col += 0.4*coo*shapes( st, 1.0-map(pq, time), 1.0 ); col *= pow( 16.0*qq.x*qq.y*(1.0-qq.x)*(1.0-qq.y), 0.05 ); return fixed4( col, 1.0 ); } ENDCG } } }
3.2D层层叠叠半透明泡泡_Bubbles
ShaderToy内的源码与效果图如下:
完整ShaderLab代码如下:
Shader"ShaderToy/Bubbles" { Properties { } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenCoord : TEXCOORD1; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.screenCoord.xy = ComputeScreenPos(o.vertex); return o; } fixed4 frag(v2f i) : SV_Target { fixed2 uv = i.uv; uv.x *= 1 / 1; fixed3 color = fixed3(0.8 + 0.2*uv.y,0.8 + 0.2*uv.y,0.8 + 0.2*uv.y); [unroll(100)] for( int i=0; i<40; i++ ) { fixed pha = sin(fixed(i)*546.13+1.0)*0.5 + 0.5; fixed siz = pow( sin(fixed(i)*651.74+5.0)*0.5 + 0.5, 4.0 ); fixed pox = sin(fixed(i)*321.55+4.1) * 1 / 1; fixed rad = 0.1 + 0.5*siz; fixed2 pos = fixed2( pox, -1.0-rad + (2.0+2.0*rad)*fmod(pha+0.1*_Time.y*(0.2+0.8*siz),1.0)); fixed dis = length( uv - pos ); fixed3 col = lerp( fixed3(0.94,0.3,0.0), fixed3(0.1,0.4,0.8), 0.5+0.5*sin(fixed(i)*1.2+1.9)); fixed f = length(uv-pos)/rad; f = sqrt(clamp(1.0-f*f,0.0,1.0)); color -= col.zyx *(1.0-smoothstep( rad*0.95, rad, dis )) * f; } color *= sqrt(1.5-0.5*length(uv)); return fixed4(color,1.0); } ENDCG } } }
4.科技感电流场_PlasmaGlobe
ShaderToy内的源码与效果图如下:
Mac电脑系统下的显示:
Windows系统下的显示:
完整ShaderLab代码如下:
Shader"ShaderToy/PlasmaGlobe" { Properties { _MainTex("MainTex", 2D) = "white"{} _iMouse("iMouse", Vector) = (0,0,0,0) } SubShader{ Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; sampler2D _MainTex; float4 _iMouse; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenCoord : TEXCOORD1; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.screenCoord.xy = ComputeScreenPos(o.vertex); return o; } #define NUM_RAYS 13. #define VOLUMETRIC_STEPS 19 #define MAX_ITER 35 #define FAR 6. #define time _Time.y*1.1 fixed2x2 mm2(in fixed a) { fixed c = cos(a), s = sin(a); return fixed2x2(c,-s,s,c); } fixed noise( in fixed x ) { return tex2Dlod(_MainTex,float4( fixed2(x*.01,1.),0.0,0)).x; } fixed hash( fixed n ) { return frac(sin(n)*43758.5453); } fixed noise(in fixed3 p) { fixed3 ip = floor(p); fixed3 f = frac(p); f = f*f*(3.0-2.0*f); fixed2 uv = (ip.xy+fixed2(37.0,17.0)*ip.z) + f.xy; fixed2 rg = tex2Dlod( _MainTex,float4( (uv+ 0.5)/256.0, 0.0 ,0)).yx; return lerp(rg.x, rg.y, f.z); } fixed3x3 m3 = fixed3x3( 0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64 ); fixed flow(in fixed3 p, in fixed t) { fixed z=2.; fixed rz = 0.; fixed3 bp = p; for (fixed i= 1.;i < 5.;i++ ) { p += time*.1; rz+= (sin(noise(p+t*0.8)*6.)*0.5+0.5) /z; p = lerp(bp,p,0.6); z = mul( z ,2.); p = mul( p ,2.01); p = mul( p,m3); } return rz; } fixed sins(in fixed x) { fixed rz = 0.; fixed z = 2.; for (fixed i= 0.;i < 3.;i++ ) { rz += abs(frac(x*1.4)-0.5)/z; x = mul( x ,1.3); z = mul( z ,1.15); x -= time*.65*z; } return rz; } fixed segm( fixed3 p, fixed3 a, fixed3 b) { fixed3 pa = p - a; fixed3 ba = b - a; fixed h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1. ); return length( pa - ba*h )*.5; } fixed3 path(in fixed i, in fixed d) { fixed3 en = fixed3(0.,0.,1.); fixed sns2 = sins(d+i*0.5)*0.22; fixed sns = sins(d+i*.6)*0.21; en.xz = mul( en.xz ,mm2((hash(i*10.569)-.5)*6.2+sns2)); en.xy = mul( en.xy ,mm2((hash(i*4.732)-.5)*6.2+sns)); return en; } fixed2 map(fixed3 p, fixed i) { fixed lp = length(p); fixed3 bg = fixed3(0.,0.,0.); fixed3 en = path(i,lp); fixed ins = smoothstep(0.11,.46,lp); fixed outs = .15+smoothstep(.0,.15,abs(lp-1.)); p = mul( p ,ins*outs); fixed id = ins*outs; fixed rz = segm(p, bg, en)-0.011; return fixed2(rz,id); } fixed march(in fixed3 ro, in fixed3 rd, in fixed startf, in fixed maxd, in fixed j) { fixed precis = 0.001; fixed h=0.5; fixed d = startf; [unroll(100)] for( int i=0; i<MAX_ITER; i++ ) { if( abs(h)<precis||d>maxd ) break; d += h*1.2; fixed res = map(ro+rd*d, j).x; h = res; } return d; } fixed3 vmarch(in fixed3 ro, in fixed3 rd, in fixed j, in fixed3 orig) { fixed3 p = ro; fixed2 r = fixed2(0.,0.); fixed3 sum = fixed3(0,0,0); fixed w = 0.; [unroll(100)] for( int i=0; i<VOLUMETRIC_STEPS; i++ ) { r = map(p,j); p += rd*.03; fixed lp = length(p); fixed3 col = sin(fixed3(1.05,2.5,1.52)*3.94+r.y)*.85+0.4; col.rgb = mul( col.rgb ,smoothstep(.0,.015,-r.x)); col = mul( col ,smoothstep(0.04,.2,abs(lp-1.1))); col = mul( col ,smoothstep(0.1,.34,lp)); sum += abs(col)*5. * (1.2-noise(lp*2.+j*13.+time*5.)*1.1) / (log(distance(p,orig)-2.)+.75); } return sum; } fixed2 iSphere2(in fixed3 ro, in fixed3 rd) { fixed3 oc = ro; fixed b = dot(oc, rd); fixed c = dot(oc,oc) - 1.; fixed h = b*b - c; if(h <0.0) return fixed2(-1.,-1.); else return fixed2((-b - sqrt(h)), (-b + sqrt(h))); } fixed4 frag(v2f i) : SV_Target{ { fixed2 p = i.uv.xy/1-0.5; p.x = mul( p.x,1/1); fixed2 um = _iMouse.xy / 1-.5; fixed3 ro = fixed3(0.,0.,5.); fixed3 rd = normalize(fixed3(p*.7,-1.5)); fixed2x2 mx = mm2(time*.4+um.x*6.); fixed2x2 my = mm2(time*0.3+um.y*6.); ro.xz = mul( ro.xz ,mx);rd.xz = mul(rd.xz ,mx); ro.xy = mul( ro.xy ,my);rd.xy = mul(rd.xy ,my); fixed3 bro = ro; fixed3 brd = rd; fixed3 col = fixed3(0.0125,0.0,0.025); #if 1 for (fixed j = 1.;j<NUM_RAYS+1.;j++) { ro = bro; rd = brd; fixed2x2 mm = mm2((time*0.1+((j+1.)*5.1))*j*0.25); ro.xy = mul( ro.xy ,mm);rd.xy = mul(rd.xy ,mm); ro.xz = mul( ro.xz ,mm);rd.xz = mul(rd.xz ,mm); fixed rz = march(ro,rd,2.5,FAR,j); if ( rz >= FAR)continue; fixed3 pos = ro+rz*rd; col = max(col,vmarch(pos,rd,j, bro)); } #endif ro = bro; rd = brd; fixed2 sph = iSphere2(ro,rd); if (sph.x > 0.) { fixed3 pos = ro+rd*sph.x; fixed3 pos2 = ro+rd*sph.y; fixed3 rf = reflect( rd, pos ); fixed3 rf2 = reflect( rd, pos2 ); fixed nz = (-log(abs(flow(rf*1.2,time)-.01))); fixed nz2 = (-log(abs(flow(rf2*1.2,-time)-.01))); col += (0.1 * nz * nz * fixed3(0.12,0.12,0.5) + 0.05 * nz2 * nz2 * fixed3(0.55,0.2,.55))*0.8; } return fixed4(col*1.3, 1.0); } }ENDCG } } }
5.实现卡通心跳_Heart2D
ShaderToy内的源码与效果图如下:
完整ShaderLab代码如下:
Shader"ShaderToy/Heart2D" { Properties { } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenCoord : TEXCOORD1; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.screenCoord.xy = ComputeScreenPos(o.vertex); return o; } fixed4 frag(v2f i) : SV_Target { fixed2 p = (2.0*i.uv-1)/min(1,1); fixed3 bcol = fixed3(1.0,0.8,0.7-0.07*p.y)*(1.0-0.25*length(p)); fixed tt = fmod(_Time.y,1.5)/1.5; fixed ss = pow(tt,.2)*0.5 + 0.5; ss = 1.0 + ss*0.5*sin(tt*6.2831*3.0 + p.y*0.5)*exp(-tt*4.0); p *= fixed2(0.5,1.5) + ss*fixed2(0.5,-0.5); #if 1 p *= 0.8; p.y = -0.1 - p.y*1.2 + abs(p.x)*(1.0-abs(p.x)); fixed r = length(p); fixed d = 0.5; #else p.y -= 0.25; fixed a = atan2(p.y,p.x)/3.141593; fixed r = length(p); fixed h = abs(a); fixed d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h); #endif fixed s = 0.75 + 0.75*p.x; s *= 1.0-0.4*r; s = 0.3 + 0.7*s; s *= 0.5+0.5*pow( 1.0-clamp(r/d, 0.0, 1.0 ), 0.1 ); fixed3 hcol = fixed3(1.0,0.5*r,0.3)*s; fixed3 col = lerp( bcol, hcol, smoothstep( -0.01, 0.01, d-r) ); return fixed4(col,1.0); } ENDCG } } }
6.卡通层级云_Clouds
ShaderToy内的源码与效果图如下:
完整ShaderLab代码如下:
Shader"ShaderMan/Clouds" { Properties { _color ("color",color) = (1,1,1,1) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc" fixed4 _color ; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 screenCoord : TEXCOORD1; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; o.screenCoord.xy = ComputeScreenPos(o.vertex); return o; } #define TAU 6.28318530718 const fixed3 BackColor = fixed3(0.0, 0.4, 0.58); const fixed3 CloudColor = fixed3(0.18,0.70,0.87); fixed Func(fixed pX) { return 0.6*(0.5*sin(0.1*pX) + 0.5*sin(0.553*pX) + 0.7*sin(1.2*pX)); } fixed FuncR(fixed pX) { return 0.5 + 0.25*(1.0 + sin(fmod(40.0*pX, TAU))); } fixed Layer(fixed2 pQ, fixed pT) { fixed2 Qt = 3.5*pQ; pT *= 0.5; Qt.x += pT; fixed Xi = floor(Qt.x); fixed Xf = Qt.x - Xi -0.5; fixed2 C; fixed Yi; fixed D = 1.0 - step(Qt.y, Func(Qt.x)); // Disk: Yi = Func(Xi + 0.5); C = fixed2(Xf, Qt.y - Yi ); D = min(D, length(C) - FuncR(Xi+ pT/80.0)); // Previous disk: Yi = Func(Xi+1.0 + 0.5); C = fixed2(Xf-1.0, Qt.y - Yi ); D = min(D, length(C) - FuncR(Xi+1.0+ pT/80.0)); // Next Disk: Yi = Func(Xi-1.0 + 0.5); C = fixed2(Xf+1.0, Qt.y - Yi ); D = min(D, length(C) - FuncR(Xi-1.0+ pT/80.0)); return min(1.0, D); } fixed4 frag(v2f i) : SV_Target { // Setup: fixed2 UV = 2.0*(i.uv.xy - 1/2.0) / min(1, 1); // Render: fixed3 Color= BackColor; [unroll(100)] for(fixed J=0.0; J<=1.0; J+=0.2) { // Cloud Layer: fixed Lt = _Time.y*(0.5 + 2.0*J)*(1.0 + 0.1*sin(226.0*J)) + 17.0*J; fixed2 Lp = fixed2(0.0, 0.3+1.5*( J - 0.5)); fixed L = Layer(UV + Lp, Lt); // Blur and color: fixed Blur = 4.0*(0.5*abs(2.0 - 5.0*J))/(11.0 - 5.0*J); fixed V = lerp( 0.0, 1.0, 1.0 - smoothstep( 0.0, 0.01 +0.2*Blur, L ) ); fixed3 Lc= lerp( CloudColor, fixed3(1.0,1.0,1.0), J); Color =lerp(Color, Lc, V); } return (fixed4(Color, 1.0) + fixed4(0,0.5,0.5,0)) * _color; } ENDCG } } }