235 lines
11 KiB
Markdown
235 lines
11 KiB
Markdown
## 纯Shader
|
||
- Uniform代表该变量在顶点与片元着色器中值都是相同的。
|
||
- fixed:低精度数字,它们以精度来换取移动设备上的速度。在台式机上,fixed只是float的别名。
|
||
|
||
## 内置库
|
||
- UnityShaderVariables.cginc定义了渲染所需的一堆着色器变量,例如变换,相机和光照数据。这些都在需要时由Unity设置。
|
||
- HLSLSupport.cginc进行了设置,因此无论代码针对的是哪个平台,都可以使用相同的代码进行编写。无需担心使用特定于平台的数据类型等。
|
||
- UnityInstancing.cginc专门用于实例化支持,这是一种减少绘制调用的特定渲染技术。尽管它不直接包含文件,但依赖于UnityShaderVariables。
|
||
|
||
## 关键字
|
||
### PropertyType
|
||
- Int
|
||
- Float
|
||
- Range
|
||
- Color
|
||
- Vector
|
||
- 2D texture
|
||
- Cube texture
|
||
- 3D texture
|
||
|
||
### SubShader
|
||
针对不同性能的显卡适配不同的Shader。
|
||
```
|
||
SubShader{
|
||
[Tags]
|
||
|
||
[RenderSetup]
|
||
|
||
Pass{
|
||
|
||
}
|
||
}
|
||
```
|
||
### Fallback关键字
|
||
Fallback关键词用于处理匹配失败的情况,指定一个用于处理这个情况的Pass或者直接跳过。
|
||
|
||
>FallBack Off
|
||
|
||
### CGPROGRAM与ENDCG
|
||
里面编写这里编写HLSL/CG,对于VertexShader与PixelShader则写在SubShader的Pass关键字的{}中。
|
||
|
||
## 内置变量
|
||
### 矩阵
|
||
- UNITY_MATRIX_MVP
|
||
- UNITY_MATRIX_MV
|
||
- UNITY_MATRIX_P
|
||
- UNITY_MATRIX_VP
|
||
- UNITY_MATRIX_T_MV
|
||
- UNITY_MATRIX_IT_MV
|
||
- _Object2World
|
||
- _World2Object
|
||
- unity_WorldToObject
|
||
|
||
### 摄像机
|
||
- WorldSpaceCameraPos
|
||
- ProjectionParams
|
||
- ScreenParams
|
||
- ZBufferParams
|
||
- unity_OrthoParams
|
||
- unity_CameraProjection
|
||
- unity_CameraInvProjection
|
||
- unity_CameraWorldClipPlanes[6]
|
||
|
||
### 灯光
|
||
- UNITY_LIGHTMODEL_AMBIENT
|
||
- _WorldSpaceLightPos0
|
||
|
||
## 定义VS与PS名称
|
||
```c++
|
||
#pragma vertex vert
|
||
#pragma fragment frag
|
||
```
|
||
## UnityCG.cginc
|
||
### 常用结构体
|
||
- appdata_base float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord: TEXCOORD0;
|
||
- appdata_tan float4 vertex : POSITION; float4 tangent : TANGENT; float3 normal : NORMAL; float4 texcoord : TEXCOORD0;
|
||
- appdata_full float4 vertex : POSITION; float4 tangent : TANGENT; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 texcoord1 : TEXCOORD1; float4 texcoord2 : TEXCOORD2; float4 texcoord3 : TEXCOORD3; # if defined(SHADER_API_XBOX360) half4 texcoord4 : TEXCOORD4; half4 texcoord5 : TEXCOORD5; # endif fixed4 color : COLOR;
|
||
- appdata_img float4 vertex : POSITION; half2 texcoord : TEXCOORD0;
|
||
- v2f_img 裁剪空间中的位置、纹理坐标
|
||
|
||
### 常用函数
|
||
- float4 WorldSpaceViewDir(float4 v)输入一个模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
|
||
- float4 UnityWorldSpaceViewDir(float4 v)输入一个世界空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向
|
||
- float4 ObjSpaceViewDir(float4 v)输入一个模型空间中的顶点位置,返回模型空间中从该店到摄像机的观察方向
|
||
- float4 WorldSpaceLightDir(flaot4 v)仅用于向前渲染。 输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向。没有被归一化
|
||
- float4 ObjectSpaceLightDir(float4 v)仅用于向前渲染中,输入一个模型空间中的顶点位置, 返回模型空间中从该点到光源的光照方向。没有被归一化
|
||
- float4 UnityWorldSpaceLightDir(float4 v)仅用于向前渲染中,输入一个世界空间中的顶点位置, 返回世界空间中从该点到光源的光照方向。没有被归一化
|
||
- float3 UnityObjectToWorldNormal(float3 norm)把法线方向从模型空间中转换到世界空间中
|
||
- float3 UnityObjectToWorldDir(float3 dir)把方向矢量从模型空间中变换到世界空间中
|
||
- float3 Unity WorldToObjectDir(float3 dir)把方向矢量从世界空间变换到模型空间中
|
||
|
||
## 浮点格式
|
||
float:32位
|
||
half:16位 -60000~+60000
|
||
fixed:11位 -2.0~+2.0
|
||
|
||
## 贴图
|
||
`Sampler2D _MainTex`使用类似`float4 _MainTex_ST`作为缩放与位移。
|
||
|
||
## 管线LightMode
|
||
定义在Pass内的Tag{}中。
|
||
- Always:总是渲染,但不计算任何光照。
|
||
- ForwardBase:用于前向渲染,该Pass会计算环境光、平行光、逐顶点SH与LightMap。
|
||
- ForwardAdd:用于前向渲染,该Pass会计算额外的逐像素光源,每个Pass对应一个光源。
|
||
- Deferred:用于延迟渲染,该Pass会计算GBuffer。
|
||
- ShadowCaster:把物体的深度信息渲染ShadowMap或是一张深度纹理中。
|
||
- PrepassBase:用于遗留的延迟渲染,该Pass会渲染法线和高光反射的指数部分。
|
||
- PrepassFinal:用于遗留的延迟渲染,该Pass通过合并纹理、光照和自发光来渲染得到最终的颜色。
|
||
- Vertex、VertexLMRGBM、VertexLM:用于遗留的顶点光照渲染。
|
||
|
||
## 不透明物体的渲染顺序
|
||
1. 先渲染所有不透明物体,并开启深度测试与深度写入
|
||
2. 把半透明物体按它距离摄像机的远近进行排序 ,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但关闭深度写入。
|
||
|
||
### Unity3d的解决方案
|
||
定义了5个渲染队列
|
||
- Backgrouond
|
||
- Geometry
|
||
- AlphaTest
|
||
- Transparent
|
||
- Overlay
|
||
|
||
可以在Tags定义队列:
|
||
```
|
||
SubShader{
|
||
Tags{"Queue"="AlphaTest"}
|
||
Pass{
|
||
ZWrite Off
|
||
}
|
||
}
|
||
```
|
||
|
||
### Blend相关命令
|
||
BlendOff
|
||
BlendSrcFactorDstFactor
|
||
BlendSrcFactorDstFactor,SrcFactorA DstFactorA
|
||
BlendOp BlendOperation
|
||
|
||
### 混合操作
|
||
1. Add
|
||
2. Sub
|
||
3. RevSub
|
||
4. Min
|
||
5. Max
|
||
|
||
### 常见的混合类型
|
||
1. Blend SrcAlpha OneMinusSrcAlpha 正常
|
||
2. Blend OneMinusDstColor One 柔和相加
|
||
3. Blend DstColor Zero 正片叠底
|
||
4. Blend DstColor SrcColor 两倍相乘
|
||
5. BlendOp Min Blend One One 变暗
|
||
6. BlendOp Max Blend One One 变亮
|
||
7. Blend One One 线性减淡
|
||
|
||
### 解决半透明乱序问题
|
||
1. 使用两个Pass来渲染模型,第一个Pass开启深度写入,但不输出颜色。第二个Pass进行正常的透明度混合。
|
||
2. 双面渲染的透明效果
|
||
|
||
## 剔除命令
|
||
Cull Back | Front | Off
|
||
|
||
## 内置时间变量
|
||
- _Time:场景加载开始到现在的时间,4个分量为:t/20,t,2t,3t
|
||
- _SinTime:时间的正弦值,4个分量为:t/8,t/4,t/2,t
|
||
- _CosTime:时间的余弦值,4个分量为:t/8,t/4,t/2,t
|
||
- untiy_DeltaTime:dt为时间的增量,4个分量为:dt,1/dt,SmoothDt,1/SmoothDt
|
||
|
||
## 预处理命令
|
||
|
||
### multi_compile
|
||
`multi_compile`定义的宏,如`#pragma multi_compile_fog`,`#pragma multi_compile_fwdbase`等,基本上适用于大部分shader,与shader自身所带的属性无关。
|
||
|
||
### shader_feature
|
||
`shader_feature`定义的宏多用于针对shader自身的属性。比如shader中有`_NormalMap`这个属性(Property),便可通`过#pragma shader_feature _NormalMap`来定义宏,用来实现这个shader在material有无`_NormalMap`时可进行不同的处理。
|
||
|
||
## 优化
|
||
减少Draw Call的方式有动态合批与静态合批。Unity中支持两种批处理方式:一种是动态批处理,一种是静态批处理。对于动态批处理来说,有点是一切处理都是Unity自动完成的,不需要我们自己做任何操作,而且物体是可以移动的,但缺点是,限制很多,可能一不小心就会破坏了这种机制,导致Unity无法动态批处理一些使用了相同材质的物体。
|
||
而对于静态批处理来说,它的优点是自由度很高,限制很少;但缺点是可能会占用更多的内存,而且经过静态批出里的所有物体都不可以再移动了。
|
||
动态批处理的原理是,每一帧把可以进行批处理的模型网格进行合并,再把合并后模型数据传递给GPU,然后使用同一个材质对其渲染。处理实现方便,动态批处理的另一个好处是,经过批处理的物体仍然可以移动,这是由于在处理每帧时Unity都会重新合并一次网格。
|
||
|
||
### 共享材质
|
||
将多张纹理合并到一起,并且制作成材质。
|
||
|
||
### 动态合批
|
||
在使用同一个材质的情况下,满足的条件后就会被动态处理,每帧都会合并一次。条件:
|
||
- 能够进行动态批处理的网格顶点属性规模要小于900.例如,如果Shader中需要使用顶点位置、法线和纹理坐标这3个顶点属性,那么想要让模型能够被动态批处理,它的顶点数目不能超过300。需要注意的是,这个数字未来有可能会发生变化,因此不要依赖这个数据。
|
||
- 一般来说,所有对象都需要使用同一个缩放尺度。一个例外的情况是,如果所有的物体都使用了不同的非统一缩放,那么它们也是可以被动态批处理的。但在Unity 5 中,这种对模型缩放的限制已经不存在了。
|
||
- 使用光照纹理的物体需要格外小心处理。这些物体需要额外的渲染参数,例如,在光照纹理上的索引、偏移量和缩放信息等。因此,为了让这些物体可以被动态批处理,我们需要保证它们指向光照纹理中的同一个位置。
|
||
- 多Pass的Shader会中断批处理。在前向渲染中,我们有时需要使用额外的Pass来为模型添加更多的光照效果,但这样一来模型就会被动态批处理了。
|
||
|
||
### 静态合批
|
||
在运行开始阶段,把需要进行静态批处理的模型合并到一个新的网格结构中。
|
||
|
||
## GeometryShader
|
||
>ShaderModel必须4.0以上`#program target 4.0`,如果低于这个目标,u3d会自定提升至该级别。
|
||
|
||
- maxvertexcount定义输出顶点数,如果只是处理三角形只需要设置为3即可。
|
||
- triangle为输入类型关键字。
|
||
- TriangleStream为输出流类型。
|
||
|
||
```
|
||
[maxvertexcount(3)]
|
||
void MyGeometryProgram (
|
||
triangle InterpolatorsVertex i[3],
|
||
inout TriangleStream<InterpolatorsGeometry> stream
|
||
)
|
||
```
|
||
|
||
### Flat线框效果(CatLikeCoding中的案例)
|
||
向三角形添加重心坐标的一种方法是使用网格的顶点颜色存储它们。每个三角形的第一个顶点变为红色,第二个顶点变为绿色,第三个顶点变为蓝色。但是,这将需要具有以此方式分配的顶点颜色的网格,并且无法共享顶点。我们想要一种适用于任何网格的解决方案。幸运的是,我们可以使用我们的几何程序添加所需的坐标。
|
||
|
||
由于网格不提供重心坐标,因此顶点程序不了解它们。所以,它们不属于InterpolatorsVertex结构。要使几何程序输出它们,我们必须定义一个新结构。首先在MyGeometryProgram上方定义InterpolatorsGeometry。它应包含与InterpolatorsVertex相同的数据,因此使用它作为其内容
|
||
```hlsl
|
||
struct InterpolatorsGeometry {
|
||
InterpolatorsVertex data;
|
||
CUSTOM_GEOMETRY_INTERPOLATORS
|
||
};
|
||
```
|
||
- MyGeometryProgram的作用为调整按照面法线调整顶点法线;在调整barycentricCoordinates值,最后塞入inout TriangleStream<InterpolatorsGeometry>中。
|
||
- GetAlbedoWithWireframe为线控效果控制,最终会在My Lighting.cginc中以宏替换的方式整合至渲染流程中。
|
||
```hlsl
|
||
float3 GetAlbedoWithWireframe (Interpolators i) {
|
||
float3 albedo = GetAlbedo(i);
|
||
float3 barys;
|
||
barys.xy = i.barycentricCoordinates;
|
||
barys.z = 1 - barys.x - barys.y;
|
||
float3 deltas = fwidth(barys);
|
||
float3 smoothing = deltas * _WireframeSmoothing;
|
||
float3 thickness = deltas * _WireframeThickness;
|
||
barys = smoothstep(thickness, thickness + smoothing, barys);
|
||
float minBary = min(barys.x, min(barys.y, barys.z));
|
||
return lerp(_WireframeColor, albedo, minBary);
|
||
}
|
||
```
|