Three.js使用CubeCamera渲染反射报错Framebuffer与active Texture形成反馈循环
报错原因
你触发的GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture是WebGL的原生限制:不允许对同一个纹理同时执行读写操作。
你在调用cubeCamera1.update(renderer, scene)时,CubeCamera会往cubeRenderTarget1里写入6个面的反射内容,但此时你的场景里的meshGLB的材质正好用了cubeRenderTarget1.texture作为envMap,就形成了「读写同一个纹理」的反馈循环,触发报错。
解决方案
最简单的处理方式是更新CubeCamera前临时隐藏使用反射材质的物体,更新完成后再恢复显示,调整后的代码如下:
// 先把meshGLB的作用域提上去,确保animate函数里能访问到 let meshGLB = null const reflection=()=> { renderer.outputEncoding = THREE.sRGBEncoding; cubeRenderTarget1 = new THREE.WebGLCubeRenderTarget( 256, { format: THREE.RGBFormat, generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter, encoding: THREE.sRGBEncoding }); cubeCamera1 = new THREE.CubeCamera( .01, 10, cubeRenderTarget1 ); cubeCamera1.position.z = 3 cubeCamera1.position.y = -4 reflectionMaterial = new THREE.MeshBasicMaterial( { envMap: cubeRenderTarget1.texture, color: 0x011111, }); } reflection() gltfLoader.load( '/exportPackages/sceneMaya.glb', (gltf) => { meshGLB= gltf.scene.children.find(child => child.name === 'mesh_0') meshGLB.material = reflectionMaterial scene.add(gltf.scene) }) const animate =()=> { requestAnimationFrame(animate) // 更新反射贴图前隐藏用了反射材质的模型 if (meshGLB) meshGLB.visible = false cubeCamera1.update( renderer, scene ) // 更新完恢复显示 if (meshGLB) meshGLB.visible = true // 补全主场景渲染逻辑,原代码缺少这一步会导致场景无内容输出 renderer.render(scene, camera) }; animate()
如果场景内有多个需要使用反射材质的物体,可以把它们统一放到一个THREE.Group里,更新CubeCamera前统一隐藏整个组即可。如果需要更精细的渲染控制,也可以用Layers做分层渲染:给CubeCamera设置只渲染不需要反射的层,反射材质物体单独放一个层仅给主相机渲染,效果和临时隐藏一致。
内容的提问来源于stack exchange,提问作者Chase Miller
相关产品推荐
相关产品推荐

