中EN
概念页

透明渲染与 Alpha 混合

Transparency & Alpha Blending

更新于 2026-10-16 约 11 分钟透明alpha混合OITPBRT随机 alpha 测试

本页讲最简单的"视角相关"透明:半透明物体只衰减其后方物体的颜色。z-buffer 每像素只存一个表面,所以透明物体通常要从后往前用 over 运算符混合;顺序无关透明 (OIT) 方法用多遍渲染、逐像素链表或近似公式避免排序,各有内存、性能或准确性代价。预乘 alpha 让过滤、混合和合成更正确高效。

alpha 的含义

alpha 描述片元对像素的不透明度和覆盖率:1 表示不透明且完全覆盖,0 表示完全透明。例:肥皂泡边缘覆盖像素 3/4、不透明度 0.1,alpha = 0.75 × 0.1 = 0.075;若用 MSAA,覆盖率由样本体现,每个被覆盖样本的 alpha 用 0.1。

不需要混合的方法

  • 屏幕门透明:用像素级棋盘格只画一半像素。简单、可任意顺序渲染;但同一区域一般只能表现一个透明物体(红、绿两个透明物体叠在蓝色上,棋盘格里只能出现两种颜色),50% 以外的比例容易看出图案。同样的思想在子像素级就是 alpha to coverage(6.6 节)。
  • 随机透明 (stochastic transparency):子像素随机点阵表示 alpha 覆盖,无需混合,抗锯齿与透明统一处理;但需要大量样本和内存,结果有噪声。

over 运算符与渲染顺序

co=αscs+(1−αs)cd\mathbf{c}_o=\alpha_s\mathbf{c}_s+(1-\alpha_s)\mathbf{c}_d

  • 例:红色物体 (0.9, 0.2, 0.1)、alpha 0.6 叠在蓝色背景 (0.1, 0.1, 0.9) 上得 (0.58, 0.16, 0.42)。
  • over 模拟的是纱布一类"部分覆盖"的效果;模拟有色玻璃不够好——红色滤光片后的蓝色物体在现实中会变暗,应当相乘(14.5 节)。
  • 加法混合 co=αscs+cd\mathbf{c}_o=\alpha_s\mathbf{c}_s+\mathbf{c}_d 适合闪电、火花等只增亮的发光效果;用于透明不对,多层烟火会颜色饱和。
  • 先关闭混合画不透明物体,再开启 over 画透明物体。透明表面一般需从后往前绘制:常用按物体中心沿视线方向的距离粗略排序。问题:只是近似;互相穿插的物体无法按网格排序解决;单个凹形网格也可能自身重叠出错。
  • 粗排序简单、快速、无需额外内存和特殊硬件,仍被广泛使用。此时最好关闭深度写入(仍做深度测试),保证透明物体总能以某种形式出现,不会因视角变化导致排序变化时突然出现或消失。每个透明网格先画背面再画正面也有帮助。

under 运算符

co=αdcd+(1−αd)αscs,ao=αs−αsαd+αd\mathbf{c}_o=\alpha_d\mathbf{c}_d+(1-\alpha_d)\alpha_s\mathbf{c}_s,\qquad a_o=\alpha_s-\alpha_s\alpha_d+\alpha_d

  • 从前往后混合可得到相同结果,但目标需要保存 alpha。alpha 公式与顺序无关,来自 Porter-Duff 的假设:两个片元的覆盖区域互不相关,按比例重叠(0.7 与 0.6 叠加共覆盖 0.88)。
  • 用法:把透明物体画到单独的颜色缓冲,再用 over 合成到不透明场景上。

顺序无关透明 (OIT)

方法思路代价 / 问题
深度剥离两个 z-buffer、多遍渲染,每遍剥出下一层并用 under 累加每层一遍完整的透明物体渲染,慢;可用像素计数判断何时停止,从前往后剥可在 alpha 接近 1 后提前结束
双深度剥离每遍同时剥最近和最远两层遍数减半
桶排序单遍捕获最多 32 层内存大,MSAA 会让代价暴增
A-buffer / GPU 逐像素链表DX11 的 UAV 和原子操作把片元插入长数组并链接,再用全屏 pass 排序后从后往前混合只分配所需片元,但帧前无法知道需要多少内存,溢出会出现明显伪影
多层 alpha 混合用像素同步 / ROV / 移动端 tile local storage 实现可编程混合,内存不足时优雅退化有性能开销
k-buffer保存并排序前几层,更深的层丢弃或合并近似
加权和 / 加权平均单遍、几乎所有 GPU 可用不考虑顺序
  • Andersson 指出复杂游戏场景中可能有多达 50 个植被等透明网格、200 个半透明粒子重叠。

加权平均: csum=∑αici, αsum=∑αi, cwavg=csumαsum, αavg=αsumn, u=(1−αavg)n, co=(1−u)cwavg+u cd\mathbf{c}_{\text{sum}}=\sum\alpha_i\mathbf{c}_i,\ \alpha_{\text{sum}}=\sum\alpha_i,\ \mathbf{c}_{\text{wavg}}=\frac{\mathbf{c}_{\text{sum}}}{\alpha_{\text{sum}}},\ \alpha_{\text{avg}}=\frac{\alpha_{\text{sum}}}{n},\ u=(1-\alpha_{\text{avg}})^n,\ \mathbf{c}_o=(1-u)\mathbf{c}_{\text{wavg}}+u\,\mathbf{c}_d

  • 加权和会饱和、背景可能被减成负值,所以通常用加权平均。但相同 alpha 时所有颜色等权,例如红纱叠在蓝纱上得到紫色而不是"红色透出一点蓝"。适合高度透明的表面和粒子,接近不透明时效果差。
  • 加权混合 OIT (McGuire & Bavoil):按距离加权,近处影响大;uu 改为 ∏(1−αi)\prod(1-\alpha_i) 得到真实总覆盖。效果更可信;缺点是大场景中相近物体的距离权重几乎相同,视距变化时权重效果也会(缓慢)变化。扩展版本把不透明场景乘以透明物体颜色存到第三个缓冲,实现有色透射——有色透射本身与顺序无关。
  • 结论:透明内容、渲染方法、GPU 能力差异很大,没有完美的透明渲染方案。

预乘 alpha 与合成

  • 合成 (compositing) 时每像素随 RGB 存 alpha,alpha 通道构成的图叫 matte。
  • 预乘 (associated) alpha:co=cs′+(1−αs)cd\mathbf{c}_o=\mathbf{c}'_s+(1-\alpha_s)\mathbf{c}_d,更高效,且不改混合状态就能同时做 over 和加法混合。预乘后 RGB 通常不大于 alpha,也可故意更大以得到特别亮的半透明值。
  • 渲染结果天然是预乘的:白色三角形覆盖某像素 40%,存为 (0.4, 0.4, 0.4, 0.4);未预乘形式是 (1, 1, 1, 0.4)。
  • 过滤和混合时最好用预乘数据:线性插值对未预乘数据不正确,会产生物体边缘的黑边。
  • 未预乘 alpha 适合图像编辑(遮罩照片而不改原始数据),能使用颜色通道的完整精度,但与线性空间相互转换要小心。PNG 只支持未预乘,OpenEXR 只支持预乘,TIFF 两者都支持。
  • 色度键 (chroma-keying):指定某一颜色为透明(如 GIF),无需存 alpha,但每像素只能完全透明或完全不透明。

GEA 的视角:两遍法与逐像素片元列表(卷 II 11.3.12)

  • 混合公式:透明片元与像素已有颜色在 RGB 立方体中做线性插值 Cp′=αCf+(1−α)Cp\mathbf{C}_p'=\alpha\mathbf{C}_f+(1-\alpha)\mathbf{C}_p;α=0\alpha=0 不贡献任何颜色,α=1\alpha=1 完全覆盖,中间值像有色玻璃(卷 II 11.3.12)。这就是本页的 over 运算符。
  • 术语提醒:程序员口头常把 α 叫"透明度",GEA 指出它其实是不透明度(α=1 时不透明)。RGBA 中的 A 应理解为大写希腊字母 alpha。alpha 通常附在材质的漫反射颜色(反照率)上,存在顶点上,逐片元颜色由光照算出或从顶点颜色插值。
  • 两遍法:第一遍只画不透明几何,片元直接覆盖;第二遍把透明几何按深度从后往前排序,开启混合。只有比不透明表面更近的透明三角形能通过深度测试,与第一遍留下的颜色混合,得到透过有色玻璃看物体的效果。GEA 强调这并不是对光穿过参与介质的物理正确模拟,只是看起来可信。
    • 补充:GEA 没有提到第二遍通常要保留深度测试、关闭深度写入(见 深度缓冲 中"测试与写入分开控制"),否则先画的透明面会挡掉其后方本应可见的其他透明面;此外有色玻璃更物理的做法是乘性混合(透射率),见本页上文 RTR4 部分。
  • OIT 的动机与做法:后向前排序继承了画家算法的毛病,相互穿插的三角形排了序也不对;只有少量薄玻璃时还行,复杂场景不适用。GEA 说 OIT"通常"维护逐像素片元列表:(这只是 OIT 的一类,即 A-buffer 系;深度剥离、加权混合 OIT、基于矩的 OIT 等并不保存逐像素列表,见本页上文 RTR4 的 OIT 表;Bavoil & Myers 2008 "Order Independent Transparency with Dual Depth Peeling",McGuire & Bavoil 2013 "Weighted Blended Order-Independent Transparency", JCGT 2(2)。)透明 pass 按任意顺序光栅化,每个片元追加到对应像素的列表,最后按深度排序并混合(卷 II 11.3.12.1)。
  • 为什么可行:第二遍中每像素重叠的透明片元通常很少,因为只有位于最近不透明表面与相机之间的片元才需要考虑。可以给每像素一个固定容量数组(蛮力),更实用的是逐像素链表;这依赖现代 GPU 的两项能力:像素着色器能写任意显存缓冲,以及原子操作让并发的着色器实例安全更新同一像素的列表。这对应本页 OIT 表中的「A-buffer / GPU 逐像素链表」。需要严格按提交顺序调用像素着色器时可用光栅顺序视图 (ROV),代价是运行时性能(卷 II 11.4.9.2)。

PBRT 的视角:光线追踪中的随机 alpha 测试(PBRT 4e 7.1.1)

上文讲的是光栅化下的透明。在光线追踪里,镂空(树叶、枝条用一个四边形加 alpha 纹理)由求交阶段决定:alpha 为 0 的点算没击中,为 1 的点算击中。中间值怎么办,PBRT 比较了三种做法:

方案问题
固定阈值(如 alpha 必须为 1 才算击中)边界生硬,形状收缩、锯齿(书中图 7.1(b))
返回 alpha 让积分器处理成半透明接口变复杂;积分器要在该点着色,还要再追一条射线看背后
随机 alpha 测试(PBRT 采用)以概率 alpha 报告击中;alpha 为 0/1 时结果正确,样本足够时边缘平滑

实现要点:

  • 随机数用 HashFloat(ray.o, ray.d),由射线起点和方向哈希得到:同一条射线每次运行结果相同(可复现,便于调试),不同射线又不同(否则退化成固定阈值)。
  • 拒绝一次交点后,要沿射线继续对同一图元求交(例如球的背面还有第二个交点):从交点处重新发射射线,tMax 减去已走的距离,命中时把那段距离加回 tHit。
  • 有 alpha 纹理时 IntersectP() 不能直接调用形状的快速谓词,必须做完整求交。

思路来源是光栅化领域的随机透明(Enderton 等 2010,即上文"随机透明")和哈希 alpha 测试(Wyman 与 McGuire 2017)。

  1. realtime_rendering_4ed.pdf 第 5 章 Shading Basics
  2. Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.3.12、11.4.9.2 节
  4. PBRT 4e source excerpt: chapter 07 (Primitives and Intersection Acceleration)
  5. Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)第 7 章 7.1.1 节,pbr-book.org/4ed/Primitives_and_Intersection_Acceleration

相关页面

图形学合并阶段与帧缓冲Merging & Framebuffer合并阶段把像素着色算出的片元颜色和缓冲区里已有的颜色结合起来,同时负责深度测试、模板测试和混合。它通常不可编程但高度可配置,也叫 ROP(光栅操作或渲染输出单元)。帧缓冲是系统中所有缓冲区的总称。图形学深度缓冲Z-Buffer深度缓冲是几乎所有图形硬件用来解决可见性的算法:为每个像素存一个当前最近图元的深度值,新片元更近才写入颜色和深度。它简单、和图元数量成线性关系、允许大多数图元以任意顺序绘制,但不能直接处理半透明。图形学半透明表面与折射Translucent Surfaces & Refraction玻璃、水、红酒等高吸收、低散射材质:覆盖率 \alpha 与透射率 Tr 是两回事——前者遮挡背景,后者按波长过滤背景。厚度变化时按 Beer-Lambert 定律计算彩色透射;折射可用环境贴图或屏幕空间扰动近似,粗糙表面按粗糙度模糊背景;焦散则用动画贴图、光线光栅化或图像空间光子溅射近似(RTR4 14.5 节)。图形学纹理映射管线Texturing Pipeline纹理通过修改着色方程中使用的值(颜色、粗糙度、法线等)来高效表现表面材质的变化。通用纹理管线是:空间位置 → 投影函数得到纹理坐标 → 对应函数变换到纹理空间 → 取值 → 值变换 → 用于着色。本页还整理纹理坐标约定、纹理表示方式、程序纹理、纹理动画、材质贴图、alpha 贴图和纹理光源。图形学像素着色器Pixel Shader像素着色器(OpenGL 里叫片元着色器)对光栅化产生的每个片元运行,用插值后的顶点数据算出颜色,也可以输出不透明度、修改深度或直接丢弃片元。多渲染目标让它一次输出多组数据,催生了延迟着色。它通常只能写自己所在的像素,但能通过 2×2 quad 拿到相邻像素的导数。图形学粒子系统Particle Systems粒子系统是一组按某种算法运动的小物体,用于火、烟、爆炸、水流、星系等,同时负责动画(生成、移动、变化、删除)和渲染。粒子通常渲染成公告板;难点在半透明排序、光照(逐顶点、逐像素低分辨率光照图块)以及接收/投射/自阴影(透射率溅射、傅里叶不透明度贴图、消光体积)(RTR4 13.8 节)。图形学公告板Billboarding公告板是根据视线方向调整朝向的带纹理矩形。配合 alpha 纹理和动画,它能表现草、烟、火、雾、爆炸、能量护盾、尾迹、云等没有光滑实体表面的现象。各类公告板的区别只在于固定哪个向量(法线或上方向);软粒子、球形公告板解决与实体相交和穿过近平面的问题,轴向公告板用于树木、激光等柱对称物体(RTR4 13.6–13.6.3 节)。图形学毛发渲染Hair & Fur Rendering毛发由角质层、皮质、髓质三层构成,可看作用曲线离散化的体积。几何上用沿引导曲线挤出的四边形条带并配合 alpha/顺序无关透明;着色用 BSDF(R、TT、TRT 分量),再加体积自阴影与多次散射近似;动物短毛可用壳与鳍或几何着色器挤出(RTR4 14.7 节)。图形学空间数据结构Spatial Data Structures空间数据结构把几何体按 n 维空间组织起来,通常是层次化的树,使"几何体是否重叠"一类查询从 O(n) 降到大约 O(\log n)。常见类型有包围体层次 (BVH)、BSP 树(轴对齐的 k-d 树与多边形对齐两种)、四叉树/八叉树(含松散八叉树),以及更偏向组织模型关系的场景图。它们是剔除、光线求交、碰撞检测等加速算法的基础。图形学细节层次Level of Detail细节层次 (LOD) 在物体对图像贡献变小时改用更简单的表示。LOD 系统由三部分组成:生成(简化或手工制作多个版本)、选择(按距离、投影面积等收益函数挑选)、切换(尽量减少跳变 popping)。LOD 主要减少顶点处理,也通过减少 quad 过度着色降低像素开销;进一步还可在预算约束下全局选择 LOD,实现时间关键(恒定帧率)渲染。图形学延迟着色Deferred Shading延迟着色先用一遍几何 pass 把所有可见表面的材质参数写入多张渲染目标(G-buffer),再以后处理方式对这些存储值逐光源计算光照,从而把"几何可见性"与"光照"彻底解耦,并把材质与光源分离。它避免了着色的过度绘制、简化了着色器管理、天然适合贴花,但 G-buffer 占用显存和带宽,且难以直接支持透明和 MSAA。本页也覆盖前向渲染下限制光源影响范围的基础手段与"光照预通道 (light prepass)"类混合方案。图形学景深Depth of Field相机在给定设置下只有一段深度范围清晰,范围外的物体越远离越模糊。实时渲染默认是完美对焦的针孔相机,所以"景深"指对近景和远景做模糊。实用算法从单张图像出发,按深度算出每像素的弥散圆半径,分离近景与其余部分分别模糊再合成;"边收集边散布"和对高亮像素单独溅射散景是游戏中的常见做法(RTR4 12.4 节)。图形学泛光与镜头光晕Bloom & Lens Flare镜头光晕是光经镜头系统或眼睛的间接反射等非预期路径产生的现象;泛光 (bloom) 是镜头和眼睛中的散射在亮光周围形成辉光、并降低其他地方对比度。显示器亮度有限,加入这些眩光效果可以暗示更高的亮度。实现上,光晕常用随光源位置变化的公告板或对亮部做图像处理,泛光则是"提取亮部 → 降采样模糊 → 加回原图"(RTR4 12.3 节)。图形学替身与深度精灵Impostors & Depth Sprites替身 (impostor) 是把复杂物体从当前视点渲染成纹理、贴在视点朝向公告板上的表示,可在多个实例或多帧间复用以摊薄生成成本。公告板云用少量相交的镂空平面近似网格;深度精灵在纹理中加入每像素深度偏移,能与周围几何正确穿插;浮雕纹理、浮雕替身和几何图像进一步模糊了图像与网格的界线(RTR4 13.6.4、13.6.5、13.7 节)。游戏开发 · UE5材质系统Material SystemUE 材质 (Material) 是用节点图描述「表面如何与光交互」的着色器生成器。它有三个正交维度:着色模型 (Shading Model) 决定光照模型(Default Lit、次表面、清漆、毛发等),混合模式 (Blend Mode) 决定与背景的合成公式(Opaque/Masked/Translucent…),参数 + 材质实例 (Material Instance) 让美术在不重编译着色器的前提下做变体。PBR 输入(Base Color/Roughness/Metallic/Specular)直接对应 RTR4 的金属度-粗糙度工作流;最大的工程坑是静态参数导致的着色器排列爆炸。图形学图形 API 设备、管线状态与资源Graphics API Devices, Pipeline State & Resources所有图形 API(OpenGL、DirectX、Vulkan、Metal)都围绕同一组概念:代表 GPU 的设备、描述各阶段配置的管线状态、承载数据的资源及其视图。GEA 把 API 分成高层(OpenGL、D3D11 及更早)和底层(D3D12、Vulkan、Metal、PlayStation 的 Gnm),并介绍 D3D11 的特性级别、设备上下文与延迟上下文、D3D12 的命令列表、PSO 和根签名。本页按 GEA 的整理讲这些跨 API 的共同概念,不是任何一个 API 的教程。图形学显示编码与 sRGBDisplay Encoding & sRGB光照、纹理等计算假设数值是线性的,但显示缓冲和纹理使用非线性编码。简短的回答是:着色器输出 [0,1] 的颜色要取 1/2.2 次幂(gamma 校正),读入的纹理和颜色做相反的变换,多数情况下可以让 GPU 自动完成。忽略它会导致画面偏暗、色相偏移、光照叠加错误和抗锯齿边缘"绳索化"。图形学覆盖层与用户界面渲染Overlays & User Interface RenderingHUD、武器选择界面、各种菜单等图形用户界面,加上调试绘制,都在主 3D 场景渲染完之后才画,所以统称覆盖层 (overlay)。它们一般关闭深度测试、用屏幕空间四边形和正交投影绘制,由文字、位图、嵌入视频和矢量图形几类二维图元组成(GEA4 卷 II 12.8)。综合角色渲染Character Rendering角色是游戏中最受关注、技术最集中的资产。本页按"动起来 → 表面细节 → 材质着色 → 特殊材质(皮肤、毛发、布料)→ 光照与阴影 → 性能"的顺序,把 wiki 中相关概念页串成一套角色渲染方案的地图。每一层只给出要点与取舍,细节见链接页。图形学随机光线追踪与路径追踪Stochastic Ray Tracing & Path Tracing光线追踪用投射光线同时解决可见性问题和光照问题。GEA 从最简单的"眼睛光线 + 着色方程"讲起,逐步加入阴影光线、透射光线、用蒙特卡洛估计渲染方程的随机光线追踪、递归间接光照,再到每次只走一条路径的路径追踪、双向路径追踪和 Metropolis 光传输,最后讨论降噪与光线投射效率(GEA4 卷 II 12.6.3–12.6.5)。图形学着色频率与材质系统Shading Frequency & Material Systems实现着色时要按"计算频率"划分工作:整个 draw call 不变的放到应用端作为 uniform,其余放在相应的可编程阶段。实践中大多数着色在像素级完成,顶点着色器负责变换和变形。材质系统把面向美术的材质与底层着色器组织起来,处理海量着色器变体的组合问题。游戏美术假室内Fake InteriorsSimon Schreibt《Game Art Tricks》48 / 12:用平面窗户着色器假装后面有房间——立方体贴图减速视差、Bump Offset 平铺室内、多层视差+假公告板等——省建模与真透明排序成本。本页忠于原文观察,不臆造引擎未写明的实现细节。游戏美术AC Black Flag 水深遮罩Black Flag WaterplaneGAT 64:水面平面切开船体是常见伪影。大船靠「看不见船腹」与位移遮罩推水;小船用只写深度的隐形盖板(Depth Mask),让后续水面深度测试失败,船舱保持干燥。

被这些页面引用3 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原