渲染管线-计算得到gl_Position(顶点着色器)之后续GPU流程

核心流程

顶点着色器写出 gl_Position 之后,这个值还不是最终屏幕坐标,它此时处在裁剪空间-Clip Space

  • GPU 后续会继续走完整的图形管线,大致顺序是:
  • 图元装配
  • 裁剪
  • 透视除法
  • 视口变换
  • 光栅化
  • 片元着色
  • 各种测试与混合
  • 写入帧缓冲

如果把它串成一句话,就是:

text 复制代码
gl_Position(裁剪空间)
-> 裁剪
-> NDC
-> 屏幕坐标
-> 生成片元
-> 计算颜色
-> 深度/模板/混合
-> 显示到屏幕

1. 图元装配

  • 顶点着色器是"逐顶点"执行的,GPU 会把多个顶点按照你的绘制方式组装成图元。
  • 例如:
    • gl.drawArrays(gl.TRIANGLES, ...) 会每 3 个顶点组装成一个三角形
    • gl.LINES 会组装成线段
    • gl.POINTS 会组装成点
  • 这一步里,gl_Position 只是每个顶点的位置结果,GPU 还要先知道这些顶点组成了什么图形。

2. 裁剪,Clipping

  • GPU 会拿组装好的图元,和裁剪空间可见范围做比较。
  • 在标准裁剪空间里,顶点需要满足类似这样的范围关系:
text 复制代码
-w <= x <= w
-w <= y <= w
-w <= z <= w
  • 如果一个三角形完全在可见范围外,就直接丢掉。
  • 如果只有一部分超出范围,GPU 会把它裁掉,只保留可见部分。
  • 所以 gl_Positionw 很重要,因为裁剪不是简单拿 x/y/z 和固定值比,而是和 w 相关。

3. 透视除法,Perspective Divide

  • 裁剪之后,GPU 会把裁剪空间坐标变成 NDC,标准化设备坐标。
  • 做法就是:
text 复制代码
x_ndc = x / w
y_ndc = y / w
z_ndc = z / w
  • 这一步非常关键,透视投影里的"近大远小"就是在这里真正体现出来的。
  • 做完之后,坐标会落到标准范围内:
text 复制代码
x: [-1, 1]
y: [-1, 1]
z: [-1, 1]
  • 这里得到的已经不是 gl_Position 原始值,而是透视除法后的标准坐标。

4. 视口变换,Viewport Transform

  • NDC 仍然不是屏幕像素坐标,GPU 接下来会把它映射到视口区域。
  • 比如:
    • x = -1 映射到屏幕左边
    • x = 1 映射到屏幕右边
    • y = -1 映射到屏幕下边
    • y = 1 映射到屏幕上边
  • 这个过程受 gl.viewport(x, y, width, height) 影响。
  • 也就是说,NDC 会被换算成真正的窗口像素区域里的位置。

5. 面剔除,可选

  • 在光栅化前,GPU 还可能做背面剔除
  • 如果启用了:
js 复制代码
gl.enable(gl.CULL_FACE);
  • 那么 GPU 会根据三角形顶点顺序判断它是正面还是背面。
  • 背向摄像机的面可以直接丢弃,不再继续处理。
  • 这样能减少后续片元计算量。

6. 光栅化,Rasterization

  • 到这一步,GPU 已经有了屏幕上的三角形轮廓。
  • 光栅化会把几何图元转换成大量片元,Fragment
  • 你可以把它理解成:
    • 三角形覆盖了哪些像素区域
    • 就为这些像素位置生成对应的片元
  • 注意:
    • 片元不完全等于最终像素
    • 它只是"候选像素数据",后面还要经过测试才可能真正写进屏幕

7. 插值,Interpolation

  • 光栅化生成片元时,GPU 会把顶点着色器输出的其他变量自动插值到每个片元上。
  • 比如你在顶点着色器里输出:
glsl 复制代码
varying vec2 vUv;
varying vec3 vColor;
varying vec3 vNormal;
  • 那么 GPU 会根据三角形内部位置,为每个片元自动算出它自己的:
    • vUv
    • vColor
    • vNormal
  • 这一步非常重要,因为片元着色器通常就是靠这些插值后的数据来计算纹理、光照和颜色的。

8. 片元着色器执行

  • 每个片元都会执行一次片元着色器。
  • 在这里你通常会做:
    • 采样纹理
    • 计算光照
    • 组合颜色
    • 输出最终颜色

例如:

glsl 复制代码
gl_FragColor = vec4(color, 1.0);

或者在 WebGL2 中:

glsl 复制代码
out vec4 outColor;
  • 这一步决定"这个片元想要显示成什么颜色"。

9. 每片元测试,Per-Fragment Tests

  • 片元着色器算出颜色后,还不一定能真正画到屏幕上。

  • GPU 还会做一系列测试,常见包括:

  • 深度测试

    • 判断这个片元是不是被前面的物体挡住了
    • 只有更靠近摄像机的片元通常才会保留
  • 模板测试

    • 根据模板缓冲决定哪些区域允许绘制
  • 裁剪/裁切规则

    • 某些片元可能仍会因为状态设置被丢弃
  • Alpha discard

    • 如果你在片元着色器里主动 discard,这个片元也会被直接丢掉

如果深度测试没过,这个片元即使颜色算出来了,也不会写入最终图像。

10. 混合,Blending

  • 如果片元通过测试,且启用了混合:
js 复制代码
gl.enable(gl.BLEND);
  • GPU 会把"新片元颜色"和"帧缓冲里已有颜色"混合。
  • 这就是透明效果的基础。
  • 常见混合公式例如:
js 复制代码
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  • 这时最终显示的颜色,可能不是片元着色器直接输出的颜色,而是混合后的结果。

11. 写入帧缓冲

  • 最终通过所有测试的片元,会把结果写入帧缓冲Framebuffer
  • 帧缓冲里通常包含:
    • 颜色缓冲
    • 深度缓冲
    • 模板缓冲
  • 当一帧全部完成后,浏览器再把颜色缓冲内容显示到屏幕上。

重点理解 gl_Position 的地位

  • gl_Position 只负责告诉 GPU:这个顶点在裁剪空间里在哪里
  • 它并不直接等于屏幕坐标。
  • 它后面还要经历:
    • 裁剪
    • 除以 w
    • 映射到视口
    • 光栅化成片元
    • 片元着色
    • 深度/混合处理
  • 所以 gl_Position 更像是"几何阶段的最终输出",不是整个渲染流程的最终输出。

最容易混淆的几点

  • gl_Position 不是屏幕像素坐标,它是裁剪空间坐标。
  • w 不是可有可无,它直接影响裁剪和透视除法。
  • 顶点着色器结束后,不是直接上屏,而是先从"顶点"变成"图元",再变成"片元"。
  • 片元着色器输出颜色后,也不一定会显示,还要过深度测试和混合。

一句话总结

  • 计算出 gl_Position 之后,GPU 会先把顶点组装成图元,再做裁剪和透视除法,把它们变成屏幕范围内的片元,然后执行片元着色器,最后经过深度测试、混合等步骤,才真正写到屏幕上。

最短记忆版

  • gl_Position 之后的主线就是:
text 复制代码
图元装配 -> 裁剪 -> 透视除法 -> 视口变换 -> 光栅化 -> 片元着色 -> 深度/混合 -> 帧缓冲
相关推荐
仿生狮子1 小时前
✂️ Nuxt 最简单的字体裁剪工具:Fontize
javascript·vue.js·nuxt.js
魔力女仆4 小时前
分享一个 JS 鼠标跟随贪吃蛇背景库
开发语言·javascript·计算机外设
别惊醒渔人6 小时前
Vue3 Diff 优化:最长递增子序列 LIS
前端·javascript·vue.js
Larcher6 小时前
从“加载模型”界面到端侧推理:拆解一个 React + WebGPU 大模型 Demo
javascript·后端
Larcher7 小时前
从状态快照到惰性初始化:读懂 React useState 的三个关键场景
javascript·人工智能·后端
Hilaku8 小时前
工作 5 年后,决定你薪资上限的究竟是什么?
前端·javascript·程序员
weixin_BYSJ19878 小时前
springboot校园自习室管理小程序---附源码32142
java·javascript·spring boot·python·django·flask·php
gis开发之家9 小时前
《Vue3 从入门到大神40篇》Vue3 源码详解(十):diff 算法全解析 —— 为什么 Vue3 比 Vue2 更快?
javascript·算法·typescript·前端框架·vue3·vue3源码
用户831348593069810 小时前
Vue+Three.js实现PCB电路板3D交互:元器件点击高亮、部件显隐、模型自动旋转
vue.js·webgl·three.js
海带紫菜菠萝汤11 小时前
WebCodecs API 实战:浏览器原生视频编解码的原理与性能测试
前端·javascript·音视频·视频编解码