顶点与片段着色器的例子
视窗坐标
Shader "Custom/WindowCoordinates/Base" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" float4 vert(appdata_base v) : POSITION { return mul (UNITY_MATRIX_MVP, v.vertex); } fixed4 frag(float4 sp:VPOS) : SV_Target { return fixed4(sp.xy/_ScreenParams.xy,0.0,1.0); } ENDCG } } }
pragma target 3.0
target指令定义了硬件需求的支持着色器
include "UnityCG.cginc"
包含文件"UnityCG.cginc",内部包含着色器代码
appdata_base v
定义了一个Unity的默认结构,用于顶点着色器的输入变量。包含在UnityCg.cginc中
truct appdata_base {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
VPOS
frag方法的输入参数,声明为一个float4类型和VPOS的语义。语义是一种特殊的字句在HLSL/CG,用于定义一个默认的顶点着色器/片段着色器的输入值。VPOS通过填充变量渲染着色器像素坐标在屏幕上的值。这个位置需要除以屏幕大小,值转换为0和1的值,所以他们可以映射RG(xy红绿)组件输出的颜色。
ScreenParams
他的屏幕的宽度和高度值存储在变量_ScreenParams,该变量声明在UnityCG.cginc文件中。
Examples
窗口坐标在着色器并不常用,因为着色器通常使用的是纹理的位置,然而一些有趣的效果像遮罩渲染或者一些纹理效果用这个属性。
Behind bars(在监狱服刑)
Shader "Custom/WindowCoordinates/Bars" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertOut { float4 pos:SV_POSITION; float4 scrPos; }; vertOut vert(appdata_base v) : POSITION { vertOut o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.scrPos = ComputeScreenPos(o.pos); return o; } fixed4 frag(vertOut i : POSITION) : SV_Target { float2 wcoord = (i.scrPos.xy/i.scrPos.w); fixed4 color; if (fmod(20.0*wcoord.x,2.0)<1.0) { color = fixed4(wcoord.xy,0.0,1.0); } else { color = fixed4(0.3,0.3,0.3,1.0); } return color; } ENDCG } } }
struct vertOut
定义一个新类型的变量,这是一个复合类型,代表一组其他变量与本地或复合类型,结构体用于超过一个的本地数据需要从顶点着色器传递到片段着色器时。作为一个函数的返回数据仅仅是一个变量,与结构的一组值可以表示为一个唯一值。
fmod
cg中的数学方法 取余
ComputeScreenPos
方法被定义在UnityCG.cginc文件中。这个方法返回了屏幕的坐标以用于片段着色器。与前面的例子的区别VPOS语义变量使用,这个函数是多平台,它不需要目标3.0。
Vignetting(光晕)
Shader "Custom/WindowCoordinates/Vignetting" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" float4 vert(appdata_base v) : POSITION { return mul (UNITY_MATRIX_MVP, v.vertex); } fixed4 frag(float4 sp:VPOS) : SV_Target { float2 wcoord = sp.xy/_ScreenParams.xy; float vig = clamp(3.0*length(wcoord-0.5),0.0,1.0); return lerp (fixed4(wcoord,0.0,1.0),fixed4(0.3,0.3,0.3,1.0),vig); } ENDCG } } }
Length
返回一个向量的模,CG中的数学函数
Circles Mask(圆形遮罩)
Shader "Custom/WindowCoordinates/CirclesMask" { Properties { _CirclesX ("Circles in X", Float) = 20 _CirclesY ("Circles in Y", Float) = 10 _Fade ("Fade", Range (0.1,1.0)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" uniform float _CirclesX; uniform float _CirclesY; uniform float _Fade; float4 vert(appdata_base v) : POSITION { return mul (UNITY_MATRIX_MVP, v.vertex); } fixed4 frag(float4 sp:VPOS) : SV_Target { float2 wcoord = sp.xy/_ScreenParams.xy; fixed4 color; if (length(fmod(float2(_CirclesX*wcoord.x,_CirclesY*wcoord.y),2.0)-1.0)<_Fade) { color = fixed4(sp.xy/_ScreenParams.xy,0.0,1.0); } else { color = fixed4(0.3,0.3,0.3,1.0); } return color; } ENDCG } } }
uniform
ShaderLab属性定义为从应用程序转移到材质的值。属性定义等不同类型的颜色,浮动,2D等等。使用关键字值定义为材质的属性uniform使用声明的变量,所以编译器识别变量作为外部值应该在每个执行转移到材质。
Texture Coordinates(纹理坐标)
着色器使用纹理坐标画网格的面具有不同的影响纹理坐标在网格上是变量texcoord0,这是每个顶点。顶点和片段着色器可以修改这个变量。你应该选择你修改texcoord0的材质,根据变量所需的操作,场景中顶点的数量和屏幕分辨率。你应该选择寻找最小的执行修改
texcoord0的值。
Shader "Custom/TextureCoordinates/Base" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" struct vertexInput { float4 vertex : POSITION; float4 texcoord0 : TEXCOORD0; }; struct fragmentInput{ float4 position : SV_POSITION; float4 texcoord0 : TEXCOORD0; }; fragmentInput vert(vertexInput i){ fragmentInput o; o.position = mul (UNITY_MATRIX_MVP, i.vertex); o.texcoord0 = i.texcoord0; return o; } fixed4 frag(fragmentInput i) : SV_Target { return fixed4(i.texcoord0.xy,0.0,1.0); } ENDCG } } }
texcoord0的值的范围从0到1,它们映射到一个特定的纹理,纹理是图像存储在内存的GPU代表一个正方形或矩形图像,片段着色器的材质也可以用作程序纹理,使用数学函数来定义每个像素在屏幕上的颜色。在上面的代码中texcoord0值被用来设置的颜色红色和绿色通道,每个颜色的渐变效果
chess(国际象棋)
Shader "Custom/TextureCoordinates/Chess" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexInput { float4 vertex : POSITION; float4 texcoord0 : TEXCOORD0; }; struct fragmentInput{ float4 position : SV_POSITION; float4 texcoord0 : TEXCOORD0; }; fragmentInput vert(vertexInput i){ fragmentInput o; o.position = mul (UNITY_MATRIX_MVP, i.vertex); o.texcoord0 = i.texcoord0; return o; } fixed4 frag(fragmentInput i) : SV_Target { fixed4 color; if ( fmod(i.texcoord0.x*8.0,2.0) < 1.0 ){ if ( fmod(i.texcoord0.y*8.0,2.0) < 1.0 ) { color = fixed4(1.0,1.0,1.0,1.0); } else { color = fixed4(0.0,0.0,0.0,1.0); } } else { if ( fmod(i.texcoord0.y*8.0,2.0) > 1.0 ) { color = fixed4(1.0,1.0,1.0,1.0); } else { color = fixed4(0.0,0.0,0.0,1.0);} } return color; } ENDCG } } }
Texture
Shader "Custom/TextureCoordinates/ActualTexture" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Pass { CGPROGRAM #pragma vertex vert_img #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; fixed4 frag(v2f_img i) : SV_Target { return tex2D(_MainTex, i.uv); } ENDCG } } }
v2f_img
包含在UnityCG.cginc文件中
struct v2f_img {
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
};