Skip to content

Commit 57db2c1

Browse files
colin3dmaxgreggman
authored andcommitted
Translate zh_cn webgl-pulling-vertices.md
1 parent 0903c9d commit 57db2c1

File tree

1 file changed

+79
-107
lines changed

1 file changed

+79
-107
lines changed

webgl/lessons/zh_cn/webgl-pulling-vertices.md

Lines changed: 79 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,23 @@
1-
Title: WebGL2 Pulling Vertices
2-
Description: Using independent indices
3-
TOC: Pulling Vertices
1+
Title: WebGL2 顶点拉取
2+
Description: 使用独立索引
3+
TOC: 顶点拉取
44

5-
This article assumes you've read many of the other articles
6-
starting with [the fundamentals](webgl-fundamentals.html).
7-
If you have not read them please start there first.
5+
本文假设你已经阅读了其他许多文章,从 [基础知识](webgl-fundamentals.html) 开始。如果你还没有阅读它们,请先从那里开始。
86

9-
Traditionally, WebGL apps put geometry data in buffers.
10-
They then use attributes to automatically supply vertex data from those buffers
11-
to the vertex shader where the programmer provides code to convert them to clip space.
7+
传统上,WebGL应用会将几何数据放入缓冲区中,然后通过属性(attributes)自动将这些缓冲区中的顶点数据传递给顶点着色器,由程序员编写代码将其转换为裁剪空间(clip space)坐标。
128

13-
The word **traditionally** is important. It's only a **tradition**
14-
to do it this way. It is in no way a requirement. WebGL doesn't
15-
care how we do it, it only cares that our vertex shaders
16-
assign clip space coordinates to `gl_Position`.
9+
这里的 **“传统上”** 非常重要。
10+
这只是一种**传统做法**,并不是必须如此。
11+
WebGL 并不关心我们是如何处理的,它只关心顶点着色器是否为 `gl_Position` 赋予了裁剪空间坐标。
1712

18-
Let's draw a texture mapped cube using code like the examples in [the article on textures](webgl-3d-textures.html).
19-
We're told we need at least 24 unique vertices. This is because even though there are only 8 corner
20-
positions the same corner gets used on 3 different faces of the
21-
cube and each face needs different texture coordinates.
13+
让我们使用类似于 [纹理](webgl-3d-textures.html) 中示例的方式,绘制一个带纹理映射的立方体。我们通常会说需要至少 24 个唯一顶点,这是因为虽然立方体只有 8 个角点位置,但每个角点会出现在立方体的 3 个不同面上,而每个面又需要不同的纹理坐标。
2214

2315
<div class="webgl_center"><img src="resources/cube-vertices-uv.svg" style="width: 400px;"></div>
2416

25-
In the diagram above we can see that the left face's use of corner 3 needs
26-
texture coordinates 1,1 but the right face's use of corner 3 needs texture coordinates
27-
0,1. The top face would need different texture coordinates as well.
17+
在上面的图示中,我们可以看到左侧面的角点 3 需要的纹理坐标是 (1,1),而右侧面对角点 3 的使用则需要纹理坐标 (0,1)。顶部面则会需要另一组不同的纹理坐标。
18+
19+
通常,我们是通过将 8 个角点位置扩展为 24 个顶点来实现这一点的。
2820

29-
This is usually accomplished by expanding from 8 corner positions
30-
to 24 vertices
3121

3222
```js
3323
// front
@@ -62,13 +52,10 @@ to 24 vertices
6252
{ pos: [-1, -1, -1], uv: [1, 0], }, // 23
6353
```
6454

65-
Those positions and texture coordinates are
66-
put into buffers and provided to the vertex shader
67-
via attributes.
55+
这些位置和纹理坐标通常会被放入缓冲区中,并通过属性传递给顶点着色器。
6856

69-
But do we really need to do it this way? What if
70-
we wanted to actually have just the 8 corners
71-
and 4 texture coordinates. Something like
57+
但我们真的需要以这种方式来做吗?如果我们实际上只想保留 8 个角点和 4 个纹理坐标,会怎样?
58+
类似于下面这样:
7259

7360
```js
7461
positions = [
@@ -89,8 +76,7 @@ uvs = [
8976
];
9077
```
9178

92-
And then for each of the 24 vertices we'd specify which of those
93-
to use.
79+
然后,对于这 24 个顶点中的每一个,我们指定要使用哪一个位置和哪一个纹理坐标。
9480

9581
```js
9682
positionIndexUVIndex = [
@@ -127,11 +113,9 @@ positionIndexUVIndex = [
127113
];
128114
```
129115

130-
Could we use this on the GPU? Why not!?
116+
我们能在 GPU 上使用这种方式吗?为什么不可以!
131117

132-
We'll upload the positions and texture coordinates
133-
each to their own textures like
134-
we covered in [the article on data textures](webgl-data-textures.html).
118+
我们会将位置和纹理坐标分别上传到各自的纹理中,就像我们在 [数据纹理](webgl-data-textures.html) 中讲到的那样。
135119

136120
```js
137121
function makeDataTexture(gl, data, numComponents) {
@@ -168,10 +152,10 @@ const positionTexture = makeDataTexture(gl, positions, 3);
168152
const texcoordTexture = makeDataTexture(gl, uvs, 2);
169153
```
170154

171-
Since textures have up to 4 values per pixel `makeDataTexture`
172-
expands whatever data we give it to 4 values per pixel.
155+
由于纹理每个像素最多可以存储 4 个值,`makeDataTexture` 会将我们提供的数据扩展为每像素 4 个值。
156+
157+
接着,我们会创建一个顶点数组对象(vertex array)来保存我们的属性状态。
173158

174-
Then we'll create a vertex array to hold our attribute state
175159

176160
```js
177161
// create a vertex array object to hold attribute state
@@ -191,7 +175,7 @@ gl.bindBuffer(gl.ARRAY_BUFFER, positionIndexUVIndexBuffer);
191175
gl.bufferData(gl.ARRAY_BUFFER, new Uint32Array(positionIndexUVIndex), gl.STATIC_DRAW);
192176
```
193177

194-
and setup the attribute
178+
接下来,我们需要将位置索引和纹理坐标索引上传到一个缓冲区。
195179

196180
```js
197181
// Turn on the position index attribute
@@ -209,14 +193,13 @@ gl.enableVertexAttribArray(posTexIndexLoc);
209193
}
210194
```
211195

212-
Notice we're calling `gl.vertexAttribIPointer` not `gl.vertexAttribPointer`.
213-
The `I` is for integer and is used for integer and unsigned integer attributes.
214-
Also note the size is 2, since there is 1 position index and 1 texcoord
215-
index per vertex.
196+
注意这里调用的是 `gl.vertexAttribIPointer`,而不是 `gl.vertexAttribPointer`
197+
其中的 `I` 表示整数,用于整数和无符号整数类型的属性。
198+
另外,`size` 设置为 2,因为每个顶点包含 1 个位置索引和 1 个纹理坐标索引。
199+
200+
虽然我们只需要 24 个顶点,但绘制 6 个面,每个面 12 个三角形,每个三角形 3 个顶点,总共 36 个顶点。
201+
为了指定每个面使用哪 6 个顶点,我们将使用 [顶点索引](webgl-indexed-vertices.html)
216202

217-
Even though we only need 24 vertices we still need draw 6 faces, 12 triangles
218-
each, 3 vertices per triangle for 36 vertices. To tell it which 6 vertices
219-
to use for each face we'll use [vertex indices](webgl-indexed-vertices.html).
220203

221204
```js
222205
const indices = [
@@ -234,9 +217,10 @@ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
234217
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
235218
```
236219

237-
As we want to draw an image on the cube itself we need a 3rd texture
238-
with that image. Let's just make another 4x4 data texture with a checkerboard.
239-
We'll use `gl.LUMINANCE` as the format since then we only need one byte per pixel.
220+
由于我们想要在立方体上绘制一张图像,因此还需要第三个纹理存储这张图像。
221+
这里我们用一个 4x4 的数据纹理,内容是棋盘格图案。
222+
纹理格式使用 `gl.LUMINANCE`,因为这样每个像素只需要一个字节。
223+
240224

241225
```js
242226
// Create a checker texture.
@@ -263,17 +247,16 @@ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
263247
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
264248
```
265249

266-
On to the vertex shader... We can look up a pixel from the texture like
267-
this
250+
接下来是顶点着色器……
251+
我们可以像这样从纹理中查找一个像素:
268252

269253
```glsl
270254
vec4 color = texelFetch(sampler2D tex, ivec2 pixelCoord, int mipLevel);
271255
```
272256

273-
So given an integer pixel coordinate the code above will pull out a pixel value.
257+
因此,给定一个整数像素坐标,上述代码将提取出对应的像素值。
274258

275-
Using the `texelFetch` function we can take a 1D array index
276-
and lookup a value out of a 2D texture like this
259+
使用 `texelFetch` 函数,我们可以将一维数组索引转换为二维纹理坐标,并从二维纹理中查找对应的值,方式如下:
277260

278261
```glsl
279262
vec4 getValueByIndexFromTexture(sampler2D tex, int index) {
@@ -284,7 +267,7 @@ vec4 getValueByIndexFromTexture(sampler2D tex, int index) {
284267
}
285268
```
286269

287-
So given that function here is our shader
270+
有了这个函数,我们的着色器如下所示:
288271

289272
```glsl
290273
#version 300 es
@@ -321,16 +304,11 @@ void main() {
321304
}
322305
```
323306

324-
At the bottom it's effectively the same shader we used
325-
in [the article on textures](webgl-3d-textures.html).
326-
We multiply a `position` by `u_matrix` and we output
327-
a texcoord to `v_texcoord` to pass on the fragment shader.
307+
在底部,它实际上和我们在 [纹理](webgl-3d-textures.html) 中使用的着色器是一样的。我们将 `position``u_matrix` 相乘,并将纹理坐标输出到 `v_texcoord`,以传递给片元着色器。
328308

329-
The difference is only in how we get the position and
330-
texcoord. We're using the indices passed in and getting
331-
those values from their respective textures.
309+
不同之处仅在于我们获取 `position``texcoord` 的方式。我们使用传入的索引,从各自的纹理中提取这些值。
332310

333-
To use the shader we need to lookup all the locations
311+
要使用这个着色器,我们需要查找所有相关的变量位置。
334312

335313
```js
336314
// setup GLSL program
@@ -347,7 +325,7 @@ const program = webglUtils.createProgramFromSources(gl, [vs, fs]);
347325
+const u_textureLoc = gl.getUniformLocation(program, "u_texture");
348326
```
349327

350-
At render time we setup the attributes
328+
在渲染阶段,我们设置属性(attributes)。
351329

352330
```js
353331
// Tell it to use our program (pair of shaders)
@@ -357,8 +335,7 @@ gl.useProgram(program);
357335
gl.bindVertexArray(vao);
358336
```
359337

360-
Then we need to bind all 3 textures and setup all the
361-
uniforms
338+
然后,我们需要绑定全部 3 个纹理,并设置所有的 uniform。
362339

363340
```js
364341
// Set the matrix.
@@ -383,74 +360,69 @@ gl.bindTexture(gl.TEXTURE_2D, checkerTexture);
383360
gl.uniform1i(u_textureLoc, 2);
384361
```
385362

386-
And finally draw
363+
最后,执行绘制操作。
387364

388365
```js
389366
// Draw the geometry.
390367
gl.drawElements(gl.TRIANGLES, 6 * 6, gl.UNSIGNED_SHORT, 0);
391368
```
392369

393-
And we get a textured cube using only 8 positions and
394-
4 texture coordinates
370+
最终,我们只使用了 8 个位置和 4 个纹理坐标,就得到了一个带贴图的立方体。
395371

396372
{{{example url="../webgl-pulling-vertices.html"}}}
397373

398-
Some things to note. The code is lazy and uses 1D
399-
textures for the positions and texture coordinates.
400-
Textures can only be so wide. [How wide is machine
401-
specific](https://web3dsurvey.com/webgl/parameters/MAX_TEXTURE_SIZE) which you can query with
374+
有几点需要注意:代码实现较为简化,使用了 1D 纹理来存储位置和纹理坐标。
375+
但纹理的宽度是有限的,[具体有多宽依赖于硬件](https://web3dsurvey.com/webgl/parameters/MAX_TEXTURE_SIZE)
376+
你可以通过以下方式查询:
402377

403378
```js
404379
const maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
405380
```
406381

407-
If we wanted to handle more data than that we'd need
408-
to pick some texture size that fits our data, and spread
409-
the data across multiple rows possibly
410-
padding the last row to make a rectangle.
382+
如果我们想处理比最大纹理宽度还多的数据,就需要选择一个合适的纹理尺寸,并将数据分布到多行中,可能还需要对最后一行进行填充以保持矩形结构。
383+
384+
我们在这里还做了另一件事:使用了两张纹理,一张存储位置,另一张存储纹理坐标。
385+
其实我们完全可以将这两类数据存储在同一张纹理中,例如交错(interleaved)存储。
411386

412-
Another thing we're doing here is using 2 textures,
413-
one for positions, one for texture coordinates.
414-
There is no reason we couldn't put both data in the
415-
same texture either interleaved
416387

417388
pos,uv,pos,uv,pos,uv...
418389

419-
or in different places in the texture
390+
或者将它们存储在纹理的不同区域。
420391

421392
pos,pos,pos,...
422393
uv, uv, uv,...
423394

424-
We'd just have to change the math in the vertex shader
425-
that computes how to pull them out of the texture.
395+
我们只需要修改顶点着色器中的数学逻辑,以正确地从纹理中提取对应的数据。
396+
397+
那么问题来了:是否应该用这种方式?
398+
答案是“视情况而定”。具体效果可能因 GPU 而异,有些情况下这比传统方式还慢。
399+
400+
本文的重点再次强调:
401+
WebGL 并不在意你是如何为 `gl_Position` 设置裁剪空间坐标的,也不在意你是如何输出颜色的。它只关心你是否设置了这些值。纹理,本质上只是可以随机访问的二维数组。
402+
403+
当你在 WebGL 中遇到问题时,请记住,WebGL 只是运行一些着色器程序,而这些着色器可以通过以下方式访问数据。
426404

427-
The question comes up, should you do things like this?
428-
The answer is "it depends". Depending on the GPU this
429-
might be slower than the more traditional way.
405+
- uniforms(全局变量)
406+
- attributes(每个顶点着色器执行时接收的数据)
407+
- textures(可以随机访问的二维数组)
430408

431-
The point of this article was to point out yet again,
432-
WebGL doesn't care how you set `gl_Position` with
433-
clip space coordinates nor does it care how you
434-
output a color. All it cares is that you set them.
435-
Textures are really just 2D arrays of random access
436-
data.
409+
不要让传统的 WebGL 使用方式限制了你的思维。
410+
WebGL 实际上具有极强的灵活性。
437411

438-
When you have a problem you want to solve in WebGL
439-
remember that WebGL just runs shaders and those shaders
440-
have access to data via uniforms (global variables),
441-
attributes (data that comes per vertex shader iteration),
442-
and textures (random access 2D arrays). Don't let the
443-
traditional ways of using WebGL prevent you from
444-
seeing the real flexibility that's there.
412+
当你想在 WebGL 中解决问题时,请记住 WebGL 只是运行着色器,
413+
这些着色器可以通过 uniforms(全局变量)、attributes(每次顶点着色器执行时传入的数据)
414+
以及 textures(可随机访问的二维数组)来访问数据。
415+
不要让传统的 WebGL 使用方式阻碍你发现它真正的灵活性。
445416

446417
<div class="webgl_bottombar">
447-
<h3>Why is it called Vertex Pulling?</h3>
448-
<p>I'd actually only heard the term recently (July 2019)
449-
even though I'd used the technique before. It comes
450-
from <a href='https://www.google.com/search?q=OpenGL+Insights+"Programmable+Vertex+Pulling"+article+by+Daniel+Rakos'>OpenGL Insights "Programmable Vertex Pulling" article by Daniel Rakos</a>.
418+
<h3>为什么叫做顶点拉取(Vertex Pulling)?</h3>
419+
<p>实际上我最近(2019年7月)才听到这个术语,
420+
尽管我之前就用过这种技术。
421+
它来源于
422+
<a href='https://www.google.com/search?q=OpenGL+Insights+"Programmable+Vertex+Pulling"+article+by+Daniel+Rakos'>
423+
OpenGL Insights 中 Daniel Rakos 撰写的“可编程顶点拉取”文章</a>。
451424
</p>
452-
<p>It's called vertex *pulling* since it's the vertex shader
453-
that decides which vertex data to read vs the traditional way where
454-
vertex data is supplied automatically via attributes. Effectively
455-
the vertex shader is *pulling* data out of memory.</p>
425+
<p>之所以叫做顶点*拉取*,是因为顶点着色器决定读取哪个顶点数据,
426+
而传统方式是通过属性自动提供顶点数据。
427+
实际上,顶点着色器是在*拉取*内存中的数据。</p>
456428
</div>

0 commit comments

Comments
 (0)