关于如何在墙上创建窗口的建议

时间:2017-10-06 10:32:06

标签: three.js mesh csg

我正在开发一个three.js应用程序,我必须创建一个建筑结构(全部在一楼),高度,宽度,长度将由用户指定。用户可以更改墙壁和屋顶颜色(使用纹理应用,因为我有每种颜色的图像和一些纹理)。他们还可以在选定的墙壁(如窗户或门)上添加任何附件,然后可以将其拖放到同一个选定的墙壁上。在确定他们想要放置窗口的位置(例如)之后,他们将点击按钮确认位置。现在我必须在墙上创建一个窗口,以便我可以看到房间内部。请就以下方法提出您的意见:

一旦用户确认门的位置 -

a。)我可以在主建筑物网格mainMesh.add(windowMesh);中添加窗口的网格。但问题是即使我将透明材料设置到窗口,墙材料仍然显示。

b。)我可以从主建筑物网格中减去窗口网格(使用CSG,threeCSG)buildingmeshcsg.subtract(windowmeshcsg)在建筑物网格中创建一个洞,然后我将窗口网格放在那个洞上。现在的问题是在任何CSG操作之后,原始几何体的面都会混淆,所以在csg操作之后,面部的颜色UV会消失。

c。)我可以用小部分创建墙, wall in sections 喜欢从一个角落到窗口角落,从另一个窗口角落到另一个角落角落。但是这会混淆我在墙壁上应用的纹理,因为我已经为前后墙创建了UV,因为纹理没有正确应用。

请提出您的意见。

必须做出类似这样的事情:https://forum.unity.com/threads/make-a-seethrough-window-without-making-hole-in-the-wall.286393/

1 个答案:

答案 0 :(得分:0)

THREE *(任何版本)

这听起来像是模板缓冲区的一个很好的候选者。绘制窗口并写入模板,围绕书写值绘制墙(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 } 需要另外两个参数来管理深度测试会发生什么。