shader飛線改進版


項目github地址:https://github.com/ecojust/flyline

 

前面寫過一個飛線(基於THREE.Line進行的顏色變化),只是簡單地將可視區片元顏色的alpha通道值設為1.0,不在可視區的設為0.0。效果是這樣的:

做得很粗糙,而且因為線是沒有粗細的,所以效果也不是很理想,后來用pointSize實現線條粗細變化,以及可視區線條顏色的處理,線段頭尾點平滑處理等等,所以,改良后的效果如下:

后續又優化了一下代碼,用於測試性能(400根線FPS60):

然后不斷增加飛線的數量到4000根,FPS依舊能保持在40:

顯卡相當於N卡1050的水平,但要比1050差一點。

其實廢話了這么多,下面直接上核心代碼吧:

    //創建ShaderMaterial紋理的函數
    function createMaterial(vertexShader, fragmentShader) {
        var vertShader = document.getElementById(vertexShader).innerHTML; //獲取頂點着色器的代碼
        var fragShader = document.getElementById(fragmentShader).innerHTML; //獲取片元着色器的代碼
        //配置着色器里面的attribute變量的值
        var attributes = {};
        //配置着色器里面的uniform變量的值
        var uniforms = {
            time: {type: 'f', value: -70.0},
            size:{type:'f',value:20.0},
        };
        var meshMaterial = new THREE.ShaderMaterial({
            uniforms: uniforms,
            defaultAttributeValues : attributes,
            vertexShader: vertShader,
            fragmentShader: fragShader,
            transparent: true
        });
        return meshMaterial;
    }
    var flylinegroup = [];
    function addline(minx,maxx){
        var flyline;
        var curve = new THREE.CubicBezierCurve3(
            new THREE.Vector3( minx, 0, minx ),
            new THREE.Vector3( minx/2,maxx % 100 + 60, maxx * 2/ 3 ),
            new THREE.Vector3( maxx/2,maxx % 100 + 60, maxx / 3  ),
            new THREE.Vector3( maxx, 0,  maxx)
        );
        var points = curve.getPoints( (maxx - minx) * 5 );

        var geometry = new THREE.Geometry();
        geometry.vertices = points;
        var material = createMaterial("vertex-shader", "fragment-shader-7");
        flyline = new THREE.PointCloud( geometry, material );
        flyline.material.uniforms.time.value = minx;
        flyline.minx = minx;
        flyline.maxx = maxx;
        flylinegroup.push(flyline);
        scene.add(flyline);
    }

貝塞爾曲線上取點,這里簡單地根據x軸的長度來決定取點的數量。

<script id="vertex-shader" type="x-shader/x-vertex">
    uniform float time;
    uniform float size;
    varying vec3 iPosition;

    void main(){
        iPosition = vec3(position);
        float end = time + size;
        float pointsize = 1.0;
        if(position.x > time && position.x < end){
            pointsize = (position.x - time)/size;
        }
        gl_PointSize = pointsize * 2.0;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }
</script>

<script id="fragment-shader-7" type="x-shader/x-fragment">
    uniform float time;
    uniform float size;
    varying vec3 iPosition;

    void main( void ) {
        float end = time + size;
        vec4 color;
        if(iPosition.x > end || iPosition.x < time){
            discard;
        }else if(iPosition.x > time && iPosition.x < end){
            float ca = fract((iPosition.x - time)/size);
            color = vec4(ca/1.9,ca,ca/1.6,1.0);
        }
        float d = distance(gl_PointCoord, vec2(0.5, 0.5));
        if(abs(iPosition.x - end) < 0.2 || abs(iPosition.x - time) < 0.2){
            if(d > 0.1){
                discard;
            }
        }
        gl_FragColor = color;
    }
</script>
for(var i = 0;i< 4000;i++){
       var minx = randomNum(-2000,-600)/10;
       var maxx = randomNum(600,2000)/10;
       addline(minx,maxx);
}

 

思路:

1、利用貝塞爾曲線繪制飛線軌跡,並取點(取點數量暫時簡單地根據x軸的跨度來算),利用 three.PointCloud 這個類將取得的頂點傳給頂點着色器;

2、在頂點着色器中,對於在可視區內的點(position.x值在time和time+size之間)的pointSize進行從左到右依次增大,實現飛線右邊粗左邊細;

3、在片元着色器中,如果頂點不在可視區那么就discard(不繪制),在可視區內的點從左到右顏色漸變(后期可以通過外部傳入的顏色進行漸變處理);

4、在片元着色器中,對於可視區頭尾附近的點,進行平滑處理(同理於繪制圓點);

5、隨機生成一定范圍內的軌跡起始點的x坐標值來生成飛線,for循環來添加n條飛線。

再來一張飛線的近照:

 

 

2019.07.26更新

此次添加了自定義飛線漸變色的功能,效果如下,具體代碼參照github


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM