截至目前為止,我們已經完成了
現在就是要把這些資料呈現在3D的地球上了! 我們要使用的是OpenGL這套API,
OpenGL是一套c語言的跨平台繪製2D和3D圖形的函式庫,想學習的推薦鼎鼎有名的nehe教學網站
或是可以購買 OpenGL SuperBible這本書來看!除了OpenGL本身之外還有OpenGL ES與WebGL
OpenGL ES (embedded system)就是嵌入式系統用的函式庫,是根據OpenGL 2.0發展而來,
WebGL又是基於OpenGL ES而發展的函式庫,所以可以說只要是OpenGL 2.0版本運行ok的程式碼,應該就可以在
OpenGL ES跟WebGL運行無誤!實際上到底可不可以只寫一次就好呢,還是要debug everywhere,可以來試試看。
因為今年已經2014了,我想這應該是沒什麼問題,我使用的作業系統是OSX 10.9.5,Safari, Chrome,Firefox都有支援
那我們第一步當然是來做個WebGL的Hello World囉, OpenGL的Hello World通常都不是輸出文字,都只是簡單的圖形,
因為其實OpenGL要輸出文字頗麻煩的。WebGL 是 JavaScript API, 內容都寫在HTML5 的 <canvas> 標籤底下
<canvas id="main_canvas" width="500" height="300" style="background-color:white”>
Your browser does not support the HTML5 canvas element.
</canvas>
為了方便辨識,我們將網頁頁面背景設成黑色,而canvas背景顏色設為白色。
當我們要在canvas標簽底下繪圖,就要先取得context,canvas context有兩種,
第一是2d,第二就是webgl 或 experimental-webgl,我有用過2d的context來做我們公司系統的文件流程圖也還算熟悉,
function initWebGL(canvas) {
gl = null;
try {
// Try to grab the standard context. If it fails, fallback to experimental.
gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
}
catch(e) {}
// If we don't have a GL context, give up now
if (!gl) {
alert("Unable to initialize WebGL. Your browser may not support it.");
gl = null;
}
return gl;
}
得到context後,就可以來進行OpenGL的一些初始設定
function init() {
var canvas = document.getElementById("main_canvas");
gl = initWebGL(canvas);
if (gl) {
gl.clearColor(1.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
}
}
window.onload = init;
我們將環境初始化為背景紅色,然後讓頁面一讀取就呼叫初始化函式,結果就是
這個樣子!代表我們初始化成功了
我們必需要寫shader程式,shader有分成兩種,vertex shader跟fragment shader,
vertex shader是控制vertex的資料,fragment shader 是控制最後pixel的顏色值,先這樣理解就好
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
void main(void) {
gl_Position = vec4(aVertexPosition, 1.0);
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
void main(void) {
gl_FragColor = vec4(1.0,1.0,1.0, 1.0);
}
</script>
稍微解釋一下上面兩段程式,gl_Position跟gl_FragColor是系統變數,就是最後的輸出,
而vec3 與 vec4是GLSL的變數,attribute就是我們可以從gl主程式傳送至shader程式的連結變數,
這邊的vertex shader就是接受我們船進去的vertex值,沒有做什麼變動,fragment shader就是將最後輸出的顏色都指定為白色
完成了程式碼後就可以初始化shader,初始化的步驟是
創建shader->連結程式碼->編譯-> 與gl程式聯結
function initShaders(){
vertexShader = gl.createShader(gl.VERTEX_SHADER);
fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
var vs_source = document.getElementById('vertex-shader').html(),
fs_source = document.getElementById('fragment-shader').html();
gl.shaderSource(vertexShader, vs_source);
gl.shaderSource(fragmentShader, fs_source);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
glProgram = gl.createProgram();
gl.attachShader(glProgram, vertexShader);
gl.attachShader(glProgram, fragmentShader);
gl.linkProgram(glProgram);
gl.useProgram(glProgram);
}
function drawScene(){
vertexPositionAttribute = gl.getAttribLocation(glProgram, "aVertexPosition");
gl.enableVertexAttribArray(vertexPositionAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesVerticeBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
}
首先我們先呼叫vertex的aVertexPosition attribute,再將VBO傳送給他,
就可以繪圖了!