Drawing a broken line 031 - to achieve a custom shader

Source Code:
https://github.com/mattdesl/three-line-2d/tree/master/test/shader-dash.js

Reference article:
https://mattdesl.svbtle.com/drawing-lines-is-hard

Drawing a broken line 031 - to achieve a custom shader

Final results:
Here Insert Picture Description

1, using the built-in methods Three.js

App.js

addLine() {
  var lineGeometry = new THREE.Geometry();//生成几何体
  lineGeometry.vertices.push(new THREE.Vector3(0, 0, 25));//线段的两个顶点
  lineGeometry.vertices.push(new THREE.Vector3(0, 1, 25));

  let material = new THREE.LineDashedMaterial({
    color: 0xffffff,//线段的颜色
    dashSize: 1,//短划线的大小
    gapSize: 3//短划线之间的距离
  })
  var line = new THREE.Line(lineGeometry, material);

  // 不可或缺的,若无,则线段不能显示为虚线
  line.computeLineDistances();
  this.stage.scene.add(line);
}

2, custom shader achieve

shader-dash.js

export default class ShaderDash{
  static getShaderData(opt){
    opt=opt||{};
    var ret=Object.assign({
        transparent:true,
        uniforms:{
          dashSteps:{type:'f',value:10},
          dashDistance:{type:'f',value:.5},
        },
        vertexShader:`
        attribute float lineDistance;
        varying float lineU;

        void main(){
          lineU=lineDistance;
          gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.);
        }`,
        fragmentShader:`
        // 当前点距离起点的距离
        varying float lineU;
        uniform float dashSteps;
        uniform float dashDistance;

        void main(){
          float lineUMod=mod(lineU,1./dashSteps)*dashSteps;
          float dash=step(dashDistance,lineUMod);
          gl_FragColor=vec4(vec3(dash),1.);
        }`
    },opt);

    return ret;
  }
}

App.js

class App {
  ...
  addDashLine() {
    var lineGeometry = new THREE.Geometry();//生成几何体
    lineGeometry.vertices.push(new THREE.Vector3(0, 0, 25));//线段的两个顶点
    lineGeometry.vertices.push(new THREE.Vector3(0, 1, 25));

    let material = new THREE.ShaderMaterial(ShaderDash.getShaderData({
      side: THREE.DoubleSide
    }))

    var line = new THREE.Line(lineGeometry, material);
    // 不可或缺的,若无,则线段不能显示为虚线
    line.computeLineDistances();
    this.stage.scene.add(line);
  }
  ...
}

3, the principle of the code

For the fragment shader:

// lineU 当前像素点距离起点的距离
varying float lineU;

// 单位直线虚线的段数 10
uniform float dashSteps;

// 虚线的间距 0.5
uniform float dashDistance;

void main(){
  float lineUMod=mod(lineU,1./dashSteps)*dashSteps;
  float dash=step(dashDistance,lineUMod);
  gl_FragColor=vec4(vec3(dash),1.);
}

Here Insert Picture Description

  • A total of 10 segments.
  • Number pitch per segment = 1 / * segment pitch * 1/10 = 0.5.
  • Each pixel is the distance regarded pixel mapped to each segment 0 ~ pitch.
    float lineUMod=mod(lineU,1./dashSteps);
    
  • The current pixel comparison distance and the line segment, return is less than 0, returns greater than 1, as the color of the pixel.
    float dash=1-step(dashDistance,lineUMod);
    gl_FragColor=vec4(vec3(dash),1.);
    

<Full end>

Published 71 original articles · won praise 6 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_21476953/article/details/104256406