Example #1
0
IECore::ConstObjectPtr OSLObject::computeProcessedObject( const ScenePath &path, const Gaffer::Context *context, IECore::ConstObjectPtr inputObject ) const
{
	const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
	if( !inputPrimitive )
	{
		return inputObject;
	}

	if( !inputPrimitive->variableData<V3fVectorData>( "P", PrimitiveVariable::Vertex ) )
	{
		return inputObject;
	}

	OSLRenderer::ConstShadingEnginePtr shadingEngine = OSLImage::shadingEngine( shaderPlug() );
	if( !shadingEngine )
	{
		return inputObject;	
	}
	
	CompoundDataPtr shadingPoints = new CompoundData;
	for( PrimitiveVariableMap::const_iterator it = inputPrimitive->variables.begin(), eIt = inputPrimitive->variables.end(); it != eIt; ++it )
	{
		if( it->second.interpolation == PrimitiveVariable::Vertex )
		{
			// cast is ok - we're only using it to be able to reference the data from the shadingPoints,
			// but nothing will modify the data itself.
			shadingPoints->writable()[it->first] = constPointerCast<Data>( it->second.data );
		}
	}

	PrimitivePtr outputPrimitive = inputPrimitive->copy();

	ConstCompoundDataPtr shadedPoints = shadingEngine->shade( shadingPoints );
	const std::vector<Color3f> &ci = shadedPoints->member<Color3fVectorData>( "Ci" )->readable();
	
	V3fVectorDataPtr p = new V3fVectorData;
	p->writable().reserve( ci.size() );
	std::copy( ci.begin(), ci.end(), back_inserter( p->writable() ) );
	
	outputPrimitive->variables["P"] = PrimitiveVariable( PrimitiveVariable::Vertex, p );

	/// \todo Allow shaders to write arbitrary primitive variables.
			
	return outputPrimitive;
}
Example #2
0
IECore::ConstCompoundDataPtr OSLImage::computeShading( const Gaffer::Context *context ) const
{
	OSLRenderer::ConstShadingEnginePtr shadingEngine;
	if( const OSLShader *shader = runTimeCast<const OSLShader>( shaderPlug()->source<Plug>()->node() ) )
	{
		shadingEngine = shader->shadingEngine();
	}

	if( !shadingEngine )
	{
		return static_cast<const CompoundData *>( shadingPlug()->defaultValue() );
	}

	const V2i tileOrigin = context->get<V2i>( ImagePlug::tileOriginContextName );
	const Format format = inPlug()->formatPlug()->getValue();

	CompoundDataPtr shadingPoints = new CompoundData();

	V3fVectorDataPtr pData = new V3fVectorData;
	FloatVectorDataPtr uData = new FloatVectorData;
	FloatVectorDataPtr vData = new FloatVectorData;

	vector<V3f> &pWritable = pData->writable();
	vector<float> &uWritable = uData->writable();
	vector<float> &vWritable = vData->writable();

	const size_t tileSize = ImagePlug::tileSize();
	pWritable.reserve( tileSize * tileSize );
	uWritable.reserve( tileSize * tileSize );
	vWritable.reserve( tileSize * tileSize );

	/// \todo Non-zero display window origins - do we have those?
	const float uStep = 1.0f / format.width();
	const float uMin = 0.5f * uStep;

	const float vStep = 1.0f / format.height();
	const float vMin = 0.5f * vStep;

	const size_t xMax = tileOrigin.x + tileSize;
	const size_t yMax = tileOrigin.y + tileSize;
	for( size_t y = tileOrigin.y; y < yMax; ++y )
	{
		const float v = vMin + y * vStep;
		for( size_t x = tileOrigin.x; x < xMax; ++x )
		{
			uWritable.push_back( uMin + x * uStep );
			vWritable.push_back( v );
			pWritable.push_back( V3f( x, y, 0.0f ) );
		}
	}

	shadingPoints->writable()["P"] = pData;
	shadingPoints->writable()["u"] = uData;
	shadingPoints->writable()["v"] = vData;

	ConstStringVectorDataPtr channelNamesData = inPlug()->channelNamesPlug()->getValue();
	const vector<string> &channelNames = channelNamesData->readable();
	for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it != eIt; ++it )
	{
		shadingPoints->writable()[*it] = boost::const_pointer_cast<FloatVectorData>( inPlug()->channelData( *it, tileOrigin ) );
	}

	CompoundDataPtr result = shadingEngine->shade( shadingPoints.get() );

	// remove results that aren't suitable to become channels
	for( CompoundDataMap::iterator it = result->writable().begin(); it != result->writable().end();  )
	{
		CompoundDataMap::iterator nextIt = it; nextIt++;
		if( !runTimeCast<FloatVectorData>( it->second ) )
		{
			result->writable().erase( it );
		}
		it = nextIt;
	}

	return result;
}