在线上的两个点之间设置线颜色

时间:2019-11-13 13:21:18

标签: javascript three.js

我基于顶点数组在three.js中绘制一条线,并希望将线的颜色设置为沿线的两个点(不是顶点)之间的特定值。 这两个点是距直线原点特定距离的点,例如我想沿着500单位的线在50到100单位的距离之间更改颜色。我该怎么做?

使用vertexColors: THREE.VertexColors,我只能指定线顶点之间的颜色。我想我需要将两个点作为附加顶点传递,但是如何获得沿线具有XYZ坐标的位置?

感谢您提示如何完成此操作!

1 个答案:

答案 0 :(得分: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>