当前位置:   article > 正文

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

getoddnegativescale

首先解释一下什么是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的模型一同动态合批。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/127784
推荐阅读
相关标签
  

闽ICP备14008679号