Three.js镜面不反射所有网格

4

目标:

  • 在Three.js中模拟反射地板(像这样)。

思路:

  • 通过将不透明度设置为0.5使地板半透明。
  • 在其下方放置一个镜子,以反射其上方的网格。

期望输出:

  • 能够通过地板镜子看到房屋的倒影。

实际输出:

  • 不反射房屋的一部分网格。
  • 相反,只在某些角度上反射天空盒。

截图:

问题:

  • 为什么房子的其他网格没有通过镜子反射出来?
  • 为什么镜子在某些摄像机方向下不反射?

附带代码:

.......
.......
function getReflectiveFloorMesh(floorMesh) {

        var WIDTH = window.innerWidth;
        var HEIGHT = window.innerHeight;

        floorMirror = new THREE.Mirror( renderer, firstPerson.camera,
                    { clipBias: 0.003,
                    textureWidth: WIDTH,
                    textureHeight: HEIGHT,
                    color: 0x889999 } );

        var mirrorMesh = floorMesh.clone();

        mirrorMesh.position.y -= 10;            // Placing the mirror just below the actual translucent floor; Fixme: To be tuned
        mirrorMesh.material = floorMirror.material;

        mirrorMesh.material.side = THREE.BackSide;  // Fixme: Normals were flipped. How to decide on normals?
        mirrorMesh.material.needsUpdate = true;

        mirrorMesh.add(floorMirror);

        return mirrorMesh;

    }

    function getSkybox() {
        var urlPrefix = "/img/skybox/sunset/";
        var urls = [urlPrefix + "px.png", urlPrefix + "nx.png",
            urlPrefix + "py.png", urlPrefix + "ny.png",
            urlPrefix + "pz.png", urlPrefix + "nz.png"];
        var textureCube = THREE.ImageUtils.loadTextureCube(urls);

        // init the cube shadder
        var shader = THREE.ShaderLib["cube"];
        shader.uniforms["tCube"].value = textureCube;
        var material = new THREE.ShaderMaterial({
            fragmentShader: shader.fragmentShader,
            vertexShader: shader.vertexShader,
            uniforms: shader.uniforms,
            side: THREE.BackSide
        });

        // build the skybox Mesh
        var skyboxMesh = new THREE.Mesh(new THREE.CubeGeometry(10000, 10000, 10000, 1, 1, 1, null, true), material);

        return skyboxMesh;
    }

    function setupScene(model, floor) {
        scene.add(model); // Adding the house which contains translucent floor
        scene.add(getSkybox()); // Adding Skybox
        scene.add(getReflectiveFloorMesh(floor)); // Adds mirror just below floor

        scope.animate();
    }
....
....
this.animate = function () {

    // Render the mirrors
    if(floorMirror)
        floorMirror.render();

    renderer.render(scene, firstPerson.camera);
};

clipBias: 0.003,将其更改为更大的值? - Careen
mirrorMesh.rotation.x = -Math.PI / 2; // 或者 x,y - Careen
是的。修改clipBias确实会影响输出,不仅反映天空盒。 clipbias:3 screenshot。 它也模糊地反映其他网格。我想需要调整clipBias。但这仍然不能解释为什么镜子在某些角度下不显示反射。23 - prahadeesh
如果你有一个链接,我可以看一下,我会在线一段时间。 - Careen
你正在使用 http://threejs.org/examples/js/Mirror.js 吗? - Careen
显示剩余5条评论
2个回答

1
在进行任何变换之前,您必须将镜像附加到网格上。因此,代码如下:
floorMirror = new THREE.Mirror( ... );

var mirrorMesh = floorMesh.clone();

    mirrorMesh.add(floorMirror); // attach first!
    mirrorMesh.position.y -= 10; 
    ...

另一个问题在于,您正在从已经被(可能)转换的 floorMesh 克隆 mirrorMesh

在创建时,镜像对象具有与带有平面几何体默认变换矩阵的常规网格相同的默认变换矩阵(默认为“垂直”)。

当将镜像附加到地板(或任何水平网格)时,矩阵与网格不匹配,这就是为什么您无法看到反射,或者只能从某个角度看到的原因。

因此,在应用变换(平移或旋转)之前,始终将镜像附加到未转换的平面网格


此外,'mirror' 对象支持在材料中使用着色器,因此您可以编写自己的着色器,并将地板纹理与反射纹理混合,就像此示例中所示:http://slayvin.net/webgl/camaro/ 。那么您就不需要通过两个网格进行“作弊”。 - Slayvin

0
想法:
“通过将不透明度设为0.5使地板半透明。在下面放一个镜子以反射上面的网格。”
我建议另一种方法,将地板做成实体,在上面放置镜子并改变镜子的透明度。我认为你可能会遇到透明地板限制镜子投影的问题。
如果你把镜子从半透明地板下面移到空场景中,只附加了基本材质的立方体或球形几何体,它是否按预期反射?
您可能需要2个镜子,一个用于房间,假设您想要拋光地板,另一个用于外部的普通反射。

如果您将镜子从半透明的地板下移动到只有一个附加基本材质的立方体或球几何体的空场景中,它是否会像预期的那样反射?
  • 不会。如此处所示,反射输出随相机方向而变化。
这个特定的例子是一个简化版本,只包含一个镜子和一个放在上面的球体。
- prahadeesh

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