three.js(五) 地形紋理混合

地形生成一般使用高度圖, 而高度圖的生成能夠使用繪圖工具,或者經過分形算法生成,例如square-diamond,  fbm方法。
這裏採用簡單求平均值+隨機波動的方法。




對於一個2^n+1  *  2^n+1 的網格, 中心點的高度是四角點的平均值加隨機偏移, 邊上中點的高度值是邊兩端點的平均值加隨機偏移。
接着將偏移的幅度縮小, 計算四個較小方塊的頂點的高度值。
這樣隨機生成了高度。


接着構造地形, 地形分割成2^n * 2^n 塊, 這樣頂點就有 2^n+1  *  2^n+1 個 
    var geo = new THREE.PlaneGeometry(3, 3, WIDTH-1, HEIGHT-1);


上面生成了每一個頂點的高度, 須要將高度值傳入shader中, 能夠直接修改geo中的全部頂點的z值,來修改高度。


咱們能夠根據地形的高度來混合紋理,例如比較高的位置爲石塊, 而低窪處爲草地, 這個紋理的混合。
c2 = mix(c0, c1, (height-minHeight)/(maxHeight-minHeight))
c0是第一張紋理獲取的顏色, c1是第二張紋理獲取的顏色, 而minHeight maxHeight 是整個地形高度的方位, height是當前高度。
c2 就是混合後的顏色。
shader以下,兩張紋理, 頂點在平面座標中的位置, 
紋理座標採用頂點的x, y 座標的小數部分。
    uniform sampler2D texture_grass;
    uniform sampler2D texture_rock;
    uniform float maxHeight;
    uniform float minHeight;
    varying vec3 pos;




void main( void ) {
        vec2 uv0;
        
        uv0.x = fract(pos.x);
        uv0.y = fract(pos.y);
        
        vec4 c0 = texture2D(texture_grass, uv2);
        vec4 c1 = texture2D(texture_rock, uv2);




        vec4 c2 = mix(c0, c1, (pos.z-minHeight)/(maxHeight-minHeight));


        gl_FragColor = c2;
     

}








而材質:
    var pmat = new THREE.ShaderMaterial({
        uniforms:{
            texture_grass:{type:'t', value:0, texture:THREE.ImageUtils.loadTexture("grassa512.bmp")},
            texture_rock:{type:'t', value:1, texture:THREE.ImageUtils.loadTexture("dirt512.bmp")},
      
            maxHeight:{type:'f', value:0},
            minHeight:{type:'f', value:1},
        },
        attributes:{
        },
        vertexShader: document.getElementById("vert").textContent,
        fragmentShader: document.getElementById("frag").textContent,
        //wireframe:true,
    
    });




其中紋理的值 0, 1 表示GPU內部的紋理編號, 這個數量受硬件限制。


頂點shader


    varying vec3 pos;
void main( void ) {


        pos = position.xyz;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xyz, 1);

}






















算法

相關文章
相關標籤/搜索