如何在Three.js中展示对象网格?

6
我有水平网格助手和场景中的多边形。
是否有任何方法可以隐藏多边形外的网格,如下图所示?

enter image description here

这里是JSFiddle

var camera, scene, renderer, controls, geometry, material, mesh, gridHelper, polygon;
var edges = [{
  "x": -204.87113421108512,
  "y": -150,
  "z": 350.73338884671745
}, {
  "x": -204.87113421108535,
  "y": -150,
  "z": -38.02713383973953
}, {
  "x": -83.08211641046344,
  "y": -150,
  "z": -39.62530388610881
}, {
  "x": -78.88807649109879,
  "y": -150,
  "z": -538.3155247201529
}, {
  "x": 220.63777329601388,
  "y": -150,
  "z": -535.796479191672
}, {
  "x": 220.63777329601444,
  "y": -150,
  "z": 176.94968924487634
}, {
  "x": -53.07402331399715,
  "y": -150,
  "z": 176.9496892448766
}, {
  "x": -53.07402331399726,
  "y": -150,
  "z": 350.41591086077415
}];

init();
animate();

function init() {

  scene = new THREE.Scene();
  
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
 renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setClearColor(0x555555, 1);
  renderer.sortObjects = true;
  
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
  scene.add(camera);
  
  camera.position.x =  1000;
  camera.position.y =  2000;
 camera.position.z =  -1000;
  
 controls = new THREE.OrbitControls( camera );


  gridHelper = new THREE.GridHelper(1500, 30);
  gridHelper.position.y = -150;
  scene.add(gridHelper);


  var shape = new THREE.Shape();
  let firstEdge = edges[0];
  shape.moveTo(firstEdge.x, -firstEdge.z);
  const len = edges.length;
  for (let i = 1; i < len; i++) {
    shape.lineTo(edges[i].x, -edges[i].z);
  }

  shape.lineTo(firstEdge.x, -firstEdge.z);
  
  var material = new THREE.MeshBasicMaterial({
      color:0x00aa00,
      opacity:0.5,
      side:THREE.DoubleSide,
      transparent:true,
      depthTest:false
    });

  var polygonGeometry = new THREE.ShapeGeometry(shape);
  polygon = new THREE.Mesh(polygonGeometry, material);
  polygon.position.y = firstEdge.y;
  polygon.rotation.x = -Math.PI / 2.;
  polygon.name = this.name;
  scene.add(polygon);

}

function animate() {
  controls.update();
  window.requestAnimationFrame(animate);
  render();

}

function render() {

  renderer.render(scene, camera);

};
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.js"></script>
      <script type="text/javascript" src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

任何建议都将不胜感激!

你尝试过什么来解决这个问题? - Humoyun Ahmad
你熟悉模板缓冲吗?也许那个会有用?https://threejs.org/docs/#api/en/renderers/WebGLRenderer.stencil - Dacre Denny
1
浮现在脑海中的是自定义着色器。 - WestLangley
@DacreDenny 我不熟悉,我会查一下。 - mudin
@imudin07 如果你找到了,请告诉我。我也非常好奇。 - prisoner849
显示剩余3条评论
1个回答

6
这个结果是通过模板缓冲实现的:https://jsfiddle.net/mmalex/g3hf4zxc/

Stencil buffer clipping threejs Grid by Mesh

const gl = renderer.getContext();
polygon.onBeforeRender = function () {
    gl.enable(gl.STENCIL_TEST)
    gl.stencilFunc(gl.ALWAYS, 1, 0xFF);
    gl.stencilMask(0xFF);
    gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
}
polygon.onAfterRender = function() {
    gl.disable(gl.DEPTH_TEST);
}
polygon.renderOrder = 999;

gridHelper.onBeforeRender = function() {
    gl.enable(gl.STENCIL_TEST)
    gl.stencilMask(0x00);
    gl.stencilFunc(gl.EQUAL, 1, 0xFF);
}
gridHelper.onAfterRender = function() {
    gl.disable(gl.STENCIL_TEST)
}
gridHelper.renderOrder = 1000

不幸的是,我牺牲了网格透明度,因为threejs独立排序不透明和透明对象:

.renderOrder : 数字 此值允许覆盖场景图对象的默认呈现顺序,尽管不透明和透明对象仍然独立排序。排序从最低到最高的renderOrder。默认值为0。

https://threejs.org/docs/#api/en/core/Object3D.renderOrder


2
你可以使助手透明:gridHelper.material.transparent = true; gridHelper.material.opacity = 0.5; 此外,我建议避免在渲染器背后更改gl状态。渲染器维护自己的状态,直接更改gl状态会导致两者不同步。相反,请参见例如此更新的fiddle:https://jsfiddle.net/tq06bhkx/. - WestLangley
1
直接使用WebGL,如果答案附带详细说明会更好。 - Humoyun Ahmad
1
@Alex Khoroshylov 非常感谢!这正是我想要的!在我的项目中,我为每个对象使用renderOrder,完全没有问题。 - mudin
@WestLangley 如果多边形数量超过一个,我是否应该为每个多边形应用stencilMask? - mudin
嗨@imudin07,正如我之前提到的,两个对象都应该是不透明或透明的。在你的例子中,请尝试设置:gridHelper.material.opacity = 0.5; gridHelper.material.transparent = true; - Alex Khoroshylov
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接