Three.js 对象在大距离处“闪烁”

问题描述 投票:0回答:3

我目前正在开展一个项目,该项目涉及在对象大小范围为 10 - 1000000 的场景中工作。我一直遇到一个问题,当我处于这些尺寸的较大范围内时,对象开始“闪烁”只有当对象相交时才会发生这种情况,然后随着相机远离对象,它会变得越来越“暴力” .

我在这里上传了问题的图片:https://i.sstatic.net/wu1lz.jpg

虽然我不知道是什么原因造成的,但我有一些可能的想法:

首先,我只是在使用对于 Three.js / webgl 来说太大的尺寸

我认为可能存在问题的第二种可能性是使用我制作的相机控件,如下所示:

    if(mouseIsDown == true){
        if(this.movementSpeed < this.maxSpeed){
            this.movementSpeed += this.acceleration
        }else{
            this.movementSpeed = this.maxSpeed
        }

    }else{
        if(this.movementSpeed > this.minSpeed){
            this.movementSpeed = this.movementSpeed/this.deceleration
        }else{
            this.movementSpeed = this.minSpeed  
        }

    }

其中 this.minSpeed = 0,并且 this.movementSpeed 用于像这样移动相机:

var actualSpeed = delta * this.movementSpeed;
this.object.translateZ( -actualSpeed * forwardOrAuto );
this.object.translateX( actualSpeed * sideSpeed );
this.object.translateY( actualSpeed * upSpeed );

我不认为这会是问题,但由于移动速度实际上永远不会等于零,所以这可能是一个问题。即使移动速度为 10^-20 或 -30,闪烁仍然会发生。

我也在 r.55,如果这很重要的话。

javascript three.js webgl
3个回答
14
投票

听起来像是精度问题。移动可以放大舍入误差的影响。当在 Three.js 中处理太阳系模型(uom:米)时,我自己遇到了许多“闪烁”纹理/模型的问题。 gaitat 绝对正确,您遇到了 z 缓冲区深度精度问题。 我和我的伴侣有几种处理方法。

z 缓冲区不是线性的。 gaitat 提到的 sjbaker 网站将非常清楚地说明这一点,就像几个月前对我所做的那样。 大多数 z 缓冲区精度位于附近。 如果您的对象的大小高达 1000000 个单位,那么对象本身(更不用说它们之间的空间)已经超出了有效精度的范围。 许多视频游戏使用的一种解决方案是“不”移动玩家(摄像机),而是移动世界。 这样,当物体靠近相机时,其精度就会提高。 这对于远处的大型重叠对象(闪烁/遮挡)上的纹理,或者对于远离轴向原点的小网格来说最为重要,其中舍入问题变得严重到足以使网格跳出视野。 但这绝对是说起来容易做起来难,因为你要么必须进行“及时”计算来移动与玩家相关的所有内容(并且仍然会遇到舍入错误),要么想出一个更优雅的解决方案。 对于非常高的远数,您将损失很少的近精度,但是对于稍大的近数,您将在中间范围内获得相当大的精度。 即使您正在使用的网格可以小至 10 个单位,接近相机设置 10 或 100 也可能会给您带来一些余地。 相机设置并不是处理 z 缓冲区的唯一方法。

polygonOffset

- 您有效地告诉 z 缓冲区哪个东西(网格上的材质)属于顶部。 不过,它所解决的问题可能会带来很多问题,并且可能需要进行大量调整。认为它类似于 css 中的 z-index,但更变化无常。 增加一种材质的偏移量以确保它在远处的某些物体上渲染,可能会使其在近处的某些物体上渲染。它会像滚雪球一样越滚越大,迫使您在大多数对象上设置偏移量。对于 PolygonOffset,因子和单位数通常在 -1.0 和 1.0 之间,并且可能需要调整。

depthWrite=false

- 这意味着“不写入深度缓冲区”,对于应该“始终”渲染在所有内容“后面”的材质来说非常有用。 天空盒和背景就是很好的例子。 我们的项目使用了上述所有方法,但结果仍然平庸,尽管我们处理的数字高达 40 天文单位米(冥王星)。 “他们”称之为“z-fighting”,所以要打好仗!

既然你的范围这么大,那么你必须将相机的近平面设置为接近 0,远平面设置为接近 1000000。但是 z 分辨率不够。您可以在

http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html

5
投票

我不知道如何实现但可能可行的解决方案是使用两个场景和两个摄像机。


0
投票

困难在于将 TrackballControls 连接到两个摄像机以同步场景。

© www.soinside.com 2019 - 2024. All rights reserved.