const Shader::Setup *CurvesPrimitive::shaderSetup( const Shader *shader, State *state ) const { bool linear, ribbons; renderMode( state, linear, ribbons ); if( linear && !ribbons ) { // we just render in the standard way. return Primitive::shaderSetup( shader, state ); } // we're rendering with ribbons and/or cubic interpolation. we need // to substitute in a geometry shader to do the work. for( MemberData::GeometrySetupVector::const_iterator it = m_memberData->geometrySetups.begin(), eIt = m_memberData->geometrySetups.end(); it != eIt; it++ ) { if( it->originalShader == shader && it->linear == linear && it->ribbons == ribbons ) { return it->shaderSetup.get(); } } ConstShaderPtr geometryShader = shader; ShaderStateComponent *shaderStateComponent = state->get<ShaderStateComponent>(); if( geometryShader->geometrySource() == "" ) { // if the current shader has a specific geometry shader component, // then we assume the user has provided one capable of doing the tesselation, // but if not then we substitute in our own geometry shader. ShaderLoader *shaderLoader = shaderStateComponent->shaderLoader(); if( ribbons ) { if( linear ) { geometryShader = shaderLoader->create( geometryShader->vertexSource(), linearRibbonsGeometrySource(), geometryShader->fragmentSource() ); } else { geometryShader = shaderLoader->create( geometryShader->vertexSource(), cubicRibbonsGeometrySource(), geometryShader->fragmentSource() ); } } else { geometryShader = shaderLoader->create( geometryShader->vertexSource(), cubicLinesGeometrySource(), geometryShader->fragmentSource() ); } } Shader::SetupPtr geometryShaderSetup = new Shader::Setup( geometryShader ); shaderStateComponent->addParametersToShaderSetup( geometryShaderSetup ); addPrimitiveVariablesToShaderSetup( geometryShaderSetup ); geometryShaderSetup->addUniformParameter( "basis", new IECore::M44fData( m_memberData->basis.matrix ) ); geometryShaderSetup->addUniformParameter( "width", new IECore::M44fData( m_memberData->width ) ); m_memberData->geometrySetups.push_back( MemberData::GeometrySetup( shader, geometryShaderSetup, linear, ribbons ) ); return geometryShaderSetup.get(); }
const Shader::Setup *Primitive::shaderSetup( const Shader *shader, State *state ) const { for( ShaderSetupVector::const_iterator it = m_shaderSetups.begin(), eIt = m_shaderSetups.end(); it != eIt; it++ ) { if( (*it)->shader() == shader ) { return it->get(); } } Shader::SetupPtr setup = new Shader::Setup( shader ); addPrimitiveVariablesToShaderSetup( setup.get() ); m_shaderSetups.push_back( setup ); return setup.get(); }
void ensureShaderSetup() const { if( m_shaderSetup ) { return; } if( !m_parameterMap ) { // we were default constructed, so we're just a facing ratio shader. m_shaderSetup = new Shader::Setup( Shader::facingRatio() ); return; } // load a shader, create a setup, and add our parameters to it. ShaderPtr shader = m_shaderLoader->create( m_vertexSource, m_geometrySource, m_fragmentSource ); m_shaderSetup = new Shader::Setup( shader ); addParametersToShaderSetup( m_shaderSetup.get() ); }
const Shader::Setup *PointsPrimitive::shaderSetup( const Shader *shader, State *state ) const { Type type = effectiveType( state ); if( type == Point ) { // rendering as gl points goes through the normal process return Primitive::shaderSetup( shader, state ); } else { // for rendering as disks, quads or spheres, we build a custom setup which we use // for instancing primitives onto our points. for( MemberData::InstancingSetupVector::const_iterator it = m_memberData->instancingSetups.begin(), eIt = m_memberData->instancingSetups.end(); it != eIt; it++ ) { if( it->originalShader == shader && it->type == type ) { return it->shaderSetup.get(); } } ConstShaderPtr instancingShader = shader; ShaderStateComponent *shaderStateComponent = state->get<ShaderStateComponent>(); if( instancingShader->vertexSource() == "" ) { // if the current shader has specific vertex source, then we assume the user has provided // a shader capable of performing the instancing, but if not then we substitute in our own // instancing vertex shader. ShaderLoader *shaderLoader = shaderStateComponent->shaderLoader(); instancingShader = shaderLoader->create( instancingVertexSource(), "", shader->fragmentSource() ); } Shader::SetupPtr instancingShaderSetup = new Shader::Setup( instancingShader ); shaderStateComponent->addParametersToShaderSetup( instancingShaderSetup.get() ); addPrimitiveVariablesToShaderSetup( instancingShaderSetup.get(), "vertex", 1 ); instancingShaderSetup->addUniformParameter( "useWidth", new BoolData( static_cast<bool>( m_memberData->widths ) ) ); if( !m_memberData->constantWidth ) { instancingShaderSetup->addUniformParameter( "constantwidth", new FloatData( 1.0f ) ); } instancingShaderSetup->addUniformParameter( "useAspectRatio", new BoolData( static_cast<bool>( m_memberData->patchAspectRatio ) ) ); instancingShaderSetup->addUniformParameter( "useRotation", new BoolData( static_cast<bool>( m_memberData->rotations ) ) ); switch( type ) { case Disk : if( !m_memberData->diskPrimitive ) { m_memberData->diskPrimitive = new DiskPrimitive( 0.5f ); } m_memberData->diskPrimitive->addPrimitiveVariablesToShaderSetup( instancingShaderSetup.get(), "instance" ); break; case Sphere : if( !m_memberData->spherePrimitive ) { m_memberData->spherePrimitive = new SpherePrimitive( 0.5f ); } m_memberData->spherePrimitive->addPrimitiveVariablesToShaderSetup( instancingShaderSetup.get(), "instance" ); break; case Quad : if( !m_memberData->quadPrimitive ) { m_memberData->quadPrimitive = new QuadPrimitive(); } m_memberData->quadPrimitive->addPrimitiveVariablesToShaderSetup( instancingShaderSetup.get(), "instance" ); break; default : break; } m_memberData->instancingSetups.push_back( MemberData::InstancingSetup( shader, type, instancingShaderSetup ) ); return instancingShaderSetup.get(); } }