【基础】为何odd negative scaling会导致Unity动态合批失败?

首先解释一下什么是odd negative scaling,假设一个物体transform的scale为 ( a , b , c ) (a, b, c) (a,b,c),如果 a ∗ b ∗ c < 0 a*b*c<0 abc<0那么该物体就具有odd negative scaling,即奇数个负缩放轴。例如 ( − 1 , 1 , 1 ) (-1,1,1) (1,1,1) ( − 1 , − 1 , − 1 ) (-1,-1,-1) (1,1,1)都是odd negative scaling, ( − 1 , − 1 , 1 ) (-1,-1,1) (1,1,1)则不是。

根据Unity文档的说明,具有odd negative scaling的物体是不可以被动态合批的。更准确地说,多个具有odd negative scaling的物体是可以被合批的,但是具有odd negative scaling的物体和不具有odd negative scaling的物体之间是无法合批的。

为什么一个简单的缩放就能够导致合批失败呢?首先无法动态合批的原因通常都是发生了render states的改变。因为动态合批是需要把多个物体合并到1个Draw Call中去的,所以被动态合批的物体必须具有相同的render states。

也就是说,渲染具有odd negative scaling的物体和渲染不具有odd negative scaling的物体,必然有render states的不同,这个不同的点在OpenGL中叫做glFrontFace,在DirectX中叫做D3DRS_CULLMODE,它的两种选择CW和CCW,分别表示顺时针和逆时针,决定了如何通过三角面顶点的环绕顺序(winding order)得到三角面的法线。
在这里插入图片描述

假设在Unity中,如上图左侧,有一个 s c a l e ( 1 , 1 , 1 ) scale(1,1,1) scale(1,1,1)的三角形,其顶点环绕顺序为 0 → 1 → 2 0→1→2 012。左手四指顺着顶点环绕方向,大拇指则指向面法线的方向,垂直屏幕向外。

接下来我们将这个三角形缩放为 s c a l e ( − 1 , 1 , 1 ) scale(-1,1,1) scale(1,1,1),如上图右侧。此时如果用同样的方式去计算法线,右侧三角形的法线应该是垂直屏幕向内,朝向我们的变成了三角形的背面。

但实际上只要打开Unity试一试就知道,如果我们把一个三角形这样子缩放,原本朝向我们的正面仍然是正面,并没有发生改变。这是因为Unity在渲染左侧三角形时,采用了CW的方式计算法线,而在渲染具有odd negative scaling的右侧三角形时,采用了CCW的方式判断面法线,其结果是和CW相反的。换句话说,对于具有odd negative scaling的物体,Unity通过CCW的模式翻转了面法线。

那么Unity为什么要这样做呢?我的理解是因为这种方式让scale操作更加符合操作者的直觉。不仅Unity这样做,在建模软件中也有类似的做法。如上图的三角形,我们横向/竖向地拉伸scale至负值,面法线永远保持垂直屏幕向外;如果我们在垂直屏幕的方向上给它一个负的scale,它的法线就会翻转。这些结果非常符合直觉,而且方便使用。

要验证这一点也很容易,在场景中摆放一个具有odd negative scaling的物体和一个不具有odd negative scaling的物体,用RenderDoc抓帧,在Rasterizer栏下的FrontCCW项就是我们所说的状态。可以看到在绘制这两个物体时该状态是不同的。

总结一下,odd negative scaling会导致glFrontFace/D3DRS_CULLMODE状态的改变,因此不能与不具有odd negative scaling的模型一同动态合批。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值