顶点着色器如何向片段着色器传递?解析两行代码输出含义
顶点着色器向片段着色器传递数据及代码解析
一、顶点着色器向片段着色器传递数据的常用方式
- 自定义输出变量:这是最灵活的方式。在顶点着色器中用
out关键字声明变量(比如示例中的out vec2 texcoord;),片段着色器中使用同名同类型的in变量即可接收该数据。GPU会自动完成顶点数据到片段的插值(除非用flat修饰取消插值)。 - 接口块:如果需要传递一组相关数据,可以用接口块打包。比如顶点着色器写:
片段着色器对应写:out VS_OUT { vec2 texcoord; vec3 color; } vs_out;
这种方式在数据量大时更清晰。in VS_OUT { vec2 texcoord; vec3 color; } fs_in; - 内置变量:部分内置变量可间接传递信息,比如顶点着色器输出的
gl_Position会影响片段着色器的gl_FragCoord(片段的窗口坐标),但这种方式灵活性差,仅适合特定场景。
二、代码中第1行和第2行的输出解析
核心内置变量gl_VertexID:代表当前处理的顶点索引,通常从0开始依次递增。
第1行:texcoord = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);
这行通过位运算生成纹理坐标,代入不同顶点ID的计算结果如下:
| gl_VertexID | 第一个分量:(gl_VertexID << 1) & 2 | 第二个分量:gl_VertexID & 2 | texcoord结果 |
|---|---|---|---|
| 0 | (0 << 1) & 2 = 0 | 0 & 2 = 0 | (0, 0) |
| 1 | (1 << 1) & 2 = 2 | 1 & 2 = 0 | (2, 0) |
| 2 | (2 << 1) & 2 = 0 | 2 & 2 = 2 | (0, 2) |
| 3 | (3 << 1) & 2 = 2 | 3 & 2 = 2 | (2, 2) |
当顶点ID大于3时,位运算会重复上述0-3的循环模式(仅取最低两位参与计算)。
第2行:gl_Position = vec4(texcoord * 2.0f - 1.0f, 0.0f, 1.0f);
这行将texcoord转换为标准化设备坐标(NDC),代入texcoord结果的计算如下:
| texcoord | gl_Position结果 | 对应屏幕位置(裁剪后) |
|---|---|---|
| (0, 0) | (-1.0, -1.0, 0.0, 1.0) | 屏幕左下角 |
| (2, 0) | (3.0, -1.0, 0.0, 1.0) | 屏幕右侧外(裁剪后仍能让三角形覆盖屏幕) |
| (0, 2) | (-1.0, 3.0, 0.0, 1.0) | 屏幕顶部外(裁剪后仍能让三角形覆盖屏幕) |
| (2, 2) | (3.0, 3.0, 0.0, 1.0) | 屏幕右上角外 |
这种写法通常用于绘制全屏三角形/四边形:仅用3个顶点(ID0、1、2)就能覆盖整个屏幕,比传统4顶点四边形更高效,超出NDC范围的顶点会被GPU自动裁剪,不影响最终渲染效果。
内容的提问来源于stack exchange,提问作者Summit
相关产品推荐
相关产品推荐

