GPU Gems 2 · Chapter 15. Blueprint Rendering and Sketchy Drawings

用 G-buffer、image-space edge enhancement 和 depth sprite 构建 blueprint;再用 depth peeling、几何锚定的 uncertainty 与纹理扰动生成稳定的 sketchy rendering。

学习目标

  • 能说明 blueprint 和 sketchy rendering 为什么都从中间渲染结果开始,而不是只靠最终 fragment color
  • 能从 normal/z buffer 的邻域不连续性提取 silhouette、border 和 crease edges
  • 能描述 depth peeling 如何得到多层 geometry,以及 depth sprite 如何恢复 image-based geometry 的深度测试
  • 能组合 visible/occluded edge maps 生成 blueprint,并用 depth masking 和 occlusion query 控制 pass 数
  • 能用几何属性驱动两套 edge/shade texture 的不同 uncertainty,降低 shower-door effect

非真实感渲染的难点不只是“画一条更粗的线”,而是让结果保留对象之间的空间关系。提供了这条桥:先把几何投影到纹理,再在屏幕对齐 quad 上做边缘增强、深度合成和风格化。

geometry → G-buffers → edge map3D objectnormal bufferencoded Nz-bufferhigh precision Zedge mapnormal / Z Δscreen-aligned quad 采样邻居 texels,输出每像素 edge intensity
先保存可以复用的中间渲染结果:normal 和 z 的不连续性提供 silhouette、border、crease 等边缘。

1. G-buffer 与 image-space edge enhancement

先把 encoded normal 和高精度 z 写入两个 texture。对每个屏幕 fragment,采样上下左右或更大邻域的 texels,累积 normal discontinuity 和 z discontinuity,得到 edge intensity。因此能同时发现 silhouette、border 和 crease;它不依赖最终材质颜色,也可以对单个对象独立计算。

这种设计的收益是中间结果只生成一次,后续 blueprint 与 sketchy 两条路径都能复用。采样半径、法线差阈值和深度差阈值则决定边缘的敏感度;高精度 buffer 能减少远处或斜面上的误判。

2. depth sprite:给屏幕图片恢复 z

屏幕对齐 quad 自己的 rasterizer z 并不代表它所携带的 3D 图像深度。在 fragment shader 中读取纹理 z,替换 quad 的 fragment depth;当 z 等于 far plane 的 1 时直接 discard,否则让普通 depth test 决定它能否进入 framebuffer。

depth peeling:layer 1 → layer 2 → layer 3layer 1visible · depth maplayer 2occluded · depth maplayer 3deep · depth map每层同时保存 z 与 color,直到 no fragment 或达到 max depth complexity
普通 depth test 只得到最小 z;depth peeling 让后续 pass 找到第二层、第三层等被遮挡结构。

这样,edge map、shade map 或 color layer map 就能像真正的几何一样和场景按深度合并。对于 blueprint,depth sprite 是把 image-space 的隐藏线重新放回正确空间关系的关键。

3. blueprint:把可见和隐藏边缘都交给用户

blueprint 需要可见边缘,也需要被遮挡但对理解结构有价值的边缘。先抽取 layer 1,再以上一层深度为约束抽取 layer 2、layer 3,直到没有 fragment 或达到最大 depth complexity。

每一层的 edge map 与 depth map 通过 depth sprite compose:fragment shader 读取 edge intensity,生成蓝色系 RGB 和由 intensity 控制的 alpha,再用 blending 叠加。可以先保存指定组件的 depth mask,每次 peel 后用 occlusion query 统计已露出的片段;达到目标比例就停止,避免为了很少的深层像素付出完整 pass。

edge layers + depth sprites → blueprintvisible edgeslayer 1occluded edges · layer 2+depth spritereplace quad zdiscard z = 1ordinary depth testblueprintblenddepth masking 可用目标组件的可见比例提前终止 peeling
每层 edge map 先以 depth sprite 恢复正确 z,再以 edge intensity 控制蓝图颜色与透明度。

4. sketchy:从 edge 到不稳定但可控的笔触

sketchy drawing 同时需要 edge map 与 surface color 的 shade map。对屏幕坐标 (s, t) 采样 noise,再用 2×2 matrix 得到不确定偏移,把坐标扰动到 (s′, t′);edge 与 shade 使用不同 matrix,才能让轮廓和色块产生互相错开的手绘感。内区与外区的采样穿过原几何边界,因而可以得到略微溢出的 crayon-like patches。

若只从屏幕坐标计算,物体一动笔触就会游移。更稳定的路径是把 object-space position、normal 等写入额外 G-buffer,再用几何值参数化 noise;也可以沿 vertex normal 稍微扩大 connected component,让边界外近邻区域也有可用属性。

geometry-aware uncertainty → sketchy drawingedge mapfEdge(s,t)shade map · fShadeuncertaintynoise textureobject position / normal2×2 perturb matrixs,t → s′,t′sketchenlarged geometry 把可靠的 uncertainty 延伸到边界附近的 exterior regions
edge 与 shade 使用不同的扰动函数;加入 object-space 几何属性后,笔触不再只在屏幕上漂移。

最后把 perturb 后的 edge intensity 与 shade color 相乘,并借助 depth sprite 和普通深度测试与其他 3D 内容合成。如此既保留了风格,也不丢掉前后遮挡关系。

5. 动手实验:质量、层数与稳定度

下面的实验把 depth layers、终止阈值、uncertainty 和 object-space 锚定暴露出来。提高 layers 会露出更多隐藏结构,但增加 pass;提高 uncertainty 会增强手绘感,也会降低轮廓稳定度;关闭几何锚定则能直观看到 shower-door effect 的风险。

Blueprint / sketchy rendering 实验

观察 peeling 层数、遮挡阈值与 geometry-aware uncertainty 如何改变覆盖率、成本和稳定度。

3 depth layers · geometry anchoredblueprint edges · 60%sketch stability · 79%estimated passes 54 · threshold 24% fragments示意值:真实效果还取决于 edge map、noise 和目标几何

扰动使用位置/法线,减少 shower-door effect。 layers 越多,隐藏结构越完整但 pass 成本越高。

小结

  • normal/z G-buffer 是 blueprint 和 sketchy 复用的 intermediate rendering result。
  • 邻域 discontinuity 生成 edge map,能找出 silhouette、border 和 crease,而不被材质颜色绑死。
  • depth peeling 抽取隐藏的唯一深度层,depth sprite 让 texture image 重新参加逐像素 depth test。
  • blueprint 通过 depth-sorted edge layers、alpha blending 与 depth masking 表达可见和不可见结构。
  • sketchy 的 edge/shade 扰动要用几何属性约束 uncertainty,才能减少 shower-door effect。

练习

问题 1|中间结果 为什么 blueprint 的 edge map 应该从 normal/z buffer 生成,而不是直接检测最终颜色?

问题 2|隐藏线 普通 depth test 为什么不能提取 blueprint 的第二层边缘?depth sprite 在这里解决了什么?

问题 3|风格稳定性 如何让 sketchy drawing 有手绘不确定性,却不随相机产生 shower-door effect?

名词解释

本章出现的专业名词,用大白话再讲一遍。

intermediate rendering result
写入纹理、供后续 image-space pass 复用的几何中间结果。
edge map
由 normal/z buffer 邻域不连续性得到的边缘强度纹理。
depth sprite
把 depth texture 作为屏幕 quad 逐像素 z 并重新参与 depth test 的渲染方式。
depth peeling
按深度逐层剥离、保存每一层 depth/color map 的多遍过程。
depth masking
按目标组件达到的可见片段比例动态终止 peeling 的优化。
uncertainty
由噪声或几何属性驱动的纹理坐标扰动量,控制 sketchy 笔触。

资料与写作方式声明

本章以GPU Gems 2 · Chapter 15. Blueprint Rendering and Sketchy Drawings权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…