使用three.js管理webgl状态并发出顺序绘制调用

时间:2017-09-14 22:06:41

标签: three.js

我试图创建一个复杂的场景节点,当在三个WebGLRenderer.render()调用中遇到时,会导致多个绘制调用和两者之间的状态更改。

具体来说,我想使用模板缓冲区,它不作为更高级别的API公开。

如果我有

var mesh = new THREE.Mesh( someGeom, someMaterial)

我需要在它被绘制之前发生这种情况:

mesh.onBeforeRender = ( renderer , scene , camera )=>{
  //because there is no someMaterial.stencilOp = THREE.SomeStencilOp
  //i need to work with the gl context

  _gl.enable(_gl.STENCIL_TEST)
  _gl.clearStencil( 0 )
  _gl.clear( _gl.STENCIL_BUFFER_BIT )
  _gl.stencilFunc( _gl.ALWAYS , 1 , 1 )
  _gl.stencilOp( _gl.REPLACE , _gl.REPLACE , _gl.REPLACE )
  //...

}

接下来是更多的平局电话:

mesh.onAfterRender = ( renderer , scene , camera )=>{

  //more state 
  _gl.stencilFunc( _gl.EQUAL , 1 , 1 )
  _gl.stencilOp( _gl.KEEP , _gl.KEEP , _gl.INCR )

  //renderer.render( someOtherMesh , camera ) //this doesn't really work
  renderer.render( anotherSceneWithOtherMesh, camera ) //this is nightmarish 

  //more state for yet another call
  _gl.stencilFunc( _gl.EQUAL, 0 ,1 )
  _gl.stencilOp( _gl.KEEP , _gl.KEEP , _gl.KEEP ) 

  //renderer.render( mesh , camera ) //not a scene so it doesnt work
  renderer.render( proxySceneForThisMeshWithThisMesh, camera ) // :( i need to either bake the transformation, or somehow sync a copy of the scene graph down to this node

  _gl.disable( _gl.STENCIL_TEST )

}

我可以用三个来做什么,r87以最少的头痛实现这个目标?

我希望我可以调用某种renderGeometryDirect方法,该方法只使用调用onBeforeRenderonAfterRender的相同节点绘制几何图形,并通过相同的{{ 1}}已在顶级camera调用中使用。

或者只是在render( scene, camera)上调用它。

代替这一点,我正在思考一些可以管理创建这些阴影图的东西,这些影子图可以与render(myObject3D, camera)一起使用,但我不确定最佳行动方案是什么。

1 个答案:

答案 0 :(得分:1)

只是一个想法,也许你可以使用图层来实现这样的目标(参见herehere)?这应该至少允许您指定场景图的子集以在渲染调用中呈现。

这样的事情:

_gl.enable(_gl.STENCIL_TEST)
_gl.clearStencil( 0 )
_gl.clear( _gl.STENCIL_BUFFER_BIT )
_gl.stencilFunc( _gl.ALWAYS , 1 , 1 )
_gl.stencilOp( _gl.REPLACE , _gl.REPLACE , _gl.REPLACE )

camera.layers.set(1);    
renderer.render(scene, camera);


_gl.stencilFunc( _gl.EQUAL , 1 , 1 )
_gl.stencilOp( _gl.KEEP , _gl.KEEP , _gl.INCR )

camera.layers.set(2);
renderer.render( scene, camera );


_gl.stencilFunc( _gl.EQUAL, 0 ,1 )
_gl.stencilOp( _gl.KEEP , _gl.KEEP , _gl.KEEP ) 

camera.layers.enable(1);
camera.layers.enable(2);
renderer.render( scene, camera );