http://blog.csdn.net/stalendp/article/details/40690185
Shader "shadertoy/TotalNoob" { //https://www.shadertoy.com/view/XdlSDs
Properties{
iMouse ("Mouse Pos", Vector) = (100,100,0,0)
iChannel0("iChannel0", 2D) = "white" {}
iChannelResolution0 ("iChannelResolution0", Vector) = (100,100,0,0)
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma target 3.0
#pragma glsl
#define vec2 float2
#define vec3 float3
#define vec4 float4
#define mat2 float2x2
#define iGlobalTime _Time.y
// #define mod fmod // mod = sign*fmod
#define mix lerp
#define atan atan2
#define fract frac
#define texture2D tex2D
// 屏幕的尺寸
#define iResolution _ScreenParams
// 屏幕中的坐标,以pixel为单位
#define gl_FragCoord ((_iParam.srcPos.xy/_iParam.srcPos.w)*_ScreenParams.xy)
#define PI2 6.28318530718
#define pi 3.14159265358979
#define halfpi (pi * 0.5)
#define oneoverpi (1.0 / pi)
fixed4 iMouse;
sampler2D iChannel0;
fixed4 iChannelResolution0;
struct v2f {
float4 pos : SV_POSITION;
float4 srcPos : TEXCOORD0;
};
// precision highp float;
v2f vert(appdata_base v){
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.srcPos = ComputeScreenPos(o.pos);
return o;
}
vec4 main(v2f _iParam);
fixed4 frag(v2f _iParam) : COLOR0 {
return main(_iParam);
}
vec4 main(v2f _iParam) {
vec2 p = (2.0*gl_FragCoord.xy-iResolution.xy)/iResolution.y;
float tau = 3.1415926535*2.0;
float a = atan(p.x,p.y);
float r = length(p)*0.75;
vec2 uv = vec2(a/tau,r);
//get the color
float xCol = (uv.x - (iGlobalTime / 3.0)) * 3.0;
xCol = sign(xCol)*fmod(xCol, 3.0);
vec3 horColour = vec3(0.25, 0.25, 0.25);
if (xCol < 1.0) {
horColour.r += 1.0 - xCol;
horColour.g += xCol;
} else if (xCol < 2.0) {
xCol -= 1.0;
horColour.g += 1.0 - xCol;
horColour.b += xCol;
} else {
xCol -= 2.0;
horColour.b += 1.0 - xCol;
horColour.r += xCol;
}
// draw color beam
uv = (2.0 * uv) - 1.0;
float beamWidth = (0.7+0.5*cos(uv.x*10.0*tau*0.15*clamp(floor(5.0 + 10.0*cos(iGlobalTime)), 0.0, 10.0))) * abs(1.0 / (30.0 * uv.y));
vec3 horBeam = vec3(beamWidth,beamWidth,beamWidth);
vec4 gl_FragColor = vec4((( horBeam)* horColour ), 1.0);
return gl_FragColor;
}
ENDCG
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
ENDCG
}
}
FallBack Off
}
以上是完整的代码,下面是每句代码的解析:
对于shadertoy来说,他是对于屏幕像素来说的,我们如果想设置为顶点或者片元shader,我们其实不需要vec2 p = (2.0*gl_FragCoord.xy-iResolution.xy)/iResolution.y;
这行代码
我们只需要在frag函数中加入o.uv = TRANSFORM_TEX(v.uv, _MainTex);
,对于坐标来说,是以左下角为原点,右上角为(1,1),因此我们需要o.uv = 2 * o.uv - 1;
将原点调整到中心点处。
主要对于main函数进行主要的解释
float tau = 3.1415926535*2.0; //tau是2pi
float a = atan(p.x,p.y);//值域是(-pi,pi),也就是整个360°
float r = length(p)*0.75;//距离原点的长度
vec2 uv = vec2(a/tau,r);//对于uv.x的值域(-1/2,1/2)
//get the color
float xCol = (uv.x - (iGlobalTime / 3.0)) * 3.0;
xCol = sign(xCol)*fmod(xCol, 3.0);//xCol的值域是(0,3)(上一篇有讲为啥是(0,3))
vec3 horColour = vec3(0.25, 0.25, 0.25);
//将xCol分为3份
if (xCol < 1.0) {
horColour.r += 1.0 - xCol;
horColour.g += xCol;
} else if (xCol < 2.0) {
xCol -= 1.0;
horColour.g += 1.0 - xCol;
horColour.b += xCol;
} else {
xCol -= 2.0;
horColour.b += 1.0 - xCol;
horColour.r += xCol;
}
// draw color beam
uv = (2.0 * uv) - 1.0;//这句是画圆的关键句 如果我们将uv.y当作颜色输出,那么如果uv是负的,那么就是黑色,因此对于uv.y<1/2的时候,图1表示的就是在uv.y小于0.5时,那么就显示为黑色,大于0.5时显示为其他颜色。
float beamWidth = (0.7+0.5*cos(uv.x*10.0*tau*0.15*clamp(floor(5.0 + 10.0*cos(iGlobalTime)), 0.0, 10.0))) * abs(1.0 / (30.0 * uv.y));
//这句代码可以分为四个部分
//1、floor(5.0 + 10.0*cos(iGlobalTime) floor()函数表示向下取整,也就是要小于或者等于x的整数,图2可以看出其值域(-5,14),因此有cos函数,因此是一个循环函数。
//2、f(x)=clamp(floor(5.0 + 10.0*cos(iGlobalTime)), 0.0, 10.0) clamp(x,a,b)函数,当x<a时,x=a,当x>b时,x=b,在ab之间的时候,就取x的值,这样我们可以看出,是将这句代码的值域限制在(0,10)之间,且其值只能为整数,图3表示出其图像。
//3、cos(uv.x*10.0*tau*0.15*f(x)) 将cos函数简化为cos(3pi*uv.x*f(x))
当f(x)=1时,cos函数的周期为2PI/3
当f(x)=2时,cos函数的周期为2PI/30
至于后面的abs(1/30*uv.y)这个数值
我们可以看一下1/30x的图形图5 我们已知的是小于当uv.y<1/2时,uv小于0,此时是黑色,因此我们只看uv.y>1/2的部分,在uv.y增大的过程中,1/30x的值逐渐趋向于0,因此图6可以表示一个圆环,将1/30x加以绝对值则左右两边都有圆环。
因此对于每个角度对应的颜色是不一样的,
图4表示图像循环,当我们将f(x)=1时,我们可以发现现在是
vec3 horBeam = vec3(beamWidth,beamWidth,beamWidth);
vec4 gl_FragColor = vec4((( horBeam)* horColour ), 1.0);
return gl_FragColor;