系统 API 作用
纹理采样系统 glActiveTexture + glBindTexture Shader 里 sampler2D
帧缓冲系统 glBindFramebuffer + glFramebufferTexture2D 决定渲染往哪画
纹理对象管理 glGenTextures + glBindTexture 配置/上传纹理属性数据

三种纹理 一种是上传到GPU的数据,一种是Fbo的渲染对象,一种是属性

OpenGL 有 多个 Texture Unit(纹理单元)

比如:

1
2
3
4
5
GL_TEXTURE0
GL_TEXTURE1
GL_TEXTURE2
...
至少 8 个,甚至 32 个

每个 Texture Unit 里, 才有 它自己的 GL_TEXTURE_2D 绑定槽位

1
2
3
4
Texture Unit 0 : 绑定一个 GL_TEXTURE_2D
Texture Unit 1 : 绑定一个 GL_TEXTURE_2D
Texture Unit 2 : 绑定一个 GL_TEXTURE_2D
……
1
2
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

意思是:

“把 texture 绑定给 Texture Unit 0 的 GL_TEXTURE_2D 槽”

Pipeline 用纹理时 不是看“当前 GL_TEXTURE_2D 指向谁” 而是:

Shader 的 sampler2D —— 指向哪个 Texture Unit Texture Unit —— 绑定哪个 GL_TEXTURE_2D 纹理对象

它跟 FBO 是完全独立的系统

FBO 有自己的:

1
GL_COLOR_ATTACHMENT0 = renderTexture

跟 Texture Units 完全不冲突, 跟 glBindTexture(GL_TEXTURE_2D …) 也不冲突。

不是只有一个 GL_TEXTURE_2D 指针。 每个 Texture Unit 都有一个 GL_TEXTURE_2D 绑定指针, Shader 用的是 Texture Unit, 不是“当前唯一 GL_TEXTURE_2D”。

而:

  • Texture Unit 系统 —— 负责 采样
  • FBO 系统 —— 负责 渲染输出
  • Unbind 只是把某个 Texture Unit 的绑定清掉 ✔ 数据仍然在 GPU ✔ 其它 Unit / FBO 完全不受影响

如果没有调用 glActiveTexture(...),那么 glBindTexture(GL_TEXTURE_2D, …) 绑定的是当前“活动纹理单元(Active Texture Unit)”,而 OpenGL 默认的活动单元就是 GL_TEXTURE0

Shader 怎么知道用哪个 Texture Unit?取决于 uniform:

1
2
3
4
5
6
7
8
9
10
// 表示:

//uniform:CPU 传给 GPU 的常量(渲染期间不随顶点/像素变化)

//sampler2D:一个**“二维纹理采样器” 类型**

//u_texture:变量名

//👉 本质:它是“指向 某个 Texture Unit 的句柄”
uniform sampler2D u_texture;

它必须被设置:

1
glUniform1i(location, 0);

表示:

1
u_texture 使用 Texture Unit 0

任何时刻,Active Texture Unit 只有 1 个,渲染时可用 Texture Unit 可以很多个,Shader 能同时采样多少,取决于 GL_MAX_TEXTURE_IMAGE_UNITS,glBindTexture 只影响当前 Active Unit

GPU Pipeline 其实同时有很多个 Texture Unit,比如:

1
2
3
4
GL_TEXTURE0
GL_TEXTURE1
GL_TEXTURE2
...

你可以:

1
2
3
4
5
6
7
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texA);
glUniform1i(u_tex0, 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texB);
glUniform1i(u_tex1, 1);

然后在 shader 里同时用:

1
2
vec4 a = texture(u_tex0, uv);
vec4 b = texture(u_tex1, uv);

👉 Pipeline 同时使用 texA + texB,没有任何问题。 并不是只有一个 unit 被“激活”在工作。

FBO = OpenGL 内部“渲染目标对象” WindowSurface = 用来“显示到屏幕”的表面 PBuffer = EGL 早期的“离屏 Surface”,现在多数被 FBO 取代