比以前就多了一点:
创建多个缓冲区,传入到顶点着色器中;
attribute float a_PointSize;//传入点的尺寸
gl_Position = a_Position;//设置点的尺寸
用bufferData把数据给a_PointSize
如图:
具体代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>设置各个点的尺寸</title>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute float a_PointSize;
void main(void){
gl_PointSize = a_PointSize;
gl_Position = a_Position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
void main(void){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
</script>
</head>
<body>
<canvas id="canvas" style=" background-color: black"></canvas>
<!--创建多个缓冲区,向着色器传值;这只适合数据量少的情况-->
<script>
onload = function () {
var canvas = document.getElementById("canvas");
canvas.width = 500;
canvas.height = 500;
var gl = canvas.getContext("webgl");
/*清空画板上的颜色,并初始化颜色*/
gl.clearColor(0.0, 0.0, 0.0, 1.0);
//设定canvas初始化时候的深度
gl.clearDepth(1.0);
//清空画面上的颜色
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//顶点着色器和片段着色器生成
var v_shader = create_shader("vs");
var f_shader = create_shader("fs");
// 程序对象的生成和连接
var program = create_program(v_shader, f_shader);
//获取a_Position变量的存储位置
var a_Position = gl.getAttribLocation(program,"a_Position");
var a_PointSize = gl.getAttribLocation(program,"a_PointSize");
//创建缓冲区
var vertices = new Float32Array([
0.0,0.5,-0.5,
-0.5,0.5,-0.5,
]);
/*各个点的尺寸*/
var sizes = new Float32Array([
10.0,20.0,30.0
]);
var n = 3;//点的个数
//创建缓冲区
var vertexBuffer = gl.createBuffer();
var sizeBuffer = gl.createBuffer();
if(!vertexBuffer){
console.log("Failed to create the buffer object");//缓冲区创建失败
return -1;
}
//将缓冲区绑定到目标对象
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//向缓冲区写入数据
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
//将缓冲区对象分配给a_Position; 参数一:传入数据;参数二:指定每个顶点传入多少个数(2表示只取两个数传入,剩下的两个数0.0和1.0补上;1.0是透明度,跟vertexAttrib2f()类似)
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
//连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
/*------ 点尺寸的数据传入------*/
gl.bindBuffer(gl.ARRAY_BUFFER,sizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER,sizes,gl.STATIC_DRAW);
gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(a_PointSize);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
//开始绘制,显示器显示结果;参数二:从哪个点开始绘制;参数三:绘制几个点
gl.drawArrays(gl.POINT, 0, n);
function create_program(v_shader, f_shader) {
var program = gl.createProgram();
gl.attachShader(program, v_shader);
gl.attachShader(program, f_shader);
gl.linkProgram(program);
gl.useProgram(program);
return program;
}
function create_shader(id) {
// 用来保存着色器的变量
var shader;
// 根据id从HTML中获取指定的script标签
var scriptElement = document.getElementById(id);
// 如果指定的script标签不存在,则返回
if (!scriptElement) {
return;
}
// 判断script标签的type属性
switch (scriptElement.type) {
// 顶点着色器的时候
case 'x-shader/x-vertex':
shader = gl.createShader(gl.VERTEX_SHADER);//生成顶点着色器
break;
// 片段着色器的时候
case 'x-shader/x-fragment':
shader = gl.createShader(gl.FRAGMENT_SHADER);//生成片元着色器
break;
default :
return;
}
// 将标签中的代码分配给生成的着色器
gl.shaderSource(shader, scriptElement.text);
// 编译着色器
gl.compileShader(shader);
// 判断一下着色器是否编译成功
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
// 编译成功,则返回着色器
return shader;
} else {
// 编译失败,弹出错误消息
alert(gl.getShaderInfoLog(shader));
}
}
function create_program(vs, fs) {
// 程序对象的生成
var program = gl.createProgram();
// 向程序对象里分配着色器
gl.attachShader(program, vs);
gl.attachShader(program, fs);
// 将着色器连接
gl.linkProgram(program);
// 判断着色器的连接是否成功
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
// 成功的话,将程序对象设置为有效
gl.useProgram(program);
// 返回程序对象
return program;
} else {
// 如果失败,弹出错误信息
alert(gl.getProgramInfoLog(program));
}
}
}
</script>
</body>
</html>
还有另一种方式:就是点的位置数据和尺寸放在一起;
例如:
var verticesSizes = new Float32Array([ 0.0,0.5,10.0, -0.5, -0.5,20.0, 0.5,-0.5,30.0 ]);
前面两个数据是点的位置信息,第三个数是尺寸信息;
着色器设置:
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute float a_PointSize;
void main(void){
gl_PointSize = a_PointSize;
gl_Position = a_Position;
}
</script>
那么是怎么区分他们呢?
//将缓冲区对象分配给a_Position; 参数一:传入数据;参数二:指定每个顶点传入多少个数(2表示只取两个数传入,剩下的两个数0.0和1.0补上;1.0是透明度,跟vertexAttrib2f()类似)
//参数五:相邻两个点字节数;传入的相当于一个点属性的字节大小,然后着色器根据这个获取;参数六:偏移数,从哪个开始;
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE*3,0);
FSIZE*3 是一个数据的大小,而一个数据包含了点位置和尺寸
所以用 第六参数和第二参数去设置;FSIZE是得到数组中每个元素的大小(字节数)
如:var FSIZE = verticesSizes.BYTES_PER_ELEMENT;//得到数组中每个元素的大小(字节数)
解读上面意思:一个数据节的大小是FSIZE*3(它里面包含了位置和尺寸),从O开始读两个数据(也就是0.0 和0.5),传入到a_Position 缓冲区中,a_Position 缓冲区绑定到着色器里的a_Position;然后着色器才去一一执行; 如果还不明白,那我就简单比喻,就好比一个流水线一样,现在我用盒子把点和尺寸装起来,现在流水线上就是一个一个的盒子,告诉机器,一个盒子是一个点的信息,盒子里面的前两个是位置信息,后面一个是尺寸;这样就很好的区分,也把一个数据包装在一起;
如图:
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>设置各个点的尺寸-顶点和尺寸在一个数据里(适合数据量大的情景)</title>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute float a_PointSize;
void main(void){
gl_PointSize = a_PointSize;
gl_Position = a_Position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
void main(void){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
</script>
</head>
<body>
<canvas id="canvas" style=" background-color: black"></canvas>
<!--创建多个缓冲区,向着色器传值;这只适合数据量少的情况-->
<script>
onload = function () {
var canvas = document.getElementById("canvas");
canvas.width = 500;
canvas.height = 500;
var gl = canvas.getContext("webgl");
/*清空画板上的颜色,并初始化颜色*/
gl.clearColor(0.0, 0.0, 0.0, 1.0);
//设定canvas初始化时候的深度
gl.clearDepth(1.0);
//清空画面上的颜色
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//顶点着色器和片段着色器生成
var v_shader = create_shader("vs");
var f_shader = create_shader("fs");
// 程序对象的生成和连接
var program = create_program(v_shader, f_shader);
//获取a_Position变量的存储位置
var a_Position = gl.getAttribLocation(program,"a_Position");
var a_PointSize = gl.getAttribLocation(program,"a_PointSize");
//顶点和点的尺寸
var verticesSizes = new Float32Array([
0.0,0.5,10.0,
-0.5, -0.5,20.0,
0.5,-0.5,30.0
]);
var n = 3;//点的个数
//创建缓冲区
var vertexSizeBuffer = gl.createBuffer();
var sizeBuffer = gl.createBuffer();
if(!vertexSizeBuffer){
console.log("Failed to create the buffer object");//缓冲区创建失败
return -1;
}
//将缓冲区绑定到目标对象
gl.bindBuffer(gl.ARRAY_BUFFER,vertexSizeBuffer);
//向缓冲区写入数据
gl.bufferData(gl.ARRAY_BUFFER,verticesSizes,gl.STATIC_DRAW);
var FSIZE = verticesSizes.BYTES_PER_ELEMENT;//得到数组中每个元素的大小(字节数)
//将缓冲区对象分配给a_Position; 参数一:传入数据;参数二:指定每个顶点传入多少个数(2表示只取两个数传入,剩下的两个数0.0和1.0补上;1.0是透明度,跟vertexAttrib2f()类似)
//参数五:相邻两个点字节数;传入的相当于一个点属性的字节大小,然后着色器根据这个获取;参数六:偏移数,从哪个开始;
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE*3,0);
//连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
/*------ 点尺寸的数据传入------*/
gl.bindBuffer(gl.ARRAY_BUFFER,vertexSizeBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesSizes,gl.STATIC_DRAW);
gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,FSIZE*3,FSIZE*2);
gl.enableVertexAttribArray(a_PointSize);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
//开始绘制,显示器显示结果;参数二:从哪个点开始绘制;参数三:绘制几个点
gl.drawArrays(gl.POINT, 0, n);
function create_program(v_shader, f_shader) {
var program = gl.createProgram();
gl.attachShader(program, v_shader);
gl.attachShader(program, f_shader);
gl.linkProgram(program);
gl.useProgram(program);
return program;
}
function create_shader(id) {
// 用来保存着色器的变量
var shader;
// 根据id从HTML中获取指定的script标签
var scriptElement = document.getElementById(id);
// 如果指定的script标签不存在,则返回
if (!scriptElement) {
return;
}
// 判断script标签的type属性
switch (scriptElement.type) {
// 顶点着色器的时候
case 'x-shader/x-vertex':
shader = gl.createShader(gl.VERTEX_SHADER);//生成顶点着色器
break;
// 片段着色器的时候
case 'x-shader/x-fragment':
shader = gl.createShader(gl.FRAGMENT_SHADER);//生成片元着色器
break;
default :
return;
}
// 将标签中的代码分配给生成的着色器
gl.shaderSource(shader, scriptElement.text);
// 编译着色器
gl.compileShader(shader);
// 判断一下着色器是否编译成功
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
// 编译成功,则返回着色器
return shader;
} else {
// 编译失败,弹出错误消息
alert(gl.getShaderInfoLog(shader));
}
}
function create_program(vs, fs) {
// 程序对象的生成
var program = gl.createProgram();
// 向程序对象里分配着色器
gl.attachShader(program, vs);
gl.attachShader(program, fs);
// 将着色器连接
gl.linkProgram(program);
// 判断着色器的连接是否成功
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
// 成功的话,将程序对象设置为有效
gl.useProgram(program);
// 返回程序对象
return program;
} else {
// 如果失败,弹出错误信息
alert(gl.getProgramInfoLog(program));
}
}
}
</script>
</body>
</html>