GPUInstance实现同材质不同属性的合批

gpuinstance修改属性(实现相同材质不同颜色等属性)

现代基于光栅化的批处理技术一般有动态批处理,静态批处理,gpuinstance,srpbatch等。

其中我要说的是gpuinstance,gpuinstance可以让同一个mesh,同一个material,来传递多个统一的数据结构到buff中。进行后面的着色等处理。

其中数据结构是我们所关心的,因为我们可能需要创建不同的位置,旋转或物体颜色,法线等信息。

gpuinstance使用比较简单,就是在shader中有#pragma multi_compile_instancing就好,那么在unity中就会在对应的材质下出现

通常来说只要同一mesh,同一material就能合并到一个drawcall。

修改gpuinstance下的材质的属性有两种方式

第一种是直接修改位置和旋转信息,这两块不会引起gpuinstance的切换。但是缩放会,如果缩放不一样的话会放到另一个drawcall里。这是因为缩放会改变顶点间的距离,所以mesh自然就不一样了。另外我们还要注意如果多个material,一定要排序好,让相同的material在同一个render queue。这样才能让相同的material在同一个队列下合并。不然会打乱合并顺序。

下面给出unity的排序的先后顺序

第二种是修改材质的颜色等内部属性。这块如果直接用material.setcolor等方式去做是不生效的,要不就新创建了一个material让他到了另一个drawcall,要不就是sharedmaterial让全部相同的material都修改了。

但我们的目的不是这个,我们的目的是每个不同的物体,能修改他们的颜色等信息但又能合并一个drawcall。

这时就要用到MaterialPropertyBlock,他是材质修改属性的工具,不会产生新的材质。

MaterialPropertyBlock props = new MaterialPropertyBlock();
props.SetColor(“_BaseColor”, new Color(0,0,0,1));
GameObject.Find(“Cube”).GetComponent().SetPropertyBlock(props);
但是如果我们直接这样修改,也不会生效,这时会出现一个错误

non-instanced properties set for instanced shader
这是因为instance不识别我们的属性,我们需要把他包入一个UNITY_INSTANCING_BUFFER_START中,然后用UNITY_DEFINE_INSTANCED_PROP来定义这个属性。当然我们还是需要在顶点和片元着色器中定义instance的idUNITY_SETUP_INSTANCE_ID(input);

这里有好几个宏,这些宏都可以再UnityInstancing.hlsl中找到定义。

下面给出解释:

#pragma multi_compile_instancing
“multi_compile_instancing”会使你的Shader生成两个Variant,其中一个定义了Shader关键字INSTANCING_ON,另外一个没有定义此关键字。 除了这个#pragma指令,下面所列其他的修改都是使用了在UnityInstancing.cginc里定义的宏(此cginc文件位于Unity_Install_Dir\Editor\Data\CGIncludes)。取决于关键字INSTANCING_ON是否被定义,这些宏将展开为不同的代码。

UNITY_INSTANCE_ID
用于在Vertex Shader输入 / 输出结构中定义一个语义为SV_InstanceID的元素。 UNITY_INSTANCING_CBUFFER_START(name) /

UNITY_INSTANCING_CBUFFER_END
每个Instance独有的属性必须定义在一个遵循特殊命名规则的Constant Buffer中。使用这对宏来定义这些Constant Buffer。“name”参数可以是任意字符串。

UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
定义一个具有特定类型和名字的每个Instance独有的Shader属性。这个宏实际会定义一个Uniform数组。

UNITY_SETUP_INSTANCE_ID(v)
这个宏必须在Vertex Shader的最开始调用,如果你需要在Fragment Shader里访问Instanced属性,则需要在Fragment Shader的开始也用一下。这个宏的目的在于让Instance ID在Shader函数里也能够被访问到。 UNITY_TRANSFER_INSTANCE_ID(v, o)
在Vertex Shader中把Instance ID从输入结构拷贝至输出结构中。只有当你需要在Fragment Shader中访问每个Instance独有的属性时才需要写这个宏。

UNITY_ACCESS_INSTANCED_PROP(_Color)
访问每个Instance独有的属性。这个宏会使用Instance ID作为索引到Uniform数组中去取当前Instance对应的数据。

如果要访问对应的属性就需要在定义属性的时候加类似下面的定义

UNITY_INSTANCING_BUFFER_START(STTest)

    UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)

UNITY_INSTANCING_BUFFER_END(STTest)

STTest是结构体名字,float4是属性类型,_BaseColor是具体的属性名。

然后在使用的地方

float4 newColor = UNITY_ACCESS_INSTANCED_PROP(STTest, _BaseColor);

这样定义后就直接用newColor 代替_BaseColor。这样就能让instance识别到具体的属性了,也就能合并批次了。

转载自VT LI 欢迎大家给原作者点赞

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值