來張效果圖先:app
var plane; function addpanel(){ var axesHelper = new THREE.AxesHelper( 400 ); scene.add( axesHelper ); var geometry = new THREE.PlaneBufferGeometry( 200,200,400, 400);1 var material = createMaterial("vertex-shader-2", "fragment-shader-2"); material.uniforms.texture_grass={ type:'t', value:new THREE.TextureLoader().load("../texture/tile_aqua.png"), } material.uniforms.texture_grass.value.wrapS = THREE.RepeatWrapping;2 material.uniforms.texture_grass.value.wrapT = THREE.RepeatWrapping; var displacement = new Float32Array(200000);3 for(var i = 0; i < 200000; i++){ displacement[i]=0; } //丘陵 displacement = addmoutain(displacement,50,170,30,30); displacement = addmoutain(displacement,100,30,30,30); displacement = addmoutain(displacement,150,270,30,30); displacement = addmoutain(displacement,200,30,30,30); displacement = addmoutain(displacement,250,170,30,30); displacement = addmoutain(displacement,300,30,30,30); geometry.addAttribute('displacement', new THREE.BufferAttribute(displacement, 1));4 plane = new THREE.Mesh( geometry, material ); plane.rotation.x = -1; scene.add( plane ); }
1.利用PlaneBufferGeometry起了一塊尺寸200X200的面板,後面的400,400是x軸y軸細分的三角形個數函數
2.爲着色器材質提供貼圖紋理,並設置repeat(貼圖尺寸必須爲2的n次冪)spa
3.由於plane被細分了(400 x 400,實際可能不是160000個頂點,就像兩個三角形4個頂點,4個三角形卻只有6個頂點,由於共用的問題)產生n個頂點,因此咱們要提供相對應數量的數據供頂點使用;code
其實這些數據是後面要傳給着色器,替換position.z的,addmoutain函數的做用是以第m個點爲中心,周圍radius半徑內的點按必定規則升降(距離中心點越近,那麼高度越高,即值越大)orm
該函數以下:blog
function addmoutain(arr,row,col,radius,height){ var colstart = (col-radius+1)>0?(col-radius+1):1; var colend = (col+radius)>400?400:(col+radius); var rowstart = (row -radius + 1)>0?(row -radius + 1):1; var rowend = (row+radius)>400?400:(row+radius); for(var i = rowstart;i<=rowend;i++){ for(var j = colstart;j<=colend;j++){ var distance = Math.sqrt(Math.pow((row-i),2) + Math.pow((col-j),2)); if(distance < radius){ var percent = (radius - distance)/radius; var h = Math.sin(percent * Math.PI/2) * height/2; arr[(i-1)*400+j-1] = h; } } } return arr; }
4.將寫好的頂點z軸數據值傳給geometry。ip
下面來看兩個着色器:it
vs:io
<script id="vertex-shader-2" type="x-shader/x-vertex"> attribute float displacement; varying vec2 vUv; varying float pt; void main(){ vUv = uv * 4.0; pt = displacement; gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy,displacement, 1); } </script>
經過uv * 4.0 實現貼圖repeat,position.z值用displacement代替,pt(varying類型)用於後續fs計算透明度的依據function
fs:
<script id="fragment-shader-2" type="x-shader/x-fragment"> uniform sampler2D texture_grass; varying vec2 vUv; varying float pt; void main(){ vec4 color = texture2D(texture_grass, vUv); float percent = 1.0; if(pt > 0.5){ percent = pt / 15.0; } gl_FragColor = color * percent; } </script>
由於最高的高度爲15.0;因此pt/15.0實現的山丘的顏色透明過渡。
這樣,就寫完了,後續考慮利用該種方法畫一個圍棋盤,敬請期待!