void VTerrainDecorationEntityModel::RenderBatchIR(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount, RenderMode_e eRenderMode) { // IR Rendering VTerrainDecorationModelManager* pManager = (VTerrainDecorationModelManager *)GetParentManager(); VShaderEffectLib* pEffectLib = pManager->GetInfraredShaderLib(); if (iCount > 0 && pManager->m_iInstancingBatchCount > 0 && pEffectLib != NULL) { int iMaxInstanceCount, iInstanceStreamMask; VisSurface_cl* pSurface = m_spMesh->GetSurface(0); if (m_spInstancingTechIRPrePass == NULL) { // lazy IR shader init RecreateIRShaders(pSurface, pEffectLib); } if (m_spInstancingTechIRPrePass == NULL || m_spInstancingTechIRMainPass == NULL) return; const int iPrimitiveCount = m_spModelMesh->GetCurrentPrimitiveCount(); const int iVertexCount = m_spModelMesh->GetVertexCount(); const VisMeshBuffer_cl::MB_PrimitiveType_e ePrimType = m_spModelMesh->GetPrimitiveType(); bool bPrePass = (eRenderMode == RENDER_MODE_IR_PREPASS); VCompiledShaderPass* pShader = bPrePass? m_spInstancingTechIRPrePass->GetShader(0) : m_spInstancingTechIRMainPass->GetShader(0); const int iStreamMask = m_spModelMesh->GetStreamMask() & (pShader->GetStreamMask() | VERTEX_STREAM_INDEXBUFFER); VisMeshBuffer_cl* pInstanceMesh = pManager->GetInstanceBuffer(iMaxInstanceCount, iInstanceStreamMask); iInstanceStreamMask &= pShader->GetStreamMask(); // perform the rendering Vision::RenderLoopHelper.BeginMeshRendering(); Vision::RenderLoopHelper.BindDefaultStateGroups(pSurface, pShader); if (!bPrePass || pSurface->GetTransparencyType() != VIS_TRANSP_NONE) Vision::RenderLoopHelper.BindMeshTexture(pSurface->GetBaseTextureObject(), 0, NULL); while (iCount > 0) { int iRenderCount = hkvMath::Min(iCount, iMaxInstanceCount); // fill the instance buffer: { VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP); VModelInstanceData_t* pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE, 0, iRenderCount); for (int i = 0; i < iRenderCount; i++, pInstList++, pDest++) pDest->Set(*pInstList[0]); pInstanceMesh->UnLockVertices(); } iCount -= iRenderCount; RENDER_INSTANCES(iRenderCount, iStreamMask); } Vision::RenderLoopHelper.EndMeshRendering(); } }
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); }
// 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::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 }
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()); }