本節将以前的内容整合下,為以後的章節打基礎。本節主要内容是讓我們繪制的圖形動起來。
圖形動起來的原理是每一幀都繪制
下面是代碼的整體結構:
//變量
var webgl = null;//WebGL對象
var vertexShaderObject = null;//vsShader對象
var fragmentShaderObject = null;//fsShader對象
var programObject = null;//顯示卡執行程式對象
var triangleBuffer = null;//頂點緩沖區對象
var indexBuffer = null;//索引緩沖區對象
var v3PositionIndex = 0;//位置輸入索引
var inColor = 1;//顔色輸入索引
var unifromAnim = 0;//anim索引
var animTime = 0;//計數
//讀取shader代碼字元串
function getShaderSource(scritptID)
{
......
}
//初始化工作:完成資源的加載
/**
*讀shader,編譯shader程式,建立顯示卡程式,連結,向顯示卡中傳輸資料。。。
*/
function init()
{
......
}
//主程式
function WebGLStart()
{
......
}
//渲染
function renderScene()
{
......
}
//循環
function tick()
{
......
}
//重新整理
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback,element ){
window.setTimeout(callback, 1000 / 60);
};
})();
我們要做的效果是讓矩形向右移動,實際上就是讓矩形的橫坐标x不斷增加。
在shader裡面的展現就是v3Position.x+anim(anim是一個增量)
其實是不斷的改變anim的值,這就要用到上節提到的uniform變量,在通過webgl.uniform1f(unifromAnim,animTime)每幀改變其值。
shader代碼如下:
<script id="shader-vs" > //頂點着色器vertexShader,處理頂點
precision lowp float;
attribute vec3 v3Position;
attribute vec4 inColor;
varying vec4 outColor;
uniform float anim;
void main(void)
{
outColor = inColor;
gl_Position = vec4(v3Position.x+anim,v3Position.y,v3Position.z,1.0);
}
</script>
<script id="shader-fs" >//片段着色器fragmentShader,填充顔色
precision lowp float;
varying vec4 outColor;
void main(void)
{
gl_FragColor = outColor;
}//兩段shader代碼都在顯示卡在執行
</script>
初始化init()代碼如下:
function init()
{
var canvas = document.getElementById("myCanvas");
webgl = canvas.getContext("webgl");
webgl.viewport(0,0,canvas.clientWidth,canvas.clientHeight);
//先将兩段shader代碼上傳到顯示卡
vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);//建立一個空的vertexShader對象,裡面什麼也沒有
fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);//同理建立一個空的fragmentShader對象
webgl.shaderSource(vertexShaderObject,getShaderSource("shader-vs"));//相當于給vertexShader指派,使其指向shader-vs裡面的代碼字元串
webgl.shaderSource(fragmentShaderObject,getShaderSource("shader-fs"));//相當于給fragmentShader指派,使其指向shader-fs裡面的代碼字元串
//編譯兩段代碼,使其形成能在顯示卡執行的二進制代碼
webgl.compileShader(vertexShaderObject);
webgl.compileShader(fragmentShaderObject);
//檢測編譯錯誤
if(!webgl.getShaderParameter(vertexShaderObject,webgl.COMPILE_STATUS))
{
alert("error:vertexShaderObject,info:"+webgl.getShaderInfoLog(vertexShaderObject));
return;
}
if(!webgl.getShaderParameter(fragmentShaderObject,webgl.COMPILE_STATUS))
{
alert("error:fragmentShaderObject,info:"+webgl.getShaderInfoLog(fragmentShaderObject));
return;
}
programObject = webgl.createProgram();//建立一個程式,相當于建立一個空的exe檔案,前面的shader相當于兩個庫檔案
//将exe檔案與庫檔案關聯在一起
webgl.attachShader(programObject,vertexShaderObject);
webgl.attachShader(programObject,fragmentShaderObject);
webgl.linkProgram(programObject);//連結,形成一個能顯示卡上執行在可執行程式,通過programObject句柄關聯
//檢測連結錯誤
if(!webgl.getProgramParameter(programObject,webgl.LINK_STATUS))
{
alert("error:programObject");
return;
}
//webgl.useProgram(programObject);//使用剛剛建立好的可執行程式,使用一個程式需要輸入輸出
var jsArrayData =
[
//x y z r g b a
-0.5, +0.5, 0.0, 1.0, 0.0, 0.0, 1.0,
+0.5, +0.5, 0.0, 0.0, 1.0, 0.0, 1.0,
+0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0,
-0.5, -0.5, 0.0, 1.0, 1.0, 0.0, 1.0,
];
var indexDatas =
[
0,1,2,
0,2,3,
];
webgl.bindAttribLocation(programObject,v3PositionIndex,"v3Position");
webgl.bindAttribLocation(programObject,inColor,"inColor");
unifromAnim = webgl.getUniformLocation(programObject,"anim");//擷取shader 中 anim 索引
triangleBuffer = webgl.createBuffer();//在顯示卡上建立一個緩沖區
webgl.bindBuffer(webgl.ARRAY_BUFFER,triangleBuffer);//申明緩存區的存儲類型為ARRAY_BUFFER
webgl.bufferData(webgl.ARRAY_BUFFER,new Float32Array(jsArrayData),webgl.STATIC_DRAW);//給緩存區指派
//建立索引緩沖區
indexBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER,indexBuffer);
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER,new Uint16Array(indexDatas), webgl.STATIC_DRAW);
}
渲染renderScene(),每幀都會調用一次
function renderScene()
{
//繪制
webgl.clearColor(0.0,0.0,0.0,1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
webgl.bindBuffer(webgl.ARRAY_BUFFER,triangleBuffer);//使用緩沖區
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER,indexBuffer);//使用緩沖區
animTime+=0.005;//每幀增加0.005
if(animTime>=1) animTime = 0;
webgl.useProgram(programObject);
{
webgl.uniform1f(unifromAnim,animTime);
webgl.enableVertexAttribArray(v3PositionIndex);//啟用v3PositionIndex
webgl.enableVertexAttribArray(inColor);//啟用inColor
webgl.vertexAttribPointer(v3PositionIndex,3,webgl.FLOAT,false,4*7,0);//給v3PositionIndex傳值
webgl.vertexAttribPointer(inColor, 4,webgl.FLOAT,false,4*7,4*3);//給inColor傳值
webgl.drawElements(webgl.TRIANGLES,6,webgl.UNSIGNED_SHORT,0);
}
//webgl.useProgram(0);
}
其他部分:
//主程式
function WebGLStart()
{
//!初始化
init();
//!進入遊戲循環
tick();
}
//循環
function tick()
{
requestAnimFrame(tick); //注:這兩個程式不能調換位置
renderScene();
}
運作後的會看到一個向右移動的矩形
本節完