看过上一节的内容,应该对webgl有了大概的认识,但还是有的模糊不清。这一节内容关键来讲解一下,buffer和attribute,webgl怎么使用buffer,怎么给对应的顶点赋值的。
attribute
在glsl语法中 attribute 用来传递逐顶点数据(per-vertex data),例如顶点的位置、颜色、法线、纹理坐标等。 这些数据在顶点着色器中处理,每个顶点都会有一个独立的 attribute值。片元着色器是逐片元(per-fragment)执行的,它的输入是顶点着色器输出的插值结果(如 varying
变量)。片元着色器无法直接访问逐顶点的 attribute
数据,因为片元着色器的执行与顶点没有直接对应关系。片元着色器可以通过变量 varying,访问到顶点着色器的attribute。完成片元着色器和顶点着色器的互动。
buffer
缓冲操作是在GPU上获取顶点和其他顶点数据的一种方式,gl.createBuffer
创建一个缓冲;gl.bindBuffer
是设置缓冲为当前使用缓冲; gl.bufferData
将数据拷贝到缓冲。一旦数据存到缓冲中,需要启用缓冲数,并且告诉WebGL怎么从缓冲中提取数据传给顶点着色器的属性。
片元着色器插值
如果片元着色器使用变量的话,他会根据顶点的颜色进行插值,在片元之间进行平滑过渡。效果如下:
下面看源码,地址: gitee.com/feng-lianxi...
顶点着色器:
ini
// an attribute will receive data from a buffer
attribute vec2 a_position;
uniform vec2 u_resolution;
// attribute vec4 a_position;
// all shaders have a main function
varying vec4 v_color;
attribute vec4 a_color;
void main() {
// gl_Position is a special variable a vertex shader
// is responsible for setting
// 从像素坐标转换到 0.0 到 1.0
vec2 zeroToOne = a_position - u_resolution / 2.0;
// 再把 0->1 转换 0->2
vec2 zeroToTwo = zeroToOne / u_resolution * 2.0;
// 把 0->2 转换到 -1->+1 (裁剪空间)
// vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(zeroToTwo, 0, 1);
gl_PointSize = 10.0;
v_color = a_color;
}
注意这里的变量 v_color,还有属性值a_color,我们将属性值赋值个变量。片元着色器是使用变量渲染的,不能和顶点属性对应。
片元着色器:
csharp
precision mediump float;
// uniform vec4 u_color;
varying vec4 v_color;
void main() {
// gl_FragColor is a special variable a fragment shader
// is responsible for setting
gl_FragColor = v_color; // return redish-purple
}
获取渲染程序的属性值:
ini
var colorLocation = gl.getAttribLocation(program, "a_color");
创建buffer,并且将buffer绑定到,ARRAR_BUFFER上,
ini
var colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
随机设置八个顶点的颜色值:
ini
function setColors(gl) {
// 生成两个随机颜色
var r1 = Math.random();
var b1 = Math.random();
var g1 = Math.random();
var r2 = Math.random();
var b2 = Math.random();
var g2 = Math.random();
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(
[ r1, b1, g1, 1,
r1, b1, g1, 1,
r1, b1, g1, 1,
r2, b2, g2, 1,
r2, b2, g2, 1,
r2, b2, g2, 1]),
gl.STATIC_DRAW);
}
启用该属性,并且告诉webgl引擎怎么来取这些值:
ini
gl.enableVertexAttribArray(colorLocation);
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
我们将来写到3D的时候,还可以引入顶点法向量的概念。
总结
通过这两节的内容,再配合手动敲一下代码,相信会对使用glsl语言做平面图形不再陌生。下一节是重点内容,重点讲解着色器和GLSL语法。其实写GLSL程序就是写着色器,并且将来关于怎么写着色器我会专门写一系列文章。