全部章节
06.frameBuffer-将webgl绘制的正方体作为材质
绘制直线
上章我们学会了给着色器程序传值的一种方式,并存放多个点的数据在缓冲区,一次性绘制多个点。 本章我们沿用上章的程序,做简单的修改来讲解如何在webgl中绘制其他的图形。
效果
代码
<canvas id="cvs" style="width: 400px; height: 400px" height="400px" width="400px"></canvas>
<script src="./03customApi.js"></script>
<script>
const VS = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = a_Position;
gl_PointSize = 10.0;
v_Color = a_Color;
}
`;
const FS = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;
</script>
<script>
const cvs = document.getElementById('cvs')
const gl = cvs.getContext('webgl')
initShader(gl, VS, FS)
const n = bindBuffer(gl, [
{
name: 'a_Position',
size: 3,
type: gl.FLOAT,
stride: 6,
offset: 0
},
{
name: 'a_Color',
size: 3,
type: gl.FLOAT,
stride: 6,
offset: 3
},
], new Float32Array([
-0.5, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
0.5, 0.0, 0.0, 0.0, 0.0, 1.0,
0.75, 0.5, 0.0, 0.0, 0.0, 1.0,
]))
gl.clearColor(1.0, 1.0, 1.0, 1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.LINES, 0, n)
</script>
解释
gl_PointSize只有在gl.POINTS的绘制模式下才有效,该程序中无效,线看不太清,就改成白色了。
把bindBuffer的实现放在customApi.js中了。然后多加了一个点的信息。
drawArrays的第一个参数
drawArrays的第二个参数和第三个参数上章讲过了,起始绘制点和总绘制的点数。
本章主要就是围绕的是drawArrays的第一个参数。 第一个参数是绘制的方式,我们看一下有哪些值
- gl.POINTS: 绘制一系列点。
- gl.LINES: 绘制一系列单独线段。每两个点作为端点,线段之间不连接。
- gl.LINE_STRIP: 绘制一个线条。即,绘制一系列线段,上一点连接下一点。
- gl.LINE_LOOP: 绘制一个线圈。即,绘制一系列线段,上一点连接下一点,并且最后一点与第一个点相连。
- gl.TRIANGLES: 绘制一系列三角形。每三个点作为顶点。
- gl.TRIANGLE_STRIP:绘制一个三角带。
- gl.TRIANGLE_FAN:绘制一个三角扇。
第一个就是绘制一个个点,之前两章一直在使用。 本例中使用了第二个,绘制多个线段,接下来我们依次介绍每种绘制方式的特点。
gl.POINTS
绘制点,根据first和count的值获取缓冲区存在的对应数量的点,并绘制,如果缓冲区的点数量不够就会报错。
gl.LINES
绘制线段,和绘制点差不多,同样缓存区的点的数量不够会报错。
不一样的是,如果绘制的点数量为奇数,会忽略最后一个点。
从结果中,我们两个点之间的颜色会根据两个点的颜色去渐变
当然也有办法阻止这样的渐变,可以利用gl_FragCoord或者gl_PointCoord这两个内置变量去处理,简单理解为一个是像素点的位置,一个片元坐标。
我们把片元着色器中的
gl_FragColor = v_Color;
替换成
gl_FragColor = gl_PointCoord.x < -0.25 ? vec4(1.0,0.5,0.5,1.0) : v_Color;
然后查看第一条线段的变化
同样我们用图来直观的理解一下LINES
gl.LINE_STRIP
连续绘制线段,第一个点和第二个点相连,第二个点和第三个点相连,以此类推,颜色规律也是两点的颜色渐变
gl.LINE_LOOP
连续绘制线段,第一个点和第二个点相连,第二个点和第三个点相连,最终第一个点和最后一个点相连,颜色规律也是两点的颜色渐变
gl.TRIANGLES
每三个点绘制一个三角形,多出来的少于三个的点忽略,颜色规律是三个点之间的渐变
当前程序中的四个点,无法绘制三角形,因为前三个点处于一条直线,无法形成三角形,但是我们可以把frist改成1,count改成3,用后三个点绘制。
不过为了更好的演示后面的绘制模式,我们将输入的四个点改成另外的六个点
0, -0.5, 0.0, 1.0, 0.0, 0.0, // 红色
0.5, 0, 0.0, 0.0, 1.0, 0.0, // 绿色
0.25, 0.25, 0.0, 0.0, 0.0, 1.0, // 蓝色
0, 0.8, 0.0, 1.0, 1.0, 0.0, // 黄色
-0.5, -0.5, 0.0, 0.0, 1.0, 1.0, // 淡蓝
-0.5, -0.8, 0.0, 1.0, 0.0, 1.0 // 紫色
gl.TRIANGLE_STRIP
连续绘制三角形,0,1,2形成第一个三角形,1,2,3形成第二个三角形,2,3,4形成第三个三角形,一直到最后不满足三个点。
由于每个点设置的颜色不同,所以每个三角形都是渐变色的,最终连续的绘制导致结果如上图,不是很清晰。
我们使用drawElements,利用gl.TRIANGLES去模拟gl.TRIANGLE_STRIP的绘制行为。
drawElements具体会在下一章讲解,本章中仅展示一个用gl.TRIANGLES模拟的结果,让大家更好的去理解。
6个点,通过模拟可以看出最终绘制出了4个三角形。 我们在使用gl.POINTS,直观的看一下6个点的位置
gl.TRIANGLE_FAN
绘制三角扇,即第一个点和每两个连续点绘制一个三角形,比如说上述六个点,1,2,3绘制一个三角形,1,3,4绘制一个三角形,1,4,5绘制一个三角形,1,5,6绘制一个三角形。
结果还是看不太清楚,我们看一下模拟的结果
总结
本章基于上章的程序上,仅对点的数据和drawArrays的入参做修改,详细了解了webgl中的七种绘制模式,以及drawArrays这个API。
在我们实际使用中,最常用的绘制模式就是gl.TRIANGLES,就像经常听到的每个模型都是由三角面组成的,本章中对于TRIANGLE_STRIP和TRIANGLE_FAN的模拟也是通过TRIANGLES实现的,实现的方法会在下一章中涉及到。