Here's a little setup that you can paste into Gaffer. It sets up a box that moves with an expression by rounding the frame to an integer, as an example of something without blur. I then set up a primvar named "v" on this cube, and then put it through a little box I hacked up named "ApplyVelocityBlur", which converts this "v" primvar into motion using OSLObject, by comparing the current time to the nearest frame. ( You can see the movement if you ctrl click on the current frame indicator at the bottom of Gaffer window and drag to a non-integer frame ). This should create proper motion blur from the "v" primvar.
import Gaffer
import GafferOSL
import GafferScene
import IECore
import imath
Gaffer.Metadata.registerNodeValue( parent, "serialiser:milestoneVersion", 0, persistent=False )
Gaffer.Metadata.registerNodeValue( parent, "serialiser:majorVersion", 43, persistent=False )
Gaffer.Metadata.registerNodeValue( parent, "serialiser:minorVersion", 0, persistent=False )
Gaffer.Metadata.registerNodeValue( parent, "serialiser:patchVersion", 0, persistent=False )
__children = {}
__children["Cube"] = GafferScene.Cube( "Cube" )
parent.addChild( __children["Cube"] )
__children["Expression"] = Gaffer.Expression( "Expression" )
parent.addChild( __children["Expression"] )
__children["Expression"]["__out"].addChild( Gaffer.FloatPlug( "p0", direction = Gaffer.Plug.Direction.Out, defaultValue = 0.0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["PrimitiveVariables"] = GafferScene.PrimitiveVariables( "PrimitiveVariables" )
parent.addChild( __children["PrimitiveVariables"] )
parent.addChild( __children["PrimitiveVariables"] )
__children["PrimitiveVariables"]["primitiveVariables"].addChild( Gaffer.CompoundDataPlug.MemberPlug( "member1", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["PrimitiveVariables"]["primitiveVariables"]["member1"].addChild( Gaffer.StringPlug( "name", defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["PrimitiveVariables"]["primitiveVariables"]["member1"].addChild( Gaffer.V3fPlug( "value", defaultValue = imath.V3f( 0, 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, interpretation = IECore.GeometricData.Interpretation.Vector ) )
__children["PrimitiveVariables"]["primitiveVariables"]["member1"].addChild( Gaffer.BoolPlug( "enabled", defaultValue = True, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ResamplePrimitiveVariables"] = GafferScene.ResamplePrimitiveVariables( "ResamplePrimitiveVariables" )
parent.addChild( __children["ResamplePrimitiveVariables"] )
__children["PathFilter"] = GafferScene.PathFilter( "PathFilter" )
parent.addChild( __children["PathFilter"] )
__children["ApplyVelocityBlur"] = Gaffer.Box( "ApplyVelocityBlur" )
parent.addChild( __children["ApplyVelocityBlur"] )
__children["ApplyVelocityBlur"].addChild( GafferOSL.OSLObject( "OSLObject" ) )
__children["ApplyVelocityBlur"].addChild( GafferScene.ScenePlug( "in", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( GafferScene.FilterPlug( "filter", defaultValue = 0, minValue = 0, maxValue = 7, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( GafferOSL.OSLCode( "OSLCode" ) )
__children["ApplyVelocityBlur"]["OSLCode"]["parameters"].addChild( Gaffer.FloatPlug( "frame", defaultValue = 0.0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"]["OSLCode"]["out"].addChild( Gaffer.V3fPlug( "out", direction = Gaffer.Plug.Direction.Out, defaultValue = imath.V3f( 0, 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, interpretation = IECore.GeometricData.Interpretation.Point ) )
__children["ApplyVelocityBlur"].addChild( GafferOSL.OSLShader( "OutObject" ) )
__children["ApplyVelocityBlur"]["OutObject"].loadShader( "ObjectProcessing/OutObject" )
__children["ApplyVelocityBlur"].addChild( GafferOSL.OSLShader( "OutPoint" ) )
__children["ApplyVelocityBlur"]["OutPoint"].loadShader( "ObjectProcessing/OutPoint", keepExistingValues=True )
__children["ApplyVelocityBlur"].addChild( Gaffer.Expression( "Expression1" ) )
__children["ApplyVelocityBlur"]["Expression1"]["__out"].addChild( Gaffer.FloatPlug( "p0", direction = Gaffer.Plug.Direction.Out, defaultValue = 0.0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( Gaffer.BoxIn( "BoxIn" ) )
__children["ApplyVelocityBlur"]["BoxIn"].addChild( GafferScene.ScenePlug( "__in", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"]["BoxIn"].addChild( GafferScene.ScenePlug( "out", direction = Gaffer.Plug.Direction.Out, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( Gaffer.BoxIn( "BoxIn1" ) )
__children["ApplyVelocityBlur"]["BoxIn1"].addChild( GafferScene.FilterPlug( "__in", defaultValue = 0, minValue = 0, maxValue = 7, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"]["BoxIn1"].addChild( GafferScene.FilterPlug( "out", direction = Gaffer.Plug.Direction.Out, defaultValue = 0, minValue = 0, maxValue = 7, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( GafferScene.SceneSwitch( "SceneSwitch" ) )
__children["ApplyVelocityBlur"].addChild( Gaffer.BoolPlug( "enabled", defaultValue = True, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( Gaffer.BoxOut( "BoxOut" ) )
__children["ApplyVelocityBlur"]["BoxOut"].addChild( GafferScene.ScenePlug( "in", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"]["BoxOut"].addChild( GafferScene.ScenePlug( "__out", direction = Gaffer.Plug.Direction.Out, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["ApplyVelocityBlur"].addChild( GafferScene.ScenePlug( "out", direction = Gaffer.Plug.Direction.Out, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Cube"]["transform"]["translate"]["x"].setInput( __children["Expression"]["__out"]["p0"] )
__children["PrimitiveVariables"]["in"].setInput( __children["Cube"]["out"] )
__children["PrimitiveVariables"]["filter"].setInput( __children["PathFilter"]["out"] )
__children["PrimitiveVariables"]["primitiveVariables"]["member1"]["name"].setValue( 'v' )
__children["PrimitiveVariables"]["primitiveVariables"]["member1"]["value"].setValue( imath.V3f( 1, 0, 0 ) )
__children["ResamplePrimitiveVariables"]["in"].setInput( __children["PrimitiveVariables"]["out"] )
__children["ResamplePrimitiveVariables"]["filter"].setInput( __children["PathFilter"]["out"] )
__children["ResamplePrimitiveVariables"]["names"].setValue( 'v' )
__children["PathFilter"]["paths"].setValue( IECore.StringVectorData( [ '/cube' ] ) )
__children["ApplyVelocityBlur"]["OSLObject"]["in"].setInput( __children["ApplyVelocityBlur"]["BoxIn"]["out"] )
__children["ApplyVelocityBlur"]["OSLObject"]["filter"].setInput( __children["ApplyVelocityBlur"]["BoxIn1"]["out"] )
__children["ApplyVelocityBlur"]["OSLObject"]["shader"].setInput( __children["ApplyVelocityBlur"]["OutObject"]["out"] )
__children["ApplyVelocityBlur"]["in"].setInput( __children["ResamplePrimitiveVariables"]["out"] )
__children["ApplyVelocityBlur"]["filter"].setInput( __children["PathFilter"]["out"] )
__children["ApplyVelocityBlur"]["OSLCode"]["type"].setValue( 'osl:shader' )
__children["ApplyVelocityBlur"]["OSLCode"]["parameters"]["frame"].setInput( __children["ApplyVelocityBlur"]["Expression1"]["__out"]["p0"] )
__children["ApplyVelocityBlur"]["OSLCode"]["code"].setValue( 'vector velocity;\ngetattribute( "v", velocity );\n\nout = P + velocity * ( frame - round( frame ) );' )
__children["ApplyVelocityBlur"]["OutObject"]["parameters"]["in0"].setInput( __children["ApplyVelocityBlur"]["OutPoint"]["out"]["primitiveVariable"] )
__children["ApplyVelocityBlur"]["OutPoint"]["parameters"]["value"].setInput( __children["ApplyVelocityBlur"]["OSLCode"]["out"]["out"] )
__children["ApplyVelocityBlur"]["BoxIn"]["__in"].setInput( __children["ApplyVelocityBlur"]["in"] )
__children["ApplyVelocityBlur"]["BoxIn"]["out"].setInput( __children["ApplyVelocityBlur"]["BoxIn"]["__in"] )
__children["ApplyVelocityBlur"]["BoxIn1"]["name"].setValue( 'filter' )
__children["ApplyVelocityBlur"]["BoxIn1"]["__in"].setInput( __children["ApplyVelocityBlur"]["filter"] )
__children["ApplyVelocityBlur"]["BoxIn1"]["out"].setInput( __children["ApplyVelocityBlur"]["BoxIn1"]["__in"] )
__children["ApplyVelocityBlur"]["SceneSwitch"]["enabled"].setInput( __children["ApplyVelocityBlur"]["enabled"] )
__children["ApplyVelocityBlur"]["SceneSwitch"]["in"]["in0"].setInput( __children["ApplyVelocityBlur"]["BoxIn"]["out"] )
__children["ApplyVelocityBlur"]["SceneSwitch"]["in"]["in1"].setInput( __children["ApplyVelocityBlur"]["OSLObject"]["out"] )
__children["ApplyVelocityBlur"]["SceneSwitch"]["index"].setValue( 1 )
__children["ApplyVelocityBlur"]["BoxOut"]["in"].setInput( __children["ApplyVelocityBlur"]["SceneSwitch"]["out"] )
__children["ApplyVelocityBlur"]["BoxOut"]["__out"].setInput( __children["ApplyVelocityBlur"]["BoxOut"]["in"] )
__children["ApplyVelocityBlur"]["out"].setInput( __children["ApplyVelocityBlur"]["BoxOut"]["__out"] )
__children["Expression"]["__engine"].setValue( 'OSL' )
__children["Expression"]["__expression"].setValue( 'parent.__out.p0 = round( context("frame", 0.0) );' )
__children["ApplyVelocityBlur"]["Expression1"]["__engine"].setValue( 'OSL' )
__children["ApplyVelocityBlur"]["Expression1"]["__expression"].setValue( 'parent.__out.p0 = context( "frame", 0.0 );' )
del __children