「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
我们已经知道,webgl只能画点线面。不像2dcanvas的fill 和stroke. 如果要实现类似的效果,只能用三角形组合,因为webgl的线是没有宽度的。
三角形绘制有三种模式,独立三角形triangles 三角带 triangle-strip三角扇triangle。
我们先声明一下顶点数据 const points = new Float32Array( [0,0.5, -0.3,-0.3, 0.3, 0.3, -0.3,0.3, -0.6,-0.3, -0.4,0.5]);。
先绘制多段线看一下效果 。顺便标记一下起点。gl.drawArrays(gl.POINTS,0,1) //
TRIANGLES
独立三角形很好理解,就是每三个点就画一个三角形。如果你给着色器传了六个点,就能画出两个三角形,前面三个点和后面三个点的。 如果只有五个点只能画出一个三角形,七个点也只能画出两个三角形 。
调用gl.drawArrays(gl.TRIANGLES, 0, 6) 。看一下效果。
独立三角形就是这么简单。
TRIANGLES_STRIP
三角带,会复用上一个三角形的第二条边,作为本次三角形的第三条边,反方向绘制。 我们先来看效果gl.drawArrays(gl.TRIANGLE_STRIP, 0, 6)
连续绘制三角形,因此应该有4个三角形,不过上图似乎看不出来, 我们先画四个点gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
所以,问题来了,什么是一个三角形的第几条边,以及绘制方向。
三角形的方向
多个三角形的绘制方向不好确定,但是第一个三角形的绘制方向容易。 假如我们传给着色器的顶点顺序是 A B C 。那么,显然,第一条边就是AB ,第二条边就是BC ,第三条就是CA。 这个三角形的绘制方向就是 A-->B-->C-->A. 我们的第一个三角形就是逆时针绘制的。
所以 ,第二条边就是BC,反方向就是逆时针。结果就绘制出了
上面的两个三角形。 并且我们也确定了三角形BDC的绘制顺序,CB是第三条边,所以DC就是第二条边。 下一个三角形以此类推。
TRIANGLE_FAN
理解了三角形的绘制方向之后, 三角扇就很容易理解了。会复用上一个三角形的第三条边,作为本次三角形的第一条边,反方向绘制。 我们还是先来看四个点的效果。 我这个点位是随意画的,体现不了三角扇的语义。
三角扇的特点就是不管画多少个三角形,起点是不变的。 第一个三角形的起点是A,那么后面全部三角形的起点都会是A。
我们先简单的封装一个圆形的画法,用三角函数来实现。
const { sin, cos, PI} = Math ;
function createCircle ( r, center={x:0, y:0}, n=10){
const { x,y} = center ;
/* 我们从12点钟方向开始 因此夹角的正弦值是x方向的位移,余弦值是y方向的位移 因为最后一个三角形也要画出来所以取等 */
const points = [x,y, x,y+r]
for( let i= 1; i<=n; i++){
let angle =2* PI * i / n
points.push(x+r* sin(angle), y+ r *cos(angle))
}
return points ;
}
然后用这个来生成我们需要的点位,绘制三角形。顺便可以看一下多段线。我们用20个三角形组成了这个圆,全部的顶点数就是 3 + 19 =22。把顶点数改成22就能最后的圆了,虽然还不够圆。
const circlePoints = new Float32Array(createCircle(0.3,{x:0.1,y:0.1}, 20)) ;
gl.bufferData(gl.ARRAY_BUFFER, circlePoints, gl.STATIC_DRAW);
gl.drawArrays(gl.LINE_STRIP,0,10) // 多段线
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 10)
关于webgl三角形的介绍就到这里。