问题
I am working on a three.js application where I have to create a building structure (all on ground floor), the height, width, length will be specified by user. User can change wall and roof color (which are applied using texture, as I have images for each color with some texture). They can also add any accessory on a selected wall (like a window or a door), which can be then dragged and dropped on that same selected wall. After deciding where they want to put the window (for eg.) they will click a button to confirm the position. Now I have to create a window in the wall, so that I can see inside of the room. Please suggest your views on following approaches:
Once the user confirms the position of the door -
a.) I can add the mesh of the window in the main building mesh mainMesh.add(windowMesh);
. But the problem is even if I set the transparent material to the window , the wall material still shows.
b.) I can subtract the window mesh from the main building mesh (using CSG, threeCSG) buildingmeshcsg.subtract(windowmeshcsg)
which creates a hole in the building mesh, and then I put the window mesh over that hole. Now the problem is after any CSG operation the faces of the original geometry gets all mixed up, so after the csg operation, the color, UV of faces goes away.
c.) I can create wall in small sections, like from one corner to window corners then, from another window corner to another wall corner. But this messes up the texture I have applied on walls, because I have created UV for front and back walls, as the texture was not applying correctly.
Please suggest your views.
Have to make something like this :https://forum.unity.com/threads/make-a-seethrough-window-without-making-hole-in-the-wall.286393/
回答1:
THREE * (any version)
This sounds like a good candidate for the stencil buffer. Draw the window and write to stencil, draw the wall around the written values (0) then draw the wall within the written value (1).
These are the methods you are interested in:
https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilOp https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/stencilFunc
You need to do this first:
const gl = renderer.getContext() //obtain the actual webgl context, because three has no stencil functionality
And then you need to manage your render logic, this is where Object3D.onBeforeRender
callback should help.
So let's assume that you have something like this:
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
}
This is the most basic attempt and it is not tested. Since it's working directly with the WebGL API it should work with any version of three. stencilOp
takes two more arguments with which you can manage what happens with the depth tests.
来源:https://stackoverflow.com/questions/46603751/suggestion-on-how-to-create-a-window-over-a-wall