BACK TO ARCHIVE
usd houdini pipeline td rendering dcc mechanics

Solaris 里实时生成 Position Reference(pRef)AOV:让 aPMatte 在变形角色上也能“粘住”

12.19.2023 ADUCG RESEARCH

原文:https://www.andreaskj.com/live-pref-in-solaris/
作者:Andreas Kjær-Jensen

Note

前半部分解释“Position Reference pass 是什么”。如果你只想直接用工具,可以跳到「在 Solaris/LOPs 中即时生成 pRef」。

什么是 Position Reference(pRef)pass?

在合成阶段,我们经常希望“在不向灯光额外要 matte 的情况下”,直接在 Nuke 里做更精细的二次选区。Point Position(pWorld)就是常见手段之一:它把每个像素在世界空间中的点位(position)编码进 AOV,合成师可以用 aPMatte 之类的工具在空间里圈选区域。

但当几何发生**变形(deform)**时,pWorld 的缺点会立刻暴露:你以为你圈的是“角色的头”,实际你圈的是“世界空间里的某个体积区域”。网格一动,遮罩就漂走了。

Tip

pWorld 在不同软件里名字可能不同;在 Houdini 的 Karma 里通常就是 AOV “P”。

下面两段视频展示了“pWorld 选区不粘住”的典型现象:

说明:pWorld 渲染结果

上面是 pWorld(Karma 里通常是 P)pass 的渲染效果。

说明:aPMatte 圈头部,但遮罩随变形漂移

因为 aPMatte 实际在“世界空间”里筛选点位,而不是绑定到角色几何上。

你可能会想到改用 Object Position(pObject):把点位存到物体空间。但如果是 deforming mesh,物体空间本身也在改变,仍然不好用(或者在很多管线里压根拿不到“稳定的 object space”定义)。

这时就需要 Position Reference pass(pRef)

  • 它把点位固定在某个指定帧(例如动画开始帧、或者你挑选的 reference 帧);
  • 然后在后续帧里无论网格如何变形,仍保持这组“参考点位”可用。

在 SOP 语境里,这个概念很像给几何做一个 rest 属性:用于绑定噪声、绑定程序纹理、或做稳定的空间参考。

用 pRef 后,你会得到“粘住”的遮罩:


在 Solaris/LOPs 中即时生成 pRef(无需 SOP Modify / 预烘焙)

很多做法要么要求上游在资产环节就把 reference attribute 烘焙好,要么要在 Solaris 里用 SOP Modify 去生成 rest。前者不一定做得到;后者在性能和稳定性上也常让人头疼。

原作者给出一个更“LOPs 原生”的方法:在 LOPs 里通过 Python,直接把某个 source frame 的 points 复制出来,写成一个新的 primvar(比如 pRef)。这在性能上很轻量:本质只是一次属性拷贝。

Note

该脚本需要 Houdini 19.5+。

使用方式

  1. 在 LOPs 里创建一个 Python LOP 节点
  2. 粘贴下面脚本
  3. 修改三个参数:primpatternsourceframeprimvarname
  • primpattern:要生成 pRef 的 prim(支持 prim pattern,比如 "/hydralisk/**"
  • sourceframe:作为 reference 的帧号
  • primvarname:写入 primvar 的名称(默认 pRef
lop-python-generate-pref.py
node = hou.pwd()
stage = node.editableStage()
 
from pxr import Sdf, Usd, UsdGeom
import loputils
 
# Get Parameters - Replace these with your own values!
primpattern = "/hydralisk/**"
sourceframe = 140
primvarname = "pRef"
 
# Parse Primpattern
ls = hou.LopSelectionRule()
ls.setPathPattern(primpattern + ' & %type:Mesh')
paths = ls.expandedPaths(stage=stage)
 
# Compute Point Reference
for prim in paths:
    prim = stage.GetPrimAtPath(prim)
    primvarsapi = UsdGeom.PrimvarsAPI(prim)
    points = prim.GetAttribute('points')
    points_values = points.Get(sourceframe)
    primvar = primvarsapi.CreatePrimvar(
        primvarname,
        Sdf.ValueTypeNames.Color3fArray,
        UsdGeom.Tokens.vertex
    )
    primvar.Set(points_values)

Bonus:在 Karma 中把 pRef 输出为自定义 AOV

在 Karma Render Settings:

  1. 打开 Image Output
  2. 滚到底部,展开 Extra Render Vars
  3. 点击 + 添加一个新的 Render Var

然后按下面配置(如果你脚本里 primvar 名就叫 pRef):

karma-extra-render-var-pref.txt
Name: pRef
Format: color3f
Data Type: color3f
Source Name: pRef
Source Type: Primvar


延伸:什么是 Primvar(以及为什么它适合做 AOV)

Primvar 本质上是一套“被渲染器识别/可被着色与 AOV 访问”的特殊属性命名空间。你把数据写成 primvar,就更容易在渲染时把它作为 AOV 或 shader 输入取出来。

如果你对 primvar 还不熟,推荐读 Luca Scheller 的 USD Survival Guide(原文链接):

https://lucascheller.github.io/VFX-UsdSurvivalGuide/core/elements/property.html#attributePrimvars

本文采用 Creative Commons BY-NC-ND 4.0 协议进行授权。

BY-NC-ND: 署名-非商业性使用-禁止演绎

End of Article