IECore::ConstCompoundObjectPtr CopyImageMetadata::computeProcessedMetadata( const Gaffer::Context *context, const IECore::CompoundObject *inputMetadata ) const { ConstCompoundObjectPtr copyFrom = copyFromPlug()->metadataPlug()->getValue(); if ( copyFrom->members().empty() ) { return inputMetadata; } const std::string names = namesPlug()->getValue(); const bool invert = invertNamesPlug()->getValue(); if ( !invert && !names.size() ) { return inputMetadata; } IECore::CompoundObjectPtr result = inputMetadata->copy(); for ( IECore::CompoundObject::ObjectMap::const_iterator it = copyFrom->members().begin(), eIt = copyFrom->members().end(); it != eIt; ++it ) { bool copy = false; if ( matchMultiple( it->first.c_str(), names.c_str() ) != invert ) { copy = true; } if ( copy ) { result->members()[it->first] = it->second; } } return result; }
IECore::CameraPtr GafferScene::camera( const ScenePlug *scene, const ScenePlug::ScenePath &cameraPath, const IECore::CompoundObject *globals ) { ConstCompoundObjectPtr computedGlobals; if( !globals ) { computedGlobals = scene->globalsPlug()->getValue(); globals = computedGlobals.get(); } std::string cameraName; ScenePlug::pathToString( cameraPath, cameraName ); if( !exists( scene, cameraPath ) ) { throw IECore::Exception( "Camera \"" + cameraName + "\" does not exist" ); } IECore::ConstCameraPtr constCamera = runTimeCast<const IECore::Camera>( scene->object( cameraPath ) ); if( !constCamera ) { std::string path; ScenePlug::pathToString( cameraPath, path ); throw IECore::Exception( "Location \"" + cameraName + "\" is not a camera" ); } IECore::CameraPtr camera = constCamera->copy(); camera->setName( cameraName ); const BoolData *cameraBlurData = globals->member<BoolData>( "option:render:cameraBlur" ); const bool cameraBlur = cameraBlurData ? cameraBlurData->readable() : false; camera->setTransform( transform( scene, cameraPath, shutter( globals ), cameraBlur ) ); applyCameraGlobals( camera.get(), globals ); return camera; }
IECore::ConstCompoundObjectPtr Attributes::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue(); if( !globalPlug()->getValue() ) { return inputGlobals; } const CompoundDataPlug *p = attributesPlug(); IECore::CompoundObjectPtr result = new CompoundObject; // Since we're not going to modify any existing members (only add new ones), // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. Be careful not to modify // them though! result->members() = inputGlobals->members(); std::string name; for( CompoundDataPlug::MemberPlugIterator it( p ); !it.done(); ++it ) { IECore::DataPtr d = p->memberDataAndName( it->get(), name ); if( d ) { result->members()["attribute:" + name] = d; } } return result; }
IECore::ConstCompoundObjectPtr OSLLight::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { IECore::CompoundObjectPtr result = new IECore::CompoundObject; ConstCompoundObjectPtr shaderAttributes = shaderInPlug()->attributes(); result->members() = shaderAttributes->members(); attributesPlug()->fillCompoundObject( result->members() ); return result; }
void ToNukeGeometryConverter::convert( GeometryList &geoList ) const { int objIndex = m_objIndexParameter->getNumericValue(); if ( objIndex == -1 ) { objIndex = (int)geoList.objects(); } geoList.add_object(objIndex); ConstCompoundObjectPtr operands = parameters()->getTypedValidatedValue<CompoundObject>(); doConversion( srcParameter()->getValidatedValue(), geoList, objIndex, operands.get() ); }
void SceneWriter::writeLocation( const GafferScene::ScenePlug *scene, const ScenePlug::ScenePath &scenePath, Context *context, IECore::SceneInterface *output, double time ) const { context->set( ScenePlug::scenePathContextName, scenePath ); ConstCompoundObjectPtr attributes = scene->attributesPlug()->getValue(); for( CompoundObject::ObjectMap::const_iterator it = attributes->members().begin(), eIt = attributes->members().end(); it != eIt; it++ ) { output->writeAttribute( it->first, it->second.get(), time ); } if( scenePath.empty() ) { ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue(); output->writeAttribute( "gaffer:globals", globals.get(), time ); } ConstObjectPtr object = scene->objectPlug()->getValue(); if( object->typeId() != IECore::NullObjectTypeId && scenePath.size() > 0 ) { output->writeObject( object.get(), time ); } Imath::Box3f b = scene->boundPlug()->getValue(); output->writeBound( Imath::Box3d( Imath::V3f( b.min ), Imath::V3f( b.max ) ), time ); if( scenePath.size() ) { Imath::M44f t = scene->transformPlug()->getValue(); Imath::M44d transform( t[0][0], t[0][1], t[0][2], t[0][3], t[1][0], t[1][1], t[1][2], t[1][3], t[2][0], t[2][1], t[2][2], t[2][3], t[3][0], t[3][1], t[3][2], t[3][3] ); output->writeTransform( new IECore::M44dData( transform ), time ); } ConstInternedStringVectorDataPtr childNames = scene->childNamesPlug()->getValue(); ScenePlug::ScenePath childScenePath = scenePath; childScenePath.push_back( InternedString() ); for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ ) { childScenePath[scenePath.size()] = *it; SceneInterfacePtr outputChild = output->child( *it, SceneInterface::CreateIfMissing ); writeLocation( scene, childScenePath, context, outputChild.get(), time ); } }
IECore::ConstCompoundObjectPtr SubTree::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue(); const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ); if( !inputSets ) { return inputGlobals; } CompoundObjectPtr outputGlobals = inputGlobals->copy(); CompoundDataPtr outputSets = new CompoundData; outputGlobals->members()["gaffer:sets"] = outputSets; std::string root = rootPlug()->getValue(); if( !root.size() || root[root.size()-1] != '/' ) { root += "/"; } size_t prefixSize = root.size() - 1; // number of characters to remove from front of each declaration if( includeRootPlug()->getValue() && prefixSize ) { size_t lastSlashButOne = root.rfind( "/", prefixSize-1 ); if( lastSlashButOne != string::npos ) { prefixSize = lastSlashButOne; } } for( CompoundDataMap::const_iterator it = inputSets->readable().begin(), eIt = inputSets->readable().end(); it != eIt; ++it ) { /// \todo This could be more efficient if PathMatcher exposed the internal nodes, /// and allowed sharing between matchers. Then we could just pick the subtree within /// the matcher that we wanted. const PathMatcher &inputSet = static_cast<const PathMatcherData *>( it->second.get() )->readable(); PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable(); vector<string> inputPaths; inputSet.paths( inputPaths ); for( vector<string>::const_iterator pIt = inputPaths.begin(), peIt = inputPaths.end(); pIt != peIt; ++pIt ) { const string &inputPath = *pIt; if( inputPath.compare( 0, root.size(), root ) == 0 ) { std::string outputPath( inputPath, prefixSize ); outputSet.addPath( outputPath ); } } } return outputGlobals; }
void ExecutableRender::execute() const { const ScenePlug *scene = inPlug()->getInput<ScenePlug>(); if( !scene ) { throw IECore::Exception( "No input scene" ); } ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue(); RendererAlgo::createDisplayDirectories( globals.get() ); // Scoping the lifetime of the renderer so that // the destructor is run before we run the system // command. This can be essential for renderman // renders, where the rib stream may not be flushed // to disk before RiEnd is called. { IECore::RendererPtr renderer = createRenderer(); RendererAlgo::outputOptions( globals.get(), renderer.get() ); RendererAlgo::outputOutputs( globals.get(), renderer.get() ); RendererAlgo::outputCameras( scene, globals.get(), renderer.get() ); RendererAlgo::outputClippingPlanes( scene, globals.get(), renderer.get() ); { WorldBlock world( renderer ); RendererAlgo::outputGlobalAttributes( globals.get(), renderer.get() ); RendererAlgo::outputCoordinateSystems( scene, globals.get(), renderer.get() ); RendererAlgo::outputLights( scene, globals.get(), renderer.get() ); outputWorldProcedural( scene, renderer.get() ); } } }
IECore::ConstInternedStringVectorDataPtr CompoundObjectSource::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr entry = entryForPath( path ); ConstCompoundObjectPtr children = entry->member<CompoundObject>( "children" ); if( !children ) { return outPlug()->childNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData; for( CompoundObject::ObjectMap::const_iterator it = children->members().begin(); it!=children->members().end(); it++ ) { result->writable().push_back( it->first.value() ); } return result; }
IECore::ImagePrimitivePtr ImagePlug::image() const { Format format = formatPlug()->getValue(); Box2i dataWindow = dataWindowPlug()->getValue(); Box2i newDataWindow( Imath::V2i(0) ); if( dataWindow.isEmpty() ) { dataWindow = Box2i( Imath::V2i(0) ); } else { newDataWindow = format.yDownToFormatSpace( dataWindow ); } // use the default format if we don't have an explicit one. /// \todo: remove this once FormatPlug is handling it for /// us during ExecutableNode::execute (see issue #887). if( format.getDisplayWindow().isEmpty() ) { format = Context::current()->get<Format>( Format::defaultFormatContextName, Format() ); } ImagePrimitivePtr result = new ImagePrimitive( newDataWindow, format.getDisplayWindow() ); ConstCompoundObjectPtr metadata = metadataPlug()->getValue(); compoundObjectToCompoundData( metadata.get(), result->blindData() ); ConstStringVectorDataPtr channelNamesData = channelNamesPlug()->getValue(); const vector<string> &channelNames = channelNamesData->readable(); vector<float *> imageChannelData; for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it!=eIt; it++ ) { FloatVectorDataPtr cd = new FloatVectorData; vector<float> &c = cd->writable(); c.resize( result->variableSize( PrimitiveVariable::Vertex ), 0.0f ); result->variables[*it] = PrimitiveVariable( PrimitiveVariable::Vertex, cd ); imageChannelData.push_back( &(c[0]) ); } parallel_for( blocked_range3d<size_t>( 0, imageChannelData.size(), 1, 0, dataWindow.size().x+1, tileSize(), 0, dataWindow.size().y+1, tileSize() ), GafferImage::Detail::CopyTiles( imageChannelData, channelNames, channelDataPlug(), dataWindow, Context::current(), tileSize()) ); return result; }
bool outputLight( const ScenePlug *scene, const ScenePlug::ScenePath &path, IECore::Renderer *renderer ) { IECore::ConstLightPtr constLight = runTimeCast<const IECore::Light>( scene->object( path ) ); if( !constLight ) { return false; } if( !visible( scene, path ) ) { /// \todo Since both visible() and fullAttributes() perform similar work, /// we may want to combine them into one query if we see this function /// being a significant fraction of render time. Maybe something like /// `fullAttributes( returnNullIfInvisible = true )`? It probably also /// makes sense to migrate all the convenience functions from ScenePlug /// into SceneAlgo. return false; } ConstCompoundObjectPtr attributes = scene->fullAttributes( path ); const M44f transform = scene->fullTransform( path ); std::string lightHandle; ScenePlug::pathToString( path, lightHandle ); LightPtr light = constLight->copy(); light->setHandle( lightHandle ); { AttributeBlock attributeBlock( renderer ); renderer->setAttribute( "name", new StringData( lightHandle ) ); outputAttributes( attributes.get(), renderer ); renderer->concatTransform( transform ); light->render( renderer ); } renderer->illuminate( lightHandle, true ); return true; }
IECore::ConstCompoundObjectPtr Prune::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue(); const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets" ); if( !inputSets ) { return inputGlobals; } CompoundObjectPtr outputGlobals = inputGlobals->copy(); CompoundDataPtr outputSets = new CompoundData; outputGlobals->members()["gaffer:sets"] = outputSets; ContextPtr tmpContext = new Context( *Context::current() ); Context::Scope scopedContext( tmpContext ); ScenePath path; for( CompoundDataMap::const_iterator it = inputSets->readable().begin(), eIt = inputSets->readable().end(); it != eIt; ++it ) { /// \todo This could be more efficient if PathMatcher exposed the internal nodes, /// and allowed sharing between matchers. Then we could do a really lightweight copy /// and just trim out the nodes we didn't want. const PathMatcher &inputSet = static_cast<const PathMatcherData *>( it->second.get() )->readable(); PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable(); vector<string> inputPaths; inputSet.paths( inputPaths ); for( vector<string>::const_iterator pIt = inputPaths.begin(), peIt = inputPaths.end(); pIt != peIt; ++pIt ) { path.clear(); ScenePlug::stringToPath( *pIt, path ); tmpContext->set( ScenePlug::scenePathContextName, path ); if( !(filterPlug()->getValue() & ( Filter::ExactMatch | Filter::AncestorMatch ) ) ) { outputSet.addPath( *pIt ); } } } return outputGlobals; }
IECore::CameraPtr GafferScene::camera( const ScenePlug *scene, const IECore::CompoundObject *globals ) { ConstCompoundObjectPtr computedGlobals; if( !globals ) { computedGlobals = scene->globalsPlug()->getValue(); globals = computedGlobals.get(); } if( const StringData *cameraPathData = globals->member<StringData>( "option:render:camera" ) ) { ScenePlug::ScenePath cameraPath; ScenePlug::stringToPath( cameraPathData->readable(), cameraPath ); return camera( scene, cameraPath, globals ); } else { CameraPtr defaultCamera = new IECore::Camera(); applyCameraGlobals( defaultCamera.get(), globals ); return defaultCamera; } }
IECore::ImagePrimitivePtr ImagePlug::image() const { Format format = formatPlug()->getValue(); Box2i dataWindow = dataWindowPlug()->getValue(); Box2i newDataWindow( Imath::V2i(0) ); if( dataWindow.isEmpty() ) { dataWindow = Box2i( Imath::V2i(0) ); } else { newDataWindow = format.yDownToFormatSpace( dataWindow ); } ImagePrimitivePtr result = new ImagePrimitive( newDataWindow, format.getDisplayWindow() ); ConstCompoundObjectPtr metadata = metadataPlug()->getValue(); compoundObjectToCompoundData( metadata.get(), result->blindData() ); ConstStringVectorDataPtr channelNamesData = channelNamesPlug()->getValue(); const vector<string> &channelNames = channelNamesData->readable(); vector<float *> imageChannelData; for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it!=eIt; it++ ) { FloatVectorDataPtr cd = new FloatVectorData; vector<float> &c = cd->writable(); c.resize( result->variableSize( PrimitiveVariable::Vertex ), 0.0f ); result->variables[*it] = PrimitiveVariable( PrimitiveVariable::Vertex, cd ); imageChannelData.push_back( &(c[0]) ); } parallel_for( blocked_range2d<size_t>( 0, dataWindow.size().x+1, tileSize(), 0, dataWindow.size().y+1, tileSize() ), GafferImage::Detail::CopyTiles( imageChannelData, channelNames, channelDataPlug(), dataWindow, Context::current(), tileSize()) ); return result; }
ConstCompoundObjectPtr SetVisualiser::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, ConstCompoundObjectPtr inputAttributes ) const { CompoundObjectPtr result = new CompoundObject; // Since we're not going to modify any existing members (only add a new one), // and our result becomes const on returning it, we can directly reference // the input members in our result without copying. Be careful not to modify // them though! result->members() = inputAttributes->members(); ConstCompoundDataPtr outSetsData = outSetsPlug()->getValue(); const InternedStringVectorData *setNamesData = outSetsData->member<InternedStringVectorData>( "names" ); const Color3fVectorData *setColorsData = outSetsData->member<Color3fVectorData>( "colors" ); int matchResult = PathMatcher::ExactMatch; if( includeInheritedPlug()->getValue() ) { matchResult |= PathMatcher::AncestorMatch; } ConstCompoundDataPtr targetSets = SceneAlgo::sets( inPlug(), setNamesData->readable() ); std::vector<Color3f> shaderColors; size_t index = 0; for( auto &setName : setNamesData->readable() ) { const PathMatcherData *pathMatchData = targetSets->member<const PathMatcherData>( setName ); if( pathMatchData->readable().match( path ) & matchResult ) { shaderColors.push_back( setColorsData->readable()[ index ] ); } // We need to pass our colors to the shader as a fixed size array if( shaderColors.size() == g_maxShaderColors ) { break; } ++index; } // Avoids shader compilation errors as its expecting g_maxShaderColors elements const size_t numColorsUsed = shaderColors.size(); shaderColors.resize( g_maxShaderColors ); result->members()["gl:surface"] = stripeShader( stripeWidthPlug()->getValue(), numColorsUsed, shaderColors ); return result; }
Parameter::Parameter( const std::string &name, const std::string &description, ObjectPtr defaultValue, const PresetsContainer &presets, bool presetsOnly, ConstCompoundObjectPtr userData ) : m_name( name ), m_description( description ), m_defaultValue( defaultValue ), m_presetsOnly( presetsOnly ), m_userData( userData ? userData->copy() : 0 ) { if ( !defaultValue ) { throw Exception( "Invalid NULL default value!" ); } for( PresetsContainer::const_iterator it=presets.begin(); it!=presets.end(); it++ ) { m_presets.push_back( PresetsContainer::value_type( it->first, it->second->copy() ) ); } /// \todo If presetsOnly is true, doesn't this allow us to set a defaultValue that isn't in the presets list? setValue( defaultValue->copy() ); }
void outputScene( const ScenePlug *scene, IECore::Renderer *renderer ) { ConstCompoundObjectPtr globals = scene->globalsPlug()->getValue(); outputOptions( globals.get(), renderer ); outputOutputs( globals.get(), renderer ); outputCamera( scene, globals.get(), renderer ); { WorldBlock world( renderer ); outputGlobalAttributes( globals.get(), renderer ); outputCoordinateSystems( scene, globals.get(), renderer ); outputLights( scene, globals.get(), renderer ); SceneProceduralPtr proc = new SceneProcedural( scene, Context::current() ); renderer->procedural( proc ); } }
IECore::ConstCompoundObjectPtr AppleseedShaderAdaptor::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr inputAttributes = inPlug()->attributesPlug()->getValue(); /// \todo Drop support for "osl:shader" assignments. They were never desirable, and the ShaderAssignment node /// no longer makes them. const ShaderNetwork *shaderNetwork = inputAttributes->member<const ShaderNetwork>( g_oslShaderAttributeName ); if( !shaderNetwork ) { shaderNetwork = inputAttributes->member<const ShaderNetwork>( g_oslSurfaceAttributeName ); } if( !shaderNetwork ) { return inputAttributes; } const Shader *outputShader = shaderNetwork->outputShader(); if( !outputShader ) { return inputAttributes; } OSLQuery::Parameter *firstOutput = firstOutputParameter( outputShader->getName() ); // Build an adaptor network ShaderNetworkPtr adaptedNetwork; if( firstOutput && firstOutput->isclosure ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { materialHandle, g_bsdfParameterName } } ); adaptedNetwork->setOutput( materialHandle ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeColor ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { emissionHandle, "Color" } } ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } else if( firstOutput && ( firstOutput->type == TypeDesc::TypeFloat || firstOutput->type == TypeDesc::TypeInt ) ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); InternedString colorBuildHandle = adaptedNetwork->addShader( "colorBuild", std::move( colorBuild ) ); for( const auto &channel : { "R", "G", "B" } ) { adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { colorBuildHandle, channel } } ); } ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); adaptedNetwork->addConnection( { { colorBuildHandle, "ColorOut" }, { emissionHandle, "Color" } } ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeVector ) { adaptedNetwork = shaderNetwork->copy(); ShaderPtr vectorSplit = new Shader( "vector/as_vector_split", "osl:shader" ); InternedString vectorSplitHandle = adaptedNetwork->addShader( "vectorSplit", std::move( vectorSplit ) ); adaptedNetwork->addConnection( { { adaptedNetwork->getOutput().shader, firstOutput->name.string() }, { vectorSplitHandle, "Vector" } } ); ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); InternedString colorBuildHandle = adaptedNetwork->addShader( "colorBuild", std::move( colorBuild ) ); for( const auto &c : { make_pair( "X", "R" ), make_pair( "Y", "G" ), make_pair( "Z", "B" ) } ) { adaptedNetwork->addConnection( { { vectorSplitHandle, c.first }, { colorBuildHandle, c.second } } ); } ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); adaptedNetwork->addConnection( { { colorBuildHandle, "ColorOut" }, { emissionHandle, "Color" } } ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } else { // Shader has no output, or an output we can't map sensibly. // Make an "error" shader. adaptedNetwork = new ShaderNetwork; ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new Color3fData( Imath::Color3f( 1, 0, 0 ) ); InternedString emissionHandle = adaptedNetwork->addShader( "emission", std::move( emission ) ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); InternedString materialHandle = adaptedNetwork->addShader( "material", std::move( material ) ); adaptedNetwork->addConnection( { { emissionHandle, "BSDF" }, { materialHandle, "BSDF" } } ); adaptedNetwork->setOutput( materialHandle ); } // Place the new network into the "osl:surface" attribute // and remove the "osl:shader" attribute. CompoundObjectPtr outputAttributes = new CompoundObject; outputAttributes->members() = inputAttributes->members(); // Shallow copy for speed - do not modify in place! outputAttributes->members()[g_oslSurfaceAttributeName] = adaptedNetwork; outputAttributes->members().erase( g_oslShaderAttributeName ); return outputAttributes; }
void InteractiveRender::update() { Context::Scope scopedContext( m_context.get() ); const State requiredState = (State)statePlug()->getValue(); ConstScenePlugPtr requiredScene = inPlug()->getInput<ScenePlug>(); // Stop the current render if it's not what we want, // and early-out if we don't want another one. if( !requiredScene || requiredScene != m_scene || requiredState == Stopped ) { // stop the current render m_renderer = NULL; m_scene = NULL; m_state = Stopped; m_lightHandles.clear(); m_shadersDirty = m_lightsDirty = m_cameraDirty = true; if( !requiredScene || requiredState == Stopped ) { return; } } // If we've got this far, we know we want to be running or paused. // Start a render if we don't have one. if( !m_renderer ) { m_renderer = createRenderer(); m_renderer->setOption( "editable", new BoolData( true ) ); ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue(); outputOptions( globals.get(), m_renderer.get() ); outputOutputs( globals.get(), m_renderer.get() ); outputCamera( inPlug(), globals.get(), m_renderer.get() ); { WorldBlock world( m_renderer ); outputGlobalAttributes( globals.get(), m_renderer.get() ); outputCoordinateSystems( inPlug(), globals.get(), m_renderer.get() ); outputLightsInternal( globals.get(), /* editing = */ false ); SceneProceduralPtr proc = new SceneProcedural( inPlug(), Context::current() ); m_renderer->procedural( proc ); } m_scene = requiredScene; m_state = Running; m_lightsDirty = m_shadersDirty = m_cameraDirty = false; } // Make sure the paused/running state is as we want. if( requiredState != m_state ) { if( requiredState == Paused ) { m_renderer->editBegin( "suspendrendering", CompoundDataMap() ); } else { m_renderer->editEnd(); } m_state = requiredState; } // If we're not paused, then send any edits we need. if( m_state == Running ) { updateLights(); updateShaders(); updateCamera(); updateCoordinateSystems(); } }
void SceneProcedural::render( RendererPtr renderer ) const { Context::Scope scopedContext( m_context ); /// \todo See above. try { // get all the attributes, and early out if we're not visibile ConstCompoundObjectPtr attributes = m_scenePlug->attributesPlug()->getValue(); const BoolData *visibilityData = attributes->member<BoolData>( "gaffer:visibility" ); if( visibilityData && !visibilityData->readable() ) { return; } // if we are visible then make an attribute block to contain everything, set the name // and get on with generating things. AttributeBlock attributeBlock( renderer ); std::string name = ""; for( ScenePlug::ScenePath::const_iterator it = m_scenePath.begin(), eIt = m_scenePath.end(); it != eIt; it++ ) { name += "/" + it->string(); } renderer->setAttribute( "name", new StringData( name ) ); // transform std::set<float> transformTimes; motionTimes( ( m_options.transformBlur && m_attributes.transformBlur ) ? m_attributes.transformBlurSegments : 0, transformTimes ); { ContextPtr timeContext = new Context( *m_context ); Context::Scope scopedTimeContext( timeContext ); MotionBlock motionBlock( renderer, transformTimes, transformTimes.size() > 1 ); for( std::set<float>::const_iterator it = transformTimes.begin(), eIt = transformTimes.end(); it != eIt; it++ ) { timeContext->setFrame( *it ); renderer->concatTransform( m_scenePlug->transformPlug()->getValue() ); } } // attributes for( CompoundObject::ObjectMap::const_iterator it = attributes->members().begin(), eIt = attributes->members().end(); it != eIt; it++ ) { if( const StateRenderable *s = runTimeCast<const StateRenderable>( it->second.get() ) ) { s->render( renderer ); } else if( const ObjectVector *o = runTimeCast<const ObjectVector>( it->second.get() ) ) { for( ObjectVector::MemberContainer::const_iterator it = o->members().begin(), eIt = o->members().end(); it != eIt; it++ ) { const StateRenderable *s = runTimeCast<const StateRenderable>( it->get() ); if( s ) { s->render( renderer ); } } } else if( const Data *d = runTimeCast<const Data>( it->second.get() ) ) { renderer->setAttribute( it->first, d ); } } // object std::set<float> deformationTimes; motionTimes( ( m_options.deformationBlur && m_attributes.deformationBlur ) ? m_attributes.deformationBlurSegments : 0, deformationTimes ); { ContextPtr timeContext = new Context( *m_context ); Context::Scope scopedTimeContext( timeContext ); unsigned timeIndex = 0; for( std::set<float>::const_iterator it = deformationTimes.begin(), eIt = deformationTimes.end(); it != eIt; it++, timeIndex++ ) { timeContext->setFrame( *it ); ConstObjectPtr object = m_scenePlug->objectPlug()->getValue(); if( const Primitive *primitive = runTimeCast<const Primitive>( object.get() ) ) { if( deformationTimes.size() > 1 && timeIndex == 0 ) { renderer->motionBegin( deformationTimes ); } primitive->render( renderer ); if( deformationTimes.size() > 1 && timeIndex == deformationTimes.size() - 1 ) { renderer->motionEnd(); } } else if( const Camera *camera = runTimeCast<const Camera>( object.get() ) ) { /// \todo This absolutely does not belong here, but until we have /// a mechanism for drawing manipulators, we don't have any other /// means of visualising the cameras. if( renderer->isInstanceOf( "IECoreGL::Renderer" ) ) { drawCamera( camera, renderer.get() ); } break; // no motion blur for these chappies. } else if( const Light *light = runTimeCast<const Light>( object.get() ) ) { /// \todo This doesn't belong here. if( renderer->isInstanceOf( "IECoreGL::Renderer" ) ) { drawLight( light, renderer.get() ); } break; // no motion blur for these chappies. } else if( const VisibleRenderable* renderable = runTimeCast< const VisibleRenderable >( object.get() ) ) { renderable->render( renderer ); break; // no motion blur for these chappies. } } } // children ConstInternedStringVectorDataPtr childNames = m_scenePlug->childNamesPlug()->getValue(); if( childNames->readable().size() ) { bool expand = true; if( m_pathsToExpand ) { expand = m_pathsToExpand->readable().match( m_scenePath ) & Filter::ExactMatch; } if( !expand ) { renderer->setAttribute( "gl:primitive:wireframe", new BoolData( true ) ); renderer->setAttribute( "gl:primitive:solid", new BoolData( false ) ); renderer->setAttribute( "gl:curvesPrimitive:useGLLines", new BoolData( true ) ); Box3f b = m_scenePlug->boundPlug()->getValue(); CurvesPrimitive::createBox( b )->render( renderer ); } else { ScenePlug::ScenePath childScenePath = m_scenePath; childScenePath.push_back( InternedString() ); // for the child name for( vector<InternedString>::const_iterator it=childNames->readable().begin(); it!=childNames->readable().end(); it++ ) { childScenePath[m_scenePath.size()] = *it; renderer->setAttribute( "name", new StringData( *it ) ); renderer->procedural( new SceneProcedural( *this, childScenePath ) ); } } } } catch( const std::exception &e ) { IECore::msg( IECore::Msg::Error, "SceneProcedural::render()", e.what() ); } }
IECore::ConstCompoundObjectPtr AppleseedShaderAdaptor::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr inputAttributes = inPlug()->attributesPlug()->getValue(); const ObjectVector *shaderNetwork = inputAttributes->member<const ObjectVector>( g_oslShaderAttributeName ); if( !shaderNetwork || shaderNetwork->members().empty() ) { return inputAttributes; } const Shader *rootShader = runTimeCast<const Shader>( shaderNetwork->members().back().get() ); if( !rootShader ) { return inputAttributes; } OSLQuery::Parameter *firstOutput = firstOutputParameter( rootShader->getName() ); // Build an adapter network if we can. bool prependInputNetwork = true; vector<ShaderPtr> adapters; if( firstOutput && firstOutput->isclosure ) { ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); adapters.push_back( material ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeColor ) { ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( emission ); adapters.push_back( material ); } else if( firstOutput && ( firstOutput->type == TypeDesc::TypeFloat || firstOutput->type == TypeDesc::TypeInt ) ) { ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); StringDataPtr colorLink = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); colorBuild->parameters()["R"] = colorLink; colorBuild->parameters()["G"] = colorLink; colorBuild->parameters()["B"] = colorLink; colorBuild->parameters()[g_handleParameterName] = new StringData( "adapterColorBuildHandle" ); ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new StringData( "link:adapterColorBuildHandle.ColorOut" ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( colorBuild ); adapters.push_back( emission ); adapters.push_back( material ); } else if( firstOutput && firstOutput->type == TypeDesc::TypeVector ) { ShaderPtr vectorSplit = new Shader( "vector/as_vector_split", "osl:shader" ); vectorSplit->parameters()["Vector"] = new StringData( "link:adapterInputHandle." + firstOutput->name.string() ); vectorSplit->parameters()[g_handleParameterName] = new StringData( "adapterVectorSplit" ); ShaderPtr colorBuild = new Shader( "color/as_color_build", "osl:shader" ); colorBuild->parameters()["R"] = new StringData( "link:adapterVectorSplit.X" ); colorBuild->parameters()["G"] = new StringData( "link:adapterVectorSplit.Y" ); colorBuild->parameters()["B"] = new StringData( "link:adapterVectorSplit.Z" ); colorBuild->parameters()[g_handleParameterName] = new StringData( "adapterColorBuildHandle" ); ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new StringData( "link:adapterColorBuildHandle.ColorOut" ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( vectorSplit ); adapters.push_back( colorBuild ); adapters.push_back( emission ); adapters.push_back( material ); } else { // Shader has no output, or an output we can't map sensibly. // Make an "error" shader. ShaderPtr emission = new Shader( "surface/as_emission_surface", "osl:shader" ); emission->parameters()["Color"] = new Color3fData( Imath::Color3f( 1, 0, 0 ) ); emission->parameters()[g_handleParameterName] = new StringData( "adapterEmissionHandle" ); ShaderPtr material = new Shader( "material/as_material_builder", "osl:surface" ); material->parameters()[g_bsdfParameterName] = new StringData( "link:adapterEmissionHandle.BSDF" ); adapters.push_back( emission ); adapters.push_back( material ); prependInputNetwork = false; // We don't need the original shaders at all } // Make a new network with the adapter network // appended onto the input network ObjectVectorPtr adaptedNetwork = new ObjectVector(); if( prependInputNetwork ) { adaptedNetwork->members() = shaderNetwork->members(); // Shallow copy for speed - do not modify in place! ShaderPtr rootShaderCopy = rootShader->copy(); rootShaderCopy->parameters()[g_handleParameterName] = new StringData( "adapterInputHandle" );; adaptedNetwork->members().back() = rootShaderCopy; } std::copy( adapters.begin(), adapters.end(), back_inserter( adaptedNetwork->members() ) ); // Place the new network into the "osl:surface" attribute // and remove the "osl:shader" attribute. CompoundObjectPtr outputAttributes = new CompoundObject; outputAttributes->members() = inputAttributes->members(); // Shallow copy for speed - do not modify in place! outputAttributes->members()[g_oslSurfaceAttributeName] = adaptedNetwork; outputAttributes->members().erase( g_oslShaderAttributeName ); return outputAttributes; }
ObjectPtr EnvMapSampler::doOperation( const CompoundObject * operands ) { ImagePrimitivePtr image = static_cast<ImagePrimitive *>( imageParameter()->getValue() )->copy(); Box2i dataWindow = image->getDataWindow(); // find the rgb channels ConstFloatVectorDataPtr redData = image->getChannel<float>( "R" ); ConstFloatVectorDataPtr greenData = image->getChannel<float>( "G" ); ConstFloatVectorDataPtr blueData = image->getChannel<float>( "B" ); if( !(redData && greenData && blueData) ) { throw Exception( "Image does not contain valid RGB float channels." ); } const vector<float> &red = redData->readable(); const vector<float> &green = greenData->readable(); const vector<float> &blue = blueData->readable(); // get a luminance channel LuminanceOpPtr luminanceOp = new LuminanceOp(); luminanceOp->inputParameter()->setValue( image ); luminanceOp->copyParameter()->getTypedValue() = false; luminanceOp->removeColorPrimVarsParameter()->getTypedValue() = false; luminanceOp->operate(); // do the median cut thing to get some samples MedianCutSamplerPtr sampler = new MedianCutSampler; sampler->imageParameter()->setValue( image ); sampler->subdivisionDepthParameter()->setNumericValue( subdivisionDepthParameter()->getNumericValue() ); ConstCompoundObjectPtr samples = boost::static_pointer_cast<CompoundObject>( sampler->operate() ); const vector<V2f> ¢roids = boost::static_pointer_cast<V2fVectorData>( samples->members().find( "centroids" )->second )->readable(); const vector<Box2i> &areas = boost::static_pointer_cast<Box2iVectorData>( samples->members().find( "areas" )->second )->readable(); // get light directions and colors from the samples V3fVectorDataPtr directionsData = new V3fVectorData; Color3fVectorDataPtr colorsData = new Color3fVectorData; vector<V3f> &directions = directionsData->writable(); vector<Color3f> &colors = colorsData->writable(); float radiansPerPixel = M_PI / (dataWindow.size().y + 1); float angleAtTop = ( M_PI - radiansPerPixel ) / 2.0f; for( unsigned i=0; i<centroids.size(); i++ ) { const Box2i &area = areas[i]; Color3f color( 0 ); for( int y=area.min.y; y<=area.max.y; y++ ) { int yRel = y - dataWindow.min.y; float angle = angleAtTop - yRel * radiansPerPixel; float weight = cosf( angle ); int index = (area.min.x - dataWindow.min.x) + (dataWindow.size().x + 1 ) * yRel; for( int x=area.min.x; x<=area.max.x; x++ ) { color[0] += weight * red[index]; color[1] += weight * green[index]; color[2] += weight * blue[index]; index++; } } color /= red.size(); colors.push_back( color ); float phi = angleAtTop - (centroids[i].y - dataWindow.min.y) * radiansPerPixel; V3f direction; direction.y = sinf( phi ); float r = cosf( phi ); float theta = 2 * M_PI * lerpfactor( (float)centroids[i].x, (float)dataWindow.min.x, (float)dataWindow.max.x ); direction.x = r * cosf( theta ); direction.z = r * sinf( theta ); directions.push_back( -direction ); // negated so we output the direction the light shines in } // return the result CompoundObjectPtr result = new CompoundObject; result->members()["directions"] = directionsData; result->members()["colors"] = colorsData; return result; }
IECore::ConstCompoundObjectPtr BranchCreator::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstCompoundObjectPtr inputGlobals = inPlug()->globalsPlug()->getValue(); ConstCompoundDataPtr mapping = boost::static_pointer_cast<const CompoundData>( mappingPlug()->getValue() ); if( !mapping->readable().size() ) { return inputGlobals; } const CompoundData *branchSets = NULL; ConstCompoundObjectPtr branchGlobals = computeBranchGlobals( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), context ); if( branchGlobals ) { branchSets = branchGlobals->member<CompoundData>( "gaffer:sets", /* throwExceptions = */ false ); } if( !branchSets ) { return inputGlobals; } IECore::CompoundObjectPtr outputGlobals = new CompoundObject; // Shallow copy of the input, because most of it will remain unchanged. outputGlobals->members() = inputGlobals->members(); // Deep copy of the input sets, because we'll be modifying them. const CompoundData *inputSets = inputGlobals->member<CompoundData>( "gaffer:sets", /* throwExeptions = */ false ); CompoundDataPtr outputSets = inputSets ? inputSets->copy() : new CompoundData; outputGlobals->members()["gaffer:sets"] = outputSets; const CompoundData *forwardMapping = mapping->member<CompoundData>( g_forwardMappingKey ); string parentString; ScenePlug::pathToString( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), parentString ); if( !boost::ends_with( parentString, "/" ) ) { parentString += "/"; } for( CompoundDataMap::const_iterator it = branchSets->readable().begin(), eIt = branchSets->readable().end(); it != eIt; ++it ) { const PathMatcher &branchSet = static_cast<const PathMatcherData *>( it->second.get() )->readable(); PathMatcher &outputSet = outputSets->member<PathMatcherData>( it->first, /* throwExceptions = */ false, /* createIfMissing = */ true )->writable(); /// \todo If PathMatcher allowed us to rename nodes and merge in other PathMatchers, this could /// be much more efficient. vector<string> branchPaths; branchSet.paths( branchPaths ); for( vector<string>::const_iterator pIt = branchPaths.begin(), peIt = branchPaths.end(); pIt != peIt; ++pIt ) { const string &branchPath = *pIt; const size_t secondSlashPos = branchPath.find( '/', 1 ); const std::string branchName( branchPath, 1, secondSlashPos - 1 ); const InternedStringData *outputName = forwardMapping->member<InternedStringData>( branchName ); if( !outputName ) { // See comments in Group::computeGlobals(). continue; } std::string outputPath = parentString + outputName->readable().string(); if( secondSlashPos != string::npos ) { outputPath += branchPath.substr( secondSlashPos ); } outputSet.addPath( outputPath ); } } return outputGlobals; }
void InteractiveRender::update() { Context::Scope scopedContext( m_context.get() ); const State requiredState = (State)statePlug()->getValue(); ConstScenePlugPtr requiredScene = inPlug()->getInput<ScenePlug>(); // Stop the current render if it's not what we want, // and early-out if we don't want another one. if( !requiredScene || requiredScene != m_scene || requiredState == Stopped ) { stop(); if( !requiredScene || requiredState == Stopped ) { return; } } // no point doing an update if the scene's empty if( inPlug()->childNames( ScenePlug::ScenePath() )->readable().empty() ) { stop(); return; } // If we've got this far, we know we want to be running or paused. // Start a render if we don't have one. if( !m_renderer ) { m_renderer = createRenderer(); m_renderer->setOption( "editable", new BoolData( true ) ); ConstCompoundObjectPtr globals = inPlug()->globalsPlug()->getValue(); outputOptions( globals.get(), m_renderer.get() ); outputOutputs( globals.get(), m_renderer.get() ); outputCameras( inPlug(), globals.get(), m_renderer.get() ); outputClippingPlanes( inPlug(), globals.get(), m_renderer.get() ); { WorldBlock world( m_renderer ); outputGlobalAttributes( globals.get(), m_renderer.get() ); outputCoordinateSystems( inPlug(), globals.get(), m_renderer.get() ); outputLightsInternal( globals.get(), /* editing = */ false ); // build the scene graph structure in parallel: m_sceneGraph.reset( new SceneGraph ); SceneGraphBuildTask *task = new( tbb::task::allocate_root() ) SceneGraphBuildTask( inPlug(), m_context.get(), m_sceneGraph.get(), ScenePlug::ScenePath() ); tbb::task::spawn_root_and_wait( *task ); // output the scene for the first time: outputScene( false ); } m_scene = requiredScene; m_state = Running; m_lightsDirty = m_attributesDirty = m_camerasDirty = false; } // Make sure the paused/running state is as we want. if( requiredState != m_state ) { if( requiredState == Paused ) { m_renderer->editBegin( "suspendrendering", CompoundDataMap() ); } else { m_renderer->editEnd(); } m_state = requiredState; } // If we're not paused, then send any edits we need. if( m_state == Running ) { EditBlock edit( m_renderer.get(), "suspendrendering", CompoundDataMap() ); updateLights(); updateAttributes(); updateCameras(); updateCoordinateSystems(); } }
void Render::outputLights( const ScenePlug *scene, const IECore::CompoundObject *globals, IECore::Renderer *renderer ) const { const CompoundData *forwardDeclarations = globals->member<CompoundData>( "gaffer:forwardDeclarations" ); if( !forwardDeclarations ) { return; } CompoundDataMap::const_iterator it, eIt; for( it = forwardDeclarations->readable().begin(), eIt = forwardDeclarations->readable().end(); it != eIt; it++ ) { const CompoundData *declaration = runTimeCast<const CompoundData>( it->second.get() ); if( !declaration ) { continue; } const IECore::TypeId type = (IECore::TypeId)declaration->member<IntData>( "type", true )->readable(); if( type != IECore::LightTypeId ) { continue; } ScenePlug::ScenePath path; ScenePlug::stringToPath( it->first.string(), path ); IECore::ConstLightPtr constLight = runTimeCast<const IECore::Light>( scene->object( path ) ); if( !constLight ) { continue; } ConstCompoundObjectPtr attributes = scene->fullAttributes( path ); const BoolData *visibilityData = attributes->member<BoolData>( "gaffer:visibility" ); if( visibilityData && !visibilityData->readable() ) { continue; } M44f transform = scene->fullTransform( path ); LightPtr light = constLight->copy(); light->setHandle( it->first.string() ); { AttributeBlock attributeBlock( renderer ); renderer->setAttribute( "name", new StringData( it->first ) ); CompoundObject::ObjectMap::const_iterator aIt, aeIt; for( aIt = attributes->members().begin(), aeIt = attributes->members().end(); aIt != aeIt; aIt++ ) { if( const Data *attribute = runTimeCast<const Data>( aIt->second.get() ) ) { renderer->setAttribute( aIt->first.string(), attribute ); } } renderer->concatTransform( transform ); light->render( renderer ); } renderer->illuminate( light->getHandle(), true ); } }