六六の魔法世界

注册

技术分享 - 渲染技术贴 - 软件插件技术贴 - 2022年4月12日

Maya相机外物体排除工具

这个脚本可以根据指定的摄像机渲染视图来获得只被这个相机渲染到的物体。这通常可以用来减小渲染时文件的计算压力,但由于算法不同,所以它并不完美。比如如果有物体完全挡住相机渲染射线,只要它在相机的可渲染立方体内,都会被记录下来,而实际上被完全挡住的物体并不一定要被用来计算。

使用方法非常简单,只需要在脚本第10行的相机名内输入相机变换节点名称再全选代码小键盘回车就可以了,代码会自动将渲染立方体内的物体选中并在脚本反馈栏中打印出来。

将persp1替换成需要的相机名

这个脚本直接使用性不强,但其思路可用于修改您已有的脚本。如果您正好需要这个功能,可以自行修改成需要的结果。

它的思路是:

1.先求出相机渲染立方体的六个面的变换矩阵,每个面并不是刚好为渲染立方体的面的面积大小,而是无限大的,但这并不影响计算。

2.获取mesh物体的bbox(边界框),通过将相机的每个平面与离其最近的bbox顶点位置进行比较,在这个平面前面则判定在渲染范围内,不在前面则在渲染范围外。

这里在使用物体的bbox的顶点时,并非直接使用的bbox的六个顶点,而是根据用作比较的面的法线方向,拿到bbox每个轴向上离这个面的正方向最近的值来组成一个顶点。通过观察mesh物体的bbox数值可以知道,transform节点的bbox是基于世界空间(其实是基于父层级,稍后再说这个),而mesh节点的bbox是基于物体自己的对象空间的。transform的bbox会随着物体的旋转而旋转,使用上述取每个轴向上最接近的点的值所建立的bbox则是绝对对齐世界轴向的。这样的好处是避开了在情况时,bbox.max或者bbox.min的值的组成都不是同一个点上的,它们只会生成两个点,一个全在正轴向上,一个全在负轴向上,这对其它顶点在渲染立方体内部的情况时并不友好。

但这种方法也有一个弊端,即当物体的旋转使得物体的基于世界轴向的bbox的点在渲染立方体内,而模型本身不在范围内时,也会被判定为真。

对齐世界轴向的bbox
对齐世界轴向的bbox

从图中可以看出,物体的模型并没有进入渲染视图,而它对齐于世界轴向的bbox的最靠近渲染视图的左侧平面的点却是在视图内的。遂,这个物体会被判定为在渲染视图内。但一般这个需求是为了保证视窗内的物体必须在,所以这个bug一般可以忽视。

该代码在计算点是否在平面内时,使用了Maya.api的MDagPaht.inclusiveMatrixInverse与MFnCamera.projectionMatrix和MFnCamera.postProjectionMatrix相乘来获取了相机渲染立方体的矩阵,关于MFnCamera的投影矩阵这块我也没看清楚,它似乎涉及到openGL之类的技术,希望有大佬能教教我。使用该矩阵的不同位置信息相加减与组合得到了六个平面的变换矩阵。再从每个平面的矩阵中提取出它的法线和平面到原点的距离,将用于比较的点的坐标*平面法线+平面到原点的距离得出的值即为该点是否在该平面的前方还是后方。其值的正负表示点的位置基于平面的前后,点的数值表示点基于平面的距离。(这里我同样没有太理解,我猜测是计算出的平面矩阵是基于相机的对象空间,其法线表示平面正方向,其距离表示朝这个方向离相机移动的距离,而非平面到原点的距离。如果有大佬明白麻烦教教我)

这里在比较bbox上各个点与相机平面矩阵位置时,作者非常巧妙的另写了一个类,让每个平面各自生成一个实例对象,再将这些点分别带入这个对象的类方法,既节省了代码,也明确了思路。在判断基于世界轴向的bbox上与平面最接近的点时,作者也非常巧妙的通过查询平面法线在每个轴向上的正负来确定该从物体的transform的bbox信息中提取每个轴向上的哪个值。可以说,非常的聪明。

另外我发现,物体的transformBbox信息是基于父节点,在场景建模完成后物体一般会分类打组等操作,如果父对象被冻结枢轴或者父对象在原点没有其它操作,则物体bbox信息还是与基于世界时相同。否则,bbox信息将会变得不准确,这将导致代码计算结果错误。所以在使用该工具时,请先将场景内所有模型对象放到世界层级下。

如果您为非专业渲染师需要注意,在测试该工具时在打开分辨率门时,需使用分辨率门(resolution gate)而非它左边的film gate。film gate会比分辨率门的范围在上下方向上多出一截,但这一截是错误的,并非渲染范围,该代码也不会检测这一段范围。(鄙人对渲染也一无所知,两者的差异也不太了解,注意这个问题就好)


如果您有需要,可以看下作者源代码,他的解释应该要比我的好很多。原文中的代码没有直接组装在一起,我制作了完整代码并可以检索整个场景中的物体来得到对方是否应该被渲染。由于算法的不完美,导致其得到了渲染立方体外的物体和不能排除被遮挡的物体,我一开始是想的用射线的方法来实现,从相机位置为原点,向每个相机渲染像素点方向发射射线,当射线击中物体,则对象在渲染立方体中。这个方法可以完美避开本代码带来的弊端,但由于鄙人的才疏学浅,无法实现这个算法,遂,如果有大佬会的,求求您教教我。

    相关文件下载地址
    该资源需登录后下载,去登录?
    ©下载资源版权归作者所有;本站所有资源均来源于网络,仅供学习使用,请支持正版!