IECore::ConstCompoundObjectPtr Grid::computeAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { if( path.size() == 1 ) { CompoundObjectPtr result = new CompoundObject; result->members()["gl:curvesPrimitive:useGLLines"] = new BoolData( true ); result->members()["gl:smoothing:lines"] = new BoolData( true ); ShaderPtr shader = new Shader( "Constant", "gl:surface" ); shader->parameters()["Cs"] = new Color3fData( Color3f( 1 ) ); result->members()["gl:surface"] = shader; return result; } else if( path.size() == 2 ) { float pixelWidth = 1.0f; if( path.back() == g_gridLinesName ) { pixelWidth = gridPixelWidthPlug()->getValue(); } else if( path.back() == g_centerLinesName ) { pixelWidth = centerPixelWidthPlug()->getValue(); } else if( path.back() == g_borderLinesName ) { pixelWidth = borderPixelWidthPlug()->getValue(); } CompoundObjectPtr result = new CompoundObject; result->members()["gl:curvesPrimitive:glLineWidth"] = new FloatData( pixelWidth ); return result; } return outPlug()->attributesPlug()->defaultValue(); }
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; }
ObjectPtr SLOReader::doOperation( const CompoundObject * operands ) { tbb::mutex::scoped_lock lock( g_mutex ); if( Slo_SetShader( (char *)fileName().c_str() ) ) { throw Exception( boost::str( boost::format( "Unable to set shader to \"%s\"" ) % fileName() ) ); } string name = Slo_GetName(); string type = Slo_TypetoStr( Slo_GetType() ); ShaderPtr result = new Shader( name, type ); CompoundDataPtr typeHints = new CompoundData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:parameterTypeHints", typeHints ) ); // we lose the ordering of parameter names when we put them in result->parameters(), // so we stick the correct order in the blind data as a workaround for anyone interested // in the true ordering. StringVectorDataPtr orderedParameterNames = new StringVectorData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:orderedParameterNames", orderedParameterNames ) ); // we don't have a way of communicating which parameters are outputs in the Shader::parametersData(), // so we work around that using the blind data too. StringVectorDataPtr outputParameterNames = new StringVectorData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:outputParameterNames", outputParameterNames ) ); int numArgs = Slo_GetNArgs(); for( int i=1; i<=numArgs; i++ ) { DataPtr data = 0; SLO_VISSYMDEF *arg = Slo_GetArgById( i ); switch( arg->svd_type ) { case SLO_TYPE_POINT : case SLO_TYPE_VECTOR : case SLO_TYPE_NORMAL : { if( arg->svd_arraylen==0 ) { const SLO_POINT *p = arg->svd_default.pointval; if( p ) { data = new V3fData( V3f( p->xval, p->yval, p->zval ) ); } else { // 0 length and null value signifies a variable length array data = new V3fVectorData(); } } else { V3fVectorDataPtr vData = new V3fVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); const SLO_POINT *p = a->svd_default.pointval; vData->writable().push_back( V3f( p->xval, p->yval, p->zval ) ); } } typeHints->writable().insert( pair<string, DataPtr>( arg->svd_name, new StringData( Slo_TypetoStr( arg->svd_type ) ) ) ); break; } case SLO_TYPE_COLOR : { if( arg->svd_arraylen==0 ) { const SLO_POINT *p = arg->svd_default.pointval; if( p ) { data = new Color3fData( Color3f( p->xval, p->yval, p->zval ) ); } else { // 0 length and null value signifies a variable length array data = new Color3fVectorData(); } } else { Color3fVectorDataPtr vData = new Color3fVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); const SLO_POINT *p = a->svd_default.pointval; vData->writable().push_back( Color3f( p->xval, p->yval, p->zval ) ); } } } break; case SLO_TYPE_SCALAR : { if( arg->svd_arraylen==0 ) { const float *value = arg->svd_default.scalarval; if( value ) { data = new FloatData( *value ); } else { // 0 length and null value signifies a variable length array data = new FloatVectorData(); } } else { FloatVectorDataPtr vData = new FloatVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); vData->writable().push_back( *(a->svd_default.scalarval) ); } if( arg->svd_arraylen==3 ) { // allow V3fData and V3fVectorData to be mapped to float[3] parameters. typeHints->writable().insert( pair<string, DataPtr>( arg->svd_name, new StringData( "float[3]" ) ) ); } } } break; case SLO_TYPE_STRING : { if( arg->svd_arraylen==0 ) { const char *defaultValue = arg->svd_default.stringval; if( defaultValue ) { data = new StringData( defaultValue ); } else { // 0 length and null value signifies a variable length array data = new StringVectorData(); } } else { StringVectorDataPtr vData = new StringVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); // sometimes the default value for an element of a string array can be a null pointer. // i'm not sure what the meaning of this is. the 3delight shaderinfo utility reports such values // as "(null)", so that's what we do too. const char *defaultValue = a->svd_default.stringval; vData->writable().push_back( defaultValue ? defaultValue : "(null)" ); } } } break; case SLO_TYPE_MATRIX : { if( arg->svd_arraylen==0 ) { const float *m = arg->svd_default.matrixval; if( m ) { M44f mm( m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); data = new M44fData( mm ); } else { // 0 length and null value signifies a variable length array data = new M44fVectorData(); } } else { M44fVectorDataPtr vData = new M44fVectorData(); data = vData; for( int j=0; j<arg->svd_arraylen; j++ ) { SLO_VISSYMDEF *a = Slo_GetArrayArgElement( arg, j ); const float *m = a->svd_default.matrixval; M44f mm( m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); vData->writable().push_back( mm ); } } } break; case SLO_TYPE_SHADER : { if( arg->svd_arraylen==0 ) { if( !arg->svd_valisvalid ) { // variable length array data = new StringVectorData(); } else { data = new StringData(); } } else { StringVectorDataPtr sData = new StringVectorData(); data = sData; sData->writable().resize( arg->svd_arraylen ); } typeHints->writable().insert( pair<string, DataPtr>( arg->svd_name, new StringData( Slo_TypetoStr( arg->svd_type ) ) ) ); } break; default : msg( Msg::Warning, "SLOReader::read", format( "Parameter \"%s\" has unsupported type." ) % arg->svd_name ); } if( data ) { orderedParameterNames->writable().push_back( arg->svd_name ); result->parameters().insert( CompoundDataMap::value_type( arg->svd_name, data ) ); if( arg->svd_storage == SLO_STOR_OUTPUTPARAMETER ) { outputParameterNames->writable().push_back( arg->svd_name ); } } } // shader annotations CompoundDataPtr annotations = new CompoundData; result->blindData()->writable().insert( pair<string, DataPtr>( "ri:annotations", annotations ) ); #ifndef PRMANEXPORT for( int i=1, n=Slo_GetNAnnotations(); i <= n; i++ ) { const char *key = Slo_GetAnnotationKeyById( i ); annotations->writable()[key] = new StringData( Slo_GetAnnotationByKey( key ) ); } #endif Slo_EndShader(); return result; }
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; }
IECore::ConstCompoundObjectPtr AttributeVisualiser::computeProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, IECore::ConstCompoundObjectPtr inputAttributes ) const { const std::string attributeName = attributeNamePlug()->getValue(); if( !attributeName.size() ) { return inputAttributes; } const std::string shaderType = shaderTypePlug()->getValue(); if( !shaderType.size() ) { return inputAttributes; } const Object *attribute = inputAttributes->member<Object>( attributeName ); if( !attribute ) { if( !inputAttributes->member<Object>( shaderType ) ) { return inputAttributes; } } 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(); if( !attribute ) { result->members().erase( shaderType ); return result; } // Compute our colour. Color3f color( 0.0f ); const Mode mode = (Mode)modePlug()->getValue(); if( mode == Random ) { Rand32 r( tbb_hasher( attribute->hash() ) ); for( int i = 0; i < 3; ++i ) { color[i] = r.nextf(); } } else if( mode == ShaderNodeColor ) { const Shader *shader = runTimeCast<const Shader>( attribute ); if( !shader ) { if( const ShaderNetwork *network = runTimeCast<const ShaderNetwork>( attribute ) ) { shader = network->outputShader(); } } if( shader ) { const Color3fData *colorData = shader->blindData()->member<const Color3fData>( "gaffer:nodeColor" ); if( colorData ) { color = colorData->readable(); } } } else { // Color or FalseColor switch( attribute->typeId() ) { case FloatDataTypeId : color = Color3f( static_cast<const FloatData *>( attribute )->readable() ); break; case DoubleDataTypeId : color = Color3f( static_cast<const DoubleData *>( attribute )->readable() ); break; case IntDataTypeId : color = Color3f( static_cast<const IntData *>( attribute )->readable() ); break; case BoolDataTypeId : color = Color3f( static_cast<const BoolData *>( attribute )->readable() ); break; case Color3fDataTypeId : color = static_cast<const Color3fData *>( attribute )->readable(); break; default : throw IECore::Exception( boost::str( boost::format( "Unsupported attribute data type \"%s\"" ) % attribute->typeName() ) ); } const Color3f min( minPlug()->getValue() ); const Color3f max( maxPlug()->getValue() ); color = ( color - min ) / ( max - min ); if( mode == FalseColor ) { const SplinefColor3f ramp = rampPlug()->getValue().spline(); color = ramp( color[0] ); } } // Apply the colour using a shader. ShaderPtr shader = new Shader( shaderNamePlug()->getValue(), shaderType ); shader->parameters()[shaderParameterPlug()->getValue()] = new Color3fData( color ); ShaderNetworkPtr shaderNetwork = new ShaderNetwork; const InternedString handle = shaderNetwork->addShader( "surface", std::move( shader ) ); shaderNetwork->setOutput( handle ); result->members()[shaderType] = shaderNetwork; return result; }