在上一篇里已经将三角形画出来了,但是图形的颜色是直接写的,没有传值。这次讲解如何传值。其实这个传值与顶点数据的传值是差不多的。都是要写一个vbo(缓冲区对象),然后再将数据传过去shader就ok了。
onload = function(){
//获取canvas对象
var c = document.getElementById('canvas');
//规定canvas的宽高
c.width = 300;
c.height = 300;
//获取webgl的上下文
var gl = c.getContext('webgl')||c.getContext('experimental-webgl');
// 设定canvas初始化的颜色
gl.clearColor(0.0,0.0,0.0,1.0);
// 设定canvas初始化时候的深度
gl.clearDepth(1.0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//创建顶点shader和片段shader
var v_shader = create_shader('vs');
var f_shader = create_shader('fs');
//程序对象生成和连接
var prg = create_program(v_shader,f_shader);
//从shader那里找到命名为position的属性
var attLocation = new Array(2);
attLocation[0] = gl.getAttribLocation(prg,'position');
attLocation[1] = gl.getAttribLocation(prg,'color');
//指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。
//(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
var attStride = new Array(2);
attStride[0] = 3;
attStride[1] = 4;
//顶点数据
var vertex_position =[
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
-1.0, 0.0, 0.0
];
var vertex_color = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
//创建缓冲区对象vbo
var position_vbo = create_vbo(vertex_position);
var color_vbo = create_vbo(vertex_color);
//绑定vbo
gl.bindBuffer(gl.ARRAY_BUFFER,position_vbo);
//开启attribute属性
gl.enableVertexAttribArray(attLocation[0]);
//添加attribute属性
gl.vertexAttribPointer(attLocation[0],attStride[0],gl.FLOAT,false,0,0);
//绑定vbo
gl.bindBuffer(gl.ARRAY_BUFFER,color_vbo);
//开启attribute属性
gl.enableVertexAttribArray(attLocation[1]);
//添加attribute属性
gl.vertexAttribPointer(attLocation[1],attStride[1],gl.FLOAT,false,0,0);
//生成矩阵
var m = new matIV();
//模型矩阵,视图矩阵,投影矩阵初始化
var mMatrix = m.identity(m.create());
var vMatrix = m.identity(m.create());
var pMatrix = m.identity(m.create());
var mvpMatrix = m.identity(m.create());
//视图坐标变换,
//第一个现在物体所在的坐标
//第二个我看向的地方的坐标
//第三个我的头部上方的方向向量
//第四个传一个标准的视图矩阵进去
m.lookAt([0.0,1.0,3.0],[0,0,0],[0,1,0],vMatrix);
//投影变换
m.perspective(90,c.width/c.height,0.1,100,pMatrix);
//矩阵相乘
m.multiply(pMatrix,vMatrix,mvpMatrix);
m.multiply(mvpMatrix,mMatrix,mvpMatrix);
//获取shader那里的mvpMatrix变量
var uniLocation = gl.getUniformLocation(prg,'mvpMatrix');
//传值到shader
gl.uniformMatrix4fv(uniLocation,false,mvpMatrix);
//画的方式是三角形,从零开始,三个一组
gl.drawArrays(gl.TRIANGLES,0,3);
//context刷新
gl.flush();
function create_shader(id){
var shader;
var scriptElement = document.getElementById(id);
if(!scriptElement){return;}
switch(scriptElement.type){
//顶点着色器
case 'x-shader/x-vertex':
shader = gl.createShader(gl.VERTEX_SHADER);
break;
//片段着色器
case 'x-shader/x-fragment':
shader = gl.createShader(gl.FRAGMENT_SHADER);
break;
default:
return;
}
//将标签为scriptElement.text的代码分配给shader
gl.shaderSource(shader,scriptElement.text);
//编译着色器
gl.compileShader(shader);
//判断是否编译成功
if(gl.getShaderParameter(shader,gl.COMPILE_STATUS)){
return shader;
}else{
alert(gl.getShaderInfoLog(shader));
}
}
function create_program(vs,fs){
//程序对象生成
var program = gl.createProgram();
//向程序对象分配(附加)着色器
gl.attachShader(program,vs);
gl.attachShader(program,fs);
//链接着色器
gl.linkProgram(program);
//判断是否链接成功
if(gl.getProgramParameter(program,gl.LINK_STATUS)){
//成功的话使用该程序
gl.useProgram(program);
return program;
}else{
alert(gl.getProgramInfoLog(program));
}
}
//创建顶点缓冲区对象
function create_vbo(data){
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vbo);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(data),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,null);
return vbo;
}
};