三 *(任何版本)
这听起来像是模板缓冲区的一个很好的候选者。绘制窗口并写入模板,在写入值 (0) 周围绘制墙,然后在写入值 (1) 内绘制墙。
这些是您感兴趣的方法:
https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp
https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
您需要先执行此操作:
const gl = renderer.getContext() //obtain the actual webgl context, because three has no stencil functionality
然后你需要管理你的渲染逻辑,这就是Object3D.onBeforeRender
回调应该帮助的地方。
所以让我们假设你有这样的东西:
const myWindow, myWall //two meshes, you loaded them, instantiated them
//for a proof of concept you can do something like this
const maskScene = new THREE.Scene()
const wallScene = new THREE.Scene()
const windowScene = new THREE.Scene()
maskScene.add(myWindow)
wallScene.add(myWall)
windowScene.add(myWindow)
render(){
gl.enable(gl.STENCIL_TEST) //enable stencil testing
gl.clearStencil( 0 ) //set stencil clear value
gl.clear( _gl.STENCIL_BUFFER_BIT ) //clear the stencil buffer with set value
gl.stencilFunc( gl.ALWAYS, 1, 1) //always pass the stencil test, with ref 1
gl.stencilOp( gl.REPLACE , gl.REPLACE , gl.REPLACE ) //replace the stencil value with the ref
gl.colorMask(false, false, false, false) //do not write any color
gl.depthMask(false) //do not write to depth
myRenderer.render(maskScene, myCamera) //only the stencil is drawn
//now you have a region in the frame buffer with stencil value of 1, and the rest 0, you can draw the wall in 0 and the window back at 1
gl.colorMask(true, true, true, true) //enable writing
gl.depthMask(true)
gl.stencilFunc( gl.EQUAL , 0 , 1 ) //set the stencil function to EQUAL
gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP ) //keep the stencil value in all three tests
myRenderer.render( wallScene, myCamera ) //draw the wall where stencil is 0 (around the window)
gl.stencilFunc( gl.EQUAL , 1 , 1 ) // now func is EQUAL but to value 1
myRenderer.render( windowScene, myCamera ) //draw the window
}
这是最基本的尝试,没有经过测试。由于它直接与 WebGL API 一起工作,它应该与三个版本的任何版本一起工作。stencilOp
需要另外两个参数,您可以使用它们来管理深度测试发生的情况。