在线上两点间设置线条颜色

3
我在three.js中基于一个顶点数组画了一条线,希望将线的颜色设置为沿线两个非顶点点之间的特定值。这两个点距离线原点有一定距离,例如我想在一条500单位长的线上50到100单位的距离之间改变颜色。我该如何实现呢?
使用vertexColors: THREE.VertexColors,我只能指定顶点之间的颜色。我认为我需要将这两个点作为额外的顶点传递进去,但是我如何获得沿线具有XYZ坐标的位置呢?
谢谢任何关于如何完成此操作的提示!

使用自定义着色器可以帮助解决问题。例如,可以使用.onBeforeCompile()来实现此结果。 - prisoner849
1个回答

2

一种选择是修改THREE.LineDashedMaterial(),使用.onBeforeCompile()

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 250, 500);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

scene.add(new THREE.GridHelper(500, 10));

var geom = new THREE.BufferGeometry().setFromPoints(
  [
    new THREE.Vector3(-250, 0, 0),
    new THREE.Vector3(250, 0, 0)
  ]
);

var mat = new THREE.LineDashedMaterial({
  color: "red"
});
var uniforms = {
  segmentStart: {
    value: 50
  },
  segmentEnd: {
    value: 100
  },
  segmentColor: {
    value: new THREE.Color("yellow")
  }
}
mat.onBeforeCompile = shader => {
  shader.uniforms.segmentStart = uniforms.segmentStart;
  shader.uniforms.segmentEnd = uniforms.segmentEnd;
  shader.uniforms.segmentColor = uniforms.segmentColor;
  shader.fragmentShader = `
    uniform float segmentStart;
    uniform float segmentEnd;
    uniform vec3 segmentColor;
  ` + shader.fragmentShader; // add uniforms
  shader.fragmentShader = shader.fragmentShader.replace(
    `if ( mod( vLineDistance, totalSize ) > dashSize ) {
  discard;
 }`, // remove the part for dash
    ``
  );
  shader.fragmentShader = shader.fragmentShader.replace(
    `gl_FragColor = vec4( outgoingLight, diffuseColor.a );`,
    `gl_FragColor = vec4( outgoingLight, diffuseColor.a );
    if (vLineDistance >= segmentStart && vLineDistance <= segmentEnd) gl_FragColor.rgb = vec3(1, 1, 0);
    `
  ); // add showing of a segment


  console.log(shader.fragmentShader);

}

var line = new THREE.Line(geom, mat);
line.computeLineDistances();
scene.add(line);

var clock = new THREE.Clock();

renderer.setAnimationLoop(() => {

  uniforms.segmentEnd.value = 250 + Math.sin(clock.getElapsedTime()) * 150;
  renderer.render(scene, camera)
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>


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