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
相关产品推荐
相关产品推荐

