【问题标题】:Three.JS Object Clipping?三.JS对象裁剪?
【发布时间】:2016-08-02 03:13:06
【问题描述】:

我正在尝试使用 three.js 以类似于 Unity 的方式分割我的 3D 模型:

我一直在玩相机控件,当然我可以调整近场/远场以沿相机方向进行剪辑,但如果我只想在 X 或 Y 平面上剪辑怎么办?我研究了可能添加一个可以在该轴上滑动的大型透明块,然后使用二进制运算来合并/减去它与对象相交的位置,但这些工具最终会沿着新平面创建一个新网格,而不是实际移除沿该平面的所有内容轴。

我需要使用多个视口,还是有更简单的方法?

【问题讨论】:

标签: javascript three.js


【解决方案1】:

可以在着色器中轻松完成剪辑。使用一些计算,您甚至可以拥有一个例如像球体这样的剪切区域。在与坐标系正交的平面上进行裁剪是最简单的。在顶点着色器中计算像素的世界位置:

worldPosition = modelMatrix * vec4( position, 1.0 );

在片段着色器中,如果像素的绘制超出您的裁剪限制,则丢弃它:

if ( worldPosition.x > clippingLimitX ) {
    discard;
}

但是,这将使网格在剪裁边缘处保持打开状态。要关闭它,请使用模板缓冲区。使用显示背面的场景减少模板。然后使用显示剪裁正面的场景来增加模板。 这些场景中使用的材质不应该是可见的,所以禁用它们的颜色和深度写入:

new THREE.ShaderMaterial( { colorWrite: false, depthWrite: false, ... } );

使用模板渲染位于剪切平面位置的平面。禁用模板后,渲染剪裁的正面。

renderer.autoClear = false;
renderer.clear();

var gl = renderer.context;

renderer.state.setStencilTest( true );

renderer.state.setStencilFunc( gl.ALWAYS, 1, 0xff );
renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.INCR );
renderer.render( backStencilScene, camera );

renderer.state.setStencilFunc( gl.ALWAYS, 1, 0xff );
renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.DECR );
renderer.render( frontStencilScene, camera );

renderer.state.setStencilFunc( gl.EQUAL, 1, 0xff );
renderer.state.setStencilOp( gl.KEEP, gl.KEEP, gl.KEEP );
renderer.render( capsScene, camera );

renderer.state.setStencilTest( false );

renderer.render( scene, camera );

我做了一个演示,展示了如何同时在多个平面上进行剪辑:

http://daign.github.io/clipping-with-caps/

我没有使用内置的 three.js 剪裁平面,因为要让这个演示工作,我必须使用一个着色器来渲染模板,该着色器确定剪裁平面是否背对相机,并且只进行剪裁在那些面向相机的平面上。

【讨论】:

  • 不错。另见this answer。然而,这两种方法都存在问题,即圆柱体的直径远大于圆柱体高度的开放式圆柱体几何形状。
  • 太棒了!您对如何在剪辑位置绘制“粗”线有什么建议吗?介于开放网格和封闭网格之间的东西。谢谢!
  • @daign 非常感谢!想知道如何实现这个效果
【解决方案2】:

现在支持剪辑。

这是要遵循的模式。根据您的用例进行调整。

var localPlane = new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 1 );

var globalPlane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 1 );

renderer.clippingPlanes = [ globalPlane ];

renderer.localClippingEnabled = true;

var material = new THREE.MeshPhongMaterial( {
    clippingPlanes: [ localPlane ],
    clipShadows: true
} );

查看这三个.js 示例:

https://threejs.org/examples/webgl_clipping.html https://threejs.org/examples/webgl_clipping_advanced.html

three.js r.85

【讨论】:

  • 对不起,我来晚了。 @WestLangley,我试图启用剪裁平面,但我不确定您的回答 - 什么是本地与全局剪裁平面?我应该同时启用吗?
  • @RahulPillai 全局剪裁平面是每个渲染器的。局部剪裁平面是每种材料的。见threejs.org/docs/index.html#api/en/materials/…。
  • 对我来说,我已经将三个.js 代码从一个项目转移到另一个项目,并花了几个小时试图找到罪魁祸首。最终是因为 render.localClippingEnabled 被设置为 false :/
猜你喜欢
  • 1970-01-01
  • 2017-09-24
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 2014-02-20
  • 1970-01-01
  • 2014-05-11
  • 2013-09-13
相关资源
最近更新 更多