本节将以前的内容整合下,为以后的章节打基础。本节主要内容是让我们绘制的图形动起来。
图形动起来的原理是每一帧都绘制
下面是代码的整体结构:
//变量
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();
}
运行后的会看到一个向右移动的矩形
本节完