gpt4 book ai didi

three.js - 从鼠标位置和深度图计算 3D 点

转载 作者:行者123 更新时间:2023-12-05 00:51:30 27 4
gpt4 key购买 nike

我需要使用渲染的深度图从屏幕空间位置计算 3D 坐标。不幸的是,使用常规光线追踪对我来说不是一个选择,因为我正在处理一个包含 5M 面数量级的几何图形。

所以我想我会做以下事情:

  • 使用 RGBADepthPacking 将深度图渲染到 renderTarget
  • 使用常规的 unproject-call 从鼠标位置计算光线(正如我在使用光线转换时所做的那样)
  • 在鼠标坐标处从深度图中查找深度,并使用该距离计算沿射线的一个点。

  • This kind of works ,但不知何故,定位点总是稍微落后于物体,所以我的深度计算可能有问题。

    现在有关上述步骤的一些详细信息

    渲染深度图非常简单:
    const depthTarget = new THREE.WebGLRenderTarget(w, h);
    const depthMaterial = new THREE.MeshDepthMaterial({
    depthPacking: THREE.RGBADepthPacking
    });

    // in renderloop
    renderer.setClearColor(0xffffff, 1);
    renderer.clear();
    scene.overrideMaterial = depthMaterial;
    renderer.render(scene, camera, depthTarget);

    在鼠标位置查找存储的颜色值:
    renderer.readRenderTargetPixels(
    depthTarget, x, h - y, 1, 1, rgbaBuffer
    );

    并使用(改编自packing.glsl中的GLSL版本)转换回 float :
    const v4 = new THREE.Vector4()
    const unpackDownscale = 255 / 256;
    const unpackFactors = new THREE.Vector4(
    unpackDownscale / (256 * 256 * 256),
    unpackDownscale / (256 * 256),
    unpackDownscale / 256,
    unpackDownscale
    );

    function unpackRGBAToDepth(rgbaBuffer) {
    return v4.fromArray(rgbaBuffer)
    .multiplyScalar(1 / 255)
    .dot(unpackFactors);
    }

    最后计算深度值(我在 examples/js/shaders/SSAOShader.js 中的 readDepth() 中找到了相应的代码,我移植到了 JS):
    function computeDepth() {
    const cameraFarPlusNear = cameraFar + cameraNear;
    const cameraFarMinusNear = cameraFar - cameraNear;
    const cameraCoef = 2.0 * cameraNear;

    let z = unpackRGBAToDepth(rgbaBuffer);
    return cameraCoef / (cameraFarPlusNear - z * cameraFarMinusNear);
    }

    现在,由于此函数返回 0..1 范围内的值,我认为它是裁剪空间坐标中的深度,因此我使用以下方法将它们转换为“真实”单位:
    const depth = camera.near + depth * (camera.far - camera.near);

    这些计算显然有些偏差,我还没有弄清楚有关如何存储深度的数学和细节。
    有人可以指出我犯的错误吗?

    另外:我尝试过的其他事情

    首先,我认为应该可以在我的 unproject-call 中使用解包的深度值作为 z 的值,如下所示:
    const x = mouseX/w * 2 - 1;
    const y = -mouseY/h * 2 + 1;
    const v = new THREE.Vector3(x, y, depth).unproject(camera);

    然而,这也没有得到正确的坐标。

    [编辑 1 2017-05-23 11:00CEST]

    根据@WestLangleys 的评论,我找到了 perspectiveDepthToViewZ()听起来应该有帮助的功能。用JS写的那个函数是
    function perspectiveDepthToViewZ(invClipZ, near, far) {
    return (near * far) / ((far - near) * invClipZ - far);
    }

    但是,当使用深度图中的解包值调用时,结果会相差几个数量级。 See here .

    最佳答案

    好的,所以。终于解决了。因此,对于遇到类似问题的每个人,这里是解决方案:

    computeDepth 函数的最后一行是错误的。有一个功能perspectiveDepthToViewZpacking.glsl ,这很容易转换为 JS:

    function perspectiveDepthToViewZ(invClipZ, near, far) {
    return (near * far) / ((far - near) * invClipZ - far);
    }

    (我相信这是逆投影矩阵的一部分)
    function computeDepth() {
    let z = unpackRGBAToDepth(rgbaBuffer);
    return perspectiveDepthToViewZ(z, camera.near, camera.far);
    }

    现在这将返回该点在 View 空间中的 z 轴值。剩下要做的是将其转换回世界空间坐标:
    const setPositionFromViewZ = (function() {
    const viewSpaceCoord = new THREE.Vector3();
    const projInv = new THREE.Matrix4();

    return function(position, viewZ) {
    projInv.getInverse(camera.projectionMatrix);
    position
    .set(
    mousePosition.x / windowWidth * 2 - 1,
    -(mousePosition.y / windowHeight) * 2 + 1,
    0.5
    )
    .applyMatrix4(projInv);

    position.multiplyScalar(viewZ / position.z);
    position.applyMatrix4(camera.matrixWorld);
    };
    }) ();

    关于three.js - 从鼠标位置和深度图计算 3D 点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44121266/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com