Open johnhaddon opened 2 years ago
I think we could just uncomment this line: https://github.com/GafferHQ/gaffer/blob/main/src/GafferCycles/IECoreCyclesPreview/Renderer.cpp#L1210
I forget why I commented it out, but that should fix things.
Ok a quick test does fix this for a batch and interactive render, but in the viewport case it has already applied the default dot-product shader and wouldn't have a unique hash. The solution here would be to return false on https://github.com/GafferHQ/gaffer/blob/main/src/GafferCycles/IECoreCyclesPreview/Renderer.cpp#L1076 for every shader change, but this seems a bit expensive to do.
The solution here would be to return false for every shader change
That's my fear - from what I've seen, that's the only general solution, other than not doing any auto-instancing. Ideally Cycles would assign shaders to the ccl::Object
and not the ccl::Geometry
so that shading was orthogonal to instancing.
The solution here would be to return false for every shader change
That's my fear - from what I've seen, that's the only general solution, other than not doing any auto-instancing. Ideally Cycles would assign shaders to the
ccl::Object
and not theccl::Geometry
so that shading was orthogonal to instancing.
I had a bit of fun with the codebase and came up with what we want: https://developer.blender.org/D17158
Might be tricky to upstream though...
I had a bit of fun with the codebase and came up with what we want
Nice one!
Might be tricky to upstream though...
I've added a comment on the review to emphasise that this would be valuable to us (and that every other renderer under the sun does it that way :) ).
A behavior I'm experiencing may be related to this issue. I'll share it here in case it's helpful.
Basically, it seems like if there are duplicates of the same geometry in the scene, the shader assignment does not work reliably. Initially I was generating copies of a sphere with a duplicate node. I was trying to make two spheres diffuse blue, and the other two spheres chrome. It seems like Cycles randomly assigns one or the other to all of the spheres.
I also tried creating each sphere individually, with unique names. Same behavior. The only thing I found that could break this behavior was to add a small random variation to the scale of the spheres. This seemed to make it work.
Basically, it seems like if there are duplicates of the same geometry in the scene, the shader assignment does not work reliably.
Yep, that's definitely the same bug we're talking about here. The best way of working around it for the moment is to use a PrimitiveVariables node to add a string primitive variable with a value of ${scene:path}
(or any other unique value).
@boberfly, one possible compromise might be to assign the new shader successfully as long as the geometry is only referenced by one object. But then fail the shader assignment if it is instanced, so we only do the geometry regeneration for the instancing case...
Just cross-referencing that this issue appeared to have come up yesterday on Gaffer Users discord here as well. Any status update on getting a fix into the Gaffer releases?
Description
When rendering two instances of an identical mesh, GafferCycles is assigning the shader for the first instance to the second instance as well. Cycles appears to assign shaders to
ccl::Geometry
rather than toccl:Object
, so it's inherently unfriendly when it comes to instancing like this.Steps to reproduce
Debug log
Click to Expand
``` import Gaffer import GafferCycles import GafferScene import IECore import imath Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 1, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 1, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 0, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 0, persistent=False ) __children = {} __children["Group"] = GafferScene.Group( "Group" ) parent.addChild( __children["Group"] ) __children["Group"]["in"].addChild( GafferScene.ScenePlug( "in1", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Group"]["in"].addChild( GafferScene.ScenePlug( "in2", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Group"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["ShaderAssignment"] = GafferScene.ShaderAssignment( "ShaderAssignment" ) parent.addChild( __children["ShaderAssignment"] ) __children["ShaderAssignment"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["PathFilter"] = GafferScene.PathFilter( "PathFilter" ) parent.addChild( __children["PathFilter"] ) __children["PathFilter"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["principled_bsdf"] = GafferCycles.CyclesShader( "principled_bsdf" ) parent.addChild( __children["principled_bsdf"] ) __children["principled_bsdf"].loadShader( "principled_bsdf" ) __children["principled_bsdf"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Sphere"] = GafferScene.Sphere( "Sphere" ) parent.addChild( __children["Sphere"] ) __children["Sphere"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Sphere1"] = GafferScene.Sphere( "Sphere1" ) parent.addChild( __children["Sphere1"] ) __children["Sphere1"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["Group"]["in"][0].setInput( __children["Sphere"]["out"] ) __children["Group"]["in"][1].setInput( __children["Sphere1"]["out"] ) __children["Group"]["__uiPosition"].setValue( imath.V2f( -3.20000005, -6.75 ) ) __children["ShaderAssignment"]["in"].setInput( __children["Group"]["out"] ) __children["ShaderAssignment"]["filter"].setInput( __children["PathFilter"]["out"] ) __children["ShaderAssignment"]["shader"].setInput( __children["principled_bsdf"]["out"]["BSDF"] ) __children["ShaderAssignment"]["__uiPosition"].setValue( imath.V2f( -3.19999886, -14.9140625 ) ) __children["PathFilter"]["paths"].setValue( IECore.StringVectorData( [ '/group/sphere' ] ) ) __children["PathFilter"]["__uiPosition"].setValue( imath.V2f( 11.0722179, -8.83143139 ) ) __children["principled_bsdf"]["parameters"]["metallic"].setValue( 1.0 ) __children["principled_bsdf"]["parameters"]["specular"].setValue( 1.0 ) __children["principled_bsdf"]["parameters"]["emission"].setValue( imath.Color3f( 1, 0.5, 1 ) ) __children["principled_bsdf"]["__uiPosition"].setValue( imath.V2f( -29.1457577, -14.9140615 ) ) __children["Sphere"]["__uiPosition"].setValue( imath.V2f( -13.5070086, 7.79442358 ) ) __children["Sphere1"]["transform"]["translate"].setValue( imath.V3f( 1.81982362, 0, 0 ) ) __children["Sphere1"]["__uiPosition"].setValue( imath.V2f( 1.80817854, 8.23983002 ) ) del __children ```