def _ValidateDistantLight(self): lightPrimPath = '/directionalLight1' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) distantLight = UsdLux.DistantLight(lightPrim) self.assertTrue(distantLight) self.assertTrue(Gf.IsClose(distantLight.GetIntensityAttr().Get(1), 2, 1e-6)) self.assertTrue(Gf.IsClose(distantLight.GetColorAttr().Get(1), Gf.Vec3f(1, 0.9, 0.8), 1e-6)) self.assertTrue(Gf.IsClose(distantLight.GetAngleAttr().Get(1), 1.5, 1e-6)) self.assertTrue(Gf.IsClose(distantLight.GetAngleAttr().Get(5), 2, 1e-6)) rotateOp = distantLight.GetOrderedXformOps() self.assertEqual(rotateOp[0].GetOpType(), UsdGeom.XformOp.TypeRotateXYZ) self.assertTrue(UsdGeom.XformCommonAPI(distantLight)) self.assertTrue(Gf.IsClose(rotateOp[0].Get(1), Gf.Vec3f(-20, -40, 0.0), 1e-6)) self.assertTrue(lightPrim.HasAPI(UsdLux.ShadowAPI)) shadowAPI = UsdLux.ShadowAPI(lightPrim) self.assertTrue(shadowAPI) self.assertTrue(shadowAPI.GetShadowEnableAttr().Get(1)) self.assertTrue(Gf.IsClose(shadowAPI.GetShadowColorAttr().Get(1), Gf.Vec3f(0.1, 0.2, 0.3), 1e-6)) return
def _ValidateAreaLight(self): lightPrimPath = '/areaLight1' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) rectLight = UsdLux.RectLight(lightPrim) self.assertTrue(rectLight) self.assertTrue(Gf.IsClose(rectLight.GetColorAttr().Get(), Gf.Vec3f(0.8, 0.7, 0.6), 1e-6)) self.assertTrue(Gf.IsClose(rectLight.GetIntensityAttr().Get(), 1.2, 1e-6)) # normalize didn't exist before Maya 2020 if getMayaAPIVersion() > 2019: self.assertTrue(rectLight.GetNormalizeAttr().Get()) self.assertTrue(lightPrim.HasAPI(UsdLux.ShadowAPI)) shadowAPI = UsdLux.ShadowAPI(lightPrim) self.assertTrue(shadowAPI) (translateOp,rotateOp,scaleOp) = rectLight.GetOrderedXformOps() self.assertEqual(translateOp.GetOpType(), UsdGeom.XformOp.TypeTranslate) self.assertEqual(rotateOp.GetOpType(), UsdGeom.XformOp.TypeRotateXYZ) self.assertEqual(scaleOp.GetOpType(), UsdGeom.XformOp.TypeScale) self.assertTrue(UsdGeom.XformCommonAPI(rectLight)) self.assertTrue(Gf.IsClose(translateOp.Get(1), Gf.Vec3d(8, 0, 10), 1e-6)) self.assertTrue(Gf.IsClose(scaleOp.Get(1), Gf.Vec3f(4,3,2), 1e-6)) self.assertTrue(Gf.IsClose(rotateOp.Get(1), Gf.Vec3f(0,23,0), 1e-6))
def _ValidateSpotLight(self): lightPrimPath = '/spotLight1' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) sphereLight = UsdLux.SphereLight(lightPrim) self.assertTrue(sphereLight) self.assertTrue(Gf.IsClose(sphereLight.GetColorAttr().Get(1), Gf.Vec3f(0.3, 1, 0.2), 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetColorAttr().Get(5), Gf.Vec3f(0, 0.2, 0.1), 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetIntensityAttr().Get(1), 0.8, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetDiffuseAttr().Get(1), 0, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetTreatAsPointAttr().Get(1), 1, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetRadiusAttr().Get(1), 0, 1e-6)) (translateOp,rotateOp) = sphereLight.GetOrderedXformOps() self.assertEqual(translateOp.GetOpType(), UsdGeom.XformOp.TypeTranslate) self.assertEqual(rotateOp.GetOpType(), UsdGeom.XformOp.TypeRotateXYZ) self.assertTrue(UsdGeom.XformCommonAPI(sphereLight)) self.assertTrue(Gf.IsClose(translateOp.Get(1), Gf.Vec3d(10, 7, -8), 1e-6)) self.assertTrue(Gf.IsClose(translateOp.Get(5), Gf.Vec3d(5, 3, 8), 1e-6)) self.assertTrue(Gf.IsClose(rotateOp.Get(1), Gf.Vec3f(-45, 90, -5), 1e-6)) self.assertTrue(lightPrim.HasAPI(UsdLux.ShadowAPI)) shadowAPI = UsdLux.ShadowAPI(lightPrim) self.assertTrue(shadowAPI) self.assertTrue(lightPrim.HasAPI(UsdLux.ShapingAPI)) shapingAPI = UsdLux.ShapingAPI(lightPrim) self.assertTrue(shapingAPI) self.assertTrue(Gf.IsClose(shapingAPI.GetShapingConeAngleAttr().Get(1), 25, 1e-6)) self.assertTrue(Gf.IsClose(shapingAPI.GetShapingConeSoftnessAttr().Get(1), 0.4, 1e-6)) self.assertTrue(Gf.IsClose(shapingAPI.GetShapingFocusAttr().Get(1), 8, 1e-6))
def emit_default_light(app, light_name, usd_tfm, visibility, usd_prim, light_type, xsi_parent, up_key, ignore_tfm): xsi_light = None if light_type == "DistantLight": xsi_light = app.GetPrimLight("Infinite.Preset", light_name, xsi_parent) usd_light = UsdLux.DistantLight(usd_prim) # for distance we set transform utils.set_xsi_transform(app, xsi_light, usd_tfm, up_key=up_key, add_tfm=usd_light.GetLocalTransformation()) utils.set_xsi_visibility(xsi_light, visibility) # and diffuse and specular params set_import_diffuse_param(app, xsi_light, usd_light) set_import_specular_param(app, xsi_light, usd_light) else: # all other lights are point lights if light_type in ["SphereLight", "RectLight", "DiskLight", "CylinderLight"]: # portal and dome lights are not supported by default lights xsi_light = app.GetPrimLight("Point.Preset", light_name, xsi_parent) # cast ptim to light usd_light = UsdLux.SphereLight(usd_prim) if light_type == "SphereLight" else (UsdLux.RectLight(usd_prim) if light_type == "RectLight" else (UsdLux.DiskLight(usd_prim) if light_type == "DiskLight" else UsdLux.CylinderLight(usd_prim))) # set transform utils.set_xsi_transform(app, xsi_light, usd_tfm, up_key=up_key, add_tfm=usd_light.GetLocalTransformation()) utils.set_xsi_visibility(xsi_light, visibility) # set diffuse and specular set_import_diffuse_param(app, xsi_light, usd_light) set_import_specular_param(app, xsi_light, usd_light) # enable area light xsi_light.Parameters("LightArea").Value = True set_import_light_geometry(app, xsi_light, usd_light, light_type) return xsi_light
def __init__(self): AttributesContainerBase.__init__(self) attribute = self.define_attribute("Intensity") #attribute.construct_usd_attribute = lambda usd_node : usd_node.GetPrim().CreateAttribute("intensity", Sdf.ValueTypeNames.Double) attribute.construct_usd_attribute = lambda usd_node: UsdLux.Light( usd_node).GetIntensityAttr() attribute.get_from_usd = lambda usd_node: usd_unreal.utils.get_usd_attribute_value( usd_node.GetPrim(), "intensity") attribute.unreal_property_path = ["light_component", "intensity"] attribute.get_from_actor = lambda actor: actor.light_component.intensity attribute = self.define_attribute("LightColor", 3) attribute.construct_usd_attribute = lambda usd_node: UsdLux.Light( usd_node).GetColorAttr() attribute.convert_unreal_to_usd = lambda color: Gf.Vec3f(color) attribute.get_from_usd = lambda usd_node: usd_unreal.utils.get_usd_attribute_value( usd_node.GetPrim(), "color") attribute.sequencer_channel_names = ["Color.R", "Color.G", "Color.B"] attribute.get_from_actor = lambda actor: LightAttributes.get_light_color( actor.light_component) attribute.set_on_unreal_actor = lambda actor, value: actor.light_component.set_light_color( value) attribute = self.define_attribute("CastShadows") attribute.construct_usd_attribute = lambda usd_node: UsdLux.ShadowAPI( usd_node).CreateShadowEnableAttr() attribute.get_from_usd = lambda usd_node: usd_unreal.utils.get_usd_attribute_value( usd_node, "shadow:enable") attribute.unreal_property_path = ["light_component", "cast_shadows"] attribute.export_compacted_boolean_keys = True attribute.get_from_actor = lambda actor: actor.light_component.cast_shadows def get_temperature_from_light_component(component): return component.temperature if not isinstance( component, unreal.SkyLightComponent) else None attribute = self.define_attribute("Temperature") attribute.construct_usd_attribute = lambda usd_node: UsdLux.Light( usd_node).GetColorTemperatureAttr() attribute.get_from_usd = lambda usd_node: usd_unreal.utils.get_usd_attribute_value( usd_node.GetPrim(), "colorTemperature") attribute.unreal_property_path = ["light_component", "temperature"] attribute.get_from_actor = lambda actor: get_temperature_from_light_component( actor.light_component) def get_use_temperature_from_light_component(component): return component.use_temperature if not isinstance( component, unreal.SkyLightComponent) else None attribute = self.define_attribute("UseTemperature") attribute.construct_usd_attribute = lambda usd_node: UsdLux.Light( usd_node).GetEnableColorTemperatureAttr() attribute.get_from_usd = lambda usd_node: usd_unreal.utils.get_usd_attribute_value( usd_node.GetPrim(), "enableColorTemperature") attribute.unreal_property_path = ["light_component", "use_temperature"] attribute.get_from_actor = lambda actor: get_use_temperature_from_light_component( actor.light_component) attribute.export_compacted_boolean_keys = True
def test_BlackbodySpectrum(self): warm_color = UsdLux.BlackbodyTemperatureAsRgb(1000) whitepoint = UsdLux.BlackbodyTemperatureAsRgb(6500) cool_color = UsdLux.BlackbodyTemperatureAsRgb(10000) # Whitepoint is ~= (1,1,1) assert Gf.IsClose(whitepoint, Gf.Vec3f(1.0), 0.1) # Warm has more red than green or blue assert warm_color[0] > warm_color[1] assert warm_color[0] > warm_color[2] # Cool has more blue than red or green assert cool_color[2] > cool_color[0] assert cool_color[2] > cool_color[1]
def test_FilterLinking(self): light_path = '/Lights/FilterLinking/filter_exclude_a' light = UsdLux.Light(stage.GetPrimAtPath(light_path)) filter_paths = light.GetFiltersRel().GetForwardedTargets() self.assertEqual(len(filter_paths), 1) light_filter = UsdLux.LightFilter(stage.GetPrimAtPath(filter_paths[0])) self.assertEqual(light_filter.GetPath(), '/Lights/FilterLinking/filter') links = light_filter.GetFilterLinkCollectionAPI() query = links.ComputeMembershipQuery() self.assertFalse(query.IsPathIncluded('/Geom/a')) self.assertTrue(query.IsPathIncluded('/Geom/b'))
def _ValidateUsdLuxShadowAPI(self): lightPrimPath = '/RfMLightsTest/Lights/RectLight' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) self.assertTrue(lightPrim.HasAPI(UsdLux.ShadowAPI)) shadowAPI = UsdLux.ShadowAPI(lightPrim) self.assertTrue(shadowAPI) self.assertTrue(shadowAPI.GetShadowEnableAttr().Get()) expectedShadowColor = Gf.Vec3f(0.6) self.assertTrue( Gf.IsClose(shadowAPI.GetShadowColorAttr().Get(), expectedShadowColor, 1e-6)) expectedShadowDistance = -0.6 self.assertTrue( Gf.IsClose(shadowAPI.GetShadowDistanceAttr().Get(), expectedShadowDistance, 1e-6)) expectedShadowFalloff = -0.6 self.assertTrue( Gf.IsClose(shadowAPI.GetShadowFalloffAttr().Get(), expectedShadowFalloff, 1e-6)) expectedShadowFalloffGamma = 0.6 self.assertTrue( Gf.IsClose(shadowAPI.GetShadowFalloffGammaAttr().Get(), expectedShadowFalloffGamma, 1e-6))
def _ValidateUsdLuxShadowAPI(self): lightPrimPath = '/RfMLightsTest/Lights/RectLight' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) self.assertTrue(lightPrim.HasAPI(UsdLux.ShadowAPI)) shadowAPI = UsdLux.ShadowAPI(lightPrim) self.assertTrue(shadowAPI) # Shadows are enabled by default, and we author sparsely, so there # should NOT be an opinion. self.assertFalse( shadowAPI.GetShadowEnableAttr().HasAuthoredValueOpinion()) expectedShadowColor = Gf.Vec3f(0.5) self.assertTrue(Gf.IsClose(shadowAPI.GetShadowColorAttr().Get(), expectedShadowColor, 1e-6)) expectedShadowDistance = -0.5 self.assertTrue(Gf.IsClose(shadowAPI.GetShadowDistanceAttr().Get(), expectedShadowDistance, 1e-6)) expectedShadowFalloff = -0.5 self.assertTrue(Gf.IsClose(shadowAPI.GetShadowFalloffAttr().Get(), expectedShadowFalloff, 1e-6)) expectedShadowFalloffGamma = 0.5 self.assertTrue(Gf.IsClose(shadowAPI.GetShadowFalloffGammaAttr().Get(), expectedShadowFalloffGamma, 1e-6))
def _ValidateUsdLuxShapingAPI(self): lightPrimPath = '/RfMLightsTest/Lights/DiskLight' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) self.assertTrue(lightPrim.HasAPI(UsdLux.ShapingAPI)) shapingAPI = UsdLux.ShapingAPI(lightPrim) self.assertTrue(shapingAPI) expectedFocus = 0.1 self.assertTrue(Gf.IsClose(shapingAPI.GetShapingFocusAttr().Get(), expectedFocus, 1e-6)) expectedFocusTint = Gf.Vec3f(0.1) self.assertTrue(Gf.IsClose(shapingAPI.GetShapingFocusTintAttr().Get(), expectedFocusTint, 1e-6)) expectedConeAngle = 91.0 self.assertTrue(Gf.IsClose(shapingAPI.GetShapingConeAngleAttr().Get(), expectedConeAngle, 1e-6)) expectedConeSoftness = 0.1 self.assertTrue(Gf.IsClose(shapingAPI.GetShapingConeSoftnessAttr().Get(), expectedConeSoftness, 1e-6)) expectedProfilePath = './DiskLight_profile.ies' self.assertEqual(shapingAPI.GetShapingIesFileAttr().Get(), expectedProfilePath) expectedProfileScale = 1.1 self.assertTrue(Gf.IsClose(shapingAPI.GetShapingIesAngleScaleAttr().Get(), expectedProfileScale, 1e-6))
def test_LinkageQueries(self): test_cases = ( ('/Lights/DefaultLinkage/include_all', '/Geom', True), ('/Lights/DefaultLinkage/include_all', '/Geom/a', True), ('/Lights/DefaultLinkage/include_all', '/Geom/a/sub_scope', True), ('/Lights/SimpleInclude/include_a', '/Geom', False), ('/Lights/SimpleInclude/include_a', '/Geom/a', True), ('/Lights/SimpleInclude/include_a', '/Geom/a/sub_scope', True), ('/Lights/SimpleInclude/include_a', '/Geom/b', False), ('/Lights/SimpleExclude/exclude_a', '/Geom', True), ('/Lights/SimpleExclude/exclude_a', '/Geom/a', False), ('/Lights/SimpleExclude/exclude_a', '/Geom/a/sub_scope', False), ('/Lights/SimpleExclude/exclude_a', '/Geom/b', True), ('/Lights/FaceSetLinking/include_faceSet_example', '/', False), ('/Lights/FaceSetLinking/include_faceSet_example', '/Geom', False), ('/Lights/FaceSetLinking/include_faceSet_example', '/Geom/meshWithFaceSet', False), ('/Lights/FaceSetLinking/include_faceSet_example', '/Geom/meshWithFaceSet/faceSet', True), ) for light_path, test_path, expected_result in test_cases: light = UsdLux.Light(stage.GetPrimAtPath(light_path)) links = light.GetLightLinkCollectionAPI() query = links.ComputeMembershipQuery() actual_result = query.IsPathIncluded(test_path) self.assertEqual(actual_result, expected_result)
def test_LinkageAuthoring(self): stage = Usd.Stage.CreateInMemory() geom_scope = UsdGeom.Scope.Define(stage, '/Geom') sphere = UsdGeom.Sphere.Define(stage, '/Geom/Sphere') light_scope = UsdGeom.Scope.Define(stage, '/Lights') light_1 = UsdLux.SphereLight.Define(stage, '/Lights/light_1') light_1_links = UsdLux.Light(light_1).GetLightLinkCollectionAPI() # Schema default: link everything query = light_1_links.ComputeMembershipQuery() self.assertTrue(query.IsPathIncluded(geom_scope.GetPath())) self.assertTrue(query.IsPathIncluded(sphere.GetPath())) self.assertTrue(query.IsPathIncluded('/RandomOtherPath')) # Exclude /Geom. light_1_links.ExcludePath('/Geom') query = light_1_links.ComputeMembershipQuery() self.assertFalse(query.IsPathIncluded(geom_scope.GetPath())) self.assertFalse(query.IsPathIncluded(sphere.GetPath())) self.assertTrue(query.IsPathIncluded('/RandomOtherPath')) # Include /Geom/Sphere light_1_links.IncludePath('/Geom/Sphere') query = light_1_links.ComputeMembershipQuery() self.assertFalse(query.IsPathIncluded(geom_scope.GetPath())) self.assertTrue(query.IsPathIncluded(sphere.GetPath())) self.assertTrue(query.IsPathIncluded('/Geom/Sphere/Child')) self.assertTrue(query.IsPathIncluded('/RandomOtherPath'))
def _ValidateUsdLuxDomeLightTextureFile(self): lightPrimPath = '/RfMLightsTest/Lights/DomeLight' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) domeLight = UsdLux.DomeLight(lightPrim) self.assertTrue(domeLight) expectedTextureFile = './DomeLight_texture.tex' self.assertEqual(domeLight.GetTextureFileAttr().Get(), expectedTextureFile)
def _ValidateUsdLuxDistantLightAngle(self): lightPrimPath = '/RfMLightsTest/Lights/DistantLight' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) distantLight = UsdLux.DistantLight(lightPrim) self.assertTrue(distantLight) expectedAngle = 0.73 self.assertTrue(Gf.IsClose(distantLight.GetAngleAttr().Get(), expectedAngle, 1e-6))
def _ValidatePointLight(self): lightPrimPath = '/pointLight1' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) sphereLight = UsdLux.SphereLight(lightPrim) self.assertTrue(sphereLight) self.assertTrue(Gf.IsClose(sphereLight.GetColorAttr().Get(1), Gf.Vec3f(1, 0.5, 0.1), 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetIntensityAttr().Get(1), 0.5, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetIntensityAttr().Get(5), 2, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetSpecularAttr().Get(1), 0, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetTreatAsPointAttr().Get(1), 1, 1e-6)) self.assertTrue(Gf.IsClose(sphereLight.GetRadiusAttr().Get(1), 0, 1e-6)) translateOp = sphereLight.GetOrderedXformOps() self.assertEqual(translateOp[0].GetOpType(), UsdGeom.XformOp.TypeTranslate) self.assertTrue(UsdGeom.XformCommonAPI(sphereLight)) self.assertTrue(Gf.IsClose(translateOp[0].Get(1), Gf.Vec3d(-10, 10, 0.0), 1e-6))
def _ValidateDiskLightXformAnimation(self): lightPrimPath = '/RfMLightsTest/Lights/DiskLight' lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) diskLight = UsdLux.DiskLight(lightPrim) self.assertTrue(diskLight) xformOps = diskLight.GetOrderedXformOps() self.assertEqual(len(xformOps), 1) translateOp = xformOps[0] self.assertEqual(translateOp.GetOpName(), 'xformOp:translate') self.assertEqual(translateOp.GetOpType(), UsdGeom.XformOp.TypeTranslate) for frame in xrange(int(self.START_TIMECODE), int(self.END_TIMECODE + 1.0)): expectedTranslation = Gf.Vec3d(1.0, float(frame), 1.0) self.assertTrue( Gf.IsClose(translateOp.Get(frame), expectedTranslation, 1e-6))
def emit_sycles_light(app, light_name, usd_tfm, visibility, usd_prim, light_type, xsi_parent, up_key, ignore_tfm): xsi_light = None usd_light = None # cylinder light is not suported by cycles lighst if light_type == "RectLight": xsi_light = app.GetPrim("cyclesArea", light_name, xsi_parent) usd_light = UsdLux.RectLight(usd_prim) # set width and height set_import_parameter(app, xsi_light, "sizeU", usd_light.GetWidthAttr()) set_import_parameter(app, xsi_light, "sizeV", usd_light.GetHeightAttr()) elif light_type == "DiskLight": xsi_light = app.GetPrim("cyclesArea", light_name, xsi_parent) usd_light = UsdLux.DiskLight(usd_prim) xsi_light.Parameters("shape").Value = 1 set_import_parameter(app, xsi_light, "sizeU", usd_light.GetRadiusAttr()) set_import_parameter(app, xsi_light, "sizeV", usd_light.GetRadiusAttr()) elif light_type == "LightPortal": xsi_light = app.GetPrim("cyclesArea", light_name, xsi_parent) usd_light = UsdLux.LightPortal(usd_prim) xsi_light.Parameters("is_portal").Value = True elif light_type == "SphereLight": xsi_light = app.GetPrim("cyclesPoint", light_name, xsi_parent) usd_light = UsdLux.SphereLight(usd_prim) set_import_parameter(app, xsi_light, "size", usd_light.GetRadiusAttr()) elif light_type == "DistantLight": xsi_light = app.GetPrim("cyclesSun", light_name, xsi_parent) usd_light = UsdLux.DistantLight(usd_prim) set_import_parameter(app, xsi_light, "angle", usd_light.GetAngleAttr()) elif light_type == "DomeLight": xsi_light = app.GetPrim("cyclesBackground", light_name, xsi_parent) usd_light = UsdLux.DomeLight(usd_prim) if xsi_light is not None: # set transform utils.set_xsi_transform(app, xsi_light, usd_tfm, up_key=up_key, add_tfm=usd_light.GetLocalTransformation()) utils.set_xsi_visibility(xsi_light, visibility) # for all lights (except dome light and portal) we can set diffuse, specular, intensity if usd_light is not None and light_type != "DomeLight" and light_type != "LightPortal": set_import_parameter(app, xsi_light, "use_diffuse", usd_light.GetDiffuseAttr()) set_import_parameter(app, xsi_light, "use_glossy", usd_light.GetSpecularAttr()) set_import_parameter(app, xsi_light, "power", usd_light.CreateIntensityAttr()) return xsi_light
def sync(obj_prim, obj: bpy.types.Object, **kwargs): """ Creates pyrpr.Light from obj.data: bpy.types.Light """ light = obj.data stage = obj_prim.GetStage() context = bpy.context is_preview_render = kwargs.get('is_preview_render', False) log("sync", light, obj) light_path = obj_prim.GetPath().AppendChild( Tf.MakeValidIdentifier(light.name)) if light.type == 'POINT': usd_light = UsdLux.SphereLight.Define(stage, light_path) size = light.shadow_soft_size usd_light.CreateRadiusAttr(size) elif light.type in ( 'SUN', 'HEMI'): # just in case old scenes will have outdated Hemi usd_light = UsdLux.DistantLight.Define(stage, light_path) angle = math.degrees(light.angle) usd_light.CreateAngleAttr(angle) intensity_attr = usd_light.CreateIntensityAttr() usd_utils.add_delegate_variants( obj_prim, { 'GL': lambda: intensity_attr. Set(light.energy * 1736000000 ), # coefficient approximated to follow RPR results 'RPR': lambda: intensity_attr.Set(light.energy) }) elif light.type == 'SPOT': usd_light = UsdLux.SphereLight.Define(stage, light_path) usd_prim = stage.GetPrimAtPath(light_path) usd_light.CreateTreatAsPointAttr(1) spot_size = math.degrees(light.spot_size) usd_shaping = UsdLux.ShapingAPI(usd_prim) usd_shaping.CreateShapingConeAngleAttr(spot_size / 2) usd_shaping.CreateShapingConeSoftnessAttr(light.spot_blend) usd_shaping.Apply(usd_prim) elif light.type == 'AREA': shape_type = light.shape if shape_type == 'SQUARE': usd_light = UsdLux.RectLight.Define(stage, light_path) usd_light.CreateWidthAttr(light.size) usd_light.CreateHeightAttr(light.size) elif shape_type == 'RECTANGLE': usd_light = UsdLux.RectLight.Define(stage, light_path) usd_light.CreateWidthAttr(light.size) usd_light.CreateHeightAttr(light.size_y) elif shape_type == 'DISK': usd_light = UsdLux.DiskLight.Define(stage, light_path) usd_light.CreateRadiusAttr(light.size / 2) # light.size is diameter else: # shape_type == 'ELLIPSE': usd_light = UsdLux.DiskLight.Define(stage, light_path) usd_light.CreateRadiusAttr((light.size + light.size_y) / 4) # average of light.size is diameter else: raise ValueError("Unsupported light type", light, light.type) power = get_radiant_power(light) color_attr = usd_light.CreateColorAttr() if is_preview_render: # Material Previews are overly bright, that's why # decreasing light intensity for material preview by 10 times power *= 0.1 color_attr.Set(tuple(power))
def test_SdrShaderNodesForLights(self): """ Test the automatic registration of SdrShaderNodes for all the UsdLux light types. """ # Get all the derived types of UsdLuxLight lightTypes = Tf.Type(UsdLux.Light).GetAllDerivedTypes() self.assertTrue(lightTypes) # Verify that at least one known light type is in our list to guard # against this giving false positives if no light types are available. self.assertIn(UsdLux.RectLight, lightTypes) stage = Usd.Stage.CreateInMemory() prim = stage.DefinePrim("/Prim") for lightType in lightTypes: # Every concrete light type will have an SdrShaderNode with source # type 'USD' registered for it under its USD schema type name. typeName = Usd.SchemaRegistry.GetConcreteSchemaTypeName(lightType) node = Sdr.Registry().GetNodeByName(typeName, ['USD']) self.assertTrue(node.IsValid()) # Set the prim to the light type so we can cross check node inputs # with the light prim built-in properties. prim.SetTypeName(typeName) light = UsdLux.Light(prim) self.assertTrue(light) # Names, identifier, and role for the node all match the USD schema # type name self.assertEqual(node.GetIdentifier(), typeName) self.assertEqual(node.GetName(), typeName) self.assertEqual(node.GetImplementationName(), typeName) self.assertEqual(node.GetRole(), typeName) self.assertTrue(node.GetInfoString().startswith(typeName)) # The context is always 'light'. Source type is 'USD' self.assertEqual(node.GetContext(), 'light') self.assertEqual(node.GetSourceType(), 'USD') # Help string is generated and encoded in the node's metadata (no # need to verify the specific wording). self.assertTrue(set(node.GetMetadata().keys()), {'primvars', 'help'}) self.assertEqual(node.GetMetadata()["help"], node.GetHelp()) # Source code and URIs are all empty. self.assertFalse(node.GetSourceCode()) self.assertFalse(node.GetResolvedDefinitionURI()) self.assertFalse(node.GetResolvedImplementationURI()) # Other classifications are left empty. self.assertFalse(node.GetCategory()) self.assertFalse(node.GetDepartments()) self.assertFalse(node.GetFamily()) self.assertFalse(node.GetLabel()) self.assertFalse(node.GetVersion()) self.assertFalse(node.GetAllVstructNames()) self.assertEqual(node.GetPages(), ['']) # Helper for comparing an SdrShaderProperty from node to the # corresponding UsdShadeInput/UsdShadeOutput from a UsdLuxLight def _CompareLightPropToNodeProp(nodeInput, lightInput): # Input names and default values match. self.assertEqual(nodeInput.GetName(), lightInput.GetBaseName()) self.assertEqual(nodeInput.GetDefaultValue(), lightInput.GetAttr().Get()) # Some USD property types don't match exactly one to one and are # converted to different types. In particular relevance to # lights, Bool becomes Int and Token becomes String. expectedTypeName = lightInput.GetTypeName() if expectedTypeName == Sdf.ValueTypeNames.Bool: expectedTypeName = Sdf.ValueTypeNames.Int elif expectedTypeName == Sdf.ValueTypeNames.Token: expectedTypeName = Sdf.ValueTypeNames.String # Verify the node's input type maps back to USD property's type # (with the noted above exceptions). self.assertEqual( nodeInput.GetTypeAsSdfType()[0], expectedTypeName, msg="Type {} != {}".format( str(nodeInput.GetTypeAsSdfType()[0]), str(expectedTypeName))) # If the USD property type is an Asset, it will be listed in # the node's asset indentifier inputs. if expectedTypeName == Sdf.ValueTypeNames.Asset: self.assertIn(nodeInput.GetName(), node.GetAssetIdentifierInputNames()) # There will be a one to one correspondence between node inputs # and light prim inputs. nodeInputs = [node.GetInput(i) for i in node.GetInputNames()] lightInputs = light.GetInputs() for nodeInput, lightInput in zip(nodeInputs, lightInputs): self.assertFalse(nodeInput.IsOutput()) _CompareLightPropToNodeProp(nodeInput, lightInput) # There will also be a one to one correspondence between node # outputs and light prim outputs. nodeOutputs = [node.GetOutput(i) for i in node.GetOutputNames()] lightOutputs = light.GetOutputs() for nodeOutput, lightOutput in zip(nodeOutputs, lightOutputs): self.assertTrue(nodeOutput.IsOutput()) _CompareLightPropToNodeProp(nodeOutput, lightOutput) # The reverse is tested just above, but for all asset identifier # inputs listed for the node there is a corresponding asset value # input property on the light prim. for inputName in node.GetAssetIdentifierInputNames(): self.assertEqual(light.GetInput(inputName).GetTypeName(), Sdf.ValueTypeNames.Asset) # These primvars come from sdrMetadata on the prim itself which # isn't supported for light schemas so it will alwasy be empty. self.assertFalse(node.GetPrimvars()) # sdrMetadata on input properties is supported so additional # primvar properties will correspond to light inputs with that # metadata set. for propName in node.GetAdditionalPrimvarProperties(): self.assertTrue(light.GetInput(propName).GetSdrMetadataByKey( 'primvarProperty')) # Default input can also be specified in the property's sdrMetadata. if node.GetDefaultInput(): defaultLightInput = light.GetInput( node.GetDefaultInput().GetName()) self.assertTrue(lightInput.GetSdrMetadataByKey('defaultInput'))
def test_SdrShaderNodesForLights(self): """ Test the automatic registration of SdrShaderNodes for all the UsdLux light types. """ # The expected shader node inputs that should be found for all of our # UsdLux light types. expectedLightInputNames = [ # LightAPI 'color', 'colorTemperature', 'diffuse', 'enableColorTemperature', 'exposure', 'intensity', 'normalize', 'specular', # ShadowAPI 'shadow:color', 'shadow:distance', 'shadow:enable', 'shadow:falloff', 'shadow:falloffGamma', # ShapingAPI 'shaping:cone:angle', 'shaping:cone:softness', 'shaping:focus', 'shaping:focusTint', 'shaping:ies:angleScale', 'shaping:ies:file', 'shaping:ies:normalize' ] # Map of the names of the expected light nodes to the additional inputs # we expect for those types. expectedLightNodes = { 'CylinderLight' : ['length', 'radius'], 'DiskLight' : ['radius'], 'DistantLight' : ['angle'], 'DomeLight' : ['texture:file', 'texture:format'], 'GeometryLight' : [], 'PortalLight' : [], 'RectLight' : ['width', 'height', 'texture:file'], 'SphereLight' : ['radius'], 'MeshLight' : [], 'VolumeLight' : [] } # Get all the derived types of UsdLuxBoundableLightBase and # UsdLuxNonboundableLightBase that are defined in UsdLux lightTypes = list(filter( Plug.Registry().GetPluginWithName("usdLux").DeclaresType, Tf.Type(UsdLux.BoundableLightBase).GetAllDerivedTypes() + Tf.Type(UsdLux.NonboundableLightBase).GetAllDerivedTypes())) self.assertTrue(lightTypes) # Augment lightTypes to include MeshLightAPI and VolumeLightAPI lightTypes.append( Tf.Type.FindByName('UsdLuxMeshLightAPI')) lightTypes.append( Tf.Type.FindByName('UsdLuxVolumeLightAPI')) # Verify that at least one known light type is in our list to guard # against this giving false positives if no light types are available. self.assertIn(UsdLux.RectLight, lightTypes) self.assertEqual(len(lightTypes), len(expectedLightNodes)) stage = Usd.Stage.CreateInMemory() prim = stage.DefinePrim("/Prim") usdSchemaReg = Usd.SchemaRegistry() for lightType in lightTypes: print("Test SdrNode for schema type " + str(lightType)) if usdSchemaReg.IsAppliedAPISchema(lightType): prim.ApplyAPI(lightType) else: typeName = usdSchemaReg.GetConcreteSchemaTypeName(lightType) if not typeName: continue prim.SetTypeName(typeName) light = UsdLux.LightAPI(prim) self.assertTrue(light) sdrIdentifier = light.GetShaderId([]) self.assertTrue(sdrIdentifier) prim.ApplyAPI(UsdLux.ShadowAPI) prim.ApplyAPI(UsdLux.ShapingAPI) # Every concrete light type and some API schemas (with appropriate # shaderId as sdr Identifier) in usdLux domain will have an # SdrShaderNode with source type 'USD' registered for it under its # USD schema type name. node = Sdr.Registry().GetNodeByIdentifier(sdrIdentifier, ['USD']) self.assertTrue(node is not None) self.assertIn(sdrIdentifier, expectedLightNodes) # Names, identifier, and role for the node all match the USD schema # type name self.assertEqual(node.GetIdentifier(), sdrIdentifier) self.assertEqual(node.GetName(), sdrIdentifier) self.assertEqual(node.GetImplementationName(), sdrIdentifier) self.assertEqual(node.GetRole(), sdrIdentifier) self.assertTrue(node.GetInfoString().startswith(sdrIdentifier)) # The context is always 'light' for lights. # Source type is 'USD' self.assertEqual(node.GetContext(), 'light') self.assertEqual(node.GetSourceType(), 'USD') # Help string is generated and encoded in the node's metadata (no # need to verify the specific wording). self.assertTrue(set(node.GetMetadata().keys()), {'primvars', 'help'}) self.assertEqual(node.GetMetadata()["help"], node.GetHelp()) # Source code and URIs are all empty. self.assertFalse(node.GetSourceCode()) self.assertFalse(node.GetResolvedDefinitionURI()) self.assertFalse(node.GetResolvedImplementationURI()) # Other classifications are left empty. self.assertFalse(node.GetCategory()) self.assertFalse(node.GetDepartments()) self.assertFalse(node.GetFamily()) self.assertFalse(node.GetLabel()) self.assertFalse(node.GetVersion()) self.assertFalse(node.GetAllVstructNames()) self.assertEqual(node.GetPages(), ['']) # The node will be valid for our light types. self.assertTrue(node.IsValid()) # Helper for comparing an SdrShaderProperty from node to the # corresponding UsdShadeInput/UsdShadeOutput from a UsdLux light def _CompareLightPropToNodeProp(nodeInput, primInput): # Input names and default values match. primDefaultValue = primInput.GetAttr().Get() self.assertEqual(nodeInput.GetName(), primInput.GetBaseName()) self.assertEqual(nodeInput.GetDefaultValue(), primDefaultValue) # Some USD property types don't match exactly one to one and are # converted to different types. In particular relevance to # lights and Token becomes String. expectedTypeName = primInput.GetTypeName() # Array valued attributes have their array size determined from # the default value and will be converted to scalar in the # SdrProperty if the array size is zero. if expectedTypeName.isArray: if not primDefaultValue or len(primDefaultValue) == 0: expectedTypeName = expectedTypeName.scalarType elif expectedTypeName == Sdf.ValueTypeNames.Token: expectedTypeName = Sdf.ValueTypeNames.String # Bool SdfTypes should Have Int SdrTypes, but still return as # Bool when queried for GetTypeAsSdfType if expectedTypeName == Sdf.ValueTypeNames.Bool: self.assertEqual(nodeInput.GetType(), Sdf.ValueTypeNames.Int) # Verify the node's input type maps back to USD property's type # (with the noted above exceptions). self.assertEqual( nodeInput.GetTypeAsSdfType()[0], expectedTypeName, msg="{}.{} Type {} != {}".format( str(node.GetName()), str(nodeInput.GetName()), str(nodeInput.GetTypeAsSdfType()[0]), str(expectedTypeName))) # If the USD property type is an Asset, it will be listed in # the node's asset identifier inputs. if expectedTypeName == Sdf.ValueTypeNames.Asset: self.assertIn(nodeInput.GetName(), node.GetAssetIdentifierInputNames()) # There will be a one to one correspondence between node inputs # and prim inputs. Note that the prim may have additional inputs # because of auto applied API schemas, but we only need to verify # that the node has ONLY the expected inputs and the prim at least # has those input proerties. expectedInputNames = \ expectedLightInputNames + expectedLightNodes[sdrIdentifier] # Verify node has exactly the expected inputs. self.assertEqual(sorted(expectedInputNames), sorted(node.GetInputNames())) # Verify each node input matches a prim input. for inputName in expectedInputNames: nodeInput = node.GetInput(inputName) primInput = light.GetInput(inputName) self.assertFalse(nodeInput.IsOutput()) _CompareLightPropToNodeProp(nodeInput, primInput) # None of the UsdLux base lights have outputs self.assertEqual(node.GetOutputNames(), []) self.assertEqual(light.GetOutputs(onlyAuthored=False), []) # The reverse is tested just above, but for all asset identifier # inputs listed for the node there is a corresponding asset value # input property on the prim. for inputName in node.GetAssetIdentifierInputNames(): self.assertEqual(light.GetInput(inputName).GetTypeName(), Sdf.ValueTypeNames.Asset) # These primvars come from sdrMetadata on the prim itself which # isn't supported for light schemas so it will always be empty. self.assertFalse(node.GetPrimvars()) # sdrMetadata on input properties is supported so additional # primvar properties will correspond to prim inputs with that # metadata set. for propName in node.GetAdditionalPrimvarProperties(): self.assertTrue(light.GetInput(propName).GetSdrMetadataByKey( 'primvarProperty')) # Default input can also be specified in the property's sdrMetadata. if node.GetDefaultInput(): defaultInput = light.GetInput( node.GetDefaultInput().GetName()) self.assertTrue(defaultInput.GetSdrMetadataByKey('defaultInput'))
def _ValidateUsdLuxLight(self, lightTypeName): primPathFormat = '/RfMLightsTest/Lights/%s' lightPrimPath = primPathFormat % lightTypeName lightPrim = self._stage.GetPrimAtPath(lightPrimPath) self.assertTrue(lightPrim) testNumber = None if lightTypeName == 'DiskLight': self.assertTrue(lightPrim.IsA(UsdLux.DiskLight)) testNumber = 1 elif lightTypeName == 'DistantLight': self.assertTrue(lightPrim.IsA(UsdLux.DistantLight)) testNumber = 2 elif lightTypeName == 'DomeLight': self.assertTrue(lightPrim.IsA(UsdLux.DomeLight)) testNumber = 3 elif lightTypeName == 'MeshLight': self.assertTrue(lightPrim.IsA(UsdLux.GeometryLight)) testNumber = 4 elif lightTypeName == 'RectLight': self.assertTrue(lightPrim.IsA(UsdLux.RectLight)) testNumber = 5 elif lightTypeName == 'SphereLight': self.assertTrue(lightPrim.IsA(UsdLux.SphereLight)) testNumber = 6 elif lightTypeName == 'AovLight': self.assertTrue(lightPrim.IsA(UsdRi.PxrAovLight)) testNumber = 7 elif lightTypeName == 'EnvDayLight': self.assertTrue(lightPrim.IsA(UsdRi.PxrEnvDayLight)) testNumber = 8 else: raise NotImplementedError('Invalid light type %s' % lightTypeName) lightSchema = UsdLux.Light(lightPrim) self.assertTrue(lightSchema) if lightTypeName == 'AovLight': # PxrAovLight doesn't have any of the below attributes. return expectedIntensity = 1.0 + (testNumber * 0.1) self.assertTrue(Gf.IsClose(lightSchema.GetIntensityAttr().Get(), expectedIntensity, 1e-6)) expectedExposure = 0.1 * testNumber self.assertTrue(Gf.IsClose(lightSchema.GetExposureAttr().Get(), expectedExposure, 1e-6)) expectedDiffuse = 1.0 + (testNumber * 0.1) self.assertTrue(Gf.IsClose(lightSchema.GetDiffuseAttr().Get(), expectedDiffuse, 1e-6)) expectedSpecular = 1.0 + (testNumber * 0.1) self.assertTrue(Gf.IsClose(lightSchema.GetSpecularAttr().Get(), expectedSpecular, 1e-6)) if lightTypeName == 'EnvDayLight': # PxrEnvDayLight doesn't have any of the below attributes. return if lightTypeName == 'DomeLight': # PxrDomeLight has no normalize attribute self.assertFalse( lightSchema.GetNormalizeAttr().HasAuthoredValueOpinion()) else: expectedNormalize = True self.assertEqual(lightSchema.GetNormalizeAttr().Get(), expectedNormalize) expectedColor = Gf.Vec3f(0.1 * testNumber) self.assertTrue(Gf.IsClose(lightSchema.GetColorAttr().Get(), expectedColor, 1e-6)) expectedEnableTemperature = True self.assertEqual(lightSchema.GetEnableColorTemperatureAttr().Get(), expectedEnableTemperature) expectedTemperature = 6500.0 + testNumber self.assertTrue(Gf.IsClose(lightSchema.GetColorTemperatureAttr().Get(), expectedTemperature, 1e-6))
def _test(self, stage): listAPI = UsdLux.ListAPI(stage.GetPrimAtPath('/World')) consult = UsdLux.ListAPI.ComputeModeConsultModelHierarchyCache ignore = UsdLux.ListAPI.ComputeModeIgnoreCache # no cache initially self.assertEqual(len(listAPI.GetLightListRel().GetTargets()), 0) # compute w/o cache should find 1 light outside payload computed_list = listAPI.ComputeLightList(ignore) self.assertEqual(len(computed_list), 1) self.assertTrue(Sdf.Path('/World/Lights/Sky_light') in computed_list) # compute w/ cache should find 1 extra light, since 1 light # inside a payload has been published to cache computed_list = listAPI.ComputeLightList(consult) self.assertEqual(len(computed_list), 2) self.assertTrue(Sdf.Path('/World/Lights/Sky_light') in computed_list) self.assertTrue(Sdf.Path('/World/Geo/torch_2/light') in computed_list) # load payloads to discover the rest of the lights stage.Load() # if we consult the cache we still won't see lights below model # hierarchy computed_list = listAPI.ComputeLightList(consult) self.assertEqual(len(computed_list), 2) self.assertTrue(Sdf.Path('/World/Lights/Sky_light') in computed_list) self.assertTrue(Sdf.Path('/World/Geo/torch_2/light') in computed_list) # but if we ignore cache we now see 3 lights computed_list = listAPI.ComputeLightList(ignore) self.assertEqual(len(computed_list), 3) self.assertTrue(Sdf.Path('/World/Lights/Sky_light') in computed_list) self.assertTrue(Sdf.Path('/World/Geo/torch_1/light') in computed_list) self.assertTrue(Sdf.Path('/World/Geo/torch_2/light') in computed_list) # store this full list in the light list listAPI.StoreLightList(computed_list) # now using the cache should return everything computed_list = listAPI.ComputeLightList(consult) self.assertEqual(len(computed_list), 3) self.assertTrue(Sdf.Path('/World/Lights/Sky_light') in computed_list) self.assertTrue(Sdf.Path('/World/Geo/torch_1/light') in computed_list) self.assertTrue(Sdf.Path('/World/Geo/torch_2/light') in computed_list) # deactivate 1 torch model torch_1 = stage.GetPrimAtPath('/World/Geo/torch_1') torch_1.SetActive(False) # if we ignore the cache(s) we do see only 2 lights self.assertEqual(len(listAPI.ComputeLightList(ignore)), 2) # but the cache should continue to report 3 lights self.assertEqual(len(listAPI.ComputeLightList(consult)), 3) # invalidating the cache should cause it to report 2 lights listAPI.InvalidateLightList() self.assertEqual(len(listAPI.ComputeLightList(consult)), 2) # add a light filter, and confirm that it gets included as a light self.assertEqual(len(listAPI.ComputeLightList(ignore)), 2) filter = UsdLux.LightFilter.Define(stage, '/World/Lights/TestFilter') self.assertEqual(len(listAPI.ComputeLightList(ignore)), 3) # add an untyped prim and apply a LightAPI. Confirm that it also gets # included as a light. self.assertEqual(len(listAPI.ComputeLightList(ignore)), 3) prim = stage.DefinePrim("/World/Lights/PrimWithLightAPI") self.assertEqual(len(listAPI.ComputeLightList(ignore)), 3) UsdLux.LightAPI.Apply(prim) self.assertEqual(len(listAPI.ComputeLightList(ignore)), 4) # discard changes stage.Reload()