6

[实用技巧]Unity利用Instancing存储UV坐标, 实现一个半透图集不同UV同一批次渲染

 3 years ago
source link: https://zhuanlan.zhihu.com/p/64586812
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[实用技巧]Unity利用Instancing存储UV坐标, 实现一个半透图集不同UV同一批次渲染

因为公司的项目是SLG, 有一个需求就是在3D世界里存在大量2D角色

加上以前项目是2D的, 半透明图渲染效率极其低下, 还会影响不透明图的合批

所以这个5.1就试着做一下优化

总体思路也很简单,

然后利用图集 和 instancing 缓存的UV信息

使看上去不同的半透明图,合并为一个批次

目前已经解决的问题是:

对于静态UI可以实现一个批次绘制完毕,

对于2D游戏前后层 能若干个批次也能绘制完毕

对于最复杂的情况还没有解决 3D场景下 大量不同2D角色, 感觉还差一步 这个我们最后再说后续方向

先讲原理和代码

Instancing其实本质是把一个信息队列存储在一个CBUFFER里,

比如要存一个fixed4类型的变量 Unity里是这么写的:

UNITY_INSTANCING_BUFFER_START(TESTUVInstance)
	UNITY_DEFINE_INSTANCED_PROP(fixed4, _UV)
		#define _ST_arr TESTSHADER
UNITY_INSTANCING_BUFFER_END(TESTUVInstance)

这玩意如果被搞的太大, 显存就爆了

UNITY_VERTEX_INPUT_INSTANCE_ID就是数组下标

通过这个下标取出对应的变量, 执行着色, 变化的部分如果都被缓存, 自然可以一个批次绘制大量物体,

那这个fixed4类型正好可以存UV的4个参数

顶点阶段我们可以这么做:

o.uv = v.uv * UNITY_ACCESS_INSTANCED_PROP(_UV_arr, _UV).xy + UNITY_ACCESS_INSTANCED_PROP(_UV_arr, _UV).zw;

这样缓存了uv之后, 在执行时用PropertyBlock传入对应UV 就实现了一个批次绘制图集上不同目标的需求

具体效果:

图上可以看到16个批次, 渲染了1327个角色

但是每个角色的样子都不一样,

如果只是做到这一步,其实已经有一定的实用价值了,

2D卷轴游戏,或者 UI上可以用啦

One More Thing

不过真正有趣的问题是另一种情况, 例如:

上面这张图显示的是4种不同的图集对应4个角色, 加上树的遮挡后,渲染性能急速下降

甚至还不如不合批

我认为是Instance绘制太细碎,反而让性能极其差

具体渲染队列:

可以看到instanced和普通绘制穿插,这个状态切换产生的损耗应该碾压了比起少量合批带来的性能提升

几种情况下CPU和GPU耗时对比:

实际上4个图集混合的时候, 因为深度,穿透等等问题,绘制被大量打断

如果你不是那么在意遮挡问题, 使用rendererPriority

让4个不同图集按一定顺序渲染也是可以的,可以达到1个图集的效果

虽然5.1想用SRP优化合批的问题,但是SRP刚接触还不熟悉,实在是没搞定啊

也许自定义一个pass, 利用不那么严谨的遮挡模型, 可以更好的合批

或者stencil? 或者利用深度+渲染顺序? 总之未来看有没有机会把这个坑填上


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK