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); }
// 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()); }
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); } } } }
// 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()); }
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; }