def testManyImages(self): allFilter = GafferScene.PathFilter() allFilter["paths"].setValue(IECore.StringVectorData(['/...'])) sphere = GafferScene.Sphere() sphere["transform"]["translate"].setValue(imath.V3f(-3, 0, 0)) standardSurface = GafferArnold.ArnoldShader() standardSurface.loadShader("standard_surface") shaderAssignment = GafferScene.ShaderAssignment() shaderAssignment["in"].setInput(sphere["out"]) shaderAssignment["filter"].setInput(allFilter["out"]) shaderAssignment["shader"].setInput(standardSurface["out"]) uvScaleCode = GafferOSL.OSLCode() uvScaleCode["out"].addChild( Gaffer.V3fPlug("uvScaled", direction=Gaffer.Plug.Direction.Out)) uvScaleCode["code"].setValue('uvScaled = vector( u * 2, v * 2, 0 );') outUV = GafferOSL.OSLShader() outUV.loadShader("ObjectProcessing/OutUV") outUV["parameters"]["value"].setInput(uvScaleCode["out"]["uvScaled"]) outObject2 = GafferOSL.OSLShader() outObject2.loadShader("ObjectProcessing/OutObject") outObject2["parameters"]["in0"].setInput( outUV["out"]["primitiveVariable"]) uvScaleOSL = GafferOSL.OSLObject() uvScaleOSL["in"].setInput(shaderAssignment["out"]) uvScaleOSL["filter"].setInput(allFilter["out"]) uvScaleOSL["shader"].setInput(outObject2["out"]["out"]) uvScaleOSL["interpolation"].setValue(5) mapOffset = GafferScene.MapOffset() mapOffset["in"].setInput(uvScaleOSL["out"]) mapOffset["filter"].setInput(allFilter["out"]) mapOffset["udim"].setValue(1033) offsetGroup = GafferScene.Group() offsetGroup["in"]["in0"].setInput(mapOffset["out"]) offsetGroup["name"].setValue('offset') offsetGroup["transform"]["translate"].setValue(imath.V3f(6, 0, 3)) combineGroup = GafferScene.Group() combineGroup["in"]["in0"].setInput(uvScaleOSL["out"]) combineGroup["in"]["in1"].setInput(offsetGroup["out"]) lights = [] for color, rotate in [((1, 0, 0), (0, 0, 0)), ((0, 1, 0), (0, 90, 0)), ((0, 0, 1), (-90, 0, 0))]: light = GafferArnold.ArnoldLight() light.loadShader("distant_light") light["parameters"]["color"].setValue(imath.Color3f(*color)) light["transform"]["rotate"].setValue(imath.V3f(*rotate)) combineGroup["in"][-1].setInput(light["out"]) lights.append(light) arnoldTextureBake = GafferArnold.ArnoldTextureBake() arnoldTextureBake["in"].setInput(combineGroup["out"]) arnoldTextureBake["filter"].setInput(allFilter["out"]) arnoldTextureBake["bakeDirectory"].setValue(self.temporaryDirectory() + '/bakeSpheres/') arnoldTextureBake["defaultResolution"].setValue(32) arnoldTextureBake["aovs"].setValue('beauty:RGBA diffuse:diffuse') arnoldTextureBake["tasks"].setValue(3) arnoldTextureBake["cleanupIntermediateFiles"].setValue(True) # Dispatch the bake script = Gaffer.ScriptNode() script.addChild(arnoldTextureBake) dispatcher = GafferDispatch.LocalDispatcher() dispatcher["jobsDirectory"].setValue(self.temporaryDirectory()) dispatcher.dispatch([arnoldTextureBake]) # Test that we are writing all expected files, and that we have cleaned up all temp files expectedUdims = [i + j for j in [1001, 1033] for i in [0, 1, 10, 11]] self.assertEqual( sorted(os.listdir(self.temporaryDirectory() + '/bakeSpheres/')), ["beauty", "diffuse"]) self.assertEqual( sorted( os.listdir(self.temporaryDirectory() + '/bakeSpheres/beauty')), ["beauty.%i.tx" % i for i in expectedUdims]) self.assertEqual( sorted( os.listdir(self.temporaryDirectory() + '/bakeSpheres/diffuse')), ["diffuse.%i.tx" % i for i in expectedUdims]) # Read back in the 4 udim tiles of a sphere reader = GafferImage.ImageReader() imageTransform = GafferImage.ImageTransform() imageTransform["in"].setInput(reader["out"]) exprBox = Gaffer.Box() expression = Gaffer.Expression() exprBox.addChild(reader) exprBox.addChild(imageTransform) exprBox.addChild(expression) expression.setExpression( inspect.cleandoc( """ i = context.get( "loop:index", 0 ) layer = context.get( "collect:layerName", "beauty" ) x = i % 2 y = i // 2 parent["ImageReader"]["fileName"] = '""" + self.temporaryDirectory() + """/bakeSpheres/%s/%s.%i.tx' % ( layer, layer, 1001 + x + y * 10 ) parent["ImageTransform"]["transform"]["translate"] = imath.V2f( 32 * x, 32 * y ) """), "python") udimLoop = Gaffer.Loop() udimLoop.setup(GafferImage.ImagePlug()) udimLoop["iterations"].setValue(4) udimMerge = GafferImage.Merge() udimMerge["in"]["in0"].setInput(imageTransform["out"]) udimMerge["in"]["in1"].setInput(udimLoop["previous"]) udimLoop["next"].setInput(udimMerge["out"]) aovCollect = GafferImage.CollectImages() aovCollect["in"].setInput(udimLoop["out"]) aovCollect["rootLayers"].setValue( IECore.StringVectorData(['beauty', 'diffuse'])) # We have a little reference image for how the diffuse should look imageReaderRef = GafferImage.ImageReader() imageReaderRef["fileName"].setValue( os.path.dirname(__file__) + "/images/sphereLightBake.exr") resizeRef = GafferImage.Resize() resizeRef["in"].setInput(imageReaderRef["out"]) resizeRef["format"].setValue(GafferImage.Format(64, 64, 1.000)) shuffleRef = GafferImage.Shuffle() shuffleRef["in"].setInput(resizeRef["out"]) for layer in ["beauty", "diffuse"]: for channel in ["R", "G", "B"]: shuffleRef["channels"].addChild( GafferImage.Shuffle.ChannelPlug()) shuffleRef["channels"][-1]["in"].setValue(channel) shuffleRef["channels"][-1]["out"].setValue(layer + "." + channel) differenceMerge = GafferImage.Merge() differenceMerge["in"]["in0"].setInput(aovCollect["out"]) differenceMerge["in"]["in1"].setInput(shuffleRef["out"]) differenceMerge["operation"].setValue( GafferImage.Merge.Operation.Difference) stats = GafferImage.ImageStats() stats["in"].setInput(differenceMerge["out"]) stats["area"].setValue(imath.Box2i(imath.V2i(0, 0), imath.V2i(64, 64))) # We should get a very close match to our single tile low res reference bake stats["channels"].setValue( IECore.StringVectorData( ['diffuse.R', 'diffuse.G', 'diffuse.B', 'diffuse.A'])) for i in range(3): self.assertLess(stats["average"].getValue()[i], 0.002) self.assertLess(stats["max"].getValue()[i], 0.02) # The beauty should be mostly a close match, but with a high max difference due to the spec pings stats["channels"].setValue( IECore.StringVectorData( ['beauty.R', 'beauty.G', 'beauty.B', 'beauty.A'])) for i in range(3): self.assertLess(stats["average"].getValue()[i], 0.1) self.assertGreater(stats["max"].getValue()[i], 0.3)
def _createPointLight(self): light = GafferArnold.ArnoldLight() light.loadShader("point_light") return light, light["parameters"]["color"]
def testLightAndShadowLinking( self ) : sphere1 = GafferScene.Sphere() sphere2 = GafferScene.Sphere() attributes = GafferScene.StandardAttributes() arnoldAttributes = GafferArnold.ArnoldAttributes() light1 = GafferArnold.ArnoldLight() light1.loadShader( "point_light" ) light2 = GafferArnold.ArnoldLight() light2.loadShader( "point_light" ) group = GafferScene.Group() render = GafferArnold.ArnoldRender() attributes["in"].setInput( sphere1["out"] ) arnoldAttributes["in"].setInput( attributes["out"] ) group["in"][0].setInput( arnoldAttributes["out"] ) group["in"][1].setInput( light1["out"] ) group["in"][2].setInput( light2["out"] ) group["in"][3].setInput( sphere2["out"] ) render["in"].setInput( group["out"] ) # Illumination attributes["attributes"]["linkedLights"]["enabled"].setValue( True ) attributes["attributes"]["linkedLights"]["value"].setValue( "/group/light" ) # Shadows arnoldAttributes["attributes"]["shadowGroup"]["enabled"].setValue( True ) arnoldAttributes["attributes"]["shadowGroup"]["value"].setValue( "/group/light1" ) render["mode"].setValue( render.Mode.SceneDescriptionMode ) render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) render["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) # the first sphere had linked lights sphere = arnold.AiNodeLookUpByName( "/group/sphere" ) # check illumination self.assertTrue( arnold.AiNodeGetBool( sphere, "use_light_group" ) ) lights = arnold.AiNodeGetArray( sphere, "light_group" ) self.assertEqual( arnold.AiArrayGetNumElements( lights ), 1 ) self.assertEqual( arnold.AiNodeGetName( arnold.AiArrayGetPtr( lights, 0 ) ), "light:/group/light" ) # check shadows self.assertTrue( arnold.AiNodeGetBool( sphere, "use_shadow_group" ) ) shadows = arnold.AiNodeGetArray( sphere, "shadow_group" ) self.assertEqual( arnold.AiArrayGetNumElements( shadows ), 1 ) self.assertEqual( arnold.AiNodeGetName( arnold.AiArrayGetPtr( shadows, 0 ) ), "light:/group/light1" ) # the second sphere does not have any light linking enabled sphere1 = arnold.AiNodeLookUpByName( "/group/sphere1" ) # check illumination self.assertFalse( arnold.AiNodeGetBool( sphere1, "use_light_group" ) ) lights = arnold.AiNodeGetArray( sphere1, "light_group" ) self.assertEqual( arnold.AiArrayGetNumElements( lights ), 0 ) # check shadows self.assertFalse( arnold.AiNodeGetBool( sphere1, "use_shadow_group" ) ) shadows = arnold.AiNodeGetArray( sphere1, "shadow_group" ) self.assertEqual( arnold.AiArrayGetNumElements( shadows ), 0 )
def testShaderSubstitutions( self ) : s = Gaffer.ScriptNode() s["plane"] = GafferScene.Plane() s["planeAttrs"] = GafferScene.CustomAttributes() s["planeAttrs"]["in"].setInput( s["plane"]["out"] ) s["planeAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "A", Gaffer.StringPlug( "value", defaultValue = 'bar' ) ) ) s["planeAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "B", Gaffer.StringPlug( "value", defaultValue = 'foo' ) ) ) s["cube"] = GafferScene.Cube() s["cubeAttrs"] = GafferScene.CustomAttributes() s["cubeAttrs"]["in"].setInput( s["cube"]["out"] ) s["cubeAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "B", Gaffer.StringPlug( "value", defaultValue = 'override' ) ) ) s["parent"] = GafferScene.Parent() s["parent"]["in"].setInput( s["planeAttrs"]["out"] ) s["parent"]["children"][0].setInput( s["cubeAttrs"]["out"] ) s["parent"]["parent"].setValue( "/plane" ) s["shader"] = GafferArnold.ArnoldShader() s["shader"].loadShader( "image" ) s["shader"]["parameters"]["filename"].setValue( "<attr:A>/path/<attr:B>.tx" ) s["filter"] = GafferScene.PathFilter() s["filter"]["paths"].setValue( IECore.StringVectorData( [ "/plane" ] ) ) s["shaderAssignment"] = GafferScene.ShaderAssignment() s["shaderAssignment"]["in"].setInput( s["parent"]["out"] ) s["shaderAssignment"]["filter"].setInput( s["filter"]["out"] ) s["shaderAssignment"]["shader"].setInput( s["shader"]["out"] ) s["light"] = GafferArnold.ArnoldLight() s["light"].loadShader( "photometric_light" ) s["light"]["parameters"]["filename"].setValue( "/path/<attr:A>.ies" ) s["goboTexture"] = GafferArnold.ArnoldShader() s["goboTexture"].loadShader( "image" ) s["goboTexture"]["parameters"]["filename"].setValue( "<attr:B>/gobo.tx" ) s["gobo"] = GafferArnold.ArnoldShader() s["gobo"].loadShader( "gobo" ) s["gobo"]["parameters"]["slidemap"].setInput( s["goboTexture"]["out"] ) s["goboAssign"] = GafferScene.ShaderAssignment() s["goboAssign"]["in"].setInput( s["light"]["out"] ) s["goboAssign"]["shader"].setInput( s["gobo"]["out"] ) s["lightBlocker"] = GafferArnold.ArnoldLightFilter() s["lightBlocker"].loadShader( "light_blocker" ) s["lightBlocker"]["parameters"]["geometry_type"].setValue( "<attr:geometryType>" ) s["lightGroup"] = GafferScene.Group() s["lightGroup"]["name"].setValue( "lightGroup" ) s["lightGroup"]["in"][0].setInput( s["goboAssign"]["out"] ) s["lightGroup"]["in"][1].setInput( s["lightBlocker"]["out"] ) s["parent2"] = GafferScene.Parent() s["parent2"]["in"].setInput( s["shaderAssignment"]["out"] ) s["parent2"]["children"][0].setInput( s["lightGroup"]["out"] ) s["parent2"]["parent"].setValue( "/" ) s["globalAttrs"] = GafferScene.CustomAttributes() s["globalAttrs"]["in"].setInput( s["parent2"]["out"] ) s["globalAttrs"]["global"].setValue( True ) s["globalAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "A", Gaffer.StringPlug( "value", defaultValue = 'default1' ) ) ) s["globalAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "B", Gaffer.StringPlug( "value", defaultValue = 'default2' ) ) ) s["globalAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "geometryType", Gaffer.StringPlug( "value", defaultValue = 'cylinder' ) ) ) s["render"] = GafferArnold.ArnoldRender() s["render"]["in"].setInput( s["globalAttrs"]["out"] ) s["render"]["mode"].setValue( s["render"].Mode.SceneDescriptionMode ) s["render"]["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) s["render"]["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) plane = arnold.AiNodeLookUpByName( "/plane" ) shader = arnold.AiNodeGetPtr( plane, "shader" ) self.assertEqual( arnold.AiNodeGetStr( shader, "filename" ), "bar/path/foo.tx" ) cube = arnold.AiNodeLookUpByName( "/plane/cube" ) shader2 = arnold.AiNodeGetPtr( cube, "shader" ) self.assertEqual( arnold.AiNodeGetStr( shader2, "filename" ), "bar/path/override.tx" ) light = arnold.AiNodeLookUpByName( "light:/lightGroup/light" ) self.assertEqual( arnold.AiNodeGetStr( light, "filename" ), "/path/default1.ies" ) gobo = arnold.AiNodeGetPtr( light, "filters" ) goboTex = arnold.AiNodeGetLink( gobo, "slidemap" ) self.assertEqual( arnold.AiNodeGetStr( goboTex, "filename" ), "default2/gobo.tx" ) lightFilter = arnold.AiNodeLookUpByName( "lightFilter:/lightGroup/lightFilter" ) self.assertEqual( arnold.AiNodeGetStr( lightFilter, "geometry_type" ), "cylinder" )
def testLightLinking(self): sphere1 = GafferScene.Sphere() sphere2 = GafferScene.Sphere() attributes = GafferScene.StandardAttributes() light1 = GafferArnold.ArnoldLight() light1.loadShader("point_light") light2 = GafferArnold.ArnoldLight() light2.loadShader("point_light") group = GafferScene.Group() group["in"].addChild(GafferScene.ScenePlug("in1")) group["in"].addChild(GafferScene.ScenePlug("in2")) group["in"].addChild(GafferScene.ScenePlug("in3")) group["in"].addChild(GafferScene.ScenePlug("in4")) evaluate = GafferScene.EvaluateLightLinks() render = GafferArnold.ArnoldRender() attributes["in"].setInput(sphere1["out"]) group["in"]["in1"].setInput(attributes["out"]) group["in"]["in2"].setInput(light1["out"]) group["in"]["in3"].setInput(light2["out"]) group["in"]["in4"].setInput(sphere2["out"]) evaluate["in"].setInput(group["out"]) render["in"].setInput(evaluate["out"]) attributes["attributes"]["linkedLights"]["enabled"].setValue(True) attributes["attributes"]["linkedLights"]["value"].setValue( "/group/light /group/light1") # make sure we pass correct data into the renderer self.assertEqual( set(render["in"].attributes("/group/sphere")["linkedLights"]), set(IECore.StringVectorData(["/group/light", "/group/light1"]))) render["mode"].setValue(render.Mode.SceneDescriptionMode) render["fileName"].setValue(self.temporaryDirectory() + "/test.ass") render["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") # the first sphere had linked lights sphere = arnold.AiNodeLookUpByName("/group/sphere") lights = arnold.AiNodeGetArray(sphere, "light_group") lightNames = [] for i in range(lights.contents.nelements): light = arnold.cast(arnold.AiArrayGetPtr(lights, i), arnold.POINTER(arnold.AtNode)) lightNames.append(arnold.AiNodeGetName(light.contents)) doLinking = arnold.AiNodeGetBool(sphere, "use_light_group") self.assertEqual(lightNames, ["light:/group/light", "light:/group/light1"]) self.assertEqual(doLinking, True) # the second sphere does not have any light linking enabled sphere1 = arnold.AiNodeLookUpByName("/group/sphere1") lights = arnold.AiNodeGetArray(sphere1, "light_group") lightNames = [] for i in range(lights.contents.nelements): light = arnold.cast(arnold.AiArrayGetPtr(lights, i), arnold.POINTER(arnold.AtNode)) lightNames.append(arnold.AiNodeGetName(light.contents)) doLinking = arnold.AiNodeGetBool(sphere1, "use_light_group") self.assertEqual(lightNames, []) self.assertEqual(doLinking, False)
def testLightLinkingAfterParameterUpdates(self): s = Gaffer.ScriptNode() s["catalogue"] = GafferImage.Catalogue() s["s"] = GafferScene.Sphere() s["PathFilter"] = GafferScene.PathFilter("PathFilter") s["PathFilter"]["paths"].setValue(IECore.StringVectorData(['/sphere'])) s["ShaderAssignment"] = GafferScene.ShaderAssignment( "ShaderAssignment") s["ShaderAssignment"]["in"].setInput(s["s"]["out"]) s["ShaderAssignment"]["filter"].setInput(s["PathFilter"]["out"]) s["lambert"], _ = self._createMatteShader() s["ShaderAssignment"]["shader"].setInput(s["lambert"]["out"]) s["StandardAttributes"] = GafferScene.StandardAttributes( "StandardAttributes") s["StandardAttributes"]["attributes"]["linkedLights"][ "enabled"].setValue(True) s["StandardAttributes"]["attributes"]["linkedLights"][ "value"].setValue("defaultLights") s["StandardAttributes"]["filter"].setInput(s["PathFilter"]["out"]) s["StandardAttributes"]["in"].setInput(s["ShaderAssignment"]["out"]) s["Light"] = GafferArnold.ArnoldLight("skydome_light") s["Light"].loadShader("skydome_light") s["c"] = GafferScene.Camera() s["c"]["transform"]["translate"]["z"].setValue(2) s["group"] = GafferScene.Group() s["group"]["in"][0].setInput(s["StandardAttributes"]["out"]) s["group"]["in"][1].setInput(s["Light"]["out"]) s["group"]["in"][2].setInput(s["c"]["out"]) s["o"] = GafferScene.Outputs() s["o"].addOutput( "beauty", IECoreScene.Output( "test", "ieDisplay", "rgba", { "driverType": "ClientDisplayDriver", "displayHost": "localhost", "displayPort": str(s['catalogue'].displayDriverServer().portNumber()), "remoteDisplayType": "GafferImage::GafferDisplayDriver", })) s["o"]["in"].setInput(s["group"]["out"]) s["so"] = GafferScene.StandardOptions() s["so"]["options"]["renderCamera"]["value"].setValue("/group/camera") s["so"]["options"]["renderCamera"]["enabled"].setValue(True) s["so"]["in"].setInput(s["o"]["out"]) s["r"] = self._createInteractiveRender() s["r"]["in"].setInput(s["so"]["out"]) # Start rendering and make sure the light is linked to the sphere with GafferTest.ParallelAlgoTest.UIThreadCallHandler() as handler: s["r"]["state"].setValue(s["r"].State.Running) handler.waitFor(1.0) self.assertAlmostEqual(self._color4fAtUV(s["catalogue"], imath.V2f(0.5)).r, 1, delta=0.01) # Change a value on the light. The light should still be linked to the sphere # and we should get the same result as before. s["Light"]['parameters']['shadow_density'].setValue(0.0) handler.waitFor(1.0) self.assertAlmostEqual(self._color4fAtUV(s["catalogue"], imath.V2f(0.5)).r, 1, delta=0.01) s["r"]["state"].setValue(s["r"].State.Stopped)
def testBasic(self): g = GafferScene.Group() inputs = [] for shader, name in [ ("spot_light", "spot1"), ("spot_light", "spot2"), ("distant_light", "distant1"), ("skydome_light", "env1"), ]: l = GafferArnold.ArnoldLight() l.loadShader(shader) l["name"].setValue(name) inputs.append(l) inputs.append(GafferScene.Camera()) for i in inputs: g["in"][-1].setInput(i["out"]) f = GafferScene.PathFilter() f['paths'].setValue( IECore.StringVectorData( ["/group/spot1", "/group/env1", "/group/distant1"])) lc = GafferScene.LightToCamera() lc["in"].setInput(g["out"]) lc["filter"].setInput(f["out"]) # Test spot to persp cam self.assertEqual( lc["out"].object("/group/spot1").parameters(), IECore.CompoundData({ 'projection:fov': IECore.FloatData(65), 'clippingPlanes': IECore.V2fData(imath.V2f(0.01, 100000)), 'projection': IECore.StringData('perspective'), 'resolutionOverride': IECore.V2iData(imath.V2i(512, 512)), 'screenWindow': IECore.Box2fData( imath.Box2f(imath.V2f(-1, -1), imath.V2f(1, 1))) })) # Test distant to ortho cam self.assertEqual( lc["out"].object("/group/distant1").parameters(), IECore.CompoundData({ 'clippingPlanes': IECore.V2fData(imath.V2f(-100000, 100000)), 'projection': IECore.StringData('orthographic'), 'resolutionOverride': IECore.V2iData(imath.V2i(512, 512)), 'screenWindow': IECore.Box2fData( imath.Box2f(imath.V2f(-1, -1), imath.V2f(1, 1))) })) # Test light with no corresponding camera ( gets default cam ) self.assertEqual( lc["out"].object("/group/env1").parameters(), IECore.CompoundData({ 'projection': IECore.StringData('perspective'), 'resolutionOverride': IECore.V2iData(imath.V2i(512, 512)) })) self.assertEqual(lc["out"].set("__lights").value.paths(), ["/group/spot2"]) self.assertEqual( set(lc["out"].set("__cameras").value.paths()), set([ "/group/camera", "/group/spot1", "/group/distant1", "/group/env1" ]))