Example #1
0
void ProcessedShaderMaterial::_initMaterialParameters()
{   
   // Cleanup anything left first.
   SAFE_DELETE( mDefaultParameters );
   for ( U32 i = 0; i < mParameterHandles.size(); i++ )
      SAFE_DELETE( mParameterHandles[i] );

   // Gather the shaders as they all need to be 
   // passed to the ShaderMaterialParameterHandles.
   Vector<GFXShader*> shaders;
   shaders.setSize( mPasses.size() );
   for ( U32 i = 0; i < mPasses.size(); i++ )
      shaders[i] = _getRPD(i)->shader;

   // Run through each shader and prepare its constants.
   for ( U32 i = 0; i < mPasses.size(); i++ )
   {
      const Vector<GFXShaderConstDesc>& desc = shaders[i]->getShaderConstDesc();

      Vector<GFXShaderConstDesc>::const_iterator p = desc.begin();
      for ( ; p != desc.end(); p++ )
      {
         // Add this to our list of shader constants
         GFXShaderConstDesc d(*p);
         mShaderConstDesc.push_back(d);

         ShaderMaterialParameterHandle* smph = new ShaderMaterialParameterHandle(d.name, shaders);
         mParameterHandles.push_back(smph);
      }
   }
}
Example #2
0
ShaderConstHandles* ProcessedShaderMaterial::_getShaderConstHandles(const U32 pass)
{
   if (pass < mPasses.size())
   {
      return &_getRPD(pass)->shaderHandles;
   }
   return NULL;
}
Example #3
0
MaterialParameters* ProcessedShaderMaterial::allocMaterialParameters()
{
   ShaderMaterialParameters* smp = new ShaderMaterialParameters();
   Vector<GFXShaderConstBufferRef> buffers( __FILE__, __LINE__ );
   buffers.setSize(mPasses.size());
   for (U32 i = 0; i < mPasses.size(); i++)
      buffers[i] = _getRPD(i)->shader->allocConstBuffer();
   // smp now owns these buffers.
   smp->setBuffers(mShaderConstDesc, buffers);
   return smp;   
}
Example #4
0
void ProcessedShaderMaterial::dumpMaterialInfo()
{
   for ( U32 i = 0; i < getNumPasses(); i++ )
   {
      const ShaderRenderPassData *passData = _getRPD( i );

      if ( passData == NULL )
         continue;

      const GFXShader      *shader = passData->shader;

      if ( shader == NULL )
         Con::printf( "  [%i] [NULL shader]", i );
      else
         Con::printf( "  [%i] %s", i, shader->describeSelf().c_str() );
   }
}
Example #5
0
//
// Runtime / rendering
//
bool ProcessedShaderMaterial::setupPass( SceneRenderState *state, const SceneData &sgData, U32 pass )
{
   PROFILE_SCOPE( ProcessedShaderMaterial_SetupPass );

   // Make sure we have the pass
   if(pass >= mPasses.size())
   {
      // If we were rendering instanced data tell
      // the device to reset that vb stream.
      if ( mInstancingState )
         GFX->setVertexBuffer( NULL, 1 );

      return false;
   }

   _setRenderState( state, sgData, pass );

   // Set shaders
   ShaderRenderPassData* rpd = _getRPD(pass);
   if( rpd->shader )
   {
      GFX->setShader( rpd->shader );
      GFX->setShaderConstBuffer(_getShaderConstBuffer(pass));      
      _setShaderConstants(state, sgData, pass);      

      // If we're instancing then do the initial step to get
      // set the vb pointer to the const buffer.
      if ( mInstancingState )
         stepInstance();
   }
   else
   {
      GFX->disableShaders();
      GFX->setShaderConstBuffer(NULL);
   } 

   // Set our textures
   setTextureStages( state, sgData, pass );
   _setTextureTransforms(pass);

   return true;
}
Example #6
0
MaterialParameterHandle* ProcessedShaderMaterial::getMaterialParameterHandle(const String& name)
{
   // Search our list
   for (U32 i = 0; i < mParameterHandles.size(); i++)
   {
      if (mParameterHandles[i]->getName().equal(name))
         return mParameterHandles[i];
   }
   
   // If we didn't find it, we have to add it to support shader reloading.

   Vector<GFXShader*> shaders;
   shaders.setSize(mPasses.size());
   for (U32 i = 0; i < mPasses.size(); i++)
      shaders[i] = _getRPD(i)->shader;

   ShaderMaterialParameterHandle* smph = new ShaderMaterialParameterHandle( name, shaders );
   mParameterHandles.push_back(smph);

   return smph;
}
Example #7
0
void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const SceneData& sgData, U32 pass)
{
   PROFILE_SCOPE( ProcessedShaderMaterial_setSceneInfo );

   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
   ShaderConstHandles* handles = _getShaderConstHandles(pass);

   // Set cubemap stuff here (it's convenient!)
   const Point3F &eyePosWorld = state->getCameraPosition();
   if ( handles->mCubeEyePosSC->isValid() )
   {
      if(_hasCubemap(pass) || mMaterial->mDynamicCubemap)
      {
         Point3F cubeEyePos = eyePosWorld - sgData.objTrans->getPosition();
         shaderConsts->set(handles->mCubeEyePosSC, cubeEyePos);      
      }
   }

   shaderConsts->setSafe(handles->mVisiblitySC, sgData.visibility);

   shaderConsts->setSafe(handles->mEyePosWorldSC, eyePosWorld);   

   if ( handles->mEyePosSC->isValid() )
   {
      MatrixF tempMat( *sgData.objTrans );
      tempMat.inverse();
      Point3F eyepos;
      tempMat.mulP( eyePosWorld, &eyepos );
      shaderConsts->set(handles->mEyePosSC, eyepos);   
   }

   shaderConsts->setSafe(handles->mEyeMatSC, state->getCameraTransform());   

   ShaderRenderPassData *rpd = _getRPD( pass );
   for ( U32 i=0; i < rpd->featureShaderHandles.size(); i++ )
      rpd->featureShaderHandles[i]->setConsts( state, sgData, shaderConsts );

   LIGHTMGR->setLightInfo( this, mMaterial, sgData, state, pass, shaderConsts );
}
bool ProcessedCustomMaterial::setupPass( SceneRenderState *state, const SceneData& sgData, U32 pass )
{
   PROFILE_SCOPE( ProcessedCustomMaterial_SetupPass );

   // Make sure we have a pass.
   if ( pass >= mPasses.size() )
      return false;

   ShaderRenderPassData* rpd = _getRPD( pass );
   U32 currState = _getRenderStateIndex( state, sgData );
   GFX->setStateBlock(rpd->mRenderStates[currState]);      

   // activate shader
   if ( rpd->shader )
      GFX->setShader( rpd->shader );
   else
      GFX->disableShaders();

   // Set our textures   
   setTextureStages( state, sgData, pass );   
   
   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);
   GFX->setShaderConstBuffer(shaderConsts);
   
   // Set our shader constants.
   _setTextureTransforms(pass);
   _setShaderConstants(state, sgData, pass);

   LightManager* lm = state ? LIGHTMGR : NULL;
   if (lm)
      lm->setLightInfo(this, NULL, sgData, state, pass, shaderConsts);

   shaderConsts->setSafe(rpd->shaderHandles.mAccumTimeSC, MATMGR->getTotalTime());   

   return true;
}
void ProcessedCustomMaterial::_setStageData()
{
   // Only do this once
   if ( mHasSetStageData ) 
      return;
   mHasSetStageData = true;   

   ShaderRenderPassData* rpd = _getRPD(0);   
   mConditionerMacros.clear();

   // Loop through all the possible textures, set the right flags, and load them if needed
   for(U32 i=0; i<CustomMaterial::MAX_TEX_PER_PASS; i++ )
   {
      rpd->mTexType[i] = Material::NoTexture;   // Set none as the default in case none of the cases below catch it.
      String filename = mCustomMaterial->mTexFilename[i];

      if(filename.isEmpty())
         continue;

      if(filename.equal(String("$dynamiclight"), String::NoCase))
      {
         rpd->mTexType[i] = Material::DynamicLight;
         mMaxTex = i+1;
         continue;
      }

      if(filename.equal(String("$dynamiclightmask"), String::NoCase))
      {
         rpd->mTexType[i] = Material::DynamicLightMask;
         mMaxTex = i+1;
         continue;
      }

      if(filename.equal(String("$lightmap"), String::NoCase))
      {
         rpd->mTexType[i] = Material::Lightmap;
         mMaxTex = i+1;
         continue;
      }

      if(filename.equal(String("$cubemap"), String::NoCase))
      {
         if( mCustomMaterial->mCubemapData )
         {
            rpd->mTexType[i] = Material::Cube;
            mMaxTex = i+1;
         }
         else
         {
            mCustomMaterial->logError( "Could not find CubemapData - %s", mCustomMaterial->mCubemapName.c_str());
         }
         continue;
      }

      if(filename.equal(String("$dynamicCubemap"), String::NoCase))
      {
         rpd->mTexType[i] = Material::SGCube;
         mMaxTex = i+1;
         continue;
      }

      if(filename.equal(String("$backbuff"), String::NoCase))
      {
         rpd->mTexType[i] = Material::BackBuff;
         mMaxTex = i+1;
         continue;
      }

      if(filename.equal(String("$reflectbuff"), String::NoCase))
      {
         rpd->mTexType[i] = Material::ReflectBuff;
         mMaxTex = i+1;
         continue;
      }

      if(filename.equal(String("$miscbuff"), String::NoCase))
      {
         rpd->mTexType[i] = Material::Misc;
         mMaxTex = i+1;
         continue;
      }

      // Check for a RenderTexTargetBin assignment
      if (filename.substr( 0, 1 ).equal("#"))
      {
         String texTargetBufferName = filename.substr(1, filename.length() - 1);
         NamedTexTarget *texTarget = NamedTexTarget::find( texTargetBufferName ); 
         rpd->mTexSlot[i].texTarget = texTarget;

         // Get the conditioner macros.
         if ( texTarget )
            texTarget->getShaderMacros( &mConditionerMacros );

         rpd->mTexType[i] = Material::TexTarget;
         mMaxTex = i+1;
         continue;
      }

      rpd->mTexSlot[i].texObject = _createTexture( filename, &GFXDefaultStaticDiffuseProfile );
      if ( !rpd->mTexSlot[i].texObject )
      {
         mMaterial->logError("Failed to load texture %s", _getTexturePath(filename).c_str());
         continue;
      }
      rpd->mTexType[i] = Material::Standard;
      mMaxTex = i+1;
   }

   // We only get one cubemap
   if( mCustomMaterial->mCubemapData )
   {
      mCustomMaterial->mCubemapData->createMap();      
      rpd->mCubeMap = mMaterial->mCubemapData->mCubemap; // BTRTODO ?
      if ( !rpd->mCubeMap )
         mMaterial->logError("Failed to load cubemap");
   }

   // If this has a output target defined, it may be writing 
   // to a tex target bin with a conditioner, so search for 
   // one and add its macros.
   if ( mCustomMaterial->mOutputTarget.isNotEmpty() )
   {
      NamedTexTarget *texTarget = NamedTexTarget::find( mCustomMaterial->mOutputTarget );
      if ( texTarget )
         texTarget->getShaderMacros( &mConditionerMacros );
   }

   // Copy the glow state over.
   mHasGlow = mCustomMaterial->mGlow[0];
}
void ProcessedCustomMaterial::setTextureStages( SceneRenderState *state, const SceneData &sgData, U32 pass )
{      
   LightManager* lm = state ? LIGHTMGR : NULL;   
   ShaderRenderPassData* rpd = _getRPD(pass);
   ShaderConstHandles* handles = _getShaderConstHandles(pass);
   GFXShaderConstBuffer* shaderConsts = _getShaderConstBuffer(pass);

   const NamedTexTarget *texTarget;
   GFXTextureObject *texObject; 
   
   for( U32 i=0; i<mMaxTex; i++ )
   {            
      U32 currTexFlag = rpd->mTexType[i];
      if ( !lm || !lm->setTextureStage(sgData, currTexFlag, i, shaderConsts, handles ) )
      {
      	GFXShaderConstHandle* handle = handles->mTexHandlesSC[i];
         if ( !handle->isValid() )
         	continue;

         S32 samplerRegister = handle->getSamplerRegister();
         
         switch( currTexFlag )
         {
         case 0:
         default:
            break;

         case Material::Mask:
         case Material::Standard:
         case Material::Bump:
         case Material::Detail:
            {
               GFX->setTexture( samplerRegister, rpd->mTexSlot[i].texObject );
               break;
            }

         case Material::Lightmap:
            {
               GFX->setTexture( samplerRegister, sgData.lightmap );
               break;
            }
         case Material::Cube:
            {
               GFX->setCubeTexture( samplerRegister, rpd->mCubeMap );
               break;
            }
         case Material::SGCube:
            {
               GFX->setCubeTexture( samplerRegister, sgData.cubemap );
               break;
            }
         case Material::BackBuff:
            {
               GFX->setTexture( samplerRegister, sgData.backBuffTex );
               //if ( sgData.reflectTex )
               //   GFX->setTexture( samplerRegister, sgData.reflectTex );
               //else
               //{
               //    GFXTextureObject *refractTex = REFLECTMGR->getRefractTex( true );
               //    GFX->setTexture( samplerRegister, refractTex );
               //}
               break;
            }
         case Material::ReflectBuff:
            {
               GFX->setTexture( samplerRegister, sgData.reflectTex );
               break;
            }
         case Material::Misc:
            {
               GFX->setTexture( samplerRegister, sgData.miscTex );
               break;
            }
         case Material::TexTarget:
            {
               texTarget = rpd->mTexSlot[i].texTarget;
               if ( !texTarget )
               {
                  GFX->setTexture( samplerRegister, NULL );
                  break;
               }
               
               texObject = texTarget->getTexture();

               // If no texture is available then map the default 2x2
               // black texture to it.  This at least will ensure that
               // we get consistant behavior across GPUs and platforms.
               if ( !texObject )
                  texObject = GFXTexHandle::ZERO;

               if ( handles->mRTParamsSC[samplerRegister]->isValid() && texObject )
               {
                  const Point3I &targetSz = texObject->getSize();
                  const RectI &targetVp = texTarget->getViewport();
                  Point4F rtParams;

                  ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
                  shaderConsts->set(handles->mRTParamsSC[samplerRegister], rtParams);
               }
              
               GFX->setTexture( samplerRegister, texObject );
               break;
            }
         }
      }
   }
}
void ProcessedCustomMaterial::_initPassStateBlocks()
{
   AssertFatal(mHasSetStageData, "State data must be set before initializing state block!");
   ShaderRenderPassData* rpd = _getRPD(0);
   _initRenderStateStateBlocks( rpd );
}
Example #12
0
//
// Material init
//
bool ProcessedShaderMaterial::init( const FeatureSet &features, 
                                    const GFXVertexFormat *vertexFormat,
                                    const MatFeaturesDelegate &featuresDelegate )
{
   // Load our textures
   _setStageData();

   // Determine how many stages we use
   mMaxStages = getNumStages(); 
   mVertexFormat = vertexFormat;
   mFeatures.clear();
   mStateHint.clear();
   SAFE_DELETE(mInstancingState);

   for( U32 i=0; i<mMaxStages; i++ )
   {
      MaterialFeatureData fd;

      // Determine the features of this stage
      _determineFeatures( i, fd, features );
   
      // Let the delegate poke at the features.
      if ( featuresDelegate )
         featuresDelegate( this, i, fd, features );

      // Create the passes for this stage
      if ( fd.features.isNotEmpty() )
         if( !_createPasses( fd, i, features ) )
            return false;
   }

   _initRenderPassDataStateBlocks();
   _initMaterialParameters();
   mDefaultParameters =  allocMaterialParameters();
   setMaterialParameters( mDefaultParameters, 0 );
   mStateHint.init( this );   

   // Enable instancing if we have it.
   if ( mFeatures.hasFeature( MFT_UseInstancing ) )
   {
      mInstancingState = new InstancingState();
      mInstancingState->setFormat( &_getRPD( 0 )->shader->mInstancingFormat, mVertexFormat );
   }

   // Check for a RenderTexTargetBin assignment
   // *IMPORTANT NOTE* 
   // This is a temporary solution for getting diffuse mapping working with tex targets for standard materials
   // It should be removed once this is done properly, at that time the sAllowTextureTargetAssignment should also be removed 
   // from Material (it is necessary for catching shadow maps/post effect this shouldn't be applied to)
   if (Material::sAllowTextureTargetAssignment)
      if (mMaterial && mMaterial->mDiffuseMapFilename[0].isNotEmpty() && mMaterial->mDiffuseMapFilename[0].substr( 0, 1 ).equal("#"))
      {
         String texTargetBufferName = mMaterial->mDiffuseMapFilename[0].substr(1, mMaterial->mDiffuseMapFilename[0].length() - 1);
         NamedTexTarget *texTarget = NamedTexTarget::find( texTargetBufferName ); 

         RenderPassData* rpd = getPass(0);      

         if (rpd)
         {
            rpd->mTexSlot[0].texTarget = texTarget;
            rpd->mTexType[0] = Material::TexTarget;
         }
      }

   return true;
}