首先,将顶点座标传入着色器,需要遵循以下几步
- 1、创建缓冲区对象;
- 2、将缓冲区对象绑定到
target
上; - 3、将顶点座标数据写入缓冲区对象;
- 4、将缓冲区对象分配给对应得
attribute
变量; - 5、开启
attribute
变量;
1、非座标数据传入顶点着色器
所以将多个顶点相关得数据通过传冲去对象传入顶点着色器,其实只需要每种数据重复以上步骤即可;
首先,需要再顶点着色器中定义可以接收顶点大小得变量,此处片元着色器和之前一致;
attribute vec4 a_Position;
attribute float a_PointSize;
void main(){
gl_Position = a_Position;
gl_PointSize = a_PointSize;
}
然后就需要重复以上5
个步骤,将顶点大小数据传递给顶点着色器
var sizes = new Float32Array([10.0, 20.0, 30.0]);//此处需要传递的单精度浮点
此时,再webgl
系统中就存在两个缓冲区,一个是顶点位置数据,一个事顶点大小数据,因此 通过为顶点得每种数据建立一个缓冲区,然后分配给对应得 attribute 变量,就可以向顶点着色器传递多份逐顶点得数据信息;
2、gl.vertexAttribPointer
得步进和偏移参数
使用多个缓冲区对象向顶点着色器传递多种数据,比较适合数据量不大得情况,但是数据较大就不适合了,但是webgl
允许 将顶点得各种信息打包到一个缓冲区对象中;
var verticesSizes = new Float32Array([
// 两种数据打包到同一个缓冲区对象中去
// 顶点位置 和 尺寸数据
0.0, 0.5, 10.0, // 第一个点
0.5, -0.5, 20.0, // 第二个点
-0.5, -0.5, 30.0 // 第三个点
]);
那么 webgl
怎么区分里面得数据那个部分是顶带你位置和尺寸呢?
因为Float32Array
是类型化数组,可以通过静态属性BYTES_PER_ELEMENT
获得数组中每个元素所占得字节数;
在
Float32Array
的情况下返回4
详细请参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Float32Array
var FSIZE = verticesSize.BYTES_PER_ELEMENT;
1、将位置数据分配给 attribute
变量
// 将缓冲区对象分配给attribute变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 3, 0);
2、将顶点大小数据分配给 attribute
变量
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE * 3, FSIZE * 2);
下面来看下方法gl.vertexAttribPointer(location,size,type,normalize,stride,offset)
参数
- 1、
location
待分配的attribute
变量的存储位置; - 2、
size
指定缓冲区中,每个顶点的分量个数; - 3、
type
指定数据格式; - 4、
normalize
true
或者false
表明是否将非浮点型的数据归一化到[0,1]
或者[-1,1]
; - 5、
stride
指定两个顶点间的字节数,默认为0
; - 6、
offset
指定缓冲区对象中的偏移量(以字节为单位)
,即attribute
变量从缓冲区中的何处开始存储,若从起始位置,则参数为0
;
再来看下类型化数组
中的数据
var verticesSizes = new Float32Array([
// 两种数据打包到同一个缓冲区对象中去
// 顶点位置 和 尺寸数据
0.0, 0.5, 10.0, // 第一个点
0.5, -0.5, 20.0, // 第二个点
-0.5, -0.5, 30.0 // 第三个点
]);
如果想要获取每个顶点的数据,参数stride
需要是 字节数乘以第一个顶点的数据个数,所以是 SIZE * 3,前三个数据是一个顶点的信息;
但是怎么区分顶点位置和大小信息呢?
那就需要设置最后一个参数,偏移量参数 offset
距首个元素的偏移距离
,从0
开始;
顶点位置数据是前两个数据,因此距离首个元素的偏移距离是 0
;
顶点大小数据是每个顶点数据的第三个数据,因此距离首个元素的偏移距离是2
;
3、修改顶点颜色
首先,需要了解顶点着色器 如何向 片元着色器传递数据;
将顶点着色器中的数据传递给片元着色器,需要通过 varying
变量, varying变量存在的作用就是,从顶点着色器向片元着色器传递数据;
下面来看着色器代码
1、顶点着色器
attribute vec4 a_Position;
attribute vec4 a_Color; //用于接收外部的顶点颜色信息
varying vec4 v_Color;// 声明 varying 变量
void main(){
gl_Position = a_Position;
gl_PointSize = 10.0;//设置顶点大小
v_Color = a_Color;//将顶点颜色赋值给varying变量
}
2、片元着色器
precision mediump float; //声明浮点数精度
void main(){
gl_FragColor = v_Color;//从顶点着色器接收颜色数据
}
varying 变量只能是 float 类型的
在webgl
中 如果顶点着色器与片元着色器中有类型和命名都相同的 varying 变量 那么顶点着色器赋值给该变量的值就会被自动的传入片元着色器
所以顶点着色器中的 v_color
中的值被传递给了,片元着色器中的v_Color
变量;
4、几何形状的装配和光栅化
- 图形装配过程:这一步骤的任务是,将孤立的顶点座标装配成集合图形,集合图形的类别是由
gl.drawArrays()
方法的第一个参数决定; - 光栅化过程:这一步的任何是,将装配好的集合图形转化为片元;
变量 gl_Position
实际上是 几何图形装配阶段输入的数据,注意,集合图形装配过程又被称为 图元装配过程,因为被装配的基本图形 (点,线,面)又被称为 图元,图元就是图形的基本元素;
而 片元其实就是像素,那么显示在屏幕上的图形,就是通过将图形转换为 片元,这个过程是 光栅化;
光栅化过程结束后,程序就会 逐片元 的调用片元着色器,也就是说有多少个片元(像素)就会调用多少次片元着色器,每调用一次就处理一个片元,直到最后一个片元被处理后,浏览器就会显示最终的效果;
光栅化 过程中,生成的片元都是带有座标信息的,调用片元着色器时,这些座标信息也随着片元传了进去,因此可以通过片元着色器中的内置变量来访问片元的座标