You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

three.js中在onBeforeRender调用CubeCamera.update引发栈溢出的问题求助

Three.js镜面着色器中CubeCamera捕获镜面反射的栈溢出问题

我正在Three.js中制作镜面着色器,相关代码如下:

mirror.onBeforeRender = function (renderer, scene, camera) {
    //获取镜面相机渲染纹理并传递给对象。
}

function animate() {
    requestAnimationFrame(animate);
    cubeCamera.update(renderer,scene);
}

animate();

mirror是一个3D对象,会在onBeforeRender函数中通过相机捕获场景;同时我有另一个依赖cubeCamera(立方相机)捕获环境纹理的对象。

我发现cubeCamera无法捕获镜面的反射结果,显示为全黑。于是尝试将cubeCamera.update(renderer,scene)放入onBeforeRender中,却引发了RangeError: Maximum call stack size exceeded(栈溢出错误),报错信息如下:

Uncaught RangeError: Maximum call stack size exceeded
    at PerspectiveCamera.updateMatrixWorld (three.module.js:11689:1)
    at CubeCamera.updateMatrixWorld (three.module.js:8068:1)
    at CubeCamera.update (three.module.js:11995:1)
    at groundMirror.onBeforeRender (App.js:581:1)
    at renderObject (three.module.js:28253:1)
    at renderObjects (three.module.js:28243:1)
    at renderScene (three.module.js:28165:1)
    at WebGLRenderer.render (three.module.js:27983:1)
    at CubeCamera.update (three.module.js:12014:1)
    at groundMirror.onBeforeRender (App.js:581:1)

请问是否有函数或参数可以在mirror.onBeforeRender之后更新cubeCamera?

已尝试的方法

  • 将cubeCamera.update放入mirror.onBeforeRender,引发栈溢出;
  • 设置cubeCamera的renderOrder为2,但无效。

2023/2/20 更新

感谢Phil的评论,我意识到可能误解了onBeforeRender的用法!以下是我的onBeforeRender代码,基于Three.js的Water示例实现,我在末尾添加了一行更新cubeCamera的代码,这引发了栈溢出;如果移除该行,代码可正常运行。

groundMirror.onBeforeRender = function (renderer, scene, camera) {
        mirrorWorldPosition.setFromMatrixPosition(groundMirror.matrixWorld);
        cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);
        rotationMatrix.extractRotation(groundMirror.matrixWorld);

        normal.set(0, 0, 1);
        normal.applyMatrix4(rotationMatrix);
        view.subVectors(mirrorWorldPosition, cameraWorldPosition);
        // Avoid rendering when mirror is facing away
        if (view.dot(normal) > 0) return;
        view.reflect(normal).negate();
        view.add(mirrorWorldPosition);

        rotationMatrix.extractRotation(camera.matrixWorld);

        lookAtPosition.set(0, 0, - 1);
        lookAtPosition.applyMatrix4(rotationMatrix);
        lookAtPosition.add(cameraWorldPosition);

        target.subVectors(mirrorWorldPosition, lookAtPosition);
        target.reflect(normal).negate();
        target.add(mirrorWorldPosition);

        mirrorCamera.position.copy(view);
        mirrorCamera.up.set(0, 1, 0);
        mirrorCamera.up.applyMatrix4(rotationMatrix);
        mirrorCamera.up.reflect(normal);
        mirrorCamera.lookAt(target);

        mirrorCamera.far = camera.far; // Used in WebGLBackground

        mirrorCamera.updateMatrixWorld();
        mirrorCamera.projectionMatrix.copy(camera.projectionMatrix);
        // Update the texture matrix
        textureMatrix.set(
          0.5, 0.0, 0.0, 0.5,
          0.0, 0.5, 0.0, 0.5,
          0.0, 0.0, 0.5, 0.5,
          0.0, 0.0, 0.0, 1.0
        );
        textureMatrix.multiply(mirrorCamera.projectionMatrix)
        textureMatrix.multiply(mirrorCamera.matrixWorldInverse);
        mirrorPlane.setFromNormalAndCoplanarPoint(normal, mirrorWorldPosition);
        mirrorPlane.applyMatrix4(mirrorCamera.matrixWorldInverse);

        clipPlane.set(mirrorPlane.normal.x, mirrorPlane.normal.y, mirrorPlane.normal.z, mirrorPlane.constant);

        var projectionMatrix = mirrorCamera.projectionMatrix;

        q.x = (Math.sign(clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
        q.y = (Math.sign(clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
        q.z = - 1.0;
        q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];

        // Calculate the scaled plane vector
        clipPlane.multiplyScalar(2.0 / clipPlane.dot(q));

        // Replacing the third row of the projection matrix
        projectionMatrix.elements[2] = clipPlane.x;
        projectionMatrix.elements[6] = clipPlane.y;
        projectionMatrix.elements[10] = clipPlane.z + 1.0 - clipBias;
        projectionMatrix.elements[14] = clipPlane.w;

        eye.setFromMatrixPosition(camera.matrixWorld);

        // Render

        if (renderer.outputEncoding !== THREE.LinearEncoding) {

          console.warn('THREE.Water: WebGLRenderer must use LinearEncoding as outputEncoding.');
          groundMirror.onBeforeRender = function () { };

          return;

        }

        if (renderer.toneMapping !== THREE.NoToneMapping) {

          console.warn('THREE.Water: WebGLRenderer must use NoToneMapping as toneMapping.');
          groundMirror.onBeforeRender = function () { };

          return;

        }

        var currentRenderTarget = renderer.getRenderTarget();
        var currentXrEnabled = renderer.xr.enabled;
        var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;

        groundMirror.visible = false;

        renderer.xr.enabled = false; // Avoid camera modification and recursion
        renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows

        renderer.setRenderTarget(renderTarget);

        renderer.state.buffers.depth.setMask(true); // make sure the depth buffer is writable so it can be properly cleared, see #18897

        if (renderer.autoClear === false) renderer.clear();
        renderer.render(scene, mirrorCamera);

        // new BlurredEnvMapGenerator( renderer ).generate( img , 0 )

        groundMirror.visible = true;

        renderer.xr.enabled = currentXrEnabled;
        renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;

        renderer.setRenderTarget(currentRenderTarget);

        // Restore viewport

        var viewport = camera.viewport;

        if (viewport !== undefined) {

          renderer.state.viewport(viewport);

        }
        
        // update cubeCamera.update() here and cause stackOverflow.

      };

希望以上信息能让问题更清晰!


内容的提问来源于stack exchange,提问作者Effie Liang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 03:54:24