目录
动态绘制点
在initBuffer中加入监听事件,代码如下
document.addEventListener("mousedown", function (e) {
debugger
let x = e.clientX;
let y = e.clientY;
let rect = e.target.getBoundingClientRect();
let pointx = ((x - rect.left) - 512) / 512;
let pointy = (350 - (y - rect.top)) / 350;
points.push(pointx);
points.push(pointy);
points.push(0);
let pointPosition = new Float32Array(points);
let pointBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, pointBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, pointPosition, webgl.STATIC_DRAW);
webgl.enableVertexAttribArray(aPsotion);
webgl.vertexAttribPointer(aPsotion, 4, webgl.FLOAT, false, 0, 0*4);
//下面的代码可以放在draw中,为了方便做笔记,才放在了initBuffer中
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);
webgl.drawArrays(webgl.POINTS, 0, points.length / 3);
})
1.计算坐标
这里的rect可以看作webgl和canvas的边距
注意:
webgl坐标系中x,y,z最大都是1,所以算法来的结果要除canvas长或者宽的一半;
webgl的y坐标系是正轴往上的,canvas是正轴往下的,所以求出的y坐标要加个负号
之后在放入points中(自己定义的数组),z坐标是0(因为我们现在是平面不考虑z轴)
2.webgl绑定并使用
bindBuffer是将webglpoint缓冲区与数组缓冲区绑定
bufferData绑定后的赋值,将位置信息以STATIC_DRAW(静态数据)的形式存入缓冲区
要赋值到aPosition中必须先启用它,用enableVertexAttribArray函数
vertexAttribPointer将缓冲区的值赋值到aPosition,其中参数分别表示:赋值的对象,赋值几个参数,格式是什么,是否转置,步长(这里传0传3*4都可以),从多少字节偏移开始
注意
这里要把shader代码改了
void main(void){
gl_Position = vec4(a_position,1.0);
gl_PointSize=60.0;
}
不能再用proj乘了,不然相当于没有坐标变换,每个点都会离canvas的原点巨近,而且注意gl_Position是4维的,所以要补一位
绘制线
gl.LINES 两点连成一条线
gl.LINES_STRIP逐个连线(头尾不相连)
gl.LINES_LOOP逐个连线(头尾相连)
多个点绘制注意
单个点直接用vertexAttrib4fv赋值即可
多个点无论是线还是多点,都是用buffer间接传值(如动态点绘制)
绘制图形
gl.TRANGLES
(注意这个和gl.LINES_LOOP的区别,这个是中间上色的,lines只连起来,是中空的。)
gl.TRANGLE_STRIP(多点连三角形)
gl.TRANGLE_FAN
(第一个三角形正常,下一个三角形是第一个三角形的最后一条边和下一个点组成的三角形,可能会遮住之前的点)
旋转,平移
先分析坐标变换,再用公式写入顶点shader中
旋转:
uniform mat4 proj;
attribute vec3 a_position;
uniform float angle;
void main(){
gl_Position =vec4(a_position.x*cos(angle)-a_position.y*sin(angle),a_position.x*sin(angle)+a_position.y*cos(angle),0,1.0);
// gl_Position =vec4(a_position,1.0);
}
平移:
attribute vec3 a_position;
uniform float anglex;
uniform float angley;
void main(){
gl_Position = vec4(a_position.x+anglex,a_position.y+angley,0,1.0);
}
之后只要用uniform1f之类的给相应变量赋值即可
如果要用键盘进行控制,则如下代码:
function initEvent() {
document.onkeydown = handleKeyDown;
}
function handleKeyDown(event) {
if (String.fromCharCode(event.keyCode) == 'W') {
angley += 0.01;
}
else if (String.fromCharCode(event.keyCode) == 'S') {
angley -= 0.01;
}
else if (String.fromCharCode(event.keyCode) == 'A') {
anglex -= 0.01;
}
else if (String.fromCharCode(event.keyCode) == 'D') {
anglex += 0.01;
}
}
还要再onload里面加入requestAnimationFrame,实现逐帧循环
function onLoad() {
init()
window.requestAnimationFrame(onLoad)
}