OpenUSD usdLux GeometryLight 详解:从几何体光源 Schema 到 MeshLight 迁移实践
2026/9/17 7:30:11 网站建设 项目流程

OpenUSD usdLux GeometryLight 详解:从几何体光源 Schema 到 MeshLight 迁移实践

【免费下载链接】OpenUSDUniversal Scene Description项目地址: https://gitcode.com/GitHub_Trending/ope/OpenUSD

GeometryLight 是 OpenUSD usdLux 体系中的一个具体类型(ConcreteTyped)光源 Schema,用于让几何体(典型如 Mesh)向外发光充当光源。本文以仓库内 GeometryLight 官方 Schema 文档 为骨架,完整讲解其属性定义、继承体系与源码实现,并说明它为何被标记为弃用(deprecated)、以及如何迁移到官方推荐的 MeshLightAPI 方案,帮助你写出正确、可运行的光照 USD 场景。

一、GeometryLight 是什么

根据 GeometryLight 官方文档 的定义,GeometryLight 是:

从一个几何 Prim(Geometric Prim,即UsdGeomGprim)向外发射的光,该几何体通常是 Mesh。该 Schema 已弃用,请改用应用于 Mesh 的 MeshLight。

其关键信息有三点:

  1. 发光方式:光从几何体表面向外辐射,而不是从点、方向或环境贴图发出;
  2. 几何来源:光所依赖的几何体通过geometry关系(relationship)指定;
  3. 弃用状态:文档明确标注 deprecated,官方推荐使用 MeshLight(即MeshLightAPI应用于 Mesh 的方案)。

在 schema.usda 中,GeometryLight 的定义如下:

class GeometryLight "GeometryLight" ( inherits = </NonboundableLightBase> doc = """\deprecated Light emitted outward from a geometric prim (UsdGeomGprim), which is typically a mesh.""" ) { rel geometry ( doc = """Relationship to the geometry to use as the light source.""" ) uniform token light:shaderId = "GeometryLight" ( customData = { bool apiSchemaOverride = true } ) }

其中\deprecated标记直接写进了 Schema 的 doc 字符串,generatedSchema.usda中也保留了同样的声明,说明这是官方在 Schema 层面正式废弃的类型。

二、GeometryLight 的属性(Properties)详解

官方文档为 GeometryLight 定义了 2 个自有属性,均为 Schema 直接声明:

1.geometry(关系属性)

  • USD 类型rel(relationship)
  • 含义:指向用作光源的几何体的关系。

该属性用于将具体的几何体(通常是 Mesh,也支持其他UsdGeomGprim派生类型)与光源 Prim 关联起来。在源码 geometryLight.h 中对应两个 API:

/// Relationship to the geometry to use as the light source. USDLUX_API UsdRelationship GetGeometryRel() const; /// See GetGeometryRel(), and also /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create USDLUX_API UsdRelationship CreateGeometryRel() const;

即通过GetGeometryRel()读取、CreateGeometryRel()创建该关系。注意它是普通 relationship(非 uniform),因此可以在不同层、不同时间采样中分别指定。

2.light:shaderId(token 属性)

  • USD 类型token
  • Fallback(默认)值GeometryLight
  • 含义:GeometryLight 的 shader ID。USD 还会在 SdrRegistry 中注册一个标识符为"GeometryLight"、着色系统为"USD"的 Sdr shader 节点,其输入与该光源的 inputs 一一对应。

这个属性其实继承自LightAPI(详见下文源码分析),GeometryLight 只是通过apiSchemaOverride = true把默认值覆盖为自身的类型名"GeometryLight",这与 DistantLight、DiskLight、RectLight 等内置光源的做法完全一致——每个内置 usdLux 光源的默认 shaderId 都是它自身的类型名。

在 tokens.h 中,该 token 被显式声明:

/// \brief "GeometryLight" /// /// Schema identifer and family for UsdLuxGeometryLight, Fallback value for UsdLuxGeometryLight schema attribute light:shaderId const TfToken GeometryLight;

三、继承属性:来自 Xformable 与 Imageable

GeometryLight 间接继承自NonboundableLightBase,而后者又继承自Xformable(见 schema.usda),因此它同时继承了 Xformable 和 Imageable 的通用属性。官方文档将其分别归为两组:

继承自 Xformable

属性USD 类型说明
xformOpOrdertoken[]变换操作(xformOp)的求值顺序列表,控制光源在场景中的位置与朝向

作为非绑定(Nonboundable)光源,GeometryLight 没有extent等绑定体积属性,但依然可以像普通 Prim 一样被平移、旋转、缩放。

继承自 Imageable

属性USD 类型Fallback 值说明
proxyPrimrel用于指定替代该 Prim 显示的代理几何体
purposetokendefault绘制目的分类(如 default / render / proxy / guide)
visibilitytokeninherited可见性,inherited表示继承父级可见性状态

这些是几乎所有UsdGeomImageable派生 Prim 都具备的标准属性,可用于控制光源在 DCC 工具与渲染器中的显示与参与方式。

四、源码级实现:UsdLuxGeometryLight 类

从源码结构看,GeometryLight 对应的 C++ 类是UsdLuxGeometryLight,完整定义在 geometryLight.h:

/// \class UsdLuxGeometryLight /// /// \deprecated /// Light emitted outward from a geometric prim (UsdGeomGprim), /// which is typically a mesh. /// class UsdLuxGeometryLight : public UsdLuxNonboundableLightBase { public: /// Compile time constant representing what kind of schema this class is. static const UsdSchemaKind schemaKind = UsdSchemaKind::ConcreteTyped; ... };

几个关键实现细节:

  • Schema 种类UsdSchemaKind::ConcreteTyped,即它是一个可以独立作为 Prim 类型名(typeName)使用的具体类型;
  • 继承关系UsdLuxGeometryLight : public UsdLuxNonboundableLightBase,而NonboundableLightBase在 schema.usda 中声明为inherits = </Xformable>prepend apiSchemas = ["LightAPI"],这意味着 GeometryLight 自动获得 LightAPI 的全部能力(intensity、exposure、color、enableColorTemperature、colorTemperature、diffuse、specular、normalize、lightLink、shadowLink 等)以及 Xformable 的变换能力;
  • 注册机制:geometryLight.cpp 中通过TF_REGISTRY_FUNCTION(TfType)调用TfType::Define<UsdLuxGeometryLight, TfType::Bases<UsdLuxNonboundableLightBase>>(),并把"GeometryLight"注册为UsdSchemaBase下的派生别名,从而支持IsA查询与 schema 类型解析;
  • Python 绑定:wrapGeometryLight.cpp 将其导出为UsdLux.GeometryLight,继承自UsdLux.NonboundableLightBase,Python 侧用法与 C++ 一一对应。

五、light:shaderId 与 Sdr 节点注册机制

官方文档提到:"USD 也会注册一个 Sdr shader 节点,标识符为 'GeometryLight'、source type 为 'USD',与该光源的 inputs 对应"。这一机制由 lightDefParser.cpp 中的UsdLux_LightDefParserPlugin实现,其工作流程大致是:

  1. 从插件的generatedSchema.usda资源中读取 Schema 定义层;
  2. 依次把LightAPI、光源类型本身(如GeometryLight)、ShadowAPIShapingAPI的属性复制到一个匿名 prim spec 上(lightDefParser.cpp);
  3. 打开该层,通过UsdShadeConnectableAPI提取所有 inputs/outputs,构造一个SdrShaderNode(lightDefParser.cpp)。

因此,任何符合 usdLux 约定的内置光源都会自动获得一个可被SdrRegistry::GetShaderNodeByIdentifier("GeometryLight")查到的 shader 节点,渲染器与材质系统无需硬编码即可识别该光源及其参数。这也解释了为什么light:shaderId默认值必须与类型名一致——它是 Sdr 发现与解析的标识符。

六、为什么弃用:从 GeometryLight 到 MeshLight 的演进

官方在 overview.md 的 "Mesh Lights" 一节中,明确给出了弃用的原因与替代方案:

你可能需要把任意形状作为光源,例如模拟霓虹灯招牌,或让一个可变形的形状同时发光。请使用MeshLightAPISchema 将光照行为应用到 Mesh。使用该 Schema 优于直接把 LightAPI 应用到 Mesh,因为它应用了常用内置行为:把默认的materialSyncMode覆盖为"materialGlowTintsLight"以使用 Mesh 绑定的材质;同时把默认shaderId设为"MeshLight",为插件挂接额外的 mesh light 属性提供挂钩。

对比两者的差异:

维度GeometryLight(已弃用)MeshLightAPI(推荐)
Schema 形态ConcreteTyped 类型,独立 PrimSingleApply API Schema,附加到现有 Mesh
几何指定方式通过geometry关系指向几何体直接应用于 Mesh Prim 本身
材质同步依赖 LightAPI 默认noMaterialResponse默认materialGlowTintsLight,发光材质可影响光色
shaderId 默认值GeometryLightMeshLight
插件扩展性无专门挂钩可通过 auto-apply 的 API Schema 附加属性

推荐方案:MeshLightAPI

MeshLightAPI 官方文档 完整列出其两个默认属性:

  • light:materialSyncModetoken,Fallback 值materialGlowTintsLight——让材质发射/辉光影响光的颜色,同时保留inputs:colorinputs:intensity等 LightAPI 控制项继续调制光照;
  • light:shaderIdtoken,Fallback 值MeshLight

源码 meshLightAPI.h 中的类注释进一步说明:该 Schema 底层自动把 LightAPI 应用到 Mesh,并覆盖默认 materialSyncMode,同时作为插件挂接额外 "mesh light" 属性的钩子(通过 auto-apply 的 API Schema 实现)。在 schema.usda 中可以找到对应声明:uniform token light:shaderId = "MeshLight"uniform token light:materialSyncMode = "materialGlowTintsLight"

一个可运行的 MeshLight 示例

下面的完整示例来自 overview.md,将 MeshLightAPI 应用到一个复杂曲面,使其作为 4 个球体的光源:

#usda 1.0 ( upAxis = "Y" ) def Xform "MeshLight" { double xformOp:rotateX = -90 uniform token[] xformOpOrder = ["xformOp:rotateX"] def Mesh "Mesh" ( prepend apiSchemas = ["MeshLightAPI"] ) { color3f inputs:color = (1, 1, 1) float inputs:intensity = 1.0 # ...faceVertexCounts/Indices/points 此处省略... } } def Xform "TestSpheres" { def Sphere "Sphere1" { color3f[] primvars:displayColor = [(1, 1, 1)] ( interpolation = "constant" ) double3 xformOp:translate = (-2.5, 3, 0) uniform token[] xformOpOrder = ["xformOp:translate"] } def Sphere "Sphere2" { color3f[] primvars:displayColor = [(1, 1, 1)] ( interpolation = "constant" ) double3 xformOp:translate = (0, 3, -4) uniform token[] xformOpOrder = ["xformOp:translate"] } def Sphere "Sphere3" { color3f[] primvars:displayColor = [(1, 1, 1)] ( interpolation = "constant" ) double3 xformOp:translate = (2.5, 3, 0) uniform token[] xformOpOrder = ["xformOp:translate"] } def Sphere "Sphere4" { color3f[] primvars:displayColor = [(1, 1, 1)] ( interpolation = "constant" ) double3 xformOp:translate = (0, 3, 4) uniform token[] xformOpOrder = ["xformOp:translate"] } }

关键点:

  • 通过prepend apiSchemas = ["MeshLightAPI"]把 Schema 附加到 Mesh 上,无需再定义独立的光源 Prim;
  • Mesh 上的inputs:colorinputs:intensity来自 LightAPI(MeshLightAPI 自动应用),分别控制光色与亮度;
  • materialSyncMode默认即为materialGlowTintsLight,绑定发光材质后,材质发射通道的颜色会与inputs:color相乘,从而让光的颜色"染"上几何体的辉光色。

渲染提示:如果你使用 Hydra 与 RenderMan 渲染,需要启用 Hydra 的 scene index(必要时在环境中设置USDIMAGINGGL_ENGINE_ENABLE_SCENE_INDEX)才能看到 mesh light 的渲染结果(见 overview.md)。

类似的便捷 Schema:VolumeLightAPI

与 MeshLightAPI 类似的还有 VolumeLightAPI,专门用于让 USD Volume 充当光源,默认shaderIdVolumeLightmaterialSyncMode同为materialGlowTintsLight(见 schema.usda)。在 lightDefParser.cpp 的ShaderIdToAPITypeNameMap中,MeshLight → MeshLightAPIVolumeLight → VolumeLightAPI的映射关系明确写入了 Sdr 解析插件,因此这两个 shaderId 同样会被自动解析为对应的 API Schema 属性集。

七、从 GeometryLight 迁移到 MeshLight

迁移的核心思路:把"独立光源 Prim + geometry 关系"改为"Mesh 上直接应用 MeshLightAPI"。

迁移前(旧式,已弃用):

def GeometryLight "MyLight" ( prepend apiSchemas = ["LightAPI"] ) { rel geometry = </Geom/MyMesh> uniform token light:shaderId = "GeometryLight" }

迁移后(推荐):

def Mesh "MyMesh" ( prepend apiSchemas = ["MeshLightAPI"] ) { uniform token light:shaderId = "MeshLight" color3f inputs:color = (1, 1, 1) float inputs:intensity = 1.0 }

在 Python 侧,可以借助UsdLux.MeshLightAPI完成程序化迁移(对应 C++ 的UsdLuxMeshLightAPI::Apply,见 meshLightAPI.h):

from pxr import Usd, UsdLux stage = Usd.Stage.Open("scene.usda") mesh = stage.GetPrimAtPath("/Geom/MyMesh") # 将 MeshLightAPI 应用到 Mesh,返回的 schema 对象可用于继续读写灯光参数 meshLight = UsdLux.MeshLightAPI.Apply(mesh) meshLight.CreateShaderIdAttr() # 默认 "MeshLight" meshLight.CreateIntensityAttr().Set(1.0) meshLight.CreateColorAttr().Set((1.0, 1.0, 1.0)) # 旧式查询方式:UsdLux.GeometryLight.Get(stage, "/Lights/MyLight") # 迁移后不再需要,直接操作 Mesh 上的 LightAPI 属性即可

注意:迁移后geometry关系不再需要,因为光源就是 Mesh 本身;原来通过geometry指向的几何体也无需再做任何关联操作。

八、总结

  • GeometryLight是 usdLux 中让几何体向外发光的光源 Schema,自有属性仅geometry(rel)与light:shaderId(默认GeometryLight),并继承 Xformable、Imageable 以及 LightAPI 的全部通用光照属性;
  • 它已被官方正式弃用(doc 中带有\deprecated标记),其 C++ 类UsdLuxGeometryLight与 token 仍保留在仓库中以便兼容旧场景,但不应在新资产中使用;
  • MeshLightAPI是官方推荐的替代方案:直接应用于 Mesh,默认materialSyncMode = "materialGlowTintsLight"shaderId = "MeshLight",并内置插件挂钩,是模拟霓虹灯、可变形发光体等任意形状光源的标准做法;
  • 无论哪种方案,light:shaderId都会通过 lightDefParser.cpp 的 Sdr 解析插件注册为 "USD" 着色系统下的 shader 节点,保证渲染器能够无硬编码地识别光源参数。

本文所依据的官方 Schema 文档位于 docs/user_guides/schemas/usdLux/GeometryLight.md,Schema 定义与实现可继续深入阅读 pxr/usd/usdLux/schema.usda、geometryLight.h、meshLightAPI.h 与 lightDefParser.cpp。

【免费下载链接】OpenUSDUniversal Scene Description项目地址: https://gitcode.com/GitHub_Trending/ope/OpenUSD

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询