KITASENJU DESIGN BLOG

memo, html, javascript, unity

vertex colorとline segmentとShaderMaterial

import * as THREE from 'three';
import vert from "./line/line.vert";
import frag from "./line/line.frag";
import glslify from 'glslify';

export class MyLine extends THREE.Object3D{

    numParticles:number=5000;
    strokes:THREE.Line;
    counter=0;

    positions   :number[];
    colors      :number[];
    scales      :number[];
    geo         :THREE.BufferGeometry;
    private mode        :string;
    //material    :THREE.LineBasicMaterial;
    material       :THREE.ShaderMaterial;
    isDirty     :boolean=false;

    init(){

        const positions = new Float32Array( this.numParticles * 3 );
        const colors = new Float32Array( this.numParticles*3 );
        
        for ( let i = 0; i < this.numParticles; i++ ) {
            positions[ i*3 + 0 ] = 9999;//(Math.random()-0.5)*20
            positions[ i*3 + 1 ] = 9999;//(Math.random()-0.5)*20
            positions[ i*3 + 2 ] = 9999;//(Math.random()-0.5)*20
            colors[ i*3 + 0 ] = Math.random();//(Math.random()-0.5)*2000
            colors[ i*3 + 1 ] = Math.random();//(Math.random()-0.5)*2000
            colors[ i*3 + 2 ] = Math.random();//(Math.random()-0.5)*2000
        }

        this.geo = new THREE.BufferGeometry();
        this.geo.setAttribute('color1', new THREE.BufferAttribute(colors, 3, true));
        this.geo.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
        //this.geo.setAttribute( 'scale', new THREE.BufferAttribute( scales, 1 ) );

        //this.material = new THREE.LineBasicMaterial({
            //color:0xffffff
            //blending: THREE.AdditiveBlending
        //});
        this.material = new THREE.ShaderMaterial({
            side: THREE.DoubleSide,
            uniforms: {
                //opacity: {value: 1.0}
            },
            transparent: true,
            //vertexColors: true,
            vertexShader: glslify(vert),
            fragmentShader: glslify(frag),
            //opacity: 0.5         
        });

        //this.material.transparent=true;
        //this.material.opacity=0.5;
        this.strokes = new THREE.LineSegments( this.geo, this.material );
        //scene.add( particles );
        this.positions  = this.geo.attributes.position.array as number[];
        this.colors     = this.geo.attributes.color1.array as number[]; 
        //this.scales = this.particles.geometry.attributes.scale.array as number[];

        this.add(this.strokes);
        this.hide();
       
    }

    show(){
        this.strokes.visible=true;
    }
    hide(){
        this.strokes.visible=false;
    }

    reset(){
        this.counter=0;
        this.strokes.visible=false;
        for ( let i = 0; i < this.positions.length; i++ ) {
            this.positions[i]=0;
        }
        this.geo.attributes.position.needsUpdate = true;
    }

    resetCount(){
        this.counter=0;
        
    }


    connectDots(
        x1:number,y1:number,z1:number,//start
        x2:number,y2:number,z2:number,//goal
        rr:number,gg:number,bb:number,//color
    ){
    
        this.isDirty=true;
        this.strokes.visible=true;
        let ratio = 0;//-Math.pow(brightness,3);
        
        //x2はゴール
        this.positions[this.counter*6+0] = x1;//x2*ratio+x1*(1-ratio);
        this.positions[this.counter*6+1] = y1;//y2*ratio+y1*(1-ratio);
        this.positions[this.counter*6+2] = z1;//z1;//z2*ratio+z1*(1-ratio);

        this.positions[this.counter*6+3] = x2;
        this.positions[this.counter*6+4] = y2;
        this.positions[this.counter*6+5] = z2;//z2;
        
        this.colors[this.counter*6+0] = Math.random();//255*Math.random();
        this.colors[this.counter*6+1] = Math.random();//255*Math.random();
        this.colors[this.counter*6+2] = Math.random();//255*Math.random();

        this.colors[this.counter*6+3] = rr
        this.colors[this.counter*6+4] = gg
        this.colors[this.counter*6+5] = bb

        if(this.counter<this.numParticles){
            this.counter += 1;
        }else{
            console.log("stroke数を超えた")
        }
        
    }


    //pointsに従ってレンダリングします
    update(){
    
        //if(this.strokes.visible && this.isDirty){
            this.geo.attributes.position.needsUpdate = true;
            this.geo.attributes.color1.needsUpdate = true;
            this.isDirty=false;
        //}
        //this.resetCount();

    }


}

shaders

varying vec3 vColor;
varying vec4 vPosition;

void main() {
    vec3 col = vColor;
    gl_FragColor = vec4(col,1.0);
}
varying vec3 vColor;
varying vec4 vPosition;

void main() {
    vec3 col = vColor;
    gl_FragColor = vec4(col,1.0);
}
"FOOTER"