We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在上一篇文章WebGL 初探中,我们熟悉了 WebGL 的简单背景以及如何绘制一个简单的点。但是只绘制点我们是无法进入三维世界的,本篇章将讲解如何使用 WebGL 绘制三角形,因为很多 3D 图形都是使用三角形为基础进行渲染的,所以有些对 GPU 性能指标的评价就是渲染三角形的能力。
前一篇文章中,绘制一个点直接将一个硬编码的矢量赋给了位置属性。但是,显然这样写是不够灵活的。所以在这篇文章的前一部分会使用变量重写前一篇文章的例子。我们的目标是将位置信息从 JavaScript 程序中传递到顶点着色器,而 attribute 变量就传输的是那些和顶点相关的数据。下图展示了如何使用 attribute 变量传输数据:
var VSHADER_SOURCE = 'attribute vec4 a_Position;\n' + 'void main() {\n' + ' gl_Position = a_Position;\n' + ' gl_PointSize = 10.0;\n' + '}\n';
如上所示,前一篇文章中,直接使用矢量进行赋值 gl_Position = vec4(0.0, 0.0, 0.0, 1.0)。而这里使用 attribute vec4 a_Position 声明一个 attribute 变量。关键字 attribute 被称为存储限定符,表示声明一个 attribute 变量,而且 attribute 变量必须声明成全局变量,数据将从着色器外传入。gl_Position = a_Position 将 attribute 变量 a_Position 赋值给 gl_Position。
gl_Position = vec4(0.0, 0.0, 0.0, 1.0)
attribute vec4 a_Position
gl_Position = a_Position
// 获得 attribute 变量 a_Position 的存储位置 var a_Position = gl.getAttribLocation(gl.program, 'a_Position'); if (a_Position < 0) { console.log('Failed to get the storage location of a_Position'); return; } // 将顶点位置传递给 attribute 变量 gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
上面,我们使用 vertexAttrib3f(location, v0, v1, v2) 方法将数据 (v0, v1, v2) 传递给 location 参数指向的 attribute 变量。而这里的 location 是要修改的 attribute 变量的存储位置。所以在这之前我们需要获取 attribute 变量的存储位置。我们可以通过 getAttribLocation(program, name) 获取 attribute 变量的存储位置。进行完这些更改之后,运行会发现和上一篇文章相同的效果。
vertexAttrib3f(location, v0, v1, v2)
getAttribLocation(program, name)
到现在,我们一次只能绘制一个点,无法一次性绘制多个点,甚至是线和面。想要一次绘制多个点,我们需要借助一个叫做缓冲区对象的东西。缓冲区对象是 WebGL 中的一块存储区域,其中保存了大量的顶点数据,可以一次性的向顶点着色器传入多个顶点到 attribute 变量。下图展示了如何使用缓冲区对象:
var vertices = new Float32Array([ 0, 0.5, -0.5, -0.5, 0.5, -0.5 ]); // 创建缓冲区对象 var vertexBuffer = gl.createBuffer(); if (!vertexBuffer) { console.log('创建缓冲区对象失败。'); return -1; } // 绑定缓冲区对象到目标 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // 将数据写入缓冲区对象 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); var a_Position = gl.getAttribLocation(gl.program, 'a_Position'); if (a_Position < 0) { console.log('获得 attriute 变量 a_Position 失败'); return -1; } // 将缓冲区对象赋值给 attriute 变量 a_Position gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0); // 开启 attribute 变量 gl.enableVertexAttribArray(a_Position);
首先,是通过 createBuffer() 方法创建一个缓冲区对象,对应的方法还有 deleteBuffer() 用于删除一个缓冲区对象。接着,使用 bindBuffer(target, buffer) 将缓冲区对象绑定到 WebGL 已经存在的目标上,以通知 WebGL 正确的处理其内容。紧接着,使用 bufferData(target, data, useage) 方法将数据写入缓冲区,这里实际是将数据写入到绑定的目标对象上,所以在第二步中进行了缓冲区对象的绑定。而第二个参数是一个定义好的类型化数组。这里的第三个参数,STATIC_DRAW 表示只会向缓冲区写入一次,绘制多次,其它用法参数可查相关 API。然后,使用 vertexAttribPointer(location, size, type, normalized, stride, offset) 将缓冲区对象赋值给 attribute 变量。这里的第二个参数定义缓冲区对象的每个顶点的分量(1到4之间),如果 size 比 attribute 变量需要的分量小,则按照一定规则补全。第三个参数指定了数据格式。第四个参数表示是否将非浮点型数据归一到 [0, 1] 或[-1,1] 之间。最后两个参数一般默认为0,此处不做具体介绍。最后通过 enableVertexAttribArray(a_Position) 方法开启缓冲区对象和 attribute 变量的连接。
createBuffer()
deleteBuffer()
bindBuffer(target, buffer)
bufferData(target, data, useage)
vertexAttribPointer(location, size, type, normalized, stride, offset)
enableVertexAttribArray(a_Position)
最后,我们可通过 drawArrays(gl.TRIANGLES, 0, n) 绘制三角形。在前一篇文章中提到 drawArrays 函数功能非常强大。现在,我们就看一下它有哪些强大的特性。函数中第一个参数指定了绘制方式,第二个参数指定从哪个顶点开始绘制,第三个参数指定需要绘制多少个顶点。下表展示了第一个参数对应的绘制方式:
drawArrays(gl.TRIANGLES, 0, n)
下图是 new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5]) 矢量的一个测试:
new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5])
这篇文章主要讲了如何利用缓冲区对象在空间中绘制点、线、面。下一篇文章将讲解矩阵变换,有了这两个知识的积累,理论上可以画出我们想要的 3D 图形。WebGL 的 API 看似复杂,但基本都很类似。当我们对这一套熟悉之后,我们会愈发轻车熟路。
The text was updated successfully, but these errors were encountered:
sundway
No branches or pull requests
绘制三角形
在上一篇文章WebGL 初探中,我们熟悉了 WebGL 的简单背景以及如何绘制一个简单的点。但是只绘制点我们是无法进入三维世界的,本篇章将讲解如何使用 WebGL 绘制三角形,因为很多 3D 图形都是使用三角形为基础进行渲染的,所以有些对 GPU 性能指标的评价就是渲染三角形的能力。
attribute 变量
前一篇文章中,绘制一个点直接将一个硬编码的矢量赋给了位置属性。但是,显然这样写是不够灵活的。所以在这篇文章的前一部分会使用变量重写前一篇文章的例子。我们的目标是将位置信息从 JavaScript 程序中传递到顶点着色器,而 attribute 变量就传输的是那些和顶点相关的数据。下图展示了如何使用 attribute 变量传输数据:
如上所示,前一篇文章中,直接使用矢量进行赋值
gl_Position = vec4(0.0, 0.0, 0.0, 1.0)
。而这里使用attribute vec4 a_Position
声明一个 attribute 变量。关键字 attribute 被称为存储限定符,表示声明一个 attribute 变量,而且 attribute 变量必须声明成全局变量,数据将从着色器外传入。gl_Position = a_Position
将 attribute 变量 a_Position 赋值给 gl_Position。上面,我们使用
vertexAttrib3f(location, v0, v1, v2)
方法将数据 (v0, v1, v2) 传递给 location 参数指向的 attribute 变量。而这里的 location 是要修改的 attribute 变量的存储位置。所以在这之前我们需要获取 attribute 变量的存储位置。我们可以通过getAttribLocation(program, name)
获取 attribute 变量的存储位置。进行完这些更改之后,运行会发现和上一篇文章相同的效果。缓冲区对象
到现在,我们一次只能绘制一个点,无法一次性绘制多个点,甚至是线和面。想要一次绘制多个点,我们需要借助一个叫做缓冲区对象的东西。缓冲区对象是 WebGL 中的一块存储区域,其中保存了大量的顶点数据,可以一次性的向顶点着色器传入多个顶点到 attribute 变量。下图展示了如何使用缓冲区对象:
首先,是通过
createBuffer()
方法创建一个缓冲区对象,对应的方法还有deleteBuffer()
用于删除一个缓冲区对象。接着,使用bindBuffer(target, buffer)
将缓冲区对象绑定到 WebGL 已经存在的目标上,以通知 WebGL 正确的处理其内容。紧接着,使用bufferData(target, data, useage)
方法将数据写入缓冲区,这里实际是将数据写入到绑定的目标对象上,所以在第二步中进行了缓冲区对象的绑定。而第二个参数是一个定义好的类型化数组。这里的第三个参数,STATIC_DRAW 表示只会向缓冲区写入一次,绘制多次,其它用法参数可查相关 API。然后,使用vertexAttribPointer(location, size, type, normalized, stride, offset)
将缓冲区对象赋值给 attribute 变量。这里的第二个参数定义缓冲区对象的每个顶点的分量(1到4之间),如果 size 比 attribute 变量需要的分量小,则按照一定规则补全。第三个参数指定了数据格式。第四个参数表示是否将非浮点型数据归一到 [0, 1] 或[-1,1] 之间。最后两个参数一般默认为0,此处不做具体介绍。最后通过enableVertexAttribArray(a_Position)
方法开启缓冲区对象和 attribute 变量的连接。绘制三角形
最后,我们可通过
drawArrays(gl.TRIANGLES, 0, n)
绘制三角形。在前一篇文章中提到 drawArrays 函数功能非常强大。现在,我们就看一下它有哪些强大的特性。函数中第一个参数指定了绘制方式,第二个参数指定从哪个顶点开始绘制,第三个参数指定需要绘制多少个顶点。下表展示了第一个参数对应的绘制方式:下图是
new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5])
矢量的一个测试:结语
这篇文章主要讲了如何利用缓冲区对象在空间中绘制点、线、面。下一篇文章将讲解矩阵变换,有了这两个知识的积累,理论上可以画出我们想要的 3D 图形。WebGL 的 API 看似复杂,但基本都很类似。当我们对这一套熟悉之后,我们会愈发轻车熟路。
系列文章
The text was updated successfully, but these errors were encountered: