Suggestion on how to create a window over a wall

心已入冬 提交于 2019-12-11 15:14:18

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!