【WebGL】gl.enableVertexAttribArray和gl.disableVertexAttribArray的理解

介绍

enableVertexAttribArray 是 WebGL 中的一个方法,用于启用指定位置的顶点属性数组。

在WebGL中,图形渲染通常涉及到顶点数据的传递和处理。enableVertexAttribArray 用于启用顶点着色器中的属性变量,使得 WebGL 能够使用这些属性的数据进行渲染。
具体用法如下:

var positionAttribLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionAttribLocation);

这样,顶点着色器中的 position 属性就被启用了,表示 WebGL 应该使用缓冲区中的数据来渲染顶点。
一般而言,enableVertexAttribArray 需要和 gl.vertexAttribPointer 配合使用。gl.vertexAttribPointer 用于指定顶点属性数组的数据格式和存储方式。在启用了顶点属性后,你可以使用它们来渲染图形。

讲解

下面案例就是绘制两个三角面,第一个attributepositioncolor,分别使用enableVertexAttribArray开启positioncolor后,渲染第一个彩色顶点着色三角面,然后disableVertexAttribArray(color),关闭color,再渲染第二个三角面可以看到颜色值没传进去,颜色使用的默认的黑色vecr(0.0)

gl.disableVertexAttribArray(colorLoc);

注意1

enableVertexAttribArray 的状态是在 WebGL 上下文中全局的,而不是特定于单个顶点着色器程序。一旦启用了某个顶点属性,这个状态就会一直保持,直到被禁用。

所以,如果在使用一个顶点着色器程序中启用了某个顶点属性,然后切换到另一个顶点着色器程序,你通常不需要再次调用 enableVertexAttribArray。已经启用的顶点属性状态会保持有效,直到显式地调用 gl.disableVertexAttribArray(index) 关闭。

// 启用顶点属性
var positionAttribLocation = gl.getAttribLocation(program1, 'position');
gl.enableVertexAttribArray(positionAttribLocation);

// ... 在 program1 中绘制 ...

// 不需要再次启用,状态会保持有效
var positionAttribLocation2 = gl.getAttribLocation(program2, 'position');

// ... 在 program2 中绘制 ...

在这个例子中,我们在 program1 中启用了 ‘position’ 属性,然后在切换到 program2 之后,不需要再次调用 gl.enableVertexAttribArray(positionAttribLocation2)。已经启用的状态会保持有效。

需要注意的是,当你在使用不同的着色器程序时,你可能需要重新设置 gl.vertexAttribPointer,因为不同的顶点着色器程序可能对顶点属性的数据格式有不同的要求。但 enableVertexAttribArray 只需要在首次设置时启用,之后会保持有效。

注意2

注意一下啊,这个方法之前理解一直是错误的,比如有两个shader,分别是shaderAshaderB

shaderA里面有两个attribute,分别是positioncolor
shaderB里面只有一个attribute,是position

此时当使用shaderA绘制的时候肯定会调用gl.enableVertexAttribArray激活positioncolor

完了再使用shaderB绘制的时候如果shaderA之前没有调用gl.disableVertexAttribArray关闭positioncolor的话,这里碰巧可能不会出现问题,就不需要调用gl.enableVertexAttribArray激活自己position了,但是最好是使用完就关闭掉

完整案例

<!doctype html>
<html>

<head>
	<meta charset="utf-8" />
	<title>Basic Draw Rectangle</title>
</script>
</head>

<body>
	<canvas id="canvas" width="400" height="400"></canvas>
	<script>
		const canvas = document.querySelector('canvas');
		const gl = canvas.getContext('webgl');

		const vsGLSL = `
  attribute vec4 position;
  attribute vec4 color;

  uniform vec4 offset;

  varying vec4 v_color;

  void main() {
    gl_Position = position + offset;
    v_color = color;
  }
`;

		const fsGLSL = `
  precision highp float;
  varying vec4 v_color;
  void main() {
    gl_FragColor = v_color;
  }
`;

		const createShader = function (gl, type, glsl) {
			const shader = gl.createShader(type)
			gl.shaderSource(shader, glsl)
			gl.compileShader(shader)
			if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
				throw new Error(gl.getShaderInfoLog(shader))
			}
			return shader
		};

		const compileShadersAndLinkProgram = function (gl, prg, vsGLSL, fsGLSL) {
			const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsGLSL)
			const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsGLSL)
			gl.attachShader(prg, vertexShader)
			gl.attachShader(prg, fragmentShader)
			gl.linkProgram(prg)
			if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
				throw new Error(gl.getProgramInfoLog(prg))
			}
			// NOTE! These are only here to unclutter the diagram.
			// It is safe to detach and delete shaders once
			// a program is linked though it is arguably not common.
			// and I usually don't do it.
			gl.detachShader(prg, vertexShader)
			gl.deleteShader(vertexShader)
			gl.detachShader(prg, fragmentShader)
			gl.deleteShader(fragmentShader)
			return prg
		};

		const prog = gl.createProgram();
		compileShadersAndLinkProgram(gl, prog, vsGLSL, fsGLSL);
		const positionLoc = gl.getAttribLocation(prog, 'position');
		const colorLoc = gl.getAttribLocation(prog, 'color');
		const offsetLoc = gl.getUniformLocation(prog, 'offset');

		// vertex positions for triangle
		const vertexPositions = new Float32Array([
			0.0, 0.4,
			-0.4, -0.4,
			0.4, -0.4,
		]);

		const vertexColors = new Float32Array([
			1, 1, 0, 1,  // yellow
			0, 1, 1, 1,  // cyan
			1, 0, 1, 1,  // magenta
		]);

		const positionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, vertexPositions, gl.STATIC_DRAW);

		const colorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
		gl.bufferData(gl.ARRAY_BUFFER, vertexColors, gl.STATIC_DRAW);

		// this is not needed. It's just here to unclutter the diagram
		gl.bindBuffer(gl.ARRAY_BUFFER, null);

		// above this line is initialization code
		// --------------------------------------
		// below is rendering code.

		// --------------------------------------
		// First draw a triangle with a different color for each vertex

		// set the attributes
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
		gl.enableVertexAttribArray(positionLoc);
		gl.vertexAttribPointer(
			positionLoc, // location
			2,           // size (components per iteration)
			gl.FLOAT,    // type of to get from buffer
			false,       // normalize
			0,           // stride (bytes to advance each iteration)
			0,           // offset (bytes from start of buffer)
		);

		gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
		gl.enableVertexAttribArray(colorLoc);
		gl.vertexAttribPointer(
			colorLoc, // location
			4,        // size (components per iteration)
			gl.FLOAT, // type of to get from buffer
			false,    // normalize
			0,        // stride (bytes to advance each iteration)
			0,        // offset (bytes from start of buffer)
		);

		// this is not needed. It's just here to unclutter the diagram
		gl.bindBuffer(gl.ARRAY_BUFFER, null);

		gl.useProgram(prog);

		// draw on left
		gl.uniform4fv(offsetLoc, [-0.5, 0, 0, 0]);

		// draw 3 vertices (1 triangle)
		gl.drawArrays(gl.TRIANGLES, 0, 3);

		// Now draw the triangle again in a solid color 
		// by turning off the color attribute and setting
		// an attribute values
		gl.disableVertexAttribArray(colorLoc);
		// gl.vertexAttrib4fv(colorLoc, [0.3, 0.6, 0.9, 1]);

		// draw on right
		gl.uniform4fv(offsetLoc, [0.5, 0, 0, 0]);

		// draw 3 vertices (1 triangle)
		gl.drawArrays(gl.TRIANGLES, 0, 3);
	</script>
</body>

</html>


Vivado2023是一款集成开发环境软件,用于设计和验证FPGA(现场可编程门阵列)和可编程逻辑器件。对于使用Vivado2023的用户来说,license是必不可少的。 Vivado2023的license是一种许可证,用于授权用户合法使用该软件。许可证分为多种类型,包括评估许可证、开发许可证和节点许可证等。每种许可证都有不同的使用条件和功能。 评估许可证是免费提供的,让用户可以在一段时间内试用Vivado2023的全部功能。用户可以使用这个许可证来了解软件的性能和特点,对于初学者和小规模项目来说是一个很好的选择。但是,使用评估许可证的用户在使用期限过后需要购买正式的许可证才能继续使用软件。 开发许可证是付费的,可以永久使用Vivado2023的全部功能。这种许可证适用于需要长期使用Vivado2023进行开发的用户,通常是专业的FPGA设计师或工程师。购买开发许可证可以享受Vivado2023的技术支持和更新服务,确保软件始终保持最新的版本和功能。 节点许可证是用于多设备或分布式设计的许可证,可以在多个计算机上安装Vivado2023,并共享使用。节点许可证适用于大规模项目或需要多个处理节点进行设计的用户,可以提高工作效率和资源利用率。 总之,Vivado2023 license是用户在使用Vivado2023时必须考虑的问题。用户可以根据自己的需求选择合适的许可证类型,以便获取最佳的软件使用体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值