Exemple #1
0
    def testTextureCoordinates(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/test.rib")

        with WorldBlock(r):

            r.setAttribute("ri:textureCoordinates",
                           FloatVectorData([0, 1, 2, 3, 4, 5, 6, 7]))
            self.assertEqual(r.getAttribute("ri:textureCoordinates"),
                             FloatVectorData([0, 1, 2, 3, 4, 5, 6, 7]))

        rib = "".join(file("test/IECoreRI/output/test.rib").readlines())

        self.assertTrue('TextureCoordinates 0 1 2 3 4 5 6 7' in rib)
Exemple #2
0
    def testProcedural(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/testProcedural.rib")
        r.worldBegin()

        p = SimpleProcedural(10.5)
        r.procedural(p)

        r.worldEnd()

        self.assertEqual(p.rendererTypeId, IECoreRI.Renderer.staticTypeId())
        self.assertEqual(p.rendererTypeName, "IECoreRI::Renderer")
        self.assertEqual(p.rendererTypeName,
                         IECoreRI.Renderer.staticTypeName())
Exemple #3
0
 def testRead(self):
     r = IECoreRI.PTCParticleReader()
     r['fileName'] = self.testfile
     pointCloud = r.read()
     self.assertEqual(type(pointCloud), IECore.PointsPrimitive)
     self.assertEqual(pointCloud.numPoints, 2975)
     self.assertEqual(len(pointCloud["P"].data), 2975)
     self.assertEqual(
         set(pointCloud.blindData()['PTCParticleIO'].keys()),
         set([
             "boundingBox", "worldToEye", "worldToNdc", "variableTypes"
         ]))
     r['percentage'] = 50
     pointCloud2 = r.read()
     self.assertEqual(len(pointCloud2["P"].data), 1502)
Exemple #4
0
    def testMissingPredefinedVariables(self):

        self.assertEqual(
            os.system(
                "shaderdl -Irsl -o test/IECoreRI/shaders/splineTest.sdl test/IECoreRI/shaders/splineTest.sl"
            ), 0)
        r = IECoreRI.SXRenderer()

        r.shader("surface", "test/IECoreRI/shaders/splineTest.sdl", {})

        b = IECore.Box2i(IECore.V2i(0), IECore.V2i(100))
        points = self.__rectanglePoints(b)
        del points["t"]  # remove information the shader requires

        s = r.shade(points)
Exemple #5
0
    def testWrongSize(self):

        self.assertEqual(
            os.system(
                "shaderdl -Irsl -o test/IECoreRI/shaders/splineTest.sdl test/IECoreRI/shaders/splineTest.sl"
            ), 0)

        r = IECoreRI.SXRenderer()

        r.shader("surface", "test/IECoreRI/shaders/splineTest.sdl", {})

        p = self.__rectanglePoints(IECore.Box2i(IECore.V2i(0), IECore.V2i(10)))
        del p["t"][-10:]

        self.assertRaises(RuntimeError, r.shade, p)
Exemple #6
0
    def _createRenderer(self):

        fileName = self.__fileName()
        directory = os.path.dirname(fileName)
        if directory:
            try:
                os.makedirs(directory)
            except OSError:
                # makedirs very unhelpfully raises an exception if
                # the directory already exists, but it might also
                # raise if it fails. we reraise only in the latter case.
                if not os.path.isdir(directory):
                    raise

        return IECoreRI.Renderer(fileName)
Exemple #7
0
    def testMultipleDisplays(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/test.rib")

        r.display("test.exr", "exr", "rgba",
                  {"quantize": FloatVectorData([0, 0, 0, 0])})
        r.display("z.exr", "exr", "z",
                  {"quantize": FloatVectorData([0, 0, 0, 0])})

        with WorldBlock(r):
            pass

        rib = "".join(file("test/IECoreRI/output/test.rib").readlines())

        self.assertTrue("+z.exr" in rib)
Exemple #8
0
    def testCommands(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/commands.rib")

        r.worldBegin()

        r.command("ri:readArchive", {"name": StringData("nameOfArchive")})

        r.worldEnd()

        l = "".join(
            file("test/IECoreRI/output/commands.rib").readlines()).replace(
                "\n", "")

        self.failUnless('ReadArchive "nameOfArchive"' in l)
Exemple #9
0
    def testCompoundDataAttributes(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/testAttributes.rib")

        with WorldBlock(r):

            r.setAttribute(
                "ri:displacementbound",
                {
                    "sphere": 10.0,
                    "coordinatesystem": "shader",
                },
            )

        lines = file("test/IECoreRI/output/testAttributes.rib").readlines()
        found = False
        for line in lines:
            if ("Attribute \"displacementbound\"" in line
                    and "\"string coordinatesystem\" [ \"shader\" ]" in line
                    and "\"float sphere\" [ 10 ]" in line):
                found = True

        self.failUnless(found)

        # check that we get appropriate warnings if not providing CompoundData

        r = IECoreRI.Renderer("test/IECoreRI/output/testAttributes.rib")

        with WorldBlock(r):

            c = CapturingMessageHandler()
            with c:
                r.setAttribute("ri:displacementbound", FloatData(10))

        self.assertEqual(len(c.messages), 1)
        self.assertEqual(c.messages[0].level, Msg.Level.Warning)
Exemple #10
0
def executeProcedural(name, version, args):

    procedural = IECore.ClassLoader.defaultProceduralLoader().load(
        name, version)()

    if procedural:

        IECore.ParameterParser().parse(args, procedural.parameters())

        renderer = IECoreRI.Renderer()
        procedural.render(renderer,
                          inAttributeBlock=False,
                          withState=False,
                          withGeometry=True,
                          immediateGeometry=True)
Exemple #11
0
    def testMissingShaders(self):
        """Check that missing shaders don't throw an exception but print a message instead."""

        with CapturingMessageHandler() as m:

            r = IECoreRI.Renderer("test/IECoreRI/output/missingShaders.rib")

            r.worldBegin()

            r.shader("surface", "aShaderWhichDoesntExist", {})

            r.worldEnd()

        self.assertEqual(len(m.messages), 1)
        self.assert_("aShaderWhichDoesntExist" in m.messages[0].message)
Exemple #12
0
	def testUserOptions( self ):

		self.assertEqual( os.system( "shaderdl -Irsl -o test/IECoreRI/shaders/sxUserOptionTest.sdl test/IECoreRI/shaders/sxUserOptionTest.sl" ), 0 )

		points = self.__rectanglePoints( IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 1 ) ) )

		r = IECoreRI.SXRenderer()
		r.shader( "surface", "test/IECoreRI/shaders/sxUserOptionTest.sdl", {} )

		s = r.shade( points )
		self.assertEqual( s["Ci"][0], IECore.Color3f( 0,0,0 ) )

		r.setOption( "user:outputColor", IECore.FloatData( 1 ) )

		s = r.shade( points )
		self.assertEqual( s["Ci"][0], IECore.Color3f( 1,1,1 ) )
Exemple #13
0
	def testSetBucketSizeViaOptions( self ) :

		with CapturingMessageHandler() as mh :

			r = IECoreRI.Renderer( "test/IECoreRI/output/test.rib" )

			r.setOption( "ri:limits:bucketsize", V2i( 32, 32 ) )

			with WorldBlock( r ) :
				pass

		self.assertEqual( len( mh.messages ), 0 )

		rib = "".join( file( "test/IECoreRI/output/test.rib" ).readlines() )

		self.assertTrue( 'Option "limits" "integer bucketsize[2]" [ 32 32 ]' in rib )
Exemple #14
0
	def testStringPrimVars( self ) :

		r = IECoreRI.Renderer( "test/IECoreRI/output/stringPrimVars.rib" )

		r.worldBegin()

		m = ObjectReader( "test/IECoreRI/data/stringPrimVars.cob" ).read()
		m.render( r )

		r.worldEnd()

		l = "".join( file( "test/IECoreRI/output/stringPrimVars.rib" ).readlines() ).replace( "\n", "" )

		self.failUnless( '"constant string ieGeneric_diffuse_Color_Textures" [ "woodTrain/woodTrainRed_v001_color_LIN.tdl" ]' in l )
		self.failUnless( '"constant string ieGeneric_displacement_Textures" [ "woodTrain/woodTrain_v001_bump_LIN.tdl" ]' in l )
		self.failUnless( '"constant string ieGeneric_reflection_Textures" [ "woodTrain/woodTrain_v001_bump_LIN.tdl" ]' in l )
Exemple #15
0
    def testZeroLength(self):

        self.assertEqual(
            os.system(
                "shaderdl -Irsl -o test/IECoreRI/shaders/splineTest.sdl test/IECoreRI/shaders/splineTest.sl"
            ), 0)

        r = IECoreRI.SXRenderer()

        r.shader("surface", "test/IECoreRI/shaders/splineTest.sdl", {})

        p = self.__rectanglePoints(IECore.Box2i(IECore.V2i(0), IECore.V2i(10)))
        for k, v in p.items():
            del v[:]

        self.assertRaises(RuntimeError, r.shade, p)
Exemple #16
0
	def testPlaneShade( self ) :
		
		r = IECoreRI.SXRenderer()
		
		self.assertEqual( os.system( "shaderdl -o test/IECoreRI/shaders/sxStTest.sdl test/IECoreRI/shaders/sxStTest.sl" ), 0 )
		r.shader( "surface", "test/IECoreRI/shaders/sxStTest.sdl", {} )
		
		data = r.shadePlane( IECore.V2i( 64, 64 ) )
		del data["P"]
		del data["N"]
		self.assertEqual( data, IECore.Reader.create( "test/IECoreRI/data/sxOutput/shadePlaneCompoundData.cob" ).read() )
		
		image = r.shadePlaneToImage( IECore.V2i( 64, 64 ) )
		expectedImage = IECore.Reader.create( "test/IECoreRI/data/sxOutput/shadePlaneImage.exr" ).read()

		self.assertEqual( IECore.ImageDiffOp()( imageA=image, imageB=expectedImage, maxError=0 ), IECore.BoolData( False ) )
Exemple #17
0
	def testTransform( self ) :

		r = IECoreRI.Renderer( self.outputFileName )

		with IECore.WorldBlock( r ) :
			c = IECore.CoordinateSystem(
				"helloWorld",
				IECore.MatrixTransform( IECore.M44f.createTranslated( IECore.V3f( 1 ) ) ),
			)
			c.render( r )

		l = "".join( file( self.outputFileName ).readlines() )
		self.failUnless( "ScopedCoordinateSystem \"helloWorld\"" in l )
		self.failUnless( "TransformBegin" in l )
		self.failUnless( "TransformEnd" in l )
		self.failUnless( "ConcatTransform" in l )
Exemple #18
0
    def testPrimVarNameValidation(self):

        m = IECore.MeshPrimitive.createPlane(
            IECore.Box2f(IECore.V2f(0, 0), IECore.V2f(1, 1)))
        e = IECoreRI.GXEvaluator(m)

        self.failIf("unlikely" in m)

        self.assertRaises(
            RuntimeError,
            e.evaluate,
            IECore.IntVectorData([0]),
            IECore.FloatVectorData([.5]),
            IECore.FloatVectorData([.5]),
            ["unlikely"],
        )
Exemple #19
0
	def testStringArrayOptions( self ):

		self.assertEqual( os.system( "shaderdl -Irsl -o test/IECoreRI/shaders/sxStringArrayOptionTest.sdl test/IECoreRI/shaders/sxStringArrayOptionTest.sl" ), 0 )

		points = self.__rectanglePoints( IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 1 ) ) )

		r = IECoreRI.SXRenderer()
		r.shader( "surface", "test/IECoreRI/shaders/sxStringArrayOptionTest.sdl", {} )

		s = r.shade( points )
		self.assertEqual( s["Ci"][0], IECore.Color3f( 0,0,0 ) )

		r.setOption( "user:stringArray", IECore.StringVectorData( ["this","should","work"] ) )

		s = r.shade( points )
		self.assertEqual( s["Ci"][0], IECore.Color3f( 1,1,1 ) )
Exemple #20
0
	def testLightPrefixes( self ) :

		r = IECoreRI.Renderer( "test/IECoreRI/output/lightPrefixes.rib" )

		with WorldBlock( r ) :

			r.light( "genericLight", "genericHandle", {} )
			r.light( "ri:renderManLight", "renderManHandle", {} )
			r.light( "ai:arnoldLight", "arnoldLight", {} )

		del r

		rib = "".join( file( "test/IECoreRI/output/lightPrefixes.rib" ).readlines() )
		self.assertTrue( 'LightSource "genericLight"' in rib )
		self.assertTrue( 'LightSource "renderManLight"' in rib )
		self.assertFalse( "arnold" in rib )
	def testPixelAspectRatio( self ) :

		r = IECoreRI.Renderer( "test/IECoreRI/output/testCamera.rib" )

		r.camera( "main", {
			"resolution" : IECore.V2i( 100, 200 ),
			"pixelAspectRatio" : 2.0,
		} )

		with IECore.WorldBlock( r ) :
			pass

		l = "".join( file( "test/IECoreRI/output/testCamera.rib" ).readlines() )
		l = " ".join( l.split() )

		self.assertTrue( "Format 100 200 2" in l )
		self.assertTrue( "ScreenWindow -1 1 -1 1" in l )
Exemple #22
0
    def testGetUserAttribute(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/getUserAttribute.rib")

        o = {
            "user:f": FloatData(10),
            "user:i": IntData(100),
            "user:s": StringData("hello"),
            "user:c": Color3fData(Color3f(1, 0, 0)),
            "user:v": V3fData(V3f(1, 2, 3)),
            "user:m": M44fData(M44f.createTranslated(V3f(1, 2, 3))),
        }

        for k, v in o.items():

            r.setAttribute(k, v)
            self.assertEqual(r.getAttribute(k), v)
	def testMotionBlurCameraRib( self ) :
	
		r = IECoreRI.Renderer( "test/IECoreRI/output/testCamera.rib" )
		
		with IECore.TransformBlock( r ) :
			with IECore.MotionBlock( r, [ 0, 1 ] ) :
				r.concatTransform( IECore.M44f.createTranslated( IECore.V3f( -0.2, 0, 1 ) ) )
				r.concatTransform( IECore.M44f.createTranslated( IECore.V3f( 0.2, 0, 1 ) ) )
			
			r.camera( "main", { "shutter" : IECore.V2f( 0, 1 ) } )
		
		r.worldBegin()
		r.worldEnd()
		
		l = "".join( file( "test/IECoreRI/output/testCamera.rib" ).readlines() )
		
		self.assert_( "MotionBegin [ 0 1 ]" in l )
Exemple #24
0
    def testMultipleGrids(self):

        self.assertEqual(
            os.system(
                "shaderdl -o test/IECoreRI/shaders/sxGridTest.sdl test/IECoreRI/shaders/sxGridTest.sl"
            ), 0)

        r = IECoreRI.SXRenderer()
        b = IECore.Box2i(IECore.V2i(0), IECore.V2i(19, 9))
        points = self.__rectanglePoints(b)

        with IECore.WorldBlock(r):

            r.shader("surface", "test/IECoreRI/shaders/sxGridTest", {})

            # there are 20 x 10 points in the input, so this call should shade four 10 x 5 grids:
            r.shade(points, IECore.V2i(10, 5))
    def testSLOReaderSupport(self):

        self.assertEqual(
            os.system(
                "shaderdl -o test/IECoreRI/shaders/coshaderTest.sdl test/IECoreRI/shaders/coshaderTest.sl"
            ), 0)

        s = IECoreRI.SLOReader("test/IECoreRI/shaders/coshaderTest.sdl").read()

        # old versions of 3delight reported the type as <unknown> (which we don't really want) but
        # new versions report it correctly as "shader".
        self.failUnless(s.type == "<unknown>" or s.type == "shader")

        k = s.parameters.keys()
        self.assertEqual(len(k), 2)
        self.failUnless("f" in k)
        self.failUnless("s" in k)
Exemple #26
0
    def testVVector(self):

        self.assertEqual(
            os.system(
                "shaderdl -Irsl -o test/IECoreRI/shaders/splineTest.sdl test/IECoreRI/shaders/splineTest.sl"
            ), 0)

        r = IECoreRI.SXRenderer()

        r.shader("surface", "test/IECoreRI/shaders/splineTest.sdl", {})

        p = self.__rectanglePoints(IECore.Box2i(IECore.V2i(0), IECore.V2i(10)))

        # this should work, as you might want to use a V3f primvar called v (velocity) in
        # your shader:
        p["v"] = p["P"]
        r.shade(p)
Exemple #27
0
    def testDisplay(self):

        r = IECoreRI.Renderer("test/IECoreRI/output/testDisplay.rib")

        r.display("test.tif", "tiff", "rgba",
                  {"quantize": FloatVectorData([0, 1, 0, 1])})

        r.worldBegin()
        r.worldEnd()

        l = "".join(
            file("test/IECoreRI/output/testDisplay.rib").readlines()).replace(
                "\n", "")

        self.failUnless(
            'Display "test.tif" "tiff" "rgba"   "float quantize[4]" [ 0 1 0 1 ]'
            in l)
    def testParameters(self):

        writer = IECoreRI.SHWDeepImageWriter(TestSHWDeepImageWriter.__output)
        self.assertEqual(writer.parameters()['fileName'].getTypedValue(),
                         TestSHWDeepImageWriter.__output)
        self.assertEqual(writer.parameters()['channelNames'].getValue(),
                         IECore.StringVectorData(["A"]))
        self.assertEqual(writer.parameters()['resolution'].getTypedValue(),
                         IECore.V2i(2048, 1556))
        self.assertEqual(writer.parameters()['tileSize'].getTypedValue(),
                         IECore.V2i(32, 32))
        self.assertEqual(
            writer.parameters()['worldToCameraMatrix'].getTypedValue(),
            IECore.M44f())
        self.assertEqual(
            writer.parameters()['worldToNDCMatrix'].getTypedValue(),
            IECore.M44f())
Exemple #29
0
	def testGetOption( self ) :

		r = IECoreRI.Renderer( "test/IECoreRI/output/testGetOption.rib" )

		r.camera( "main", { "resolution" : V2iData( V2i( 1024, 768 ) ) } )

		r.setOption( "ri:shutter:offset", FloatData( 10 ) )

		r.worldBegin()

		s = r.getOption( "shutter" )
		self.assertEqual( s, V2fData( V2f( 0 ) ) )

		self.assertEqual( r.getOption( "camera:resolution" ), V2iData( V2i( 1024, 768 ) ) )
		self.assertEqual( r.getOption( "ri:shutter:offset" ), FloatData( 10 ) )

		r.worldEnd()
Exemple #30
0
    def testAttributes(self):

        tests = [
            # format is : name value expectedRib getAttributeShouldWork
            ("ri:shadingRate", FloatData(2), "ShadingRate 2", True),
            ("ri:matte", BoolData(0), "Matte 0", True),
            ("ri:matte", BoolData(1), "Matte 1", True),
            ("user:whatever", StringData("whatever"),
             "Attribute \"user\" \"string whatever\" [ \"whatever\" ]", True),
            ("ri:color", Color3fData(Color3f(0, 1,
                                             1)), "Color [ 0 1 1 ]", False),
            ("color", Color3fData(Color3f(1, 2, 3)), "Color [ 1 2 3 ]", False),
            ("ri:opacity", Color3fData(Color3f(1, 1, 1)), "Opacity [ 1 1 1 ]",
             False),
            ("opacity", Color3fData(Color3f(0, 1,
                                            0)), "Opacity [ 0 1 0 ]", False),
            ("ri:sides", IntData(1), "Sides 1", False),
            ("ri:geometricApproximation:motionFactor", FloatData(1),
             "GeometricApproximation \"motionfactor\" 1", False),
            ("ri:geometricApproximation:focusFactor", FloatData(1),
             "GeometricApproximation \"focusfactor\" 1", False),
            ("ri:cull:hidden", IntData(0),
             "Attribute \"cull\" \"int hidden\" [ 0 ]", False),
            ("name", StringData("oioi"),
             "Attribute \"identifier\" \"string name\" [ \"oioi\" ]", True),
            ("ri:trace:bias", FloatData(2),
             "Attribute \"trace\" \"float bias\" [ 2 ]", True),
            ("user:myString", StringData("wellHello"),
             "Attribute \"user\" \"string myString\" [ \"wellHello\" ]", True),
            ("ri:automaticInstancing", BoolData(True),
             "Attribute \"user\" \"int cortexAutomaticInstancing\" [ 1 ]",
             True),
        ]

        for t in tests:

            r = IECoreRI.Renderer("test/IECoreRI/output/testAttributes.rib")
            with WorldBlock(r):
                r.setAttribute(t[0], t[1])
                if t[3]:
                    self.assertEqual(r.getAttribute(t[0]), t[1])

            l = "".join(
                file("test/IECoreRI/output/testAttributes.rib").readlines())
            l = " ".join(l.split())
            self.assert_(t[2] in l)
Exemple #31
0
	def testProceduralLevelInstancing( self ) :
		
		if IECoreRI.withRiProceduralV():

			class InstanceTestProcedural( Renderer.Procedural ) :

				renderCount = 0

				def __init__( self, instanceHash ) :

					Renderer.Procedural.__init__( self )

					self.__instanceHash = instanceHash

				def bound( self ) :

					return Box3f( V3f( -10 ), V3f( 10 ) )

				def render( self, renderer ) :
					InstanceTestProcedural.renderCount = InstanceTestProcedural.renderCount + 1
					pass

				def hash( self ) :
					return self.__instanceHash

			r = IECoreRI.Renderer("")

			# give it a camera using the ray trace hider, and turn shareinstances on:
			r.camera( "main", {
				"resolution" : V2iData( V2i( 1024, 200 ) ),
				"screenWindow" : Box2fData( Box2f( V2f( -1 ), V2f( 1 ) ) ),
				"cropWindow" : Box2fData( Box2f( V2f( 0.1, 0.1 ), V2f( 0.9, 0.9 ) ) ),
				"clippingPlanes" : V2fData( V2f( 1, 1000 ) ),
				"projection" : StringData( "perspective" ),
				"projection:fov" : FloatData( 45 ),
				"ri:hider" : StringData( "raytrace" ),
			} )
			r.setOption( "ri:trace:shareinstances", IntData( 1 ) )
			
			# chuck a couple of procedurals at it:
			h1 = MurmurHash()
			h2 = MurmurHash()
			
			h1.append( "instance1" )
			h2.append( "instance2" )
			
			with WorldBlock( r ) :
				r.procedural( InstanceTestProcedural(h1) )
				r.procedural( InstanceTestProcedural(h1) )
				r.procedural( InstanceTestProcedural(h2) )
				r.procedural( InstanceTestProcedural(h2) )

			# only two unique instances here, as there were 2 unique hashes....
			self.assertEqual( InstanceTestProcedural.renderCount, 2 )
			
			InstanceTestProcedural.renderCount = 0
			
			# the system shouldn't perform instancing when the hash method returns empty hashes:
			with WorldBlock( r ) :
				r.procedural( InstanceTestProcedural( MurmurHash() ) )
				r.procedural( InstanceTestProcedural( MurmurHash() ) )
				r.procedural( InstanceTestProcedural( MurmurHash() ) )
				r.procedural( InstanceTestProcedural( MurmurHash() ) )
			
			self.assertEqual( InstanceTestProcedural.renderCount, 4 )
Exemple #32
0
	def testParameterisedProceduralInstancing( self ) :
	
		if IECoreRI.withRiProceduralV():

			class InstanceTestParamProcedural( ParameterisedProcedural ) :
				
				renderCount = 0

				def __init__( self ) :
					
					ParameterisedProcedural.__init__( self, "Instancing test" )
					
					self.parameters().addParameters(
			
						[
							BoolParameter(
								name = "p1",
								description = "whatever.",
								defaultValue = True,
							),

							StringParameter(
								name = "p2",
								description = "yup.",
								defaultValue = "blah"
							),
						]

					)
				
				def doBound( self, args ) :

					return Box3f( V3f( -10 ), V3f( 10 ) )

				def doRender( self, renderer, args ) :
					InstanceTestParamProcedural.renderCount = InstanceTestParamProcedural.renderCount + 1
					pass
			
			r = IECoreRI.Renderer("")
			
			# give it a camera using the ray trace hider, and turn shareinstances on:
			r.camera( "main", {
				"resolution" : V2iData( V2i( 1024, 200 ) ),
				"screenWindow" : Box2fData( Box2f( V2f( -1 ), V2f( 1 ) ) ),
				"cropWindow" : Box2fData( Box2f( V2f( 0.1, 0.1 ), V2f( 0.9, 0.9 ) ) ),
				"clippingPlanes" : V2fData( V2f( 1, 1000 ) ),
				"projection" : StringData( "perspective" ),
				"projection:fov" : FloatData( 45 ),
				"ri:hider" : StringData( "raytrace" ),
			} )
			r.setOption( "ri:trace:shareinstances", IntData( 1 ) )
			
			# chuck a couple of procedurals at it:
			
			proc1 = InstanceTestParamProcedural()
			proc2 = InstanceTestParamProcedural()
			
			proc1["p1"].setValue( False )
			proc1["p2"].setValue( StringData( "humpf" ) )
			
			with WorldBlock( r ) :
				
				proc1.render( r )
				proc2.render( r )
				proc2.render( r )
				proc2.render( r )
			
			# only two unique instances here....
			self.assertEqual( InstanceTestParamProcedural.renderCount, 2 )