Skip to content

Commit 89171aa

Browse files
committed
Translate webgl-framebuffers.md into Chinese
1 parent 0284480 commit 89171aa

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
Title: WebGL2 帧缓冲区(Framebuffers)
2+
Description: WebGL 中的 帧缓冲区(Framebuffers) 是什么?
3+
TOC: 帧缓冲区(Framebuffers)
4+
5+
本文旨在帮助你建立对 WebGL 中 framebuffer 的一个直观理解。
6+
framebuffer 之所以重要,是因为它们允许你[渲染到纹理](webgl-render-to-texture.html)
7+
8+
一个 `Framebuffer` 其实就是一个**附件的集合(attachments)**。就是这样!
9+
它的作用是让你可以将内容渲染到`纹理``渲染缓冲区`中。
10+
11+
你可以将一个 Framebuffer 对象想象成这样:
12+
13+
```
14+
class Framebuffer {
15+
constructor() {
16+
this.attachments = new Map(); // attachments by attachment point
17+
this.drawBuffers = [gl.BACK, gl.NONE, gl.NONE, gl.NONE, ...];
18+
this.readBuffer = gl.BACK,
19+
}
20+
}
21+
```
22+
23+
`WebGL2RenderingContext`(也就是 `gl` 对象)可以理解为如下结构:
24+
25+
```js
26+
// pseudo code
27+
gl = {
28+
drawFramebufferBinding: defaultFramebufferForCanvas,
29+
readFramebufferBinding: defaultFramebufferForCanvas,
30+
}
31+
```
32+
33+
这里有两个绑定点(binding point),设置方式如下:
34+
35+
```js
36+
gl.bindFramebuffer(target, framebuffer) {
37+
framebuffer = framebuffer || defaultFramebufferForCanvas; // if null use canvas
38+
switch (target) {
39+
case: gl.DRAW_FRAMEBUFFER:
40+
this.drawFramebufferBinding = framebuffer;
41+
break;
42+
case: gl.READ_FRAMEBUFFER:
43+
this.readFramebufferBinding = framebuffer;
44+
break;
45+
case: gl.FRAMEBUFFER:
46+
this.drawFramebufferBinding = framebuffer;
47+
this.readFramebufferBinding = framebuffer;
48+
break;
49+
default:
50+
... error ...
51+
}
52+
}
53+
```
54+
55+
`DRAW_FRAMEBUFFER`:用于向 `framebuffer` 绘制内容,如通过 `gl.clear``gl.draw???``gl.blitFramebuffer`
56+
`READ_FRAMEBUFFER`:用于从 `framebuffer` 中读取内容,如通过 `gl.readPixels``gl.blitFramebuffer`
57+
58+
你可以通过三个函数向 framebuffer 添加附件,`framebufferTexture2D`
59+
`framebufferRenderbuffer``framebufferTextureLayer`
60+
61+
它们的内部逻辑可以想象成如下实现:
62+
63+
```js
64+
// pseudo code
65+
gl._getFramebufferByTarget(target) {
66+
switch (target) {
67+
case gl.FRAMEBUFFER:
68+
case gl.DRAW_FRAMEBUFFER:
69+
return this.drawFramebufferBinding;
70+
case gl.READ_FRAMEBUFFER:
71+
return this.readFramebufferBinding;
72+
}
73+
}
74+
gl.framebufferTexture2D(target, attachmentPoint, texTarget, texture, mipLevel) {
75+
const framebuffer = this._getFramebufferByTarget(target);
76+
framebuffer.attachments.set(attachmentPoint, {
77+
texture, texTarget, mipLevel,
78+
});
79+
}
80+
gl.framebufferTextureLayer(target, attachmentPoint, texture, mipLevel, layer) {
81+
const framebuffer = this._getFramebufferByTarget(target);
82+
framebuffer.attachments.set(attachmentPoint, {
83+
texture, texTarget, mipLevel, layer
84+
});
85+
}
86+
gl.framebufferRenderbuffer(target, attachmentPoint, renderbufferTarget, renderbuffer) {
87+
const framebuffer = this._getFramebufferByTarget(target);
88+
framebuffer.attachments.set(attachmentPoint, {
89+
renderbufferTarget, renderbuffer
90+
});
91+
}
92+
```
93+
94+
你可以使用 `gl.drawBuffers` 设置 `framebuffer` 的绘制目标数组,其内部实现如下所示:
95+
96+
97+
```js
98+
// pseudo code
99+
gl.drawBuffers(drawBuffers) {
100+
const framebuffer = this._getFramebufferByTarget(gl.DRAW_FRAMEBUFFER);
101+
for (let i = 0; i < maxDrawBuffers; ++i) {
102+
framebuffer.drawBuffers[i] = i < drawBuffers.length
103+
? drawBuffers[i]
104+
: gl.NONE
105+
}
106+
}
107+
```
108+
109+
`drawBuffers` 数组决定了哪些附件会被渲染。
110+
111+
合法值包括:
112+
113+
* `gl.NONE`:不渲染到这个附件
114+
* `gl.COLOR_ATTACHMENTx`:其中 `x` 和附件索引一样
115+
* `gl.BACK`:仅在当前 `framebuffer``null` 时有效,表示渲染到默认 canvas 的 `backbuffer`
116+
117+
你还可以使用 `gl.readBuffer` 设置读缓冲:
118+
119+
```js
120+
// pseudo code
121+
gl.readBuffer(readBuffer) {
122+
const framebuffer = this._getFramebufferByTarget(gl.READ_FRAMEBUFFER);
123+
framebuffer.readBuffer = readBuffer;
124+
}
125+
```
126+
127+
readBuffer 决定在调用 `gl.readPixels` 时会从哪个附件读取。
128+
129+
重点总结:framebuffer 本质上只是一个附件的简单集合。
130+
真正复杂的是这些附件之间的限制与兼容性。
131+
例如:浮点纹理附件默认不能被渲染,除非通过扩展如 `EXT_color_buffer_float` 开启支持。
132+
此外,如果 framebuffer 包含多个附件,它们必须具有相同的尺寸。
133+

0 commit comments

Comments
 (0)