目标:
1.了解 varying变量 的用法,以及顶点着色器与片元着色器的交流(即顶点着色器的数据进入片元着色器)
2.了解矩阵变换和动画的基础知识,让三角形绕z轴旋转起来
当顶点着色器与片元着色器varying的命名且类型相同时,顶点着色器的数据就会自动的传递给片元着色器,这样就可以达到数据传递。 而varying(变化的)可以把顶点设置成不同的颜色,解决uniform(统一)顶点颜色相同的问题。
矩阵变换:
webgl里按列主序的意思就是他的矩阵形式就是行和列进行交换,按上面的数据来写的话即为以z轴旋转。 但是这样太麻烦,会使用矩阵库来代替它进行旋转、平移、缩放。接下来我就直接用改良后的方法来说了。
uniform mat4 u_ModelMatrix;
gl_Position =u_ModelMatrix * a_Position;
先定义一个4*4的矩阵,然后用顶点坐标左乘它,就完成了矩阵变换。
var modelMatrix = new Matrix4();
modelMatrix.setRotate(currentAngle,0,0,1);
modelMatrix.translate(0,0.5,0);
var u_ModelMatrix = gl.getUniformLocation(gl.program,'u_ModelMatrix');
gl.uniformMatrix4fv(u_ModelMatrix,false,modelMatrix.elements);
这几行代码简单来说就是创建了一个矩阵对象,然后设置了平移和旋转。在得到attribute的u_ModelMatrix的存储地址后,把这个矩阵传递给它,进而顶点着色器就接收到了这个矩阵。最后一行中的modelMatrix.elements的原因是顶点着色器不能接收对象,需要得到的是个矩阵数据。
而变换的先后顺序可以简单记成带set的后进行,本例子就是先进行平移,再旋转。如何想反过来就换一下代码顺序:
modelMatrix.setTranslate(0,0.5,0);
modelMatrix.rotate(currentAngle,0,0,1);
缩放的话就是对矩阵的对角元素进行修改就好了(即x、y、z)
动画:
关于三角形的旋转其实就是不断地清除三角形和绘制三角形的过程。requesAnimationFrame(Rotates)和Rotates()这两个函数实现反复调用,我接下来直接把所有代码发出来吧。
var vsSource = `
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_ModelMatrix;
varying lowp vec4 v_Color;
void main(void){
gl_Position =u_ModelMatrix * a_Position;
gl_PointSize =20.0;
v_Color = a_Color;
}
`;
var fsSource = `
varying lowp vec4 v_Color;
void main(void){
gl_FragColor = v_Color;
}
`;
var gl;
function main() {
var canvas = document.getElementById('glcanvas');
gl = canvas.getContext('webgl');
initShaders();
var n =initBuffers(gl);
var u_ModelMatrix = gl.getUniformLocation(gl.program,'u_ModelMatrix');
var modelMatrix = new Matrix4();
var currentAngle =0.0;
function Rotates(){
currentAngle =animate(currentAngle)
draw(gl,n,currentAngle,modelMatrix,u_ModelMatrix)
requestAnimationFrame(Rotates)
}
Rotates()
}
function initShaders() {
let vsshader = gl.createShader(gl.VERTEX_SHADER);
let fsshader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vsshader, vsSource);
gl.shaderSource(fsshader, fsSource);
gl.compileShader(vsshader);
gl.compileShader(fsshader);
let program = gl.createProgram();
gl.attachShader(program, vsshader);
gl.attachShader(program, fsshader);
gl.linkProgram(program);
gl.useProgram(program);
gl.program = program
}
function initBuffers(gl) {
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
var verticesColors = new Float32Array ([
0.0,0.5,1.0,0.0,0.0,
-0.5,-0.5,0.0,1.0,0.0,
0.5,-0.5,0.0,0.0,1.0,
]);
var n=3
var vertexColorsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorsBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
var FSIZE = verticesColors.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE*5,0);
gl.enableVertexAttribArray(a_Position);
var a_Color = gl.getAttribLocation(gl.program,'a_Color');
gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE*5,FSIZE*2);
gl.enableVertexAttribArray(a_Color);
return n;
}
function draw(gl,n,currentAngle,modelMatrix,u_ModelMatrix){
modelMatrix.setRotate(currentAngle,0,0,1);
modelMatrix.translate(0,0.5,0);
gl.uniformMatrix4fv(u_ModelMatrix,false,modelMatrix.elements);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES,0,n)
}
var angle_step = 45.0;
var g_last = Date.now()
function animate(angle){
var now = Date.now();
var elapsed = now -g_last;
g_last = now;
var newAngle =angle + (angle_step * elapsed)/1000.0;
return newAngle %=360;
}
然后这个三角形会绕原点逆时针旋转并出现一个渐变色,渐变色的原因是顶点着色器中varying变量v_Color在传入片元着色器之前进行了内插过程。前者与后者的变量实际就不是一回事。
内插过程:
总结:
本篇内容其实写的不太细,尤其是动画方面,建议具体的还是大家结合书来学习吧。