Draw Call
对 Catlike Coding 教程的解析与补充
点击传送——>CustomRenderPipeline
1.防止重复声明
1 2 3 4 5 6
| #ifndef CUSTOM_UNLIT_PASS_INCLUDE #define CUSTOM_UNLIT_PASS_INCLUDE
...
#endif
|
#include引入HLSL时会将所有内容插入,且允许多次或循环引用,这会导致编译错误,可以通过这种方式对着色器代码进行保护。在定义宏之前先判断时候定义过该标示符,如果定义过,直接调到#endif段后。这样就可以保证只有第一次#include时有效
2.SRP Batcher
- SRP批处理
目的是减少Set Pass Call,他将模型的坐标信息、材质信息、光源阴影等参数保存到不同的常量缓冲区(CBUFFER),只有CBUFFER发生变化时才会重新提交到GPU并保存
1 2 3 4 5 6 7 8 9 10
| CBUFFER_START(UnityPerMaterial) float4 _BaseColor CBUFFER_END
CBUFFER_START(UnityPerDraw) float4x4 unity_ObjectToWorld float4x4 unity_WorldToObject float4 unity_LODFade real4 unity_WorldTransformParams CBUFFER_END
|
- UnityPerMaterial:所有材质相关的数据都应该在名为 UnityPerMaterial 的 CBUFFER 中声明,通常是指在着色器属性块声明的变量
- UnityPerDraw:该 CBUFFER 应当包含所有 Unity 的内置引擎变量
- 开启SRP合批
1 2 3 4
| public CustomRenderPipeline() { GraphicsSettings.useScriptableRenderPipelineBatching = true; }
|
一般写在构造函数中
Tips: real4只是个别名,具体可能是float4或half4,这取决于目标平台
3.同材质设置不同颜色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| [DisallowMultipleComponent] public class PerObjectMaterialProperties : MonoBehaviour { static int baseColorId = Shader.PropertyToID("_BaseColor");
[SerializeField] Color baseColor = Color.white; static MaterialPropertyBlock block;
private void OnValidate() { if(block == null) { block = new MaterialPropertyBlock(); }
block.SetColor(baseColorId, baseColor); GetComponent<Renderer>().SetPropertyBlock(block); } private void Awake() { OnValidate(); } }
|
- DisallowMultipleComponent防止脚本被多次添加
- Shader.PropertyToID 获取着色器属性名称的唯一标示符(Unity为着色器的每个属性都分配唯一整数)
- MaterialPropertyBlock 绘制相同材质但属性不同的对象可以用该类 Renderer组件下有SetPropertyBlock方法来设置block
- OnValidate 在以下两种情况下被调用:
4.GPU Instancing
- GPU多例化
能够在一个绘制调用中渲染多个具有相同网格的物体,CPU收集每个物体的材质属性和变换放入数组发送到GPU,GPU拿到数组后顺序遍历渲染
- 开启
1
| #pragma multi_compile_instancing
|
添加指令后材质面板就可以看到开关
3. 应用
绘制许多网格小球(无需生成多个对象,只填充变换)
1 2 3 4 5 6 7
| Matrix4x4[] matrices = new Matrix4x4[1023];
for(int i = 0; i < matrices.Length; i++) { matrices[i] = Matrix4x4.TRS(Random.insideUnitSphere * 10f, Quaternion.Euler(Random.value * 360f, Random.value * 360f, Random.value * 360f), Vector3.one * Random.Range(0.5f, 1.5f)); baseColors[i] = new Vector4(Random.value, Random.value, Random.value); }
|
- Matrix4x4.TRS(Vector3 translation, Quaternion rotation, Vector3 scaling)创建平移、旋转、缩放矩阵
1 2 3 4 5 6 7 8 9
| private void Update() { if (block == null) { block = new MaterialPropertyBlock(); block.SetVectorArray(baseColorId, baseColors); } Graphics.DrawMeshInstanced(mesh, 0, material, matrices, 1023, block); }
|
- SetVectorArray 设置向量数组属性
- Graphics.DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count= matrices.Length, MaterialPropertyBlock properties = null) submeshIndex适用于若干材质构成的网格,选择要绘制网格的哪个子集。
5.混合模式
- Src 当前需要渲染的像素(上层图像)
- Dst 已在栈中的像素(已有图像)
1 2 3 4 5 6
| [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1 [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 0
Blend[_SrcBlend][_DstBlend]
|
常用混合模式:
- BlendOp Min Blend One One(变暗)
- BlendOp Max Blend One One(变亮)
- Blend SrcAlpha OneMinusSrcAlpha(正常/透明度混合)
- Blend OneMinusDstAlpha One(滤色/柔和相加)
- Blend One OneMinusSrcAlpha(同上)
- Blend DstColor Zero(相乘/正片叠加)
- Blend DstColor SrcColor(两倍相乘)
- Blend One One(线性减淡)
(下接 自底向上的SRP教程 III)