void VTerrainDecorationEntityModel::UpdateParameter()
{
  VBaseMesh *pOldMesh = m_spMesh;
  m_spMesh = Vision::Game.LoadDynamicMesh(GetFilename(),true);

  m_bNeedsLightmap = false;
  m_iLightmapSampler = -1;
  bool bSupportsDepthRendering = true;
  bool bSupportsShadowmapRendering = true;
  if (m_spMesh)
  {
    m_spMesh->GetVisibilityBoundingBox(m_LocalBBox);

    // check shader requirements
    for (int i=0;i<(int)m_spMesh->GetSurfaceCount();i++)
    {
      VisSurface_cl *pSrf = m_spMesh->GetSurface(i);
      if (pSrf->m_spDepthFill==NULL)
        bSupportsDepthRendering = false;
      if (pSrf->m_spShadowmapFill==NULL)
        bSupportsShadowmapRendering = false;

      VCompiledTechnique *pSrfTech = pSrf->GetTechnique();
      
      if (!pSrfTech)
        continue;
      for (int j=0;j<pSrfTech->GetShaderCount();j++)
      {
        const VCompiledShaderPass *pShader = pSrfTech->GetShader(j);
        const int iActiveSamplerCount = (int)pShader->GetActiveSamplerCount(VSS_PixelShader);
        for (int k=0;k<iActiveSamplerCount;k++)
        {
          const VStateGroupTexture *pStateGroupTexture = pShader->GetStateGroupTexture(VSS_PixelShader, k);
          VASSERT(pStateGroupTexture != NULL);
          if (pStateGroupTexture->m_cTextureType == TEXTURETYPE_LIGHTMAP)
          {
            m_iLightmapSampler = k;
            m_bNeedsLightmap = true;
          }
        }
      }
    }
  }

  IVTerrainDecorationModel::UpdateParameter();

  if (pOldMesh != m_spMesh)
    ReapplyShaders();

  if (!bSupportsShadowmapRendering)
    m_iSupportedContextTypes &= ~(1<<VIS_CONTEXTUSAGE_DEPTHSHADOW);
  if (bSupportsDepthRendering)
    m_iSupportedContextTypes |= (1<<VIS_CONTEXTUSAGE_DEPTHFILL);

}
Пример #2
0
// Returns the wallmark shader and modifies it according to the passed VProjectedWallmark object.
VProjectorShaderPass *VWallmarkManager::GetWallmarkShader(const VProjectedWallmark *pWallmark, VisStaticGeometryType_e eGeomType)
{
  VASSERT(eGeomType==STATIC_GEOMETRY_TYPE_MESHINSTANCE || eGeomType==STATIC_GEOMETRY_TYPE_TERRAIN);
  V_COMPILE_ASSERT(STATIC_GEOMETRY_TYPE_MESHINSTANCE<4 && STATIC_GEOMETRY_TYPE_TERRAIN<4 && STATIC_GEOMETRY_TYPE_FIRSTCUSTOM<4);

  VCompiledTechnique *pTech = pWallmark->m_spCustomTechnique[eGeomType]; // first try with wallmark's own technique
  if (pTech == NULL)
    pTech = m_spWallmarkTechnique[eGeomType][pWallmark->IsLightmapped() ? 1:0];
  if (pTech == NULL)
  {
    if (Vision::Shaders.LoadShaderLibrary("\\Shaders\\Projectors.ShaderLib", SHADERLIBFLAG_HIDDEN) == NULL)
    {
      VASSERT(!"failed to load 'Shaders\\Projectors.ShaderLib'");
      return NULL;
    }

  #if defined( SUPPORTS_BORDERCOLOR )
    VTechniqueConfig defaultConfig( "", NULL );
  #else
    VTechniqueConfig defaultConfig( "NO_BORDERCOLOR", NULL );
  #endif

    m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_MESHINSTANCE][0] = Vision::Shaders.CreateTechnique("ProjectorFullbright", NULL, &defaultConfig);
    m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_MESHINSTANCE][1] = Vision::Shaders.CreateTechnique("ProjectorLightmapped", NULL, &defaultConfig);
    VASSERT_MSG(m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_MESHINSTANCE][0] && m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_MESHINSTANCE][1],"failed to create shaders for projectors");
  #if !defined(_VISION_IOS) 
    #if defined( SUPPORTS_BORDERCOLOR )
      VTechniqueConfig terrainConf("VTerrain",NULL);
    #else // defined( SUPPORTS_BORDERCOLOR )
      VTechniqueConfig terrainConf("NO_BORDERCOLOR;VTerrain",NULL);
    #endif  // defined( SUPPORTS_BORDERCOLOR )
    m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_TERRAIN][0] = Vision::Shaders.CreateTechnique("ProjectorFullbright", NULL, &terrainConf);
    m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_TERRAIN][1] = Vision::Shaders.CreateTechnique("ProjectorLightmapped", NULL, &terrainConf);
    VASSERT_MSG(m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_TERRAIN][0] && m_spWallmarkTechnique[STATIC_GEOMETRY_TYPE_TERRAIN][1],"failed to create shaders for terrain projectors. Please use latest Projectors.ShaderLib");
  #endif  // !defined(_VISION_IOS) 
    pTech = m_spWallmarkTechnique[eGeomType][pWallmark->IsLightmapped() ? 1:0];
  }
  VASSERT(pTech->GetShaderCount()==1 && "Invalid shader pass count for projectors");
  VProjectorShaderPass *pWallmarkShader = (VProjectorShaderPass *)pTech->GetShader(0);
  VASSERT(pWallmarkShader->IsOfType(VProjectorShaderPass::GetClassTypeId()));

  // update the shader registers
  pWallmarkShader->SetProperties(pWallmark);
  return pWallmarkShader;
}
void RPG_GuiMinimap_VisionGUI::InitShaders()
{
  // Load shader library
  Vision::Shaders.LoadShaderLibrary("GUI\\Shaders\\GUIAlphaMask.Shaderlib");
  VCompiledTechnique *pTechnique = Vision::Shaders.CreateTechnique("GUIAlphaMask",NULL);
  VASSERT(pTechnique);
  m_maskShader = pTechnique->GetShader(0);

  // Apply a custom texture here
  int iMaskSampler = m_maskShader->GetSamplerIndexByName(VSS_PixelShader, "MaskTexture");
  VASSERT(iMaskSampler>=0);
  m_maskShader->GetStateGroupTexture(VSS_PixelShader, iMaskSampler)->m_spCustomTex = m_maskTex;

  // Cache the shader registers:
  m_regTransform.Init(m_maskShader,"BaseTransform");
  m_regFadeColor.Init(m_maskShader,"FadeColor");
  VASSERT(m_regTransform.IsValid());
  VASSERT(m_regFadeColor.IsValid());
}
Пример #4
0
bool HmdRenderLoop::InitPostProcess( HMDPostProcess ePostProcess )
{
  const char* szPostProcessString = GetPostProcessString( ePostProcess );
  char szTechniqueName[ 256 ];
  sprintf_s( szTechniqueName, "HMDPostProcess_%s", szPostProcessString );
  VCompiledTechnique *pTech = Vision::Shaders.CreateTechnique( szTechniqueName, NULL, NULL, EFFECTCREATEFLAG_NONE, m_spOculusVRShaderLib );
  VASSERT_MSG( pTech != NULL, "Unable to create technique '%s'!", szTechniqueName );

  m_spPostProcess[ ePostProcess ] = pTech->GetShader( 0 );
  VASSERT_MSG( m_spPostProcess[ ePostProcess ] != NULL, "Unable to retrieve shader from HMDPostProcess technique '%s'!", szTechniqueName );

  VShaderConstantBuffer *pConstantBuffer = m_spPostProcess[ ePostProcess ]->GetConstantBuffer( VSS_PixelShader );
  VASSERT_MSG( pConstantBuffer != NULL, "Unable to retrieve pixel shader constant buffer from '%s'!", szTechniqueName );

  ShaderRegisterSet& regSet = m_shaderRegisters[ ePostProcess ];
  regSet.m_iLensCenter_ScreenCenter = pConstantBuffer->GetRegisterByName( "f4LensCenter_ScreenCenter" );
  regSet.m_iScale_ScaleIn = pConstantBuffer->GetRegisterByName( "f4Scale_ScaleIn" );
  regSet.m_iHmdWarpParameters = pConstantBuffer->GetRegisterByName( "f4HmdWarpParameters" );
  regSet.m_iChromaticAberration = pConstantBuffer->GetRegisterByName( "f4ChromaticAberration" );

  return true;
}
/////////////////////////////////////////////////////////////////////////////
// RenderAllShadows : render all shadow instances
/////////////////////////////////////////////////////////////////////////////
void VBlobShadowManager::RenderAllShadows()
{
    // if enabled, a 2D bounding box is additionally used for clipping, which saves a lot of fillrate!

    // TODO: PSP2 - fix 2d clipping
#if defined(_VISION_PSP2)
    static bool bClipScissor = false;
#else
    static bool bClipScissor = true;
#endif
    VisFrustum_cl viewFrustum;
    IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
    if (pVisColl==NULL || pVisColl->GetBaseFrustum()==NULL)
        return;
    viewFrustum.CopyFrom((VisFrustum_cl&)*pVisColl->GetBaseFrustum());

    // render all shadows
    VISION_PROFILE_FUNCTION(PROFILING_BS_OVERALL);

    // get the collection of visible (opaque) primitives. For each shadow instance determine
    // the primitives in this list, which intersect with the shadow box
    // (we do not want to render primitives that are not visible)
    const VisStaticGeometryInstanceCollection_cl *pVisibleGeom = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass);

    VRectanglef clipRect(false);
    VRectanglef screenRect(0.f,0.f,(float)Vision::Video.GetXRes(),(float)Vision::Video.GetYRes());
    hkvVec3 vBoxCorner[8];
    hkvVec2 vCorner2D(false);

    // now render the shadows:
    FOR_ALL_SHADOWS

    if (pShadow->GetOwner())
        pShadow->SetBoundingBoxFromOwnerProperties();

    // shadow box visible?
    if (!viewFrustum.Overlaps(pShadow->m_ShadowBox))
        continue;

    // build 2D bounding box for scissor clipping
    if (bClipScissor)
    {
        VISION_PROFILE_FUNCTION(PROFILING_BS_SCISSORRECT);
        clipRect.Reset();
        pShadow->m_ShadowBox.getCorners(vBoxCorner);
        for (int i=0; i<8; i++)
        {
            // if one vertex is behind camera, do not use clipping
            if (!Vision::Contexts.GetCurrentContext()->Project2D(vBoxCorner[i],vCorner2D.x,vCorner2D.y))
            {
                Vision::RenderLoopHelper.SetScissorRect(NULL);
                goto render_shadow;
            }
            clipRect.Add(vCorner2D);
        }
        VASSERT(clipRect.IsValid());
        clipRect = clipRect.GetIntersection(screenRect);
        if (!clipRect.IsValid())
            continue; // do not render shadows at all if rect is outside the screen
        Vision::RenderLoopHelper.SetScissorRect(&clipRect);
    }

render_shadow:

    // get the visible primitives in the shadow bounding box
    {
        VISION_PROFILE_FUNCTION(PROFILING_BS_DETERMINE_PRIMS);
        // affected static geometry:
        shadowGeom.Clear();
        pVisibleGeom->DetermineEntriesTouchingBox(pShadow->m_ShadowBox,shadowGeom);
    }

    // split into geometry types:
    if (!shadowGeom.GetNumEntries())
        continue;

    const VisStaticGeometryType_e relevantTypes[2] = {STATIC_GEOMETRY_TYPE_MESHINSTANCE,STATIC_GEOMETRY_TYPE_TERRAIN};

    // two relevant geometry types:
    for (int iType=0; iType<2; iType++)
    {
        shadowGeomOfType.Clear();
        shadowGeom.GetEntriesOfType(shadowGeomOfType,relevantTypes[iType]);
        VCompiledTechnique *pFX = GetDefaultTechnique(relevantTypes[iType]);
        if (shadowGeomOfType.GetNumEntries()==0 || pFX==NULL)
            continue;

        // for all the shader in the projection effect (usually 1 shader), render the primitive collection
        const int iShaderCount = pFX->GetShaderCount();

        for (int j=0; j<iShaderCount; j++)
        {
            VBlobShadowShader *pShader = (VBlobShadowShader *)pFX->GetShader(j);

            {   // code block for easier profiling
                VISION_PROFILE_FUNCTION(PROFILING_BS_PREPARE_SHADER);
                // prepare the shader, i.e. setup shadow specific projection planes, colors etc.
                pShader->UpdateShadow(pShadow);
            }
            {   // code block for easier profiling
                VISION_PROFILE_FUNCTION(PROFILING_BS_RENDER_PRIMS);
                Vision::RenderLoopHelper.RenderStaticGeometryWithShader(shadowGeomOfType,*pShader);
            }
        }
    }


}
Пример #6
0
// Simplified version of dynamic light rendering for mirrors
void MirrorRenderLoop_cl::DrawDynamicLight()
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::DrawDynamicLight");

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
  VCompiledTechnique *pTechnique = NULL;

  VisMirror_cl::VReflectionShaderSets_e shaderMode = m_pMirror->m_eReflectionShaderMode;

  // Get all visible light sources
  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;

  const VisLightSrcCollection_cl *pLightSourceCollection = pVisColl->GetVisibleLights();
  unsigned int i;
  unsigned int iNumLights = pLightSourceCollection->GetNumEntries();
  if (iNumLights == 0)
    return;

  // Set depth-stencil state
  VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);
  
  // For all visible lights...
  for (i=0; i<iNumLights; i++)
  {
    VisLightSource_cl *pLight = pLightSourceCollection->GetEntry(i);
    // We're only interested in dynamic lights
    if (!pLight->IsDynamic()) 
      continue;

    // Clear the collections of geo instances and entities, since we want to build them from scratch for each light
    s_LitEntityCollection.Clear();
    s_LitGeoInstanceCollection.Clear();

    // See which geometry types have to cast shadows
    int iReceiverFlags = GetLightReceiverFlags(pLight);

    // If nothing receives light from this light source, we can proceed to the next light.
    if (!iReceiverFlags)
      continue;

    // ***************** Create lists of illuminated scene elements *****************

    // If no shadows are cast, we simply illuminate all visible geometry within the range (spherical) of the light.
    VisEntityCollection_cl *pEntColl = NULL;
    if (iReceiverFlags & VIS_LIGHTSRCVIS_MODELS)
      pEntColl = &s_LitEntityCollection;
    VisStaticGeometryInstanceCollection_cl *pGeoInstanceColl = NULL;
    if (iReceiverFlags & VIS_LIGHTSRCVIS_PRIMITIVES)
    {
      pGeoInstanceColl = &s_LitGeoInstanceCollection;
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pGeoInstanceColl, pEntColl, NULL, *pLight);

    // For all illuminated entities: Render a dynamic lighting pass now.
    if (pLight->GetLightInfluenceBitMaskEntity())
    {
      int j;
      
      int iNumLitEntities = s_LitEntityCollection.GetNumEntries();

      Vision::RenderLoopHelper.BeginEntityRendering();

      for (j=0; j<iNumLitEntities; j++)
      {
        VisBaseEntity_cl *pEntity = s_LitEntityCollection.GetEntry(j);
        // Ignore foreground entities (they don't trivially support additive lighting)
        if (pEntity->IsObjectAlwaysInForegroundEnabled())
          continue;
        if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
          continue;
        if (!pVisColl->IsEntityVisible(pEntity))
          continue;
          
        VDynamicMesh *pMesh = pEntity->GetMesh();
          
        // Get list of all the surfaces in the model
        int iNumSubmeshes = pMesh->GetSubmeshCount();
        int iNumSurfaceShaders = 0;
        VisSurface_cl **ppSurfaceArray = pEntity->GetSurfaceArray();

        // For all the surfaces...
        for (int k=0; k<iNumSubmeshes; k++)
        {
          VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
          VASSERT(pSubmesh != NULL);
          VisSurface_cl* pSurface = &m_dummySurface; 
          VisSurface_cl* pMeshSurface = pSubmesh->m_pSurface;
          VASSERT(pMeshSurface != NULL);

          bool bHasManualTemplateShaderAssignment = pMeshSurface->GetShaderMode() == VisSurface_cl::VSM_Template 
            && pMeshSurface->GetMaterialTemplate() != NULL && pMeshSurface->GetMaterialTemplate()->HasManualAssignment();

          if (shaderMode == VisMirror_cl::AlwaysSurfaceShaders || 
            (shaderMode == VisMirror_cl::SimpleForAUTO && ( (pMeshSurface->GetShaderMode() == VisSurface_cl::VSM_Manual) || bHasManualTemplateShaderAssignment) ) )
          {
            pSurface = ppSurfaceArray[pSubmesh->m_iMaterialIndex]; // use the real surface
          }
          pTechnique = Vision::GetApplication()->GetShaderProvider()->GetDynamicLightShader(pLight, pSurface, true);
          if (pTechnique==NULL)
            continue;
            
          VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
          info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
        }
        // Finally, render the entity with a surface shader list.
        if (iNumSurfaceShaders>0)
          Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
      }

      Vision::RenderLoopHelper.EndEntityRendering();
    }

    // For all illuminated world primitives: Render a dynamic lighting pass now
    if (pLight->GetLightInfluenceBitMaskWorld() > 0)
    {
      // For all illuminated static geometry instances: Render a dynamic lighting pass now.
      int iNumLitGeoInstances = s_LitGeoInstanceCollection.GetNumEntries();

      s_RenderGeoInstanceCollection.Clear();

      // Render illuminated geometry instances. 
      for (int j=0; j < iNumLitGeoInstances; j++)
      {
        VisStaticGeometryInstance_cl *pGI = s_LitGeoInstanceCollection.GetEntry(j);

        if (pGI->GetSurface()==NULL || pGI->GetSurface()->IsFullbright())
          continue;
       
        // We have to append the primitive to our collection
        s_RenderGeoInstanceCollection.AppendEntry(pGI);
      }

      // render the collection
      const int iLitGeoCount = s_RenderGeoInstanceCollection.GetNumEntries();
      if (iLitGeoCount > 0)
      {
        VCompiledTechnique *pLastTech = NULL;
        VisSurface_cl* pLastSurface = NULL;
        m_CustomGeoInstances.EnsureSize(iLitGeoCount);
        m_CustomGeoInstances.Clear();

        for (int j=0; j < iLitGeoCount; j++)
        {
          VisStaticGeometryInstance_cl *pGI = s_RenderGeoInstanceCollection.GetEntry(j);

          GetLightShader (pLight, pGI, m_pMirror->m_eReflectionShaderMode, pLastSurface, pLastTech, pLastSurface, pTechnique);
          
          // The current technique has changed, so we have to render the previously gathered geometry.
          if (pLastTech != pTechnique)
          {
            if ((m_CustomGeoInstances.GetNumEntries() > 0) && (pLastTech != NULL) && (pLastTech->GetShaderCount() > 0))
            {
              Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pLastTech->m_Shaders.GetAt(0) );
              m_CustomGeoInstances.Clear();
            }
            pLastTech = pTechnique;
          }
          m_CustomGeoInstances.AppendEntryFast(pGI);
        }
        // Render remaining geometry
        if ((m_CustomGeoInstances.GetNumEntries() > 0) && (pLastTech != NULL) && (pLastTech->GetShaderCount() > 0))
        {
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pTechnique->m_Shaders.GetAt(0) );
        }

        s_RenderGeoInstanceCollection.Clear();
      }
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}
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;
  }
}
VCompiledTechnique *VMobileForwardRenderLoop::GetLightShader(VisLightSource_cl *pLight, bool bBasePass, const VisSurface_cl *pSurface,  
                                                             float fFade, IVShadowMapComponent *pShadowMapComponent)
{
  VASSERT(pLight!=NULL && pSurface!=NULL);

  VCompiledTechnique *pTech = NULL;
  bool bDynamicLighting = pLight->IsDynamic()==TRUE;
  VisLightSourceType_e lightType = pLight->GetType(); 
  VASSERT(lightType==VIS_LIGHT_POINT || lightType==VIS_LIGHT_SPOTLIGHT || lightType==VIS_LIGHT_DIRECTED);

  VTextureObject *pProjTexture = NULL;
  hkvPlane plane_x(hkvNoInitialization);
  hkvPlane plane_y(hkvNoInitialization);
  hkvPlane plane_z(hkvNoInitialization);
  
  int iLightingFlags = 0;
  if (bBasePass)
    iLightingFlags |= VMOBILE_LIGHTING_FLAG_BASEPASS;
  if (bDynamicLighting)
    iLightingFlags |= VMOBILE_LIGHTING_FLAG_DYNAMIC;
  if (pShadowMapComponent)
    iLightingFlags |= VMOBILE_LIGHTING_FLAG_SHADOW;

  // 1: pick light shader from material
  switch (iLightingFlags)
  {
  case VMOBILE_LIGHTING_FLAG_DYNAMIC:
    {
      if (lightType == VIS_LIGHT_POINT)
        pTech = pSurface->m_spDynPointLight;
      else if (lightType == VIS_LIGHT_SPOTLIGHT)
        pTech = pSurface->m_spDynSpotLight;
      else if (lightType == VIS_LIGHT_DIRECTED)
        pTech = pSurface->m_spDynDirectionalLight; 
      break;
    }

  case (VMOBILE_LIGHTING_FLAG_DYNAMIC | VMOBILE_LIGHTING_FLAG_SHADOW):
    {
      if (lightType == VIS_LIGHT_SPOTLIGHT)
        pTech = pSurface->m_spDynSpotLightShadow;
      else if (lightType == VIS_LIGHT_DIRECTED)
        pTech = pSurface->m_spDynDirectionalLightShadow; 
      break;
    }
   
  case (VMOBILE_LIGHTING_FLAG_BASEPASS | VMOBILE_LIGHTING_FLAG_DYNAMIC):
    {
      if (lightType == VIS_LIGHT_POINT)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_POINTLIGHT];
      else if (lightType == VIS_LIGHT_SPOTLIGHT)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_SPOTLIGHT]; 
      else if (lightType == VIS_LIGHT_DIRECTED)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_DIRLIGHT];
      break;
    }

  case (VMOBILE_LIGHTING_FLAG_BASEPASS | VMOBILE_LIGHTING_FLAG_DYNAMIC | VMOBILE_LIGHTING_FLAG_SHADOW):
    {
      if (lightType == VIS_LIGHT_SPOTLIGHT)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_SPOTLIGHT_SHADOW];
      else if (lightType == VIS_LIGHT_DIRECTED)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_DIRLIGHT_SHADOW];
      break;
    }

  case (VMOBILE_LIGHTING_FLAG_BASEPASS | VMOBILE_LIGHTING_FLAG_SHADOW):
    {
      if (lightType == VIS_LIGHT_SPOTLIGHT)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_SPOTLIGHT_SUBTRACTIVE_SHADOW];
      else if (lightType == VIS_LIGHT_DIRECTED)
        pTech = pSurface->m_spCustomTechniques[VMOBILE_BASEPASS_TECHNIQUE_DYN_DIRLIGHT_SUBTRACTIVE_SHADOW];
      break;
    }
 
  case VMOBILE_LIGHTING_FLAG_BASEPASS:
    break; // rendering in base pass without lights and shadows results in rendering within the default base pass

  default:
    VASSERT_MSG(false, "Unsupported lighting flags");
  }
  if (!pTech)
    return NULL;

  if (bDynamicLighting && lightType==VIS_LIGHT_SPOTLIGHT)
  {
    pProjTexture = pLight->GetProjectionTexture();
    if (!pProjTexture)
      pProjTexture = GetDefaultSpotlightTexture();
    pLight->GetProjectionPlanes(plane_x, plane_y, plane_z); // this has the cone angle encoded already
  }

  // 2: modify light shader
  hkvVec3 vColor, lightDir;
  float fMultiplier = 0.0f;
  if (bDynamicLighting)
  {
    vColor = pLight->GetColor().ToFloat();
    fMultiplier = pLight->GetMultiplier()*fFade;
    if (lightType == VIS_LIGHT_DIRECTED || lightType == VIS_LIGHT_SPOTLIGHT)
    {
      lightDir = pLight->GetDirection();
      lightDir.normalize();
    }
  }

  // Attenuation texture not used by MobileShaders.ShaderLib, but may be used
  // by manually assigned shader libs.
  VTextureObject *pAttTexture = pLight->GetAttenuationTexture();
  if (pAttTexture == NULL)
    pAttTexture = GetDefaultAttenuationTexture();

  const int iPassCount = pTech->GetShaderCount();
  for (int i=0;i<iPassCount;i++)
  {
    VDynamicLightShaderBase *pPass = vdynamic_cast<VDynamicLightShaderBase*>(pTech->GetShader(i));
    VASSERT_MSG(pPass != NULL, "Dynamic light shaders must be of class VDynamicLightShaderBase");   
    if (!pPass)
    { 
      Vision::Error.Warning("Dynamic light shader is not of class VDynamicLightShaderBase; dynamic light will have no effect.");
      continue;
    }
   
    // If the lighting shader is not mobile specific, we can't use the shadow component, since 
    // it is mobile specific. In this case we recall this method without a valid shadow component,
    // in order to render the lit surfaces without shadows.
    if (!pTech->GetShader(i)->IsOfType(VMobileDynamicLightShader::GetClassTypeId()) && pShadowMapComponent)
      return GetLightShader(pLight, bBasePass, pSurface, fFade, NULL);

    pPass->SetAttenuationTexture(pAttTexture);

    if (bDynamicLighting)
    {
      // set light source properties
      pPass->SetPosition(pLight->GetPosition());
      pPass->SetRadius(pLight->GetRadius());
      pPass->SetColor(vColor, fMultiplier);
      
      // set light direction for directed lights
      if (lightType == VIS_LIGHT_DIRECTED)
        pPass->SetDirection(lightDir);

      // set light direction and cone angle for spot lights
      else if (lightType == VIS_LIGHT_SPOTLIGHT)
      {
        pPass->SetDirection(lightDir);
        pPass->SetProjectionAngle(pLight->GetProjectionAngle());
      }

      if (pProjTexture)
      {
        VDynamicLightShader *pDynamicLightShader = vdynamic_cast<VDynamicLightShader*>(pPass);
        if (pDynamicLightShader)
        {
          pDynamicLightShader->SetProjectedTexture(pProjTexture);
          pDynamicLightShader->SetProjectionPlanes(plane_x,plane_y,plane_z);
        }
      }
    }

#ifdef SUPPORTS_SHADOW_MAPS
    if (pShadowMapComponent)
    {
      VMobileShadowMapComponentSpotDirectional *pMobileSpotDirShadowMapComponent = vstatic_cast<VMobileShadowMapComponentSpotDirectional*>(pShadowMapComponent);
      if (pMobileSpotDirShadowMapComponent)
        pMobileSpotDirShadowMapComponent->UpdateLightShader((VMobileDynamicLightShader*)pPass);
    }
#endif
    
    pPass->m_bModified = true;
  }

  return pTech;
}
void VMobileForwardRenderLoop::RenderLitGeometry(VisLightSource_cl *pLight, IVShadowMapComponent *pShadowMapComponent, bool bBasePass, bool bUsesLightClippingVolume, bool bEntities, bool bStaticGeometry)
{
  if (!pLight)
    return;

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VCompiledTechnique *pTechnique = NULL;
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  const hkvVec3 &vCamPos = pContext->GetCamera()->GetPosition();
 
  const float fFade = pLight->GetFadeWeight(vCamPos);

  VisStaticGeometryInstanceCollection_cl *pLitGeoInstanceCollection = NULL;
  VisEntityCollection_cl *pLitEntityCollection = NULL;

  if (bBasePass || pLight != m_pBasePassLight)
  {
    if (bStaticGeometry)
    {
      pLitGeoInstanceCollection = &s_LitGeoInstanceCollection;
      pLitGeoInstanceCollection->Clear();
    }
    if (bEntities)
    {
      pLitEntityCollection = &s_LitEntityCollection;
      pLitEntityCollection->Clear();
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pLitGeoInstanceCollection, pLitEntityCollection, NULL, *pLight);
  }
  else
  {
    if (bStaticGeometry)
      pLitGeoInstanceCollection = &m_AdditiveLitGeoInstanceCollection;
    if (bEntities)
      pLitEntityCollection = &m_AdditiveLitEntityCollection;
  }

#ifdef SUPPORTS_SHADOW_MAPS
  VShadowMapGenSpotDir *pShadowMapGenDir = NULL;
  if (pShadowMapComponent)
  {
    VShadowMapGenerator *pShadowMapGen = pShadowMapComponent->GetShadowMapGenerator();
    if (pShadowMapGen->GetProjectionType()==SHADOW_PROJECTION_ORTHOGRAPHIC)
      pShadowMapGenDir = static_cast<VShadowMapGenSpotDir*>(pShadowMapGen);
  }
#endif

  // Set the stencil render state for reading light clipping volume information
  if(bUsesLightClippingVolume)
  {
    const VLightClippingVolumeComponent* pLightClippingComponent = pLight->Components().GetComponentOfBaseType<VLightClippingVolumeComponent>();
    VASSERT(pLightClippingComponent != NULL && V_ARRAY_SIZE(m_lightClippingStencilStatesRead)==2);
    VisRenderStates_cl::SetDepthStencilState(m_lightClippingStencilStatesRead[pLightClippingComponent->GetClipHandedness()]);
  }
  else
    VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);

  // For all illuminated entities: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskEntity() != 0  && bEntities)
  {
    int iNumLitEntities = pLitEntityCollection->GetNumEntries();

    Vision::RenderLoopHelper.BeginEntityRendering();

    for (int j=0; j<iNumLitEntities; j++)
    {
      VisBaseEntity_cl *pEntity = pLitEntityCollection->GetEntry(j);

      if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
        continue;

      VDynamicMesh *pMesh = pEntity->GetMesh();
      VisSurface_cl **ppSurfaces = pEntity->GetSurfaceArray();

      // Get list of all the surfaces in the model
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      int iNumSurfaceShaders = 0;

      // For all the surfaces...
      for (int k=0; k<iNumSubmeshes; k++)
      {
        VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
        VisSurface_cl *pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];

        // Full-bright surfaces can't be rendered in the compound base pass, since such surfaces are not illuminated. Since tagging
        // of already rendered geometry happens per entity instance, in case an entity contains full-bright surfaces, all surfaces 
        // of this entity have to be rendered in the normal rendering pipeline.
        const VisLightingMethod_e eLightingMethod = pSurface->GetLightingMode();
        if (bBasePass)
        {
          // Since entities can contain several surfaces with different lighting methods (full-bright, dynamic only, etc.), entities 
          // with full-bright surfaces have to be also added to the additive lit entity collection, in order to ensure rendering of 
          // dynamic only surfaces.
          if (eLightingMethod==VIS_LIGHTING_FULLBRIGHT)
          {
            iNumSurfaceShaders = 0;
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
            break; 
          }
        }
        else
        {
          if (eLightingMethod == VIS_LIGHTING_FULLBRIGHT)
            continue;
        }

        // If not all surfaces have a primary opaque pass type in the base pass, then render corresponding entity 
        // in the additive lighting pass.
        if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
        {
          iNumSurfaceShaders = 0;
          m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          break; 
        }

        // Check whether entity is in current shadow volume for orthographic shadows. In that case the entity is rendered
        // without shadows since it is not in the relevant shadow volume.
        IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
        if (pShadowMapGenDir)
        {
          if (!pShadowMapGenDir->IsEntityInsideOrthoShadowVolume(pEntity))
            pTmpShadowMapComponent = NULL;
        }
#endif

        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);
        if (!pTechnique || !pTechnique->GetShaderCount()) // do not light this surface
        {
          // If base-pass lighting technique could not be retrieved, render lit entity in the additive pass.
          if (bBasePass && pLight->IsDynamic())
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          iNumSurfaceShaders = 0;
          break; 
        }

        // Generate a list of surface shader from the combined surface/shader information
        VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
        info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
      }

      // Finally, render the entity with a surface shader list.
      if (iNumSurfaceShaders>0)
      {
        Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
        if (bBasePass)
          pEntity->Tag();
      }
    }

    Vision::RenderLoopHelper.EndEntityRendering();
  }

  // For all illuminated world primitives: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskWorld() != 0 && bStaticGeometry)
  {
    VisSurface_cl *pSurface;
    VisSurface_cl *pLastSurface = NULL;
    VCompiledTechnique *pLastTechnique = NULL;

    // We start collecting illuminated mesh instances. Whenever a relevant property changes, we set the
    // shader information, render all collected world instances, and start collecting from scratch.
    int iNumLitGeoInstances = pLitGeoInstanceCollection->GetNumEntries();
    pLastSurface = NULL;
    s_RenderGeoInstanceCollection.Clear();
    pLastTechnique = NULL;

    for (int j=0; j<iNumLitGeoInstances; j++)
    {
      VisStaticGeometryInstance_cl *pGI = pLitGeoInstanceCollection->GetEntry(j);

      pSurface = pGI->GetSurface();
      VASSERT(pSurface);
      if (pSurface->IsFullbright()) 
        continue; 

      // If surface does not have a primary opaque pass type in the base pass, then render corresponding static
      // mesh instance in the additive lighting pass.
      if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
      {
        m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue;
      }

      // Check whether mesh is in current shadow volume for orthographic shadows. In that case the mesh is rendered
      // without shadows since it is not in the relevant shadow volume.
      IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
      if (pShadowMapGenDir)
      {
        if (!pShadowMapGenDir->IsMeshInsideOrthoShadowVolume(pGI))
          pTmpShadowMapComponent = NULL;
      }
#endif

      if (pLastSurface!=pSurface)
      { 
        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);          
        pLastSurface = pSurface;
      }
      if (pTechnique == NULL || !pTechnique->GetShaderCount())
      {
        // If base-pass lighting technique could not be retrieved, render lit mesh in the additive pass.
        if (bBasePass && pLight->IsDynamic())
          m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue; 
      }

      // If the state information is different from the previous one, we have to render the world primitives we
      // have collected so far
      if (pLastTechnique!=pTechnique)
      {
        if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
        {
          VASSERT(pLastTechnique != NULL);
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
          if (bBasePass)
            s_RenderGeoInstanceCollection.TagEntries();
          s_RenderGeoInstanceCollection.Clear();      
        }
        // Update the stored state information
        pLastTechnique = pTechnique;
      }
      // Naturally, we have to append the primitive to our collection (otherwise it won't be collected =) ).
      s_RenderGeoInstanceCollection.AppendEntry(pGI);
    }

    // If there's still something left in the collection, render it as well.
    if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
    {
      if (pLastTechnique && pLastTechnique->GetShaderCount()>0)
      {
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
        if (bBasePass)
          s_RenderGeoInstanceCollection.TagEntries();
      } 
      s_RenderGeoInstanceCollection.Clear();
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}
Пример #10
0
void VPostProcessFXAA::InitializePostProcessor()
{
  if (m_bIsInitialized || !m_bActive)
    return;

  SetupContext();

  // Load glow shader library
  BOOL bResult = Vision::Shaders.LoadShaderLibrary("\\Shaders\\FXAA.ShaderLib", SHADERLIBFLAG_HIDDEN) != NULL;
  VASSERT(bResult); // file not found?

  GetTargetContext()->GetSize(m_iWidth, m_iHeight);

  m_spMask = new VisScreenMask_cl();
  m_spMask->SetPos(0,0);
  m_spMask->SetTargetSize((float)m_iWidth,(float)m_iHeight);
  m_spMask->SetTextureRange(0.0f, 0.0f, (float)m_iWidth, (float)m_iHeight);
#ifdef _VR_DX9
  m_spMask->SetUseOpenGLTexelShift(TRUE);
#else
  m_spMask->SetUseOpenGLTexelShift(FALSE);
#endif
  //m_spMask->SetUseOpenGLTexelShift(FALSE);

  m_spMask->SetTransparency(VIS_TRANSP_NONE);
  m_spMask->SetVisible(FALSE);
  m_spMask->SetDepthWrite(FALSE);
  m_spMask->SetWrapping(FALSE, FALSE);
  m_spMask->SetVisibleBitmask(0); // this mask is rendered manually via a collection

  // no wireframe for this mask
  VSimpleRenderState_t s = m_spMask->GetRenderState();
  s.SetFlag(RENDERSTATEFLAG_NOWIREFRAME);
  m_spMask->SetRenderState(s);

  VTechniqueConfig vc;

  VString tags;
  tags.Format("FXAA_PRESET=%d", (int)Quality);
  vc.SetInclusionTags(tags);

  VCompiledTechnique *pTech = Vision::Shaders.CreateTechnique("FXAA", NULL, &vc, EFFECTFLAGS_FORCEUNIQUE);
  VASSERT(pTech!=NULL && "Could not create technique for FXAA postprocessor!");
  m_spMask->SetTechnique(pTech);
  m_spMask->SetTransparency(VIS_TRANSP_NONE);

  VShaderConstantBuffer *pPS = pTech->GetShader(0)->GetConstantBuffer(VSS_PixelShader);
  m_iRegScreenSize = pPS->GetRegisterByName("rcpFrame");
  
  // make frame copy only if this is not the last PP
  bool bFrameCopy = !IsLastComponent();
  if (bFrameCopy && GetTargetContext()->GetRenderTarget() == m_spSourceTextures[0])
  {
    m_spFrameCopyTexture = ScratchTexturePool_cl::GlobalManager().GetScratchTexture(m_iWidth, m_iHeight, m_spSourceTextures[0]->GetTextureFormat(), 0);
    m_spMask->SetTextureObject(m_spFrameCopyTexture);
  }
  else
  {
    m_spFrameCopyTexture = NULL;
    m_spMask->SetTextureObject(m_spSourceTextures[0]);
  }

  m_bIsInitialized = true;
}