shader简述总结和常用函数说明

Shader简要概括:

1、Shader在可编程渲染流水线中,所处的位置是顶点着色器和片元着色器,这两个部分是高度可编程的。

2、Unity的ShaderLab是Untiy特有的着色器编程语言,他是对Cg/HLSL/的一层封装,是为了简化编程而诞生的。

3、Shader脚本和Material密切相关,和Material一起作用在GameObject上。

4、Unity的着色器包括2种类型,一种是表面着色器,一种是顶点/片元着色器。其中表面着色器其实是对顶点/片元着色器的更高一层封装,它具有简单,易用性,但同时牺牲了控制的灵活性。需要注意的是顶点/片元着色器的“顶点着色器”和“片元着色器”写在同个shader文件里面,两个不连续的过程之所以可以放在一起,也是因为Unity为用户进行了封装。

5、一个Shader可以有多个SubShader,但必须至少有一个SubShader。

6、一个SubShader可以有多个Pass,多个Pass可以实现更加复杂的效果。

各种语义的意义和范围

1、Unity中Renderer组件传递给顶点着色器的关联语义

POSITION : 模型空间(相对于模型自身)的顶点坐标,float4类型。分量xyz可用于表示的范围为[-0.5,0.5],分量w的取值为0或1,0代表点,1代表向量。

NORMAL : 顶点法线,float3类型

TANGENT :顶点切线,float4类型

TEXCOORDn :第n套纹理坐标,float2或float4类型

COLOR : 顶点颜色,fixed4或float4类型

2、顶点着色器输出数据的语义

SV_POSITION :剪裁空间(屏幕空间)下的坐标。左下角为原点(0,0) 横轴的范围是(0,屏幕宽度) 纵轴的范围是(0,屏幕高度)。结构体中必须包含一个用该语义修饰的变量。

COLOR0 : 通常用于输出第一组顶点颜色,但不是必需的

COLOR1 : 通常用于输出第二组顶点颜色,但不是必需的

TEXCOORD0~TEXCOORD7 : 通常用于输出纹理坐标,但不是必需的

3、片元着色器输出数据的语义

SV_TARGET : 最终输出屏幕的颜色值,fixed4或float4类型。有时候这个语义可以写成COLOR,但是由于SV_TARGET在各个平台上都容易被识别,所以还是选用这个。

UntiyShader中,编译指令分为两种:

1.顶点片元着色器(Vetex & Fragment Shader)使用的编译指令

2.表面着色器(Surface Shader)使用的编译指令

相同点:

1.都使用了#pragma语句的编写

2.都需要写在CGPROGRAM和ENDCG之间

区别:

1.VF编译指令写在Pass里面

2.表面着色器编译指令写在SubShader里面,表面着色器会自行编译到多通道里去,并且需要使用#pragma surface …指令来标识这是一个表面着色器。

顶点着色器和片段着色器的编译指令

1、#pragma vertex name:编译name函数为顶点着色器

2、#pragma fragment name:编译name函数为片段着色器

6、#pragma target name: 表明编译目标

7、#pragma only_renderers space_separated_names:只为指定的渲染平台渲染着色器

8、#pragma exclude_renderers pace_separated_names:排除指定的渲染平台

9、#pragma multi_compile … :根据不同的情况,使用不同的预处理器指令,来多次编译Shader代码

表面着色器编译指令

表面着色器放在CGPROGRAM .. ENDCG块里面。表面着色器必须嵌在子着色器(SubShader)块里面,而不是Pass{}里面。因为表面着色器(Surface Shader)将在多重通道(multiple passes)内编译自己,而不是放在某个Pass中。

编译指令#pragma surface surfFunc lightingModel [optional params]

1、surfaceFunction

通常就是名为surf的函数(函数名可以任意)必须指定,其固定格式为:

void surf(Input IN,inout SurfaceOutput o)

表示指定名称的Cg函数中有表面着色器(surface shader)代码。这个函数的格式应该是这样:

void surf(Input IN,inout SurfaceOutput o),其中Input是我们自己定义的结构。Input结构中应该包含所需的纹理坐标(texture coordinates)和表面函数(surfaceFunction)所需要的额外的必须变量。

2、lightModel

使用的光照模式。内置的是Lambert(diffuse)和BlingPhong(specular)两种,一般习惯使用Lambert

Unity内置了一些光照模型,默认情况下使用的是内置的Lambert模型,包括:

Standard:基于物理的漫反射模型

StandardSpecular:基于物理的高光模型

Lambert:不基于物理的漫反射模型

BlinnPhong:不基于物理的高光模型

通过声明一个新的光照模型函数我们就能够创建一个新的关照模型,函数名的格式为:Lighting<任意名字>你可以使用以下三种格式的光照模型函数:

(1)half4 LightingName(SurfaceOutput s,half3 lightDir,half atten){}

该函数用于不需要视角方向的前向着色

(2)half4 LightingName(SurfaceOutput s,half3 lightDir,half3 viewDir,half atten){}

该函数用于需要视角方向的前向着色

(3)half4 LightingName_PrePass(SurfaceOutput s,half4 light){}

该函数用于需要实现延迟着色的项目

数学函数

max(a, b) 比较两个标量或等长向量元素,返回最大值。

min(a,b) 比较两个标量或等长向量元素,返回最小值。

pow(x, y) 计算x的y次方的值

mul(M, N) 矩阵M和矩阵N的积

mul(M, v) 矩阵M和列向量v的积

clip(x) 如果x的任何分量小于零,则丢弃当前像素。

clamp(x, start, end) 把值限制在起始值和结束值之间

mul(v, M) 行向量v和矩阵M的积

dot(A,B) 计算A,B的点积

cross(A,B) 计算A,B的叉积

saturate(x) 把x限制到[0,1]之间

abs(x) 返回输入参数的绝对值

lerp(a,b,w) 根据w返回a到b之间的插值 ,即: a + w*(b-a);

ceil(x) 对输入参数向上取整。

floor(x) 对输入参数向下取整。

round(x) 返回四舍五入值。

frac(x) 返回输入值的小数部分。

step(x,y) 返回(x>=y)?1:0。

几何函数

length(v) 返回向量v的模

normalize(v) 返回向量v的单位向量

reflect(I, N) 根据入射光方向向量 I,和顶点法向量 N,计算反射光方向向量。

其中 I 和 N 必须被归一化,需要非常注意的是,这个 I 是指向顶点的;

函数只对三元向量有效

refract(I,N,eta) 计算折射向量,I 为入射光线,N 为法向量,eta 为折射系数;

其中 I 和 N 必须被归一化,如果 I 和 N 之间的夹角太大,则返回(0,0,0),也就是没有折射光线;I 是指向顶点的;

函数只对三元向量有效

distance(x, y) 返回x,y两点之间的距离。

纹理映射函数

tex2D(sampler2D tex, float2 s) 二维纹理查询

tex2D(sampler2D tex, float3 sz) 二维纹理查询,并进行深度值比较

Tex3Dproj(sampler3D tex, float4 szq) 查询三维投影纹理,并进行深度值比较

Unity Shader 内置数学常量

UNITY_PI 3.14159265359f 圆周率

UNITY_TWO_PI 6.28318530718f 2倍圆周率

UNITY_FOUR_PI 12.56637061436f 4倍圆周率

UNITY_INV_PI 0.31830988618f 圆周率的倒数

UNITY_INV_TWO_PI 0.15915494309f 2倍圆周率的倒数

UNITY_INV_FOUR_PI 0.07957747155f 4倍圆周率的倒数

UNITY_HALF_PI 1.57079632679f 0.5倍圆周率

UNITY_INV_HALF_PI 0.636619772367f 0.5倍圆周率的倒数

Unity Shader 内置变换矩阵(float4x4)

UNITY_MATRIX_MVP 当前模型 * 视图 * 投影矩阵。

UNITY_MATRIX_MV 当前模型 * 视图矩阵。

UNITY_MATRIX_V 当前视图矩阵。

UNITY_MATRIX_P 当前投影矩阵。

UNITY_MATRIX_VP 当前视图 * 投影矩阵。

UNITY_MATRIX_IT_MV //UNITY_MATRIX_MV的逆转置矩阵

//用于将法线从模型空间转换到观察空间

//也可以用于得到UNITY_MATRIX_MV的逆矩阵

UNITY_MATRIX_T_MV //UNITY_MATRIX_MV的转置矩阵

unity_ObjectToWorld 当前模型矩阵。

unity_WorldToObject 当前世界矩阵的逆矩阵。

Unity Shader 内置空间变换函数

float4 UnityWorldToClipPos(float3 pos ) 把世界坐标空间中某一点pos变换到齐次裁剪空间

float4 UnityViewToClipPos(float3 pos ) 把观察坐标空间中某一点pos变换到齐次裁剪空间

float3 UnityObjectToViewPos(float3 pos或float4 pos) 模型局部空间坐标系中某一个点pos变换到观察空间坐标系

float3 UnityWorldToViewPos(float3 pos ) 把世界坐标系下的一个点pos变换到观察空间坐标系

float3 UnityObjectToWorldDir(float3 dir ) 把方向矢量从模型空间转换到世界空间(返回值已归一化)

float3 UnityWorldToObjectDir(float3 dir ) 把方向矢量从世界空间转换到模型空间(返回值已归一化)

float3 UnityObjectToWorldNormal(float3 norm ) 将法线从模型空间转换到世界空间(返回值已归一化)

float3 UnityWorldSpaceLightDir(float3 worldPos ) 输入参数worldPos是一个世界坐标系下的坐标,得到世界空间中从该点到光源(_WorldSpaceLightPos0)的光照方向。(返回值未归一化)

float3 WorldSpaceLightDir(float4 localPos ) 输入一个模型顶点坐标,得到世界空间中从该点到光源的光照方向。(返回值未归一化)

float3 ObjSpaceLightDir(float4 v ) 输入一个模型顶点坐标,得到模型空间中从该点到光源的光照方向。(返回值未归一化)

float3 UnityWorldSpaceViewDir(float3 worldPos ) 输入参数worldPos是一个世界坐标系下的坐标,得到世界空间中从该点到摄像机的观察方向。(返回值未归一化)

float3 WorldSpaceViewDir(float4 localPos ) 输入一个模型顶点坐标,得到世界空间中从该点到摄像机的观察方向。(返回值未归一化)

float3 ObjSpaceViewDir(float4 v ) 输入一个模型顶点坐标,得到模型空间中从该点到摄像机的观察方向。(返回值未归一化)

Unity Shader 内置摄像机和屏幕相关变量

_WorldSpaceCameraPos float3 摄像机的世界空间位置。

unity_CameraProjection float4x4 摄像机的投影矩阵。

unity_CameraInvProjection float4x4 摄像机投影矩阵的逆矩阵。

unity_OrthoParams float4 x 是正交摄像机的宽度,y 是正交摄像机的高度,z 未使用,w 在摄像机为正交模式时是 1.0,而在摄像机为透视模式时是 0.0。

Unity Shader 内置时间相关变量(float4)

_Time 自关卡加载以来的时间 (t/20, t, t*2, t*3),用于将着色器中的内容动画化。

_SinTime 时间正弦:(t/8, t/4, t/2, t)。

_CosTime 时间余弦:(t/8, t/4, t/2, t)。

unity_DeltaTime 增量时间:(dt, 1/dt, smoothDt, 1/smoothDt)。

Unity Shader 内置光照相关变量(ForwardBase和ForwardAdd通道类型)

_LightColor0(在 UnityLightingCommon.cginc 中声明) fixed4 光源颜色。

_WorldSpaceLightPos0 float4 方向光:(世界空间方向,0)。其他光源:(世界空间位置,1)。

unity_WorldToLight(在 AutoLight.cginc 中声明) float4x4 世界/光源矩阵。用于对剪影和衰减纹理进行采样。

unity_4LightPosX0、unity_4LightPosY0、unity_4LightPosZ0 float4 前四个非重要点光源的世界空间位置。(仅限 ForwardBase 通道)

unity_4LightAtten0 float4 前四个非重要点光源的衰减因子。(仅限 ForwardBase 通道)

unity_LightColor half4[4] 前四个非重要点光源的颜色。(仅限 ForwardBase 通道)

unity_WorldToShadow float4x4[4] 世界/阴影矩阵。聚光灯的一个矩阵,方向光级联最多有四个矩阵。

TRANSFORM_TEX方法比较简单,就是将模型顶点的uv和Tiling、Offset两个变量进行运算,计算出实际显示用的定点uv。

float/half/fixed区别

大多数移动GPU都支持这两种精度类型,half类型效率要高。所以,如果你在优化移动设备,那么尽可能多地使用half是有意义的。根据使用经验,只在位置(Positions)和纹理坐标(Texture Coordinates)上使用float,其他的在结果足够好的情况下使用half。

float(32bits),half(16bits)和fixed(11bits)

对于世界空间位置和纹理坐标,使用float精度。

对于其他一切(矢量,HDR颜色等),首先使用half精度,必要时增加精度。

对于纹理数据的非常简单的操作,使用fixed精度。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值