Unity相机剪裁问题

5

我遇到了一个与相机有关的问题,它正在剪裁我的一个3D模型(参见下面的图片)。

enter image description here enter image description here

我的相机近裁剪面已经调到最低值,并且所有的着色器都采用了不透明的渲染模式。

这种情况只出现在我使用Fuse CC生成的3D模型上。我用Blender做的那个没有裁剪!有什么想法吗?谢谢!


2
问题是那个人的腿消失了吗?这不是近平面或远平面裁剪。这是截锥体剔除:渲染器认为该对象在相机可视区域之外,因此将其剔除。 - Draco18s no longer trusts SE
谢谢@Draco18s,我找到了一种方法来禁用那个游戏对象上的视锥体剔除,并且它起作用了。 - drn
1
很高兴能帮忙。有时,“我看到的这个东西叫什么?”是一个难以回答的问题。我曾经有一个问题涉及协变和逆变,这些术语在有人回答问题之前我从未听说过(后来他删除了回答,因为Unity使用的.NET版本没有这些功能)。 - Draco18s no longer trusts SE
2个回答

5
实际问题似乎在于您的模型边界不正确。剪裁平截头体可以通过将边界与摄像机平截头体进行比较来跳过视线外的模型渲染,这对于获得良好的渲染性能非常重要。因此,如果只是为了解决类似边界不正确的简单问题而禁用它并不是最好的选择。
如果在场景中选择网格渲染器,则应该看到一个线框立方体围绕其周围。该立方体可视化了网格的边界。您应该看到它们在Blender模型上适合得很好,在Fuse CC模型上则明显偏差。
一旦您确认Fuse CC模型的边界有误,就可以尝试手动或通过更改导入设置来修复它们。
可能导致边界错误的原因包括:
- 您正在导入没有动画的模型。如果Unity不知道如何动画模型,则很可能会将边界设得太紧。 - 您正在使用扭曲模型以使其超出边界的顶点着色器。 - 您正在通过IK、布娃娃或类似方式在运行时编程移动骨骼。
所有这些都可以通过在编辑器中调整网格的边界来修复,以使其留出足够的空间以容纳运行时动画/修改。
当满足以下所有条件时,边界被正确选择:
- 网格从未超出边界(如线框立方体所示)。 - 边界尽可能紧密而不违反第一条规则。

1
感谢Thomas提供如此详细的解释。我的模型确实没有导入动画,而且我的边界框非常小。我将其放大后问题得到了解决!这是比我所建议的(禁用视锥体剔除脚本)更加干净和合适的解决方案。 - drn

1
感谢Draco18s带我了解截锥体剔除。我找到了这篇文章,它演示了如何在特定游戏对象上停用截锥体剔除,我的问题已经解决!脚本有点过时,这里是更新后的版本。
// Update is called once per frame
void Update () {
    // boundsTarget is the center of the camera's frustum, in world coordinates:
    Vector3 camPosition = Camera.main.transform.position;
    Vector3 normCamForward = Vector3.Normalize(Camera.main.transform.forward);
    float boundsDistance = (Camera.main.farClipPlane - Camera.main.nearClipPlane) / 2 + Camera.main.nearClipPlane;
    Vector3 boundsTarget = camPosition + (normCamForward * boundsDistance);

    // The game object's transform will be applied to the mesh's bounds for frustum culling checking.
    // We need to "undo" this transform by making the boundsTarget relative to the game object's transform:
    Vector3 realtiveBoundsTarget = this.transform.InverseTransformPoint(boundsTarget);

    // Set the bounds of the mesh to be a 1x1x1 cube (actually doesn't matter what the size is)
    SkinnedMeshRenderer mesh = this.GetComponent<SkinnedMeshRenderer>();
    mesh.localBounds = new Bounds(realtiveBoundsTarget, Vector3.one);
}

将此脚本放置在导致问题的游戏对象上。
注意:将SkinnedMeshRenderer替换为您的游戏对象所具有的网格渲染器类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接