切换到Three.js中的对数深度缓冲区后,我遇到了一个问题。除了附近的剔除地面外,一切都运行良好,如下图所示:
如您所见,相机显着高于地面。显示的字符框大约离地面2个单位,我的相机设置如下:
var WIDTH = window.innerWidth
, HEIGHT = window.innerHeight;
var VIEW_ANGLE = 70
, ASPECT = WIDTH / HEIGHT
, NEAR = 1e-6
, FAR = 9000;
var aspect = WIDTH / HEIGHT;
var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.rotation.order = 'YXZ';
所以我的NEAR
参数远不及2,即相机与地面之间的距离。您可以在第二张图片中看到我甚至使用我的PointerLockControls向上移动相机并仍然遇到问题。
任何人都可以诊断我的问题吗?
我还通过查看静态相机是否发生此错误来测试我的问题。确实如此。
此外,此问题仅发生在对数深度缓冲区中,因为默认深度缓冲区不会发生此问题。
我的相机是controls
对象的孩子,其定义如下:
controls = new THREE.PointerLockControls(camera);
controls.getObject().position.set(strtx, 50, strtz);
scene.add(controls.getObject());
camera.position.z += 2;
camera.position.y += .1;
这是PointerLockControls的相关代码:
var pitchObject, yawObject;
var v = new THREE.Vector3(0, 0, -1);
THREE.PointerLockControls = function(camera){
var scope = this;
camera.rotation.set(0, 0, 0);
pitchObject = new THREE.Object3D();
pitchObject.rotation.x -= 0.3;
pitchObject.add(camera);
yawObject = new THREE.Object3D();
yawObject.position.y = 10;
yawObject.add(pitchObject);
var PI_2 = Math.PI / 2;
var onMouseMove = function(event){
if (scope.enabled === false) return;
var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
yawObject.rotation.y -= movementX * 0.002;
pitchObject.rotation.x -= movementY * 0.002;
pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) );
};
this.dispose = function() {
document.removeEventListener( 'mousemove', onMouseMove, false );
};
document.addEventListener( 'mousemove', onMouseMove, false );
this.enabled = false;
this.getObject = function () {
return yawObject;
};
this.getDirection = function() {
// assumes the camera itself is not rotated
var rotation = new THREE.Euler(0, 0, 0, "YXZ");
var direction = new THREE.Vector3(0, 0, -1);
return function() {
rotation.set(pitchObject.rotation.x, yawObject.rotation.y, 0);
v.copy(direction).applyEuler(rotation);
return v;
};
}();
};
你还会注意到它只是被剔除的地面,而不是其他物品
编辑:
我掀起了一个显示更大问题的孤立环境。在第一张图片中,我有一个平面PlaneBufferGeometry
,其宽度和高度分别为400个,由var g = new THREE.PlaneBufferGeometry(380, 380, 400, 400);
定义。即使非常接近表面,也不会出现削波:
但是,如果我只提供1个段var g = new THREE.PlaneBufferGeometry(380, 380, 1, 1);
,则存在剪辑
我不确定这是否适用于Three.js / WebGL,但似乎我需要做一些事情来解决它。
答案 0 :(得分:0)
我不认为这是一个错误,我认为这是不同设置中深度缓冲区的工作原理。 Look at this example。在右边,深度缓冲无法在“微观”和球体中的字母之间作出决定。这是因为它在非常小的尺度上具有较低的精度,并且开始在一个物体和另一个物体之间进行振荡,并且有利于z深度的绘制顺序。
这总是一个权衡。如果你想放弃这个问题,你可以尝试整体提高场景的比例,这样相机的“近处”永远不会那么接近它可以绕过它的东西 - 所以只需要工作在一个范围内,不会在对数z缓冲区的指数模型中舍入。
另外一个问题 - 蓝色是如何定义的,因为你所看到的可能不是因为太近而不是剪裁,而是蓝色或地面之间的混淆。如果它只是一个包含所有东西的蓝色盒子,你可以尝试让它更大,更远离地面。
修改强>: 好的,这看起来应该可行。所以我会开始寻找边缘情况。您可以做些什么来改变场景以使其发挥作用?你可以做些什么让其他事情开始破碎?
基本上我没有看到一个明显的错误,所以我猜它很难被发现,或者它的工作正是应该的。找出你可以做些什么来改善效果/使情况变得更糟,这将澄清一个方向。
调试的一个好的经验法则是尝试将事情发挥到极致,而不是试图修复它,或者保持代码真正达到其目的,并且只看它以何种方式进一步突破/改变。当你发现某事时报告回来。