WebGL编程指南三:js向shader一次传入多个(点)的坐标位置值和多个点的尺寸值

目标:

  1. 在canvas中绘制基本图形以及js向shader一次传入多个(点)坐标位置值

基本概念

  • 构成三维模型的基本单位是三角形,不论其形状多么复杂。通过创建更细小和更大量的三角形,就可以创建更复杂和更逼真的三维模型。

  • 缓冲区对象:WebGL系统中的一块内存区域,我们可以一次性向缓冲区对象中填充大量的顶点数据,然后将这些数据保存在其中,以供顶点着色器使用。
    使用缓冲区对象向顶点着色器传入多个顶点数据的五个步骤:
    (创建缓冲区对象前WebGL里的状态)

    1. 创建缓冲区对象(gl.createBuffer())

    2. 绑定缓冲区对象(gl.bindBuffer());【就是将缓冲区对象绑定到WebGL系统中已经存在的目标(target)上,这个目标表示缓冲区对象的用途(如:向顶点着色器提供传给attribute变量的数据),这样WebGL才能正确处理其中的内容。】

    3. 将数据写入缓冲区对象(gl.bufferData());【我们不能直接向缓冲区写入数据,只能向目标(target)写入数据,所以要向缓冲区写入数据,必须先绑定。】

    4. 将缓冲区对象分配给一个attribute变量(gl.vertexAttribPointer())【gl.vertexAttrib[1234]f系列函数一次只能向attribute变量分配一个值,vertexAttribPointer可以将整个缓冲区对象(的指针)分配给attribute变量】

    5. 开启attribute变量(gl.enableVertexAttribArray())【为了使顶点着色器能够访问缓冲区内的数据,虽然函数名称似乎表示该函数是处理顶点数组的,但实际上它处理的对象是缓冲区,这是历史原因造成的】

类型化数组

为了绘制三维图形,WebGL通常需要同时处理大量相同类型的数据,如顶点的坐标和颜色数据。为了优化性能(普通Array既可以存数字也可存字符串,并没有对“大量元素都是同一种类型”这种情况进行优化),WebGL为每种基本数据类型引入了一种特殊的数组(类型化数组),浏览器事先知道数组中的数据类型,所有处理起来更加有效率。WebGL中很多操作都要用到类型化数组
在这里插入图片描述

必须掌握的方法(js向shader一次传入多个(点)的坐标位置值和多个点的尺寸值)
  1. gl.createBuffer(); 创建缓冲区对象;
    参数:无;
    返回值:非null 新创建的缓冲区对象; null 创建缓冲区对象失败;

  2. gl.deleteBuffer(buffer); 删除参数buffer表示的缓冲区对象
    参数:buffer 待删除的缓冲区对象
    返回值:无

  3. gl.bindBuffer(target,buffer) 允许使用buffer表示的缓冲区对象并将其绑定到target表示的目标上
    参数:
    target 表示缓冲区对象的用途,这样WebGL才能够正确处理其中的内容,可选值有 gl.ARRAY_BUFFER(表示缓冲区对象中包含了顶点的数据); gl.ELEMENT_ARRAY_BUFFER (表示缓冲区对象中包含了顶点的索引值);
    buffer (指定之前由gl.createBuffer()返回的待绑定的缓冲区对象),如果指定为null,则禁用对target的绑定。
    返回值:无

  4. gl.bufferData(target,data,usage)开辟存储空间,向绑定在target上的缓冲区对象中写入数据data
    参数:
    target同上,可选值gl.ARRAY_BUFFERgl.ELEMENT_ARRAY_BUFFER;
    data 写入缓冲区对象的数据(类型化数组);
    usage 表示程序将如何使用存储在缓存区对象中的数据,可选值gl.STATIC_DRAW(只会向缓冲区对象中写入一次数据,但需要绘制很多次),gl.STREAM_DRAW(只会向缓冲区对象写入一次数据,然后绘制若干次),gl.DYNAMIC_DRAW(会向缓冲区对象中多次写入数据,并绘制很多次)
    返回值:无

  5. gl.vertexAttribPointer(location,size,type,normalized,stride,offset)将绑定到gl.ARRAY_BUFFER的缓冲区对象分配给由location指定的attribute变量;
    参数:
    location 待分配的attribute变量的存储位置;
    size 指定缓冲区中每个顶点的分量个数(1到4),若size比attribute变量需要的分量数小,缺失分量将按照与gl.vertexAttrib[1234]f()相同的规则自动补全,如:如果size为1,那么第2 3分量自动设为0,第四分量为1;
    type 指定数据格式,可选值:gl.UNSIGEND_BYTE, gl.SHORT,gl.UNSIGNED_SHORT, gl.INT, gl.UNSIGEND_INT, gl.FLOAT
    normalize 传入true或false,表明是否将非浮点型的数据归一化到[0,1]或[-1,1]区间;
    stride 指定相邻两个顶点间的字节数,默认为0(也可解释为在缓冲区对象中,单个顶点的所有数据【如顶点坐标,尺寸,颜色】总的字节数。也就是相邻两个顶点间的距离,即步进参数);
    offset 指定缓冲区对象中的偏移量(以字节为单位),即attribute变量从缓冲区中的何处开始存储。
    返回值:无

  6. gl.enableVertexArray(location)开启location指定的attribute变量;
    参数: location attribute变量的存储位置;
    返回值:无

  7. gl.disableVertexArray(location)关闭location指定的attribute变量;
    返回值:无

  8. gl.drawingBufferWidth 获取颜色缓冲区的宽度(了解)

  9. gl.drawingBufferHeight获取颜色缓冲区的高度(了解)

示例:
var VSHADER_SOURCE = `
	attribute vec4 a_Position;\n
	attribute float a_PointSize;\n
	void main(){\n
		gl_Position = a_Position;\n
		gl_PointSize = a_PointSize;\n
	}\n
`

var FSHADER_SOURCE = `
	void main(){\n
		gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n
	}\n
`

function main() {
	var canvas = document.getElementById('webgl');
	var gl = getWebGLContext(canvas);
	gl.clearColor(0.0,0.0,0.0,1.0);
	if (!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)) {
		return;
	}
	var n = initVertexBuffers(gl);
	gl.clear(gl.COLOR_BUFFER_BIT);
	gl.drawArrays(gl.POINTS,0,n);
}
main();
function initVertexBuffers(gl) {
	// 顶点的坐标和尺寸
	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();
	// 将缓冲区对象绑定到目标
	gl.bindBuffer(gl.ARRAY_BUFFER,vertexSizeBuffer);
	// 给目标赋值
	/* @param
		*target(gl_ARRAY_BUFFER或gl.ELEMENT_ARRAY_BUFFER);
		*data(写入缓冲区对象的数据----类型化数组)
		*usage(表示程序将如何使用存储在缓冲区对象中的数据,帮助WebGL优化操作,就算传入错误的值也不会终止程序)
	*/
	gl.bufferData(gl.ARRAY_BUFFER,verticesSizes,gl.STATIC_DRAW);
	// 将verticeSize数组中每个元素的大小(字节数)存储到FSIZE中。
	// 类型化数组具有BYTES_PER_ELEMENT属性,可以从中获知数组中每个元素所占的字节数
	var FSIZE = verticesSizes.BYTES_PER_ELEMENT;
	
	var a_Position = gl.getAttribLocation(gl.program,'a_Position');
	// vertexAttribPointer 将缓冲区对象分配给a_Position变量
	/* @param:
		*location(变量地址),
		*size(指定缓冲区中每个顶点的分量个数,比如本例中顶点只给了x,y,所以分量为2),
		*type(指定数据格式),
		*normalized(是否将非浮点型的数据归一化到[0,1]或[-1,1]区间),
		*stride(指定相邻两个顶点间的字节数,默认为0,(也可解释为在缓冲区对象中,单个顶点的所有数据【如顶点坐标,尺寸,颜色】总的字节数。也就是相邻两个顶点间的距离,即步进参数)),
		*offset(缓冲区对象中的偏移量,以字节为单位,即attribute变量从缓存区中的何处开始存储)
	*/
	gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,FSIZE*3,0);
	gl.enableVertexAttribArray(a_Position);

	var a_PointSize = gl.getAttribLocation(gl.program,'a_PointSize');
	gl.vertexAttribPointer(a_PointSize,1,gl.FLOAT,false,FSIZE*3,FSIZE*2);
	gl.enableVertexAttribArray(a_PointSize);
 	return n;
}

绘制结果:
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值