void MirrorRenderLoop_cl::CreateSimpleShaders()
{
  // create a dummy diffuse-only surface
  m_dummySurface.SetEffect(NULL); // make sure all lighting shaders are set properly
  VCompiledEffect *pFX = m_dummySurface.m_spCurrentEffect;
  VVERIFY_MSG(pFX != NULL,"failed to initialize mirror shaders");

  VTechniqueConfig *pGlobalConfig = Vision::Shaders.GetGlobalTechniqueConfig();
  VTechniqueConfig usageConfig;

  // default technique to render lightmapped geometry
  usageConfig.SetInclusionTags("MIRROR;LIGHTMAP");
  m_spDefaultLightMapping = pFX->FindCompatibleTechnique(&usageConfig, pGlobalConfig);
  if (!m_spDefaultLightMapping)
    m_spDefaultLightMapping = pFX->GetDefaultTechnique();

  // technique to render geometry with light grid
  usageConfig.SetInclusionTags("MIRROR;LIGHTGRID");
  m_spDefaultLightGrid = pFX->FindCompatibleTechnique(&usageConfig, pGlobalConfig);
  if (!m_spDefaultLightGrid)
    m_spDefaultLightGrid = pFX->GetDefaultTechnique();

  // depth stencil state
  m_dynLightDefaultState = *VisRenderStates_cl::GetDepthStencilDefaultState();
  m_dynLightDefaultState.m_cDepthComparisonFunc = COMPARISON_EQUAL;
  m_dynLightDefaultState.m_iStencilReadMask = 0;
  m_dynLightDefaultState.m_bDepthWriteEnabled = false;
  m_dynLightDefaultState.ComputeHash();

  VASSERT(m_spDefaultLightMapping && m_spDefaultLightGrid);
}
void VTerrainDecorationEntityModel::RecreateIRShaders(VisSurface_cl* pSurface, VShaderEffectLib* pEffectLib)
{
  if (pSurface == NULL)
    return;

  // check for supported transparency types
  if (pSurface->GetTransparencyType() != VIS_TRANSP_NONE &&
      pSurface->GetTransparencyType() != VIS_TRANSP_ALPHATEST &&
      pSurface->GetTransparencyType() != VIS_TRANSP_ALPHA)
    return;

  char szParam[1024];
  VTechniqueConfig baseCfg("INSTANCING;WIND", NULL);

//   if (Vision::Renderer.GetCurrentRendererNode() != NULL && Vision::Renderer.GetRendererNode()->GetMultisampleMode() != VVIDEO_MULTISAMPLE_OFF)
//     baseCfg.AddInclusionTag("MSAA");

  switch (pSurface->GetGeometryTopology())
  {
    case VisSurface_cl::VGT_3DMesh:
      baseCfg.AddInclusionTag("GEO_3D");
      break;

    default:
      Vision::Error.Warning("VTerrainDecorationEntityModel::RecreateIRShaders: Only 3DMesh geometry topology is supported");
      return;
  }

  hkvVec4 vWindPhaseParams(0.0071f, 0.0092f, 0.0f, 0.0f);
  const hkvAlignedBBox& bbox = m_spMesh->GetBoundingBox();
  if (bbox.isValid())
    vWindPhaseParams.w = -bbox.m_vMin.z;

  {
    // 1. Assign G-Pass pass technique
    ////////////////////////////////////
    szParam[0] = '\0';

    // Get params needed for IR shader creation from IR renderer
    char* pszParamPos = GetParamStringForIRSurface(pSurface, szParam);
    pszParamPos += sprintf(pszParamPos, "WindPhaseParams=%g,%g,%g,%g;", vWindPhaseParams.x, vWindPhaseParams.y, vWindPhaseParams.z, vWindPhaseParams.w);

    VTechniqueConfig cfg(baseCfg);

    bool bHasMaterialTex = pSurface->GetAuxiliaryTextureCount() >= 1 && pSurface->GetAuxiliaryTexture(0) != NULL;
    bool bHasHotSpotTex = pSurface->GetAuxiliaryTextureCount() >= 2 && pSurface->GetAuxiliaryTexture(1) != NULL;

    if (bHasMaterialTex)
    {
      // --- Thermal params are taken from auxiliary texture
      cfg.AddInclusionTag("AUX_TEX");
    }
    else
    {
      int iMaterialID = 0;
      if (pSurface->GetMesh() != NULL)
        iMaterialID = (int)pSurface->GetMesh()->GetBaseSubmesh(0)->GetGeometryInfo().m_sUserFlags;
      
      // --- Thermal params are taken from submesh user flags
      pszParamPos += sprintf(pszParamPos, "ThermalMaterialID=%i;", iMaterialID);
    }

    if (bHasHotSpotTex)
      cfg.AddInclusionTag("HEATING_POWER");

    VCompiledEffect* pFX = Vision::Shaders.CreateEffect("InitialPass", szParam, EFFECTCREATEFLAG_NONE, pEffectLib);
    if (pFX == NULL)
    {
      Vision::Error.Warning("VTerrainDecorationEntityModel::RecreateIRShaders: Failed to create InitialPass effect");
      return;
    }
  
    VCompiledTechnique* pTechnique = pFX->FindCompatibleTechnique(&cfg);
    if (pTechnique == NULL)
    {
      Vision::Error.Warning("VTerrainDecorationEntityModel::RecreateIRShaders: No compatible technique found; using default technique");
      pTechnique = pFX->GetDefaultTechnique(); // find default technique
    }

    VASSERT(pTechnique != NULL && pTechnique->GetShaderCount() == 1);

    m_spInstancingTechIRMainPass = pTechnique;
  }

  {
    // 2. Assign Pre-Pass pass technique
    /////////////////////////////////////
    szParam[0] = '\0';
    char* pszParamPos = szParam;
    pszParamPos += sprintf(pszParamPos, "WindPhaseParams=%g,%g,%g,%g;", vWindPhaseParams.x, vWindPhaseParams.y, vWindPhaseParams.z, vWindPhaseParams.w);

    VTechniqueConfig cfg(baseCfg);

    if (pSurface->GetTransparencyType() == VIS_TRANSP_ALPHATEST || pSurface->GetTransparencyType() == VIS_TRANSP_ALPHA)
    {
      cfg.AddInclusionTag("ALPHATEST");
      pszParamPos += sprintf(pszParamPos, "AlphaTestThreshold=%g;", pSurface->GetAlphaTestThreshold());
    }

    VCompiledEffect* pFX = Vision::Shaders.CreateEffect("PrePass", szParam, EFFECTCREATEFLAG_NONE, pEffectLib);
    if (pFX == NULL)
    {
      Vision::Error.Warning("VTerrainDecorationEntityModel::RecreateIRShaders: Failed to create PrePass effect");
      return;
    }

    VCompiledTechnique* pTechnique = pFX->FindCompatibleTechnique(&cfg);
    if (pTechnique == NULL)
    {
      Vision::Error.Warning("VTerrainDecorationEntityModel::RecreateIRShaders: No compatible technique found; using default technique");
      pTechnique = pFX->GetDefaultTechnique(); // find default technique
    }

    VASSERT(pTechnique != NULL && pTechnique->GetShaderCount() == 1);

    m_spInstancingTechIRPrePass = pTechnique;
  }
}
void VTerrainDecorationEntityModel::ReapplyShaders()
{
  m_spVegetationShaders = NULL;

  // set default material to vegetation (when AUTO mode is used):
  if (m_spMesh!=NULL)
  {

#if defined( HK_ANARCHY )
    const BOOL bUseDeferred = FALSE;
#else
    const BOOL bUseDeferred =  Vision::Renderer.IsRendererNodeOfType(V_RUNTIME_CLASS(VDeferredRenderingSystem));
#endif
    
    int iSubmeshCount = m_spMesh->GetSubmeshCount();
    for (int i=0;i<iSubmeshCount;i++)
    {
      VCompiledEffect *pVegetationFX = NULL;
      VBaseSubmesh *pSubmesh = m_spMesh->GetSubmesh(i);
      VisSurface_cl *pSurf = pSubmesh->GetSurface();
      if (m_spVegetationShaders==NULL)
        m_spVegetationShaders = new VisShaderSet_cl();

      if (pSurf->GetShaderMode()==VisSurface_cl::VSM_Auto)
      {
        char szParamStr[1024];
      
        const hkvAlignedBBox &bbox = m_spMesh->GetBoundingBox();
        float fBaseZ = bbox.isValid() ? -bbox.m_vMin.z : 0.f;
        sprintf(szParamStr,"MaterialParams=%.4f,%.4f,%.4f,%.4f;AlphaThreshold=%.3f;fBaseZ=%.2f", 
          pSurf->GetSpecularMultiplier(),
          pSurf->GetSpecularExponent(),
          pSurf->GetParallaxScale (), pSurf->GetParallaxBias (),
          pSurf->GetAlphaTestThreshold(),fBaseZ
          );

        if (bUseDeferred)
        {
          if (Vision::RenderLoopHelper.GetLightGrid()!=NULL)
          {
            VShaderEffectLib *pLib = Vision::Shaders.LoadShaderLibrary("\\Shaders\\DeferredShadingVegetationLG.ShaderLib", SHADERLIBFLAG_HIDDEN);
            pVegetationFX = Vision::Shaders.CreateEffect("DeferredVegetation_Wind_LG",szParamStr,EFFECTCREATEFLAG_NONE,pLib);
          } else
          {
            VShaderEffectLib *pLib = Vision::Shaders.LoadShaderLibrary("\\Shaders\\DeferredShadingVegetation.ShaderLib", SHADERLIBFLAG_HIDDEN);
            pVegetationFX = Vision::Shaders.CreateEffect("DeferredVegetation_Wind",szParamStr,EFFECTCREATEFLAG_NONE,pLib);
          }
        } else
        {
          BOOL bRes = Vision::Shaders.LoadShaderLibrary("\\Shaders\\TerrainVegetation.ShaderLib", SHADERLIBFLAG_HIDDEN) != NULL;
          if (pSurf->m_spNormalMap!=NULL)
          {
            if (pSurf->m_spSpecularMap!=NULL)
              pVegetationFX = Vision::Shaders.CreateEffect("VegetationNrmlSpec_Wind",szParamStr);
            else
              pVegetationFX = Vision::Shaders.CreateEffect("VegetationNrml_Wind",szParamStr);
          } 
          else
            pVegetationFX = Vision::Shaders.CreateEffect("Vegetation_Wind",szParamStr);
        }
      }
      
      if (pVegetationFX==NULL)
        pVegetationFX = pSurf->GetEffect();
      else
      {
        pSurf->SetEffect(pVegetationFX); // sets up depth technique etc.
        pSurf->SetShaderMode(VisSurface_cl::VSM_Auto);
      }
      if (pSurf->GetTechnique())
        m_spVegetationShaders->Add(pSubmesh, pSurf, pSurf->GetTechnique());
    }
  }

  if (m_spVegetationShaders==NULL)
    m_spVegetationShaders = m_spMesh->GetShaderSet();  // no clone


  // supports instancing at all?
#if defined (WIN32)
  m_spInstancingTech = NULL;
  m_spInstancingTechShadow = NULL;
  m_spInstancingTechIRPrePass = NULL;
  m_spInstancingTechIRMainPass = NULL;
  if (Vision::Renderer.SupportsInstancing() && m_bValidState && m_spVegetationShaders->Count()==1)
  {
    const VisDrawCallInfo_t &drawCall(m_spVegetationShaders->GetDrawCallList()[0]);
    VisSurface_cl *pMat = drawCall.GetSurface();
    bool bAnyInstancingShader = false;
    VCompiledEffect *pFX = pMat->m_spCurrentEffect;
    if (pFX) // checks whether the assigned shader effect holds an instancing version
    {
      VTechniqueConfig cfg;

#ifdef _VR_DX10
      if ((Vision::Renderer.GetRendererNode ()) && (Vision::Renderer.GetRendererNode ()->GetMultisampleMode() != VVIDEO_MULTISAMPLE_OFF))
        cfg.SetInclusionTags("Instancing;MSAA");
      else
#endif
      cfg.SetInclusionTags("Instancing");
      m_spInstancingTech = pFX->FindCompatibleTechnique(&cfg, Vision::Shaders.GetGlobalTechniqueConfig());
      if (m_spInstancingTech!=NULL && m_spInstancingTech->GetShaderCount()==1)
        bAnyInstancingShader = true;

      // shadowmap instancing?
      VTechniqueConfig cfg_shadow("Instancing;SpecificShadowmapFill",NULL);
      m_spInstancingTechShadow = pFX->FindCompatibleTechnique(&cfg_shadow, Vision::Shaders.GetGlobalTechniqueConfig());
      if (m_spInstancingTechShadow!=NULL && m_spInstancingTechShadow->GetShaderCount()==1)
        bAnyInstancingShader = true;
    }


    if (bAnyInstancingShader)
    {
      VisMBVertexDescriptor_t desc;
      int iIndexCount = m_spMesh->GetMeshBuffer()->GetIndexCount();
      VVertexBuffer* pVB = m_spMesh->GetMeshBuffer()->GetVertexBuffer();
      m_spMesh->GetMeshBuffer()->GetVertexDescriptor(desc);

      VIndexBuffer* pIB = m_spMesh->GetMeshBuffer()->GetIndexBuffer();

      m_spModelMesh = new VisMeshBuffer_cl();
      m_spModelMesh->SetVertexBuffer(pVB,desc,m_spMesh->GetNumOfVertices(),VIS_MEMUSAGE_STATIC, 0);
      m_spModelMesh->SetIndexBuffer(pIB,iIndexCount,pIB->GetUsageFlags(), 0);
      m_spModelMesh->SetPrimitiveCount(iIndexCount/3);
      m_spModelMesh->SetPrimitiveType(VisMeshBuffer_cl::MB_PRIMTYPE_INDEXED_TRILIST);
      #ifdef HK_DEBUG
      m_spModelMesh->SetFilename("<TerrainDecorationEntity>");
      #endif
      m_iModelStreams = m_spModelMesh->GetStreamMask() & (m_spInstancingTech->GetShader(0)->GetStreamMask () | VERTEX_STREAM_INDEXBUFFER);
    }
  }
#endif
}