WebGL 踩坑系列-3

WebGL 踩坑系列-3

繪製球體

在 WebGL 中繪製物體時須要的頂點是以直角座標表示的,
固然了,gl_Position 是一個四維的向量,通常將頂點賦值給 gl_Position 時,最後一維會設爲 1,web

gl_Position = uMVPMatrix * vec4(aVertexPosition, 1.0);

這個時候的 aVertexPosition 三維向量就表明了頂點的直角座標。
若是咱們計算出球面上的頂點,並以直角座標的形式傳入着色器中,用合適的方式繪製,就能畫出球面了。canvas

可是,繪製球體須要用到頂點,若是直接用直角座標,並很差計算,
這時候須要用到球座標系將球面上的各個頂點表示出來,而後再將球座標表示成直角座標。數組

/**
 * 假設球心即爲原點,將球面座標系轉換成平面直角座標系
 * @param   theta   球心到頂點的連線與 Z 軸正方向的夾角爲 theta,範圍是 [0, 180]
 * @param   beta    球心到頂點的連線在 xoy 平面上的投影與 X 軸正方向的夾角爲 beta,範圍是 [0, 360]
 * @param   r   球半徑
 * @return      頂點的座標,用三維數組表示
 */
function calcVertex(theta, beta, r) {
    var st = Math.sin(Math.PI * theta / 180);
    var ct = Math.cos(Math.PI * theta / 180);
    var sb = Math.sin(Math.PI * beta / 180);
    var cb = Math.cos(Math.PI * beta / 180);
    var x = r * st * cb;
    var y = r * st * sb;
    var z = r * ct;
    return [x, y, z];
}

這個 calcVertex 函數就夠把特定角度和半徑的球座標轉換成相應的直角座標了。
如今只須要從 0 - 180 遍歷 theta,0 - 360 遍歷 beta 角,就能夠獲得球面上的全部頂點了。app

var n = 48;
var vetices = [];
var r = 1;
for( var j = 0; j < n; j++ ) {
  for( var i = 0; i < n: i++ ) {
    vertices.push.apply( vertices, calcVertex( i * 180 / n, j * 360 / n, r ) );
    // 或者用數組的 concat 方法,效果是同樣的,不過聽說 concat 方法更高效
    // vertices = vertices.concat( calcVertex( i * 180 / n, j * 360 / n, r ) );
  }
}

接下來把獲得的頂點傳入 gl 的緩衝區中,框架

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

若是隻是利用這些頂點,還不能畫出球面,藉助索引緩衝區能夠實現:函數

var index = [];
for ( j = 0; j < n; j++ ) {  
    for ( i = 0; i < n+1; i++ ) {
        index.push(
            i     + j       * (n+1),    // 0
            i+1 + j       * (n+1),    // 1
            i+1 + (j+1) * (n+1)    // n+1
        );
        index.push(
            i     + j       * (n+1),    // 0
            i+1 + (j+1) * (n+1)    // n+1
            i     + (j+1) * (n+1)    // n
        );
    }
}

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
gl.drawElements(gl.TRIANGLES, index.length, gl.UNSIGNED_SHORT, 0);

最後就能在 canvas 畫布上畫出球面了,n 越大,球面越精細,畫出的球越圓滑。webgl

ThreeJS 繪製球形

因爲有導入模型的需求,開始接觸 ThreeJS,用這個框架只須要調用 SphereGeometry 的 API 生成一個球,最後把球添加到場景中並進行渲染便可。spa

sphere = new THREE.Mesh(
    new THREE.SphereGeometry(4, 36, 36), 
    new THREE.MeshPhongMaterial( {
            opacity: 0.65,
            transparent: true,
            color: 0xeeeeee
    } )
);
scene.add(sphere);

總結

儘管 ThreeJS 對底層的 WebGL 封裝的很好,可是我只須要導入 OBJ 格式的模型就好了,ThreeJS 很強大,用起來也很方便。
而要從 WebGL 寫的話,還須要去了解 GLSL 着色器語言,本身編寫着色器代碼,繁瑣不少。code

相關文章
相關標籤/搜索