我正在开发一个three.js应用程序,我必须创建一个建筑结构(全部在一楼),高度,宽度,长度将由用户指定。用户可以更改墙壁和屋顶颜色(使用纹理应用,因为我有每种颜色的图像和一些纹理)。他们还可以在选定的墙壁(如窗户或门)上添加任何附件,然后可以将其拖放到同一个选定的墙壁上。在确定他们想要放置窗口的位置(例如)之后,他们将点击按钮确认位置。现在我必须在墙上创建一个窗口,以便我可以看到房间内部。请就以下方法提出您的意见:
一旦用户确认门的位置 -
a。)我可以在主建筑物网格mainMesh.add(windowMesh);
中添加窗口的网格。但问题是即使我将透明材料设置到窗口,墙材料仍然显示。
b。)我可以从主建筑物网格中减去窗口网格(使用CSG,threeCSG)buildingmeshcsg.subtract(windowmeshcsg)
在建筑物网格中创建一个洞,然后我将窗口网格放在那个洞上。现在的问题是在任何CSG操作之后,原始几何体的面都会混淆,所以在csg操作之后,面部的颜色UV会消失。
c。)我可以用小部分创建墙, 喜欢从一个角落到窗口角落,从另一个窗口角落到另一个角落角落。但是这会混淆我在墙壁上应用的纹理,因为我已经为前后墙创建了UV,因为纹理没有正确应用。
请提出您的意见。
必须做出类似这样的事情:https://forum.unity.com/threads/make-a-seethrough-window-without-making-hole-in-the-wall.286393/
答案 0 :(得分:0)
这听起来像是模板缓冲区的一个很好的候选者。绘制窗口并写入模板,围绕书写值绘制墙(0),然后在书写值(1)内绘制墙。
这些是您感兴趣的方法:
https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
您需要先执行此操作:
Stream
然后你需要管理你的渲染逻辑,这是const gl = renderer.getContext() //obtain the actual webgl context, because three has no stencil functionality
回调应该帮助的地方。
所以我们假设你有类似的东西:
Object3D.onBeforeRender
这是最基本的尝试,未经测试。由于它直接使用WebGL API,因此它应该适用于任何三个版本。 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
}
需要另外两个参数来管理深度测试会发生什么。