Alpha 测试
AlphaTest Great: 大于
AlphaTest Less: 小于
AlphaTest Equal: 等于
AlphaTest GEqual: 大于等于
AlphaTest LEqual: 小于等于
AlphaTest Never: 全不渲染
AlphaTest Always: 全部渲染
如果使用后两项的命名的情况下, 比较后的数字项没有意义
AlphaTest 比较项 数字
- AlphaTest Great 0.5 // 表示只渲染 alpha 值大于 0.5 的部分
- AlphaTest Less 0.5 // 表示只渲染 alpha 值小于 0.5 的部分
混合命令
Blend SrcFactor DstFactor
SrcFactor DstFactor 可以的取值
One 表示 1
Zero 表示 0
SrcColor 当前的颜色
DstColor 已经存在的颜色
SrcAlpha 当前的透明度
DstAlpha 已经存在的颜色的透明度
OneMinusSrcColor 当前的颜色取反向 1-SrcColor
OneMinusSrcAlpha 当前的 Alpha 值取反向 1-SrcAlpha
OneMinusDstColor 已经存在的颜色取反向 1-DstColor
OneMinusDstAlpha 已经存在的颜色的透明度取反向 1-DstAlpha
最终颜色 = 新颜色 * SrcFactor + 旧颜色 * DstFactor
新颜色: 即将写入到颜色缓冲区的颜色
旧颜色: 已经在颜色缓冲区的颜色
颜色运算法则(不同于向量运算法则)
- (r,g,b) * a = (r*a,g*a,b*a)
- (r,g,b) * (x,y,z) = (r*x,g*y,b*z)
- (r,g,b) + (x,y,z) = (r+x,g+y,b+z)
- A - (r,g,b) = (a-x,a-y,a-z)
例如
- Blend Zero One // 仅仅显示背景的颜色, 自身的效果不会显示
- Blend One Zero // 显示贴图的 RGB 颜色, 即使有透明通道的部分也显示原色, 不会透过去
- Blend One One // 贴图色与背景色叠加, 没有透明通道处理, 结果可能更趋近于(1,1,1)
- Blend SrcAlpha Zero // 没有透明通道部分显示的是贴图的原色, 有透明通道 0 的部分, 显示黑色, 0.5 部分更趋近于黑色
- Blend SrcAlpha OneMinusSrcAlpha // 最终颜色 = 新颜色 * 当前透明度 + 旧颜色 * (1 - 当前透明度), 最常用的透明混合方式
- Shader "Lesson/AlphaTest" {
- Properties {
- _Tex("纹理", 2D) = "white"{}
- _Alpha("透明度", Range(0,1)) = 0
- }
- SubShader {
- Pass
- {
- // 表示只渲染 alpha 值大于 0.5 的部分
- AlphaTest Greater 0.5
- AlphaTest Greater [_Alpha]
- //Blend SrcAlpha OneMinusSrcAlpha
- Blend SrcAlpha zero
- SetTexture[_Tex]
- {
- Combine texture
- }
- }
- }
- FallBack "Diffuse"
- }
Cg 语言, 详见 PPT
顶点 / 片元着色器
核心:
顶点函数:
片元函数:
顶点函数在几何阶段, 能从应用程序获取顶点信息. 这些信息就是通过顶点函数的参数传递进来的. 顶点函数的返回值就是传递到片元函数里的, 片元函数也是通过参数去接收的
Float4 vertex: 顶点坐标(模型空间下)
Float4 normal: 顶点的法线向量
Float4 tangent: 顶点的切线向量
Float4 texcoord: 第一 UV 颜色
Float4 texcoord1: 第二 UV 颜色
Float4 color: 顶点颜色
语义: 语句的含义
顶点函数的形参后跟的语义: 表示该形参的是接收应用程序传递来的是什么.
对于顶点函数的方法后跟的语义: 修饰的返回值, 代表该返回值表示的是什么.
对于片元函数的方法后跟的语义: 修饰的是片元函数的返回值, 代表的是告诉应该 GPU 是什么
从应用程序阶段到顶点函数阶段
1.POSITION: 表示应用程序把顶点坐标传递过来并且存储在修饰的参数
2.NORMAL: 表示法线, 通常是 float3
3TANGENT: 表示切线
4.TEXCOORD0-N: 从第 1 套 UV 到第 7 套 UV
5.COLOR: 顶点颜色
从顶点函数到片元函数能表示的语义
1.SV_POSITION: 代表转换之后的齐次空间坐标
2.COLOR0: 代表一组颜色
2.COLOR1: 代表一组颜色
4.TEXCOORD0-N: 从第 1 套 UV 到第 7 套 UV
从片元函数输出的语义
SV_Target: 输出的值会渲染到屏幕上
- // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
- Shader "Lesson/VFColor" {
- Properties {
- _Color("颜色", Color) = (1,0,0,1)
- }
- SubShader {
- //1. 顶点片元程序也要写在 Pass 块里
- Pass
- {
- //2. 把 Cg 语言的开始和结束写出来
- // 表示 Cg 语言程序的开始
- CGPROGRAM
- //3. 定义顶点函数和片元函数的名字
- //#pragma 不变 vertex 关键字, 后跟的是顶点函数的名字, vert 顶点函数的名字
- #pragma vertex vert // 定义函数名为 vert 的函数为顶点函数
- //#pragma 不变 fragment 关键字
- #pragma fragment frag // 定义函数名为 frag 的函数为片元函数
- fixed4 _Color;// 如果要在 Cg 语言中去使用属性面板定义的一些变量, 需要在 Cg 语言中进行重定义
- //4. 实现顶点函数
- //POSITION 修饰的是顶点函数参数 vet, 证明 vet 是顶点坐标
- //SV_POSITION 修饰的是 vet 函数的返回值, 证明返回值是转换之后的坐标
- float4 vert(float4 vet : POSITION, float3 normal : NORMAL) : SV_POSITION
- {
- // 顶点函数的核心作用必须做的是空间坐标转换
- //mul 是 Cg 语言的提供的 API, 计算向量与矩阵相乘
- float4 position = UnityObjectToClipPos(vet); //
- return position;
- }
- //5. 实现片元函数
- fixed4 frag() : SV_Target
- {
- // 最重要的必须的做到就是返回一个颜色
- return _Color;
- }
- // 表示 Cg 语言程序的结束
- ENDCG
- }
- }
- FallBack "Diffuse"
- }
Unity\Editor\Data\CGIncludes\UnityShaderUtilities.cginc 里的 UnityObjectToClipPos()函数
UnityCG.cginc 常用的 API
- #ifndef UNITY_SHADER_UTILITIES_INCLUDED
- #define UNITY_SHADER_UTILITIES_INCLUDED
- // This file is always included in all unity shaders.
- #include "UnityShaderVariables.cginc"
- // Tranforms position from object to homogenous space
- inline float4 UnityObjectToClipPos(in float3 pos)
- {
- // More efficient than computing M*VP matrix product
- return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
- }
- inline float4 UnityObjectToClipPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return UnityObjectToClipPos(pos.xyz);
- }
- #endif
UNITY_MATRIX_MVP 的 MVP 是几何阶段的三次转变
M 模型到世界
V 世界到观察
P 观察到剪裁
- // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
- Shader "Lesson/VFNormal" {
- Properties {
- }
- SubShader {
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- // 定义一个结构体, 作为顶点函数的参数
- struct m2v
- {
- float4 vex : POSITION;// 告诉应用程序把模型空间下的顶点坐标放在这
- float3 normal : NORMAL;// 告诉应用程序把模型空间下的法线放在这
- float3 tangent : TANGENT;// 告诉应用程序把模型空间下的切线放在这
- };
- // 定义一个结构体, 作为顶点函数的返回值和片元函数的参数
- struct v2f
- {
- float4 position : SV_POSITION;// 转换之后的顶点坐标
- float3 normal : COLOR0;// 法线
- float3 tangent : COLOR1;// 切线
- };
- // 结构体作为参数和返回值
- v2f vert(m2v v)
- {
- v2f f;
- f.position = UnityObjectToClipPos(v.vex); // 必须变换顶点坐标
- f.normal = v.normal;// 法线赋值
- f.normal = mul(UNITY_MATRIX_M, v.normal);
- //f.tangent = v.tangent;// 切线赋值
- return f;
- }
- fixed4 frag(v2f f) : SV_Target
- {
- return fixed4(f.normal.x, f.normal.y, f.normal.z, 1);// 把法线作为颜色输出
- //return fixed4(f.tangent.x, f.tangent.y, f.tangent.z, 1);// 把切线作为颜色输出
- }
- ENDCG
- }
- }
- FallBack "Diffuse"
- }
UV 坐标, 可以通过顶点的 UV 坐标去获取纹理对应的颜色. 对于图片的纹理来说 UV 的 (0,0) 点在左下角, UV 的 (1,1) 点在右上角
- // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
- Shader "Lesson/VFTexture" {
- Properties{
- // 定义一个图片
- _MainTex("纹理", 2D) = "white"{}
- }
- SubShader{
- // 透明的纹理处理要把渲染队列调高
- Tags{ "Queue" = "Transparent" }
- Pass
- {
- //Cull off
- // 处理带有透明通道贴图的混合
- Blend SrcAlpha OneMinusSrcAlpha
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- // 重定义纹理
- sampler2D _MainTex;
- // 定义结构体, 作为顶点函数的参数
- struct m2v
- {
- float4 vex : POSITION;
- float2 uv : TEXCOORD0;// 告诉应用程序要 UV 信息
- };
- // 定义一个结构体, 作为顶点函数的返回值和片元函数的参数
- struct v2f
- {
- float4 position : SV_POSITION;
- float2 uv : TEXCOORD0;
- };
- v2f vert(m2v v)
- {
- v2f f;
- // 转换顶点坐标
- f.position = UnityObjectToClipPos(v.vex);
- f.uv = v.uv;
- return f;
- }
- fixed4 frag(v2f f) : SV_Target
- {
- // 通过顶点的 uv 坐标去访问纹理对应的颜色
- fixed4 color = tex2D(_MainTex, f.uv);
- //return fixed4(f.uv.x,f.uv.y, 0, 1);
- return color;
- }
- ENDCG
- }
- }
- FallBack "Diffuse"
- }
属性面板的变量, 如果想在 Cg 程序中去使用, 必须在 Cg 程序中重新定义:
Color - fixed4 或 float4
- Vector - float4
- Float - float
- Range - float
- 2D - sampler2D
- Rect - samplerRect
- Cube - samplerCube
裁剪可以做场景切换的幕布效果
- // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
- Shader "Lesson/VFDiscard" {
- Properties{
- _MainTex("纹理", 2D) = "white"{}
- _Radius("半径", Range(0, 0.75)) = 0
- }
- SubShader{
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- sampler2D _MainTex;
- float _Radius;
- struct m2v
- {
- float4 vex : POSITION;
- float2 uv : TEXCOORD0;
- };
- struct v2f
- {
- float4 position : SV_POSITION;
- float2 uv : TEXCOORD0;
- };
- v2f vert(m2v v)
- {
- v2f f;
- f.position = UnityObjectToClipPos(v.vex);
- f.uv = v.uv;
- return f;
- }
- fixed4 frag(v2f f) : SV_Target
- {
- //discard;// 裁剪命令
- fixed4 color = tex2D(_MainTex, f.uv);
- //0.2 圆的半径
- // 圆心是 0.5 0.5
- float2 current = f.uv;
- float2 center = float2(0.5, 0.5);
- float dis = pow((current.x - center.x), 2) + pow((current.y - center.y), 2);
- if (dis <pow(_Radius, 2))
- {
- // 在圆内
- discard;
- }
- return color;
- }
- ENDCG
- }
- }
- FallBack "Diffuse"
- }
Emission, 类似 RawImage 的 UV Rect
----Tiling: 图片的左右偏移
----Offset: 图片的大小比例
练习 - 实现西瓜的效果
- Shader "Lesson/VFWatermelon" {
- Properties {
- _LightColor("浅色条纹", Color) = (1,1,1,1)
- _DarkColor("深色条纹", Color) = (1,1,1,1)
- _Number("深色条纹数量", int) = 3
- _Width("深色条纹宽度", Range(0.01, 0.2)) = 0.02
- }
- SubShader{
- Pass
- {
- CGPROGRAM
- fixed4 _LightColor;
- fixed4 _DarkColor;
- int _Number;
- float _Width;
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- struct m2v
- {
- float4 vex : POSITION;
- float3 uv : TEXCOORD0;
- };
- struct v2f
- {
- float4 position : SV_POSITION;
- float3 uv : TEXCOORD0;
- };
- v2f vert(m2v v)
- {
- v2f f;
- f.position = UnityObjectToClipPos(v.vex);
- f.uv = v.uv;
- return f;
- }
- fixed4 frag(v2f f) : SV_Target
- {
- // 实现 1
- // 浅色条纹的宽度
- float width = 1.0 / _Number - _Width;
- for (int i = 0; i < _Number; i++)
- {
- if (f.uv.x> i * (width + _Width) && f.uv.x < width + i * (width + _Width))
- {
- return _DarkColor;
- }
- }
- return _LightColor;
- /*
- // 实现 2
- // 每对条纹的宽度(1 深 1 浅)
- float wid = 1.0 / _Number;
- float x = fmod(f.uv.x, wid); // 对 wid 取模(余)
- if (x < _Width)
- {
- return _DarkColor;
- }
- return _LightColor;
- */
- }
- ENDCG
- }
- }
- FallBack "Diffuse"
- }
Unity3D 学习笔记(三十五):Shader 着色器(2)- 顶点片元着色器
来源: http://www.bubuko.com/infodetail-2950935.html