前文:TA Shader基础
ShaderLab+CG
以下盒子默认数据如下,可以自己灵活改变,装载任意数据类型(float,float2,float3,float4):
POSITION:位置
NORMAL:法线
TANGENT:切线
TEXCOORD0:纹理坐标
TEXCOORD(n):自己定义内容,Shader Model为2/3的时候最多有8个这样的盒子,如果是4/5,最多有16个盒子
COLOR0:颜色,此外还有COLOR1
以下是系统指定用途,最好不要改变:
SV_POSITION:顶点shader返回的顶点位置
SV_Target:片元着色器shader返回给渲染管线的颜色
顶点shader的有一个入口函数vert,其默认传递的参数是一个结构体appdata,在结构体中我们可以把数据盒子中的数据(基于模型的顶点数据)赋给其成员,默认的成员是传递顶点坐标的float4 vertex : POSITION和传递纹理坐标的float2 uv : TEXCOORD0;,具体什么成员变量存放什么数据完全由我们自己决定。然后我们就可以在vert函数中使用这个结构体进行计算了。
vert返回的数据默认也是一个名为v2f的结构体,这个结构体的成员变量定义了要传递给片元着色器shader的数据,存放的盒子可以自己来定,默认是vertex:ST_POSITION和uv:TEXCOORD0,其中ST_POSITION是顶点shader返回给系统的片元坐标数据,我们不要修改它,其他变量例如uv是传给着色shader的,可以自己定。在vert函数中我们需要通过appdata传进来的数据计算出v2f返回的数据。
顶点shader对传递给片元着色shader的数据v2f会经过三角形插值处理,经过插值后,每一个片元都拥有和顶点一样格式的v2f数据,然后片元着色shader会对片元进行逐个处理。
片元着色shader接收顶点shader返回插值后的数据,对片元进行逐个处理。
处理时通过法线,光源位置,片元本色等信息,计算出片元应当显示的颜色。
处理完成之后,返回值是片元的颜色,通过ST_Target返回渲染管线。
在shader中,CPU通过在CGProgram中定义的变量把数据传递给GPU,例如:
sampler2D _MainTex;
float4 _MainTex_ST:
float3 _MyColor:
float _MyValue:
这些变量前面可以加上一个uniform,Unity中可以省略,这些数据在shader中只读不能修改,但是为了操作方便,我们可以把数据绑定到材质球的属性面板中进行修改,可以在属性列表properties中定义。
Properties
{
// 变量名字("显示名字",类型) = 默认值
_MainTex ("Texture", 2D) = "white" {}
_MyPos("MyPos", Vector) = (1.0, 1.0, 1.0, 1.0)
_MyColor ("MyColor", Color) = (1.0, 1.0, 1.0, 1.0)
_MyValue ("MyValue", Range(0, 1.0)) = 0.5
}
下面是Properties中类型对应的变量:
Color,Vector --> float4,half4,fixed4
Range,Float --> float
2D --> Sampler2D
Cube --> SamplerCube
3D --> Sampler3D
一个shader脚本可以包含多个SubShader,但是只会运行一个,如果前面的不能运行,才会运行后面的。如果所有的SubShader不能运行的时候,可以在最后指定默认的shader:
Fallback "VertexLit"
每个SubShader会包含若干个Pass,每个Pass都是一个完整的渲染流水线,Pass的渲染管线状态可以进行如下设置(如果写到SubShader则所有SubShader的Pass都用):
Cull Back|Front|off //设置提出模式:剔除背面/正面/关闭,默认是Back
Ztest Less|Greater|LEqual|GEqual|Equal|NotEqual|Alway //设置深度测试使用的规则
Zwrite On|Off //开启/关闭深度写入
Blend SrcFactor DstFactor //开启并设置混合模式
在pass中可以定义名字:
name "myShader"
这样就能直接使用这个名字进行调用了
Tag可以在SubShader或Pass中设置:
格式:Tag{“Key”=“Value” “Key2”=“Value2”}
Queue:渲染队列 Qpaque/Transparent,渲染队列的值可以在材质面板中设置,它的默认值就是基于Qpaque(2000),Tansparent(3000)的
RanderType:对着色器进行分类,不透明着色器/半透明着色器 Qpaque/Transparent
DisableBatching:指明是否对该物体使用批处理 “DisableBatching”=True
ForceNoShadowCasting:控制是否会投射阴影
IgnoreProjector:如果设置为True,物体不会受Projector影响,用于半透明
CanUsePriteAtlas:如果用于精灵,设置为False
PreviewType:材质在属性面板中如何显示,默认是球,可以设置为Plane,SkyBox
LightMode:定义该Pass在渲染流水线中的角色
主要包括float(32)、half(16)、fixed三种精度
所有平台显卡都支持float,fixed部分显卡不支持,但是如果代码用到了就会自动用float进行替代,一般情况下我们使用float就可以了。
浮点数用于表示向量或颜色:
初始化:
float3 color = float3(1,0,0)
float4 view = float4(1,1,1,1)
访问(降维和加维):
color.r
color.g
color.b
color.rgb // 会输出三维的浮点数
view.x
view.y
view.z
view.w
view.xy
view.xyz
float value = float4(view.xyz,1.0)
struct temp_data{
int a;
float2 b;
uint c;
}
struct temp_data temp;
temp.a = 10
temp.b = float2(10.0,10.0)
// 三种纹理类型
sampler2D a;
samplerCUBE b;
sampler3D c;
// 采样函数
float4 col = tex2D(a,i.uv);
float3 col2 = texCUBE(b,float3(1.0,0.0,0.0));
float3 col3 = tex3D(c,float3(1.0,0.0,0.0));
颜色有两种描述方式,两种可以相互转换
bool isSelf = false
int mask = 0xff
int value = 0xffffffff
// 与或非:&& || !
// 位运算:左移<< 右移>> 按位或| 按位与& 按位取反~ 按位异或^
if(isSelf) // 条件和循环语句与C#一致
{
mask = mask | value;
}
else if(mask==value){
}
int i = 0;
while(i < 10){
i++;
}
for(int k = 0;k < 10;k++){
}
矩阵是描述线性变换的数学工具,用一个矩阵乘以一个向量,我们就可以把这个向量映射到另一个向量。Unity中矩阵往往表示一个点在N维空间的变换。包括但不限于缩放,平移,旋转。在Unity中矩阵最多只有4x4。
// 矩阵的定义
float2x2 a = float2x2(1,0,0,1);
float3x3 b = float2x2(1,0,0,1,1,0,0,1,1);
float2x3 c = float2x3(1,0,0,1,1,0);
float4 v1 = float4(1,0,0,0);
float4x4 d = float4x4(v1,v1,v1,v1);
float value = d[3][3]
radians(degrees) // 度转弧度
degrees(radians) // 弧度转度
sin
cos
tan
asin
acos
atan
pow
exp
log:e为底
exp2:2的几次方
log2:2为底
sqrt
inversesqrt:开根号的倒数
abs
sign
floor:向下取整
ceil:向上取整
fract:取小数部分
mod:传入x,y,返回x-y*floor(x/y)
min
max
clamp
mix:传入x,y,a,返回x*(1-a) + y*a
step:传入edge,x,x大于等于edge返回1,否则返回0
smoothstep:传入edge0,edge1,x,t=clamp((x-edge0)*(edge1-edge0),0,1),返回t*t*(3-2*t)
matrixCompMult(mat x,mat y):两个矩阵对应的元素相乘,并非常识上的矩阵乘法
// 向量相关
lessThan
lessThanEqual
greaterThan
greaterThanEqual
equal
any
all
not
// 材质查找
texture2D
texture2DProj
texture2DLod
texture2DProjLod
textureCube
textureCubeLod
// 几何函数
distance
faceforward
length
normalize
reflect
refract