// // filename: ShaderLib.cpp // description: Class controlling loading of shaders // written by: Adam Fowler // #include "shaders/ShaderLib.h" // Rage headers #include "bank/bank.h" #include "bank/bkmgr.h" #include "grmodel/shader.h" #include "grmodel/shaderfx.h" #include "grcore/device.h" #include "grcore/effect.h" #include "grcore/im.h" #include "streaming/streaming.h" #include "system/xtl.h" // Framework headers #include "fwsys/gameskeleton.h" #include "fwdrawlist/drawlistmgr.h" // Game headers #include "debug/debug.h" #include "debug/Rendering/DebugDeferred.h" #include "game/weather.h" #include "peds/ped.h" #include "Renderer/Renderer.h" #include "renderer/DrawLists/drawListMgr.h" #include "renderer/Deferred/DeferredLighting.h" #include "renderer/PostProcessFX.h" #include "renderer/RenderPhases/RenderPhaseCascadeShadows.h" // for IsEnabled #include "renderer/RenderPhases/RenderPhaseEntitySelect.h" // for ENTITYSELECT_ENABLED_BUILD #include "shader_source/vehicles/vehicle_common_values.h" // For GPU_DAMAGE_WRITE_ENABLED #include "renderer/Deferred/GBuffer.h" #include "renderer/rendertargets.h" #include "renderer/SpuPm/SpuPmMgr.h" #include "scene/world/GameWorld.h" #include "timecycle/TimeCycle.h" #include "vfx/misc/LinearPiecewiseFog.h" #if RSG_ORBIS #include "gnmx/helpers.h" #endif //OPTIMISATIONS_OFF() // PSN: when enabled, AlphaRefs constants must be enabled as variables in common.fxh #define USE_ALPHAREF (__XENON || __PPU || __D3D11 || RSG_ORBIS) // See also USE_SSTAA define for Durango in shader code, common.fxh, l. 331 #define USE_TRANSPARENCYAA (1) // Generated via: for (int i=0; i<256; i++) printf("%d.0f/255,%s",i,(i&7)!=7?"":"\n\t"); float CShaderLib::ms_divideBy255[256] = { 0.0f/255,1.0f/255,2.0f/255,3.0f/255,4.0f/255,5.0f/255,6.0f/255,7.0f/255, 8.0f/255,9.0f/255,10.0f/255,11.0f/255,12.0f/255,13.0f/255,14.0f/255,15.0f/255, 16.0f/255,17.0f/255,18.0f/255,19.0f/255,20.0f/255,21.0f/255,22.0f/255,23.0f/255, 24.0f/255,25.0f/255,26.0f/255,27.0f/255,28.0f/255,29.0f/255,30.0f/255,31.0f/255, 32.0f/255,33.0f/255,34.0f/255,35.0f/255,36.0f/255,37.0f/255,38.0f/255,39.0f/255, 40.0f/255,41.0f/255,42.0f/255,43.0f/255,44.0f/255,45.0f/255,46.0f/255,47.0f/255, 48.0f/255,49.0f/255,50.0f/255,51.0f/255,52.0f/255,53.0f/255,54.0f/255,55.0f/255, 56.0f/255,57.0f/255,58.0f/255,59.0f/255,60.0f/255,61.0f/255,62.0f/255,63.0f/255, 64.0f/255,65.0f/255,66.0f/255,67.0f/255,68.0f/255,69.0f/255,70.0f/255,71.0f/255, 72.0f/255,73.0f/255,74.0f/255,75.0f/255,76.0f/255,77.0f/255,78.0f/255,79.0f/255, 80.0f/255,81.0f/255,82.0f/255,83.0f/255,84.0f/255,85.0f/255,86.0f/255,87.0f/255, 88.0f/255,89.0f/255,90.0f/255,91.0f/255,92.0f/255,93.0f/255,94.0f/255,95.0f/255, 96.0f/255,97.0f/255,98.0f/255,99.0f/255,100.0f/255,101.0f/255,102.0f/255,103.0f/255, 104.0f/255,105.0f/255,106.0f/255,107.0f/255,108.0f/255,109.0f/255,110.0f/255,111.0f/255, 112.0f/255,113.0f/255,114.0f/255,115.0f/255,116.0f/255,117.0f/255,118.0f/255,119.0f/255, 120.0f/255,121.0f/255,122.0f/255,123.0f/255,124.0f/255,125.0f/255,126.0f/255,127.0f/255, 128.0f/255,129.0f/255,130.0f/255,131.0f/255,132.0f/255,133.0f/255,134.0f/255,135.0f/255, 136.0f/255,137.0f/255,138.0f/255,139.0f/255,140.0f/255,141.0f/255,142.0f/255,143.0f/255, 144.0f/255,145.0f/255,146.0f/255,147.0f/255,148.0f/255,149.0f/255,150.0f/255,151.0f/255, 152.0f/255,153.0f/255,154.0f/255,155.0f/255,156.0f/255,157.0f/255,158.0f/255,159.0f/255, 160.0f/255,161.0f/255,162.0f/255,163.0f/255,164.0f/255,165.0f/255,166.0f/255,167.0f/255, 168.0f/255,169.0f/255,170.0f/255,171.0f/255,172.0f/255,173.0f/255,174.0f/255,175.0f/255, 176.0f/255,177.0f/255,178.0f/255,179.0f/255,180.0f/255,181.0f/255,182.0f/255,183.0f/255, 184.0f/255,185.0f/255,186.0f/255,187.0f/255,188.0f/255,189.0f/255,190.0f/255,191.0f/255, 192.0f/255,193.0f/255,194.0f/255,195.0f/255,196.0f/255,197.0f/255,198.0f/255,199.0f/255, 200.0f/255,201.0f/255,202.0f/255,203.0f/255,204.0f/255,205.0f/255,206.0f/255,207.0f/255, 208.0f/255,209.0f/255,210.0f/255,211.0f/255,212.0f/255,213.0f/255,214.0f/255,215.0f/255, 216.0f/255,217.0f/255,218.0f/255,219.0f/255,220.0f/255,221.0f/255,222.0f/255,223.0f/255, 224.0f/255,225.0f/255,226.0f/255,227.0f/255,228.0f/255,229.0f/255,230.0f/255,231.0f/255, 232.0f/255,233.0f/255,234.0f/255,235.0f/255,236.0f/255,237.0f/255,238.0f/255,239.0f/255, 240.0f/255,241.0f/255,242.0f/255,243.0f/255,244.0f/255,245.0f/255,246.0f/255,247.0f/255, 248.0f/255,249.0f/255,250.0f/255,251.0f/255,252.0f/255,253.0f/255,254.0f/255,255.0f/255 }; // // // // grcEffectGlobalVar CShaderLib::ms_globalScalarsID; //x=globalAlpha y=HDRMultiplier z=AmbientScale grcEffectGlobalVar CShaderLib::ms_globalScalars2ID; grcEffectGlobalVar CShaderLib::ms_globalScalars3ID; // scale, invscale, normalScaler, naturalAmbientPush #if !RSG_ORBIS && !RSG_DURANGO grcEffectGlobalVar CShaderLib::ms_globalFadeID; u16 CShaderLib::ms_FadeMask16; #endif // !RSG_ORBIS && !RSG_DURANGO grcDepthStencilStateHandle CShaderLib::ms_gDefaultState_DS = grcStateBlock::DSS_Invalid; grcDepthStencilStateHandle CShaderLib::ms_gNoDepthWrite_DS = grcStateBlock::DSS_Invalid; grcDepthStencilStateHandle CShaderLib::ms_gNoDepthRead_DS = grcStateBlock::DSS_Invalid; grcRasterizerStateHandle CShaderLib::ms_frontFaceCulling_RS = grcStateBlock::RS_Invalid; grcRasterizerStateHandle CShaderLib::ms_disableFaceCulling_RS = grcStateBlock::RS_Invalid; grcDepthStencilStateHandle CShaderLib::DSS_Default_Invert; grcDepthStencilStateHandle CShaderLib::DSS_LessEqual_Invert; grcDepthStencilStateHandle CShaderLib::DSS_TestOnly_Invert; grcDepthStencilStateHandle CShaderLib::DSS_TestOnly_LessEqual_Invert; grcBlendStateHandle CShaderLib::BS_NoColorWrite; static grcBlendStateHandle previousBS[NUMBER_OF_RENDER_THREADS]; #if __DEV bool CShaderLib::ms_gReflectTweakEnabled = false; float CShaderLib::ms_gReflectTweak = 0.1f; bool CShaderLib::ms_gDisableShaderVarCaching = false; #endif // __DEV strLocalIndex CShaderLib::ms_txdId = strLocalIndex(-1); #if SHADERLIB_USE_MSAA_PARAMS static grcEffectGlobalVar globalTargetAAParamsID; #endif // SHADERLIB_USE_MSAA_PARAMS static grcEffectGlobalVar globalAOEffectScaleID; static grcEffectGlobalVar globalScreenSizeID; //screensize static grcEffectGlobalVar gFogParamsID; static grcEffectGlobalVar gFogColorID; static grcEffectGlobalVar gFogColorEID; static grcEffectGlobalVar gFogColorNID; #if LINEAR_PIECEWISE_FOG static grcEffectGlobalVar gLinearPiecewiseFogParamsID; #endif // LINEAR_PIECEWISE_FOG static grcEffectGlobalVar gReflectionTweaksID; static grcEffectGlobalVar gDynamicBakesAndWetnessID; static grcEffectGlobalVar globalPlayerLFootPosID; static grcEffectGlobalVar globalPlayerRFootPosID; #if RSG_PC static grcEffectGlobalVar gReticuleDistID; static grcEffectGlobalVar globalTreesUseDiscardId; static grcEffectGlobalVar globalShaderQualityID; static grcEffectGlobalVar gStereoParamsID; static grcEffectGlobalVar gStereoParams1ID; #endif static grcEffectGlobalVar globalUseFogRayId; static grcEffectGlobalVar gFogRayTextureID; static grcEffectGlobalVar gFogRayIntensityID; #if DEVICE_MSAA static grcEffectGlobalVar globalTransparencyAASamples; #endif // DEVICE_MSAA static grcEffectGlobalVar globalAlphaTestRef; #if USE_ALPHAREF static grcEffectGlobalVar alphaRefVec0ID = (grcEffectGlobalVar)0; static grcEffectGlobalVar alphaRefVec1ID = (grcEffectGlobalVar)0; static s32 global_alphaRef = 90; #if HACK_RDR3 static s32 ped_alphaRef = 0; #else static s32 ped_alphaRef = 128; #endif static s32 ped_longhair_alphaRef = 128; static s32 foliage_alphaRef = 90; // valve distance-map alpha will use middle value of 0.35 to compensate static s32 foliageImposter_alphaRef = 88; static s32 billboard_alphaRef = 148; static s32 shadowBillboard_alphaRef = 88; static s32 grass_alphaRef = 32; #endif // USE_ALPHAREF... static bool useTransparencyAA = USE_TRANSPARENCYAA; static u32 maxStipplingAA = 2; ThreadVector4 CShaderLib::ms_gCurrentScalarGlobals[NUMBER_OF_RENDER_THREADS] = {{1.0f, 1.0f, 1.0f, 1.0f}}; u32 CShaderLib::ms_giCurrentScalarGlobals[NUMBER_OF_RENDER_THREADS][4] = {{255, 255, 255, 255}}; //setting to same values as ms_gCurrentScalarGlobals ThreadVector4 CShaderLib::ms_gCurrentScalarGlobals2[NUMBER_OF_RENDER_THREADS] = {{1.0f, 1.0f, 1.0f, 1.0f}}; ThreadVector4 CShaderLib::ms_gCurrentScalarGlobals3[NUMBER_OF_RENDER_THREADS] = {{16.0f,1.0f/16.0f,0.0f,0.0f}}; ThreadVector4 CShaderLib::ms_gCurrentDirectionalAmbient[NUMBER_OF_RENDER_THREADS] = {{ 0.0f, 0.0f, 0.0f, 0.0f }}; bool CShaderLib::ms_facingBackwards[NUMBER_OF_RENDER_THREADS] = {false}; bool CShaderLib::ms_fogDepthFxEnabled[NUMBER_OF_RENDER_THREADS] = {true}; float CShaderLib::ms_overridesEmissiveScale = 0.0f; float CShaderLib::ms_overridesEmissiveMult = 0.0f; float CShaderLib::ms_overridesArtIntAmbDown = 0.0f; float CShaderLib::ms_overridesArtIntAmbBase = 0.0f; float CShaderLib::ms_overridesArtExtAmbDown = 0.0f; float CShaderLib::ms_overridesArtExtAmbBase = 0.0f; float CShaderLib::ms_overridesArtAmbScale = 0.0f; // Other things are packed into the "unused" W component of these vectors CShaderLib::CFogParams CShaderLib::ms_globalFogParams[NUMBER_OF_RENDER_THREADS]; #if LINEAR_PIECEWISE_FOG ThreadVector4 CShaderLib::ms_linearPiecewiseFog[NUMBER_OF_RENDER_THREADS][LINEAR_PIECEWISE_FOG_NUM_SHADER_VARIABLES]; #endif // LINEAR_PIECEWISE_FOG u32 CShaderLib::ms_gDeferredMaterial[NUMBER_OF_RENDER_THREADS] = { DEFERRED_MATERIAL_DEFAULT }; u32 CShaderLib::ms_gDeferredMaterialORMask[NUMBER_OF_RENDER_THREADS] = { 0x0 }; ThreadVector4 CShaderLib::ms_gCurrentScreenSize[NUMBER_OF_RENDER_THREADS] = { {1.0f, 1.0f, 1.0f, 1.0f} }; ThreadVector4 CShaderLib::ms_gCurrentAOEffectScale[NUMBER_OF_RENDER_THREADS] = {{1.0f, 1.0f, 1.0f, 1.0f}}; bool CShaderLib::ms_gDeferredWetBlend[NUMBER_OF_RENDER_THREADS] = { false }; ThreadVector4 CShaderLib::ms_gReflectionTweaks = {1.0f, 1.0f, 1.0f, 0.0f}; bool CShaderLib::ms_gMotionBlurMask = true; float CShaderLib::ms_alphaTestRef[NUMBER_OF_RENDER_THREADS] = {NUMBER_OF_RENDER_THREADS_INITIALIZER_LIST(0.f)}; Vector4 CShaderLib::ms_PlayerLFootPos[2]; Vector4 CShaderLib::ms_PlayerRFootPos[2]; ThreadVector4 CShaderLib::ms_gCurrentPlayerLFootPos[NUMBER_OF_RENDER_THREADS] = { {0,0,0,0} }; ThreadVector4 CShaderLib::ms_gCurrentPlayerRFootPos[NUMBER_OF_RENDER_THREADS] = { {0,0,0,0} };; #if RSG_PC float CShaderLib::ms_ShaderQuality[2] = {2.0f,2.0f}; #endif static grcMaterialLibrary *s_MtlLib; #if __PS3 namespace rage { extern u32 TotalUcode, TotalUcodeWithoutCache, TotalUcodeInDebugHeap; } #endif namespace rage { extern u32 TotalReferenceInstanceData; } // We do this to minimize the amount of time spent between starting the // game and the first draw call. loading the remaining shaders is left // until the intro movie is active void CShaderLib::LoadInitialShaders() { grcEffect *effect = NULL; #if __FINAL ASSET.PushFolder("update2:/common/shaders"); #else ASSET.PushFolder("common:/shaders"); #endif effect = grcEffect::Create("im"); Assert(effect); effect = grcEffect::Create("rage_bink"); Assert(effect); effect = grcEffect::Create("scaleform_shaders"); Assert(effect); effect = grcEffect::Create("rage_fastmipmap"); Assert(effect); if( GRCDEVICE.GetMSAA()>1 ) { effect = grcEffect::Create("imMS"); Assert(effect); } ASSET.PopFolder(); } void CShaderLib::LoadAllShaders() { grmShaderFactory::GetInstance().PreloadShaders("common:/shaders"); if( GRCDEVICE.GetMSAA()>1 ) { grmShaderFactory::GetInstance().PreloadShaders("common:/shaders","preloadMS"); } #if __ASSERT grcEffect::SetAllowShaderLoading(false); #endif } void CShaderLib::PreInit() { ms_globalScalarsID = grcEffect::LookupGlobalVar("globalScalars"); grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)ms_gCurrentScalarGlobals[g_RenderThreadIndex]); sysMemUseMemoryBucket b(MEMBUCKET_RENDER); size_t used = sysMemGetMemoryUsed(MEMBUCKET_RENDER); // We need to register all techniques before any shaders get loaded: #if __XENON || __D3D11 || RSG_ORBIS // special-case "ld" being used for local light shadows on 360 .. { grmShaderFx::RegisterTechniqueGroup("ld"); grmShaderFx::RegisterTechniqueGroup("shadtexture_ld"); } #endif // __XENON || __D3D11 || RSG_ORBIS // CRenderPhaseCascadeShadows grmShaderFx::RegisterTechniqueGroup("wdcascade"); #if __PPU && USE_EDGE grmShaderFx::RegisterTechniqueGroup("wdcascadeedge"); grmShaderFx::RegisterTechniqueGroup("shadtexture_wdcascadeedge"); #else // __PPU && USE_EDGE grmShaderFx::RegisterTechniqueGroup("shadtexture_wdcascade"); #endif // CParaboloidShadow #if __PPU grmShaderFx::RegisterTechniqueGroup("ldpoint"); // xenon uses "ld" grmShaderFx::RegisterTechniqueGroup("shadtexture_ldpoint"); #if USE_EDGE grmShaderFx::RegisterTechniqueGroup("ldedgepoint"); grmShaderFx::RegisterTechniqueGroup("shadtexture_ldedgepoint"); #endif // USE_EDGE #endif // __PPU // CRenderPhaseWaterReflection grmShaderFx::RegisterTechniqueGroup("waterreflection"); grmShaderFx::RegisterTechniqueGroup("waterreflectionalphaclip"); grmShaderFx::RegisterTechniqueGroup("waterreflectionalphacliptint"); // CRenderPhaseReflection grmShaderFx::RegisterTechniqueGroup("cube"); #if GS_INSTANCED_CUBEMAP grmShaderFx::RegisterTechniqueGroup("cubeinst"); #endif //Generic grmShaderFx::RegisterTechniqueGroup("alt0"); //UnderwaterLowTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt1"); //UnderwaterHighTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt2"); //UnderwaterEnvLowTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt3"); //UnderwaterEnvHighTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt4"); //EnvTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt5"); //SinglePassTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt6"); //SinglePassEnvTechniqueGroup grmShaderFx::RegisterTechniqueGroup("alt7"); //FoamTechniqueGrou grmShaderFx::RegisterTechniqueGroup("alt8"); //WaterHeightTechniqueGroup // CLights grmShaderFx::RegisterTechniqueGroup("lightweight0"); grmShaderFx::RegisterTechniqueGroup("lightweight4"); grmShaderFx::RegisterTechniqueGroup("lightweight8"); grmShaderFx::RegisterTechniqueGroup("lightweight0CutOut"); grmShaderFx::RegisterTechniqueGroup("lightweight4CutOut"); grmShaderFx::RegisterTechniqueGroup("lightweight8CutOut"); grmShaderFx::RegisterTechniqueGroup("lightweight0CutOutTint"); grmShaderFx::RegisterTechniqueGroup("lightweight4CutOutTint"); grmShaderFx::RegisterTechniqueGroup("lightweight8CutOutTint"); grmShaderFx::RegisterTechniqueGroup("lightweightNoCapsule4"); grmShaderFx::RegisterTechniqueGroup("lightweightNoCapsule8"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality0"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality4"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality8"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality0CutOut"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality4CutOut"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality8CutOut"); // CTreeImposters grmShaderFx::RegisterTechniqueGroup("imposter"); grmShaderFx::RegisterTechniqueGroup("imposterdeferred"); // CMarkers #if __PPU grmShaderFx::RegisterTechniqueGroup("manualdepth"); #endif // CPedVariationMgr grmShaderFx::RegisterTechniqueGroup("deferredbs"); // DeferredLighting grmShaderFx::RegisterTechniqueGroup("deferred"); grmShaderFx::RegisterTechniqueGroup("deferredalphaclip"); grmShaderFx::RegisterTechniqueGroup("deferredsubsamplealphaclip"); grmShaderFx::RegisterTechniqueGroup("deferredalphacliptint"); grmShaderFx::RegisterTechniqueGroup("deferredsubsamplealpha"); grmShaderFx::RegisterTechniqueGroup("deferredsubsamplewritealpha"); grmShaderFx::RegisterTechniqueGroup("deferredcutscene"); grmShaderFx::RegisterTechniqueGroup("deferredsubsamplealphatint"); //Vehicle Fade Override Techniques grmShaderFx::RegisterTechniqueGroup("lightweight0WaterRefractionAlpha"); grmShaderFx::RegisterTechniqueGroup("lightweight4WaterRefractionAlpha"); grmShaderFx::RegisterTechniqueGroup("lightweight8WaterRefractionAlpha"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality0WaterRefractionAlpha"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality4WaterRefractionAlpha"); grmShaderFx::RegisterTechniqueGroup("lightweightHighQuality8WaterRefractionAlpha"); // RenderPhaseSeeThrough grmShaderFx::RegisterTechniqueGroup("seethrough"); // UI grmShaderFx::RegisterTechniqueGroup("ui"); #if ENTITYSELECT_ENABLED_BUILD // Entity Select debug technique grmShaderFx::RegisterTechniqueGroup("entityselect"); #endif // ENTITYSELECT_ENABLED_BUILD #if GPU_DAMAGE_WRITE_ENABLED // Adding new damage circles to the vehicles' damage texture when collisions occur grmShaderFx::RegisterTechniqueGroup("applydamage"); #endif // for adding clouds to the light rays grmShaderFx::RegisterTechniqueGroup("clouddepth"); #if __BANK // CRenderPhaseDebugOverlay grmShaderFx::RegisterTechniqueGroup("debugoverlay"); #endif // __BANK #if __XENON MEMORYSTATUS before, after; GlobalMemoryStatus(&before); #endif #if __ASSERT // Assert on late loaded shaders. grcEffect::SetAllowShaderLoading(true); #endif // __ASSERT LoadInitialShaders(); used = sysMemGetMemoryUsed(MEMBUCKET_RENDER) - used; Displayf("CShaderLib::PreInit - %" SIZETFMT "u bytes consumed by inital shader load",used); } // // name: FullInit // description: Initialise shader library. void CShaderLib::Init() { size_t used = sysMemGetMemoryUsed(MEMBUCKET_RENDER); CShaderLib::LoadAllShaders(); #if __ASSERT // Assert on late loaded shaders. grcEffect::SetAllowShaderLoading(false); #endif // __ASSERT used = sysMemGetMemoryUsed(MEMBUCKET_RENDER) - used; Displayf("CShaderLib::Init - %" SIZETFMT "u bytes consumed by full shader load",used); #if __PS3 Displayf("CShaderLib::Init - %u bytes in cached shaders, %u if uncached, %u saved (%u in debug heap)",TotalUcode,TotalUcodeWithoutCache,TotalUcodeWithoutCache - TotalUcode,TotalUcodeInDebugHeap); #endif #if __XENON GlobalMemoryStatus(&after); Displayf("CShaderLib::Init - %u bytes of physical memory consumed by shaders",before.dwAvailPhys - after.dwAvailPhys); #endif Displayf("CShaderLib::Init - %u bytes consumed by reference instance data",TotalReferenceInstanceData); s_MtlLib = grcMaterialLibrary::Preload("common:/shaders/db/"); if (Verifyf(s_MtlLib,"Material library didn't load, you're probably in a world of suck.")) grcMaterialLibrary::SetCurrent(s_MtlLib); #if NUMBER_OF_RENDER_THREADS > 1 Assert(g_RenderThreadIndex==0); // make sure we're running on mainRT Assert(g_IsSubRenderThread==false); // initialise global vars for render subthreads: for(int i=1; i= CSettings::High); globalTransparencyAASamples = grcEffect::LookupGlobalVar("gTransparencyAASamples", shaderQuality != CSettings::Low); grcEffect::SetGlobalVar(globalTransparencyAASamples, useTransparencyAA ? (float)GRCDEVICE.GetMSAA() : 0.0f); #endif // USE_TRANSPARENCYAA #endif // DEVICE_MSAA globalUseFogRayId = grcEffect::LookupGlobalVar("gUseFogRay", RSG_PC ? false : true); gFogParamsID = grcEffect::LookupGlobalVar("globalFogParams"); grcEffect::SetGlobalVar(gFogParamsID, (Vec4V*)&ms_globalFogParams[g_RenderThreadIndex], sizeof(CFogParams)/sizeof(Vec4V)); gFogColorID = grcEffect::LookupGlobalVar("globalFogColor"); grcEffect::SetGlobalVar(gFogColorID, Vec4V(V_ONE)); gFogColorEID = grcEffect::LookupGlobalVar("globalFogColorE"); grcEffect::SetGlobalVar(gFogColorEID, Vec4V(V_ONE)); gFogColorNID = grcEffect::LookupGlobalVar("globalFogColorN"); grcEffect::SetGlobalVar(gFogColorNID, Vec4V(V_ONE)); #if LINEAR_PIECEWISE_FOG gLinearPiecewiseFogParamsID = grcEffect::LookupGlobalVar("linearPiecewiseFogParams"); LinearPiecewiseFog_ShaderParams linearParams; // Default to off. SetLinearPiecewiseFogParams(linearParams); grcEffect::SetGlobalVar(gLinearPiecewiseFogParamsID, (Vec4V*)ms_linearPiecewiseFog[g_RenderThreadIndex], LINEAR_PIECEWISE_FOG_NUM_SHADER_VARIABLES); #endif // LINEAR_PIECEWISE_FOG gReflectionTweaksID = grcEffect::LookupGlobalVar("gReflectionTweaks"); grcEffect::SetGlobalVar(gReflectionTweaksID, (Vec4V&)(ms_gReflectionTweaks)); gDynamicBakesAndWetnessID = grcEffect::LookupGlobalVar("gDynamicBakesAndWetness"); grcEffect::SetGlobalVar(gDynamicBakesAndWetnessID, Vec4V(V_ONE)); #if __XENON GRCDEVICE.SetColorExpBiasNow(0); #endif #if RSG_PC gReticuleDistID = grcEffect::LookupGlobalVar("StereoReticuleDistTexture", (GRCDEVICE.CanUseStereo() && GRCDEVICE.IsStereoEnabled()) ? true : false); globalShaderQualityID = grcEffect::LookupGlobalVar("GlobalShaderQuality", true); grcEffect::SetGlobalVar(globalShaderQualityID, ms_ShaderQuality[0]); gStereoParamsID = grcEffect::LookupGlobalVar("gStereoParams", false); gStereoParams1ID = grcEffect::LookupGlobalVar("gStereoParams1", false); #endif gFogRayTextureID = grcEffect::LookupGlobalVar("FogRayTex", RSG_PC ? false : true); gFogRayIntensityID = grcEffect::LookupGlobalVar("gGlobalFogIntensity"); globalAlphaTestRef = grcEffect::LookupGlobalVar("alphaTestRef"); #if USE_ALPHAREF alphaRefVec0ID = grcEffect::LookupGlobalVar("alphaRefVec0"); alphaRefVec1ID = grcEffect::LookupGlobalVar("alphaRefVec1",false); // This one only exists when certain grass code path are enabled. CShaderLib::SetAlphaRefConsts(); #endif // USE_ALPHAREF... #if !RSG_ORBIS && !RSG_DURANGO ms_globalFadeID = grcEffect::LookupGlobalVar("globalFade"); #endif // !RSG_ORBIS globalPlayerLFootPosID = grcEffect::LookupGlobalVar("gPlayerLFootPos"); grcEffect::SetGlobalVar(globalPlayerLFootPosID, (Vec4V&)(ms_gCurrentPlayerLFootPos[g_RenderThreadIndex])); globalPlayerRFootPosID = grcEffect::LookupGlobalVar("gPlayerRFootPos"); grcEffect::SetGlobalVar(globalPlayerRFootPosID, (Vec4V&)(ms_gCurrentPlayerRFootPos[g_RenderThreadIndex])); // initialise state blocks // default depth/stencil block grcDepthStencilStateDesc defaultStateDS; defaultStateDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL); defaultStateDS.StencilEnable = 1; defaultStateDS.FrontFace.StencilFailOp = grcRSV::STENCILOP_KEEP; defaultStateDS.FrontFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP; defaultStateDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE; defaultStateDS.FrontFace.StencilFunc = grcRSV::CMP_ALWAYS; defaultStateDS.BackFace.StencilFailOp = grcRSV::STENCILOP_KEEP; defaultStateDS.BackFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP; defaultStateDS.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE; defaultStateDS.BackFace.StencilFunc = grcRSV::CMP_ALWAYS; ms_gDefaultState_DS = grcStateBlock::CreateDepthStencilState(defaultStateDS); // write depth disabled block grcDepthStencilStateDesc noDepthWriteStateDS; noDepthWriteStateDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL); noDepthWriteStateDS.DepthWriteMask = 0; noDepthWriteStateDS.StencilEnable = 1; noDepthWriteStateDS.FrontFace.StencilFailOp = grcRSV::STENCILOP_KEEP; noDepthWriteStateDS.FrontFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP; noDepthWriteStateDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE; noDepthWriteStateDS.FrontFace.StencilFunc = grcRSV::CMP_ALWAYS; noDepthWriteStateDS.BackFace.StencilFailOp = grcRSV::STENCILOP_KEEP; noDepthWriteStateDS.BackFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP; noDepthWriteStateDS.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE; noDepthWriteStateDS.BackFace.StencilFunc = grcRSV::CMP_ALWAYS; ms_gNoDepthWrite_DS = grcStateBlock::CreateDepthStencilState(noDepthWriteStateDS); // write read disabled block grcDepthStencilStateDesc noDepthReadStateDS; noDepthReadStateDS.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_ALWAYS); noDepthReadStateDS.StencilEnable = 1; noDepthReadStateDS.FrontFace.StencilFailOp = grcRSV::STENCILOP_KEEP; noDepthReadStateDS.FrontFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP; noDepthReadStateDS.FrontFace.StencilPassOp = grcRSV::STENCILOP_REPLACE; noDepthReadStateDS.FrontFace.StencilFunc = grcRSV::CMP_ALWAYS; noDepthReadStateDS.BackFace.StencilFailOp = grcRSV::STENCILOP_KEEP; noDepthReadStateDS.BackFace.StencilDepthFailOp = grcRSV::STENCILOP_KEEP; noDepthReadStateDS.BackFace.StencilPassOp = grcRSV::STENCILOP_REPLACE; noDepthReadStateDS.BackFace.StencilFunc = grcRSV::CMP_ALWAYS; ms_gNoDepthRead_DS = grcStateBlock::CreateDepthStencilState(noDepthReadStateDS); grcRasterizerStateDesc faceCullingRS; faceCullingRS.CullMode=grcRSV::CULL_FRONT; ms_frontFaceCulling_RS = grcStateBlock::CreateRasterizerState(faceCullingRS); faceCullingRS.CullMode=grcRSV::CULL_NONE; ms_disableFaceCulling_RS = grcStateBlock::CreateRasterizerState(faceCullingRS); grcDepthStencilStateDesc DefaultDepthStencilInvertStateBlockDesc; DefaultDepthStencilInvertStateBlockDesc.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESS); DSS_Default_Invert = grcStateBlock::CreateDepthStencilState(DefaultDepthStencilInvertStateBlockDesc); DefaultDepthStencilInvertStateBlockDesc.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESSEQUAL); DSS_LessEqual_Invert = grcStateBlock::CreateDepthStencilState(DefaultDepthStencilInvertStateBlockDesc); DefaultDepthStencilInvertStateBlockDesc.DepthWriteMask = false; DSS_TestOnly_LessEqual_Invert = grcStateBlock::CreateDepthStencilState(DefaultDepthStencilInvertStateBlockDesc); DefaultDepthStencilInvertStateBlockDesc.DepthFunc = rage::FixupDepthDirection(grcRSV::CMP_LESS); DSS_TestOnly_Invert = grcStateBlock::CreateDepthStencilState(DefaultDepthStencilInvertStateBlockDesc); grcBlendStateDesc noColorWrite; noColorWrite.IndependentBlendEnable = true; noColorWrite.BlendRTDesc[0].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_NONE; noColorWrite.BlendRTDesc[1].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_NONE; noColorWrite.BlendRTDesc[2].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_NONE; noColorWrite.BlendRTDesc[3].RenderTargetWriteMask = grcRSV::COLORWRITEENABLE_NONE; BS_NoColorWrite = grcStateBlock::CreateBlendState(noColorWrite); }// end of CShaderLib::Init()... // // name: Shutdown // description: Shutdown shader library. void CShaderLib::Shutdown() { if (s_MtlLib) { grcMaterialLibrary::SetCurrent(NULL); s_MtlLib->Release(); s_MtlLib = NULL; } } void CShaderLib::InitTxd(unsigned initmode) { if(initmode == INIT_CORE) { ms_txdId = g_TxdStore.FindSlot(strStreamingObjectName("platform:/textures/graphics",0xA306598)); Assert(ms_txdId != -1); CStreaming::LoadObject(ms_txdId, g_TxdStore.GetStreamingModuleId()); g_TxdStore.AddRef(ms_txdId, REF_OTHER); } } void CShaderLib::ShutdownTxd(unsigned shutdownmode) { if(shutdownmode == SHUTDOWN_CORE) { g_TxdStore.RemoveRef(ms_txdId, REF_OTHER); ms_txdId = -1; } } // // name: InitWidgets // description: Creates widgets for shader library #if __BANK static bkBank* ms_pShadersBank=NULL; static bkButton* ms_pAddShadersWidgetsBtn=NULL; static void AddShaderDbWidgetsOnDemandCB() { if(ms_pShadersBank) { // remove old button: if(ms_pAddShadersWidgetsBtn) { ms_pShadersBank->Remove( *((bkWidget*)ms_pAddShadersWidgetsBtn) ); ms_pAddShadersWidgetsBtn = NULL; } // add shaders db buttons: if (s_MtlLib) s_MtlLib->AddWidgets(*ms_pShadersBank); } } void CShaderLib::InitWidgets(Static0 BANK_ONLY(shaderReloadCB)) { // add debug widgets bkBank& bank = BANKMGR.CreateBank("Shader database"); ms_pShadersBank = &bank; #if __DEV bank.AddToggle("Disable Shader Var Caching", &ms_gDisableShaderVarCaching); #endif // __DEV bank.PushGroup("Shader Reload", false); bank.AddButton("Reload All Shaders", (CFA(shaderReloadCB))); bank.PopGroup(); #if USE_ALPHAREF bank.PushGroup("Alpha Refs", true); bank.AddSlider("global_alphaRef", &global_alphaRef, 0, 255, 1); bank.AddSlider("ped_alphaRef", &ped_alphaRef, 0, 255, 1); bank.AddSlider("ped_longhair_alphaRef", &ped_longhair_alphaRef, 0, 255, 1); bank.AddSlider("foliage/trees_alphaRef", &foliage_alphaRef, 0, 255, 1); bank.AddSlider("foliageImposter_alphaRef", &foliageImposter_alphaRef, 0, 255, 1); bank.AddSlider("billboard_alphaRef", &billboard_alphaRef, 0, 255, 1); bank.AddSlider("shadowBillboard_alphaRef", &shadowBillboard_alphaRef, 0, 255, 1); bank.AddSlider("grass_alphaRef", &grass_alphaRef, 0, 255, 1); bank.PopGroup(); #endif // USE_ALPHAREF.... bank.AddToggle("Use Supersample transparency anti-aliasing (best for true cutout)", &useTransparencyAA); bank.AddSlider("Maximum MSAA level that still uses stippling", &maxStipplingAA, 1, 8, 1); ms_pAddShadersWidgetsBtn = bank.AddButton("Activate Shader DB bank(s).", (CFA(AddShaderDbWidgetsOnDemandCB))); } #endif //__BANK... void CShaderLib::ResetBlendState() { grcStateBlock::SetBlendState(previousBS[g_RenderThreadIndex], grcStateBlock::ActiveBlendFactors, grcStateBlock::ActiveSampleMask); } void CShaderLib::SetGlobals(u8 natAmb, u8 artAmb, bool setAlpha, u32 alpha, bool setStipple, bool bInvertStipple, u32 stippleAlpha, bool bDontWriteDepth, bool bDontReadDepth, bool bDontWriteColor) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (bDontReadDepth) { Assertf(!bDontWriteDepth, "No Z read and no Z write not supported"); grcStateBlock::SetDepthStencilState(ms_gNoDepthRead_DS, ms_gDeferredMaterial[g_RenderThreadIndex]); // need to preserve the stencil ref } else if (bDontWriteDepth) { grcStateBlock::SetDepthStencilState(ms_gNoDepthWrite_DS, ms_gDeferredMaterial[g_RenderThreadIndex]); // need to preserve the stencil ref } if( bDontWriteColor ) { previousBS[g_RenderThreadIndex] = grcStateBlock::BS_Active; grcStateBlock::SetBlendState(BS_NoColorWrite, grcStateBlock::ActiveBlendFactors, grcStateBlock::ActiveSampleMask); } bool updateGlobals = false; if (setAlpha && !gDrawListMgr->IsExecutingDrawList(DL_RENDERPHASE_REFLECTION_MAP)) { // Set alpha if (ms_giCurrentScalarGlobals[g_RenderThreadIndex][0] != alpha DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(0, alpha, CShaderLib::DivideBy255(alpha)); updateGlobals = true; } } if( setStipple ) { Assert(!DRAWLISTMGR->IsExecutingWaterReflectionDrawList()); SetStippleAlpha(stippleAlpha, bInvertStipple); } if (ms_giCurrentScalarGlobals[g_RenderThreadIndex][1] != artAmb || ms_giCurrentScalarGlobals[g_RenderThreadIndex][2] != natAmb DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(1, artAmb, CShaderLib::DivideBy255(artAmb)); SetScalarGlobalConstant(2, natAmb, CShaderLib::DivideBy255(natAmb)); updateGlobals = true; } if (updateGlobals) { grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } u16 CShaderLib::GetStippleMask(u32 stippleAlpha, bool #if !__D3D11 bInvertStipple #endif ) { u16 aaMaskLUT = 0xff; stippleAlpha = stippleAlpha & 0xff; //Make sure we don't access out of bounds if alpha is invalid! #if !__D3D11 if( bInvertStipple ) { aaMaskLUT = ~(ms_aaMaskLut[stippleAlpha >> 3]); } else { aaMaskLUT = ms_aaMaskLut[stippleAlpha >> 3]; } #else if (!CShaderLib::UsesStippleFades()) { aaMaskLUT = ms_aaMaskLut[stippleAlpha >> 3]; } else { aaMaskLUT = ms_aaMaskFadeLut[stippleAlpha >> 3]; } #endif // __D3D11 return aaMaskLUT; } void CShaderLib::SetStippleAlpha(u32 stippleAlpha, bool bInvertStipple) { // State block path, set the current BS block with a new reference. #if RSG_ORBIS || RSG_DURANGO u64 sampleMask = ComputeSampleMask(stippleAlpha); if (bInvertStipple) sampleMask = ~sampleMask; grcStateBlock::SetBlendState(grcStateBlock::BS_Active, grcStateBlock::ActiveBlendFactors, sampleMask); #else if (!CShaderLib::UsesStippleFades()) { u64 sampleMask = ComputeSampleMask(stippleAlpha); if (bInvertStipple) sampleMask = ~sampleMask; grcStateBlock::SetBlendState(grcStateBlock::BS_Active, grcStateBlock::ActiveBlendFactors, sampleMask); # if MSAA_EDGE_PROCESS_FADING const u64 activeMask = (1<> 3]; if (bInvertStipple) fadeMask = ~fadeMask; int u32FadeMask[4] = { (fadeMask >> 0) & 0xf, (fadeMask >> 4) & 0xf, (fadeMask >> 8) & 0xf, (fadeMask >> 12) & 0xf }; Vec4V vectorFadeMask( ((float)u32FadeMask[0])/15.0f, ((float)u32FadeMask[1])/15.0f, ((float)u32FadeMask[2])/15.0f, ((float)u32FadeMask[3])/15.0f ); ms_FadeMask16 = fadeMask; grcEffect::SetGlobalVar(ms_globalFadeID,vectorFadeMask); } #endif // RSG_ORBIS || RSG_DURANGO } bool CShaderLib::UsesStippleFades() { return GRCDEVICE.GetMSAA() <= maxStipplingAA; } void CShaderLib::SetScreenDoorAlpha(bool setAlpha, u32 alpha, bool setStipple, bool bInvertStipple, u32 stippleAlpha, bool bDontWriteDepth) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (bDontWriteDepth) { grcStateBlock::SetDepthStencilState(ms_gNoDepthWrite_DS, ms_gDeferredMaterial[g_RenderThreadIndex]); // need to preserve the stencil ref } bool updateGlobals = false; if (setAlpha) { // Set alpha if (ms_giCurrentScalarGlobals[g_RenderThreadIndex][0] != alpha DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(0, alpha, CShaderLib::DivideBy255(alpha)); updateGlobals = true; } } if( setStipple ) { Assert(!DRAWLISTMGR->IsExecutingWaterReflectionDrawList()); SetStippleAlpha(stippleAlpha, bInvertStipple); } if (updateGlobals) { grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } void CShaderLib::ResetAlpha(bool resetAlpha, bool resetStipple) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); bool updateGlobals = false; if( resetAlpha ) { // Set alpha updateGlobals = ms_giCurrentScalarGlobals[g_RenderThreadIndex][0] != 255; SetScalarGlobalConstant(0, 255, 1.0f); } if( resetStipple ) { // State block path, set the current BS block with a new reference. grcStateBlock::SetBlendState(grcStateBlock::BS_Active, grcStateBlock::ActiveBlendFactors, ~0ULL); #if RSG_PC if (CShaderLib::UsesStippleFades()) { u16 fadeMask = 0xFFFF; int u32FadeMask[4] = { (fadeMask >> 0) & 0xf, (fadeMask >> 4) & 0xf, (fadeMask >> 8) & 0xf, (fadeMask >> 12) & 0xf }; Vec4V vectorFadeMask( ((float)u32FadeMask[0])/15.0f, ((float)u32FadeMask[1])/15.0f, ((float)u32FadeMask[2])/15.0f, ((float)u32FadeMask[3])/15.0f ); ms_FadeMask16 = fadeMask; grcEffect::SetGlobalVar(ms_globalFadeID,vectorFadeMask); } # if MSAA_EDGE_PROCESS_FADING else if (GBuffer::IsRenderingTo()) { grcStateBlock::SetDepthStencilState(grcStateBlock::DSS_Active, grcStateBlock::ActiveStencilRef & ~EDGE_FLAG); } # endif // MSAA_EDGE_PROCESS_FADING #endif // RSG_PC } if (updateGlobals) { grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } u64 eqaa1NSampleMask[32] = { 0x0000000000000000, // 0x0000, 0x0000000000000000, // 0x0000, 0x0000000000000001, // 0x000F, 0x0000000000000001, // 0x000F, 0x0000000000000003, // 0x000F, 0x0000000000000003, // 0x000F, 0x0000000000000005, // 0x000F, 0x0000000000000005, // 0x000F, 0x0000000000000007, // 0x000F, 0x0000000000000007, // 0x000F, 0x000000000000000F, // 0x000F, 0x000100000000000F, // 0xF00F, 0x000100000000000F, // 0xF00F, 0x000300000000000F, // 0xF00F, 0x000300000000000F, // 0xF00F, 0x000500000000000F, // 0xF00F, 0x000500000000000F, // 0xF00F, 0x000700000000000F, // 0xF00F, 0x000700000000000F, // 0xF00F, 0x000F00000000000F, // 0xF00F, 0x000F00000001000F, // 0xF0FF, 0x000F00000003000F, // 0xF0FF, 0x000F00000005000F, // 0xF0FF, 0x000F00000005000F, // 0xF0FF, 0x000F00000007000F, // 0xF0FF, 0x000F0000000F000F, // 0xF0FF, 0xFFFFFFFFFFFFFFFF, // 0xFFFF, // Pushing full on FFFFFF's so that the hardware gets a chance to not disable any early Z optimisations. 0xFFFFFFFFFFFFFFFF, // 0xFFFF, 0xFFFFFFFFFFFFFFFF, // 0xFFFF, 0xFFFFFFFFFFFFFFFF, // 0xFFFF, 0xFFFFFFFFFFFFFFFF, // 0xFFFF, 0xFFFFFFFFFFFFFFFF, // 0xFFFF, }; // This is just used for MSAA fade. The other is used for FadeDiscard() in shader on PC. u16 CShaderLib::ms_aaMaskLut[32] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01 , 0x01, 0x01, 0x01, 0x01 , 0x05, 0x05, 0x05, 0x05 , 0x05, 0x05, 0x05, 0x05 , 0x0d, 0x0d, 0x0d, 0x0d , 0x0d, 0x0d, 0x0d, 0x0d , 0x0f, 0x0f, 0x0f, 0x0f }; u16 CShaderLib::ms_aaMaskFadeLut[32] = { 0x0000, 0x0000, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0xF00F, 0xF00F, 0xF00F, 0xF00F, 0xF00F, 0xF00F, 0xF00F, 0xF00F, 0xF00F, 0xF0FF, 0xF0FF, 0xF0FF, 0xF0FF, 0xF0FF, 0xF0FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, }; u64 CShaderLib::ComputeSampleMask(u32 stippleAlpha) { // numSamples is different form numFragments if EQAA is enabled #if DEVICE_EQAA const u32 numSamples = GRCDEVICE.GetMSAA().m_uSamples; const u32 numFragments = GRCDEVICE.GetMSAA().m_uFragments; #else const u32 numSamples = GRCDEVICE.GetMSAA(); const u32 numFragments = numSamples; #endif // DEVICE_EQAA u64 sampleMask = ~0x0UL; u32 baseMask = ~0x0U; if( (numFragments == 1 && numSamples != numFragments) #if RSG_ORBIS || RSG_DURANGO || numFragments == 0 #endif // RSG_ORBIS || RSG_DURANGO ) { // EQAA 1/N, we need to go special.. return eqaa1NSampleMask[stippleAlpha >> 3]; } else { // the mask is designed for MSAA-4, hence we modify it const u32 origMask = ms_aaMaskLut[stippleAlpha >> 3]; Assert( origMask < 0x10 ); switch (numSamples) { case 2: baseMask = origMask>>2; break; case 4: baseMask = origMask; break; case 8: baseMask = origMask * 0x11; break; case 16:baseMask = origMask * 0x1111; break; default: baseMask = ~0x0U; break; } sampleMask = (((u64)baseMask & 0xFFFF)<<48) | (((u64)baseMask & 0xFFFF)<<32) | (((u64)baseMask & 0xFFFF)<<16) | (((u64)baseMask & 0xFFFF)); } return sampleMask; } void CShaderLib::SetGlobalAlpha(float alpha) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentScalarGlobals[g_RenderThreadIndex].x!=alpha DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(0, (u32)(alpha * 255.0f), alpha); grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } void CShaderLib::SetAlphaTestRef(float alphaTestRef) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); const unsigned rti = g_RenderThreadIndex; if (ms_alphaTestRef[rti]!=alphaTestRef DEV_ONLY(||ms_gDisableShaderVarCaching)) { ms_alphaTestRef[rti] = alphaTestRef; grcEffect::SetGlobalVar(globalAlphaTestRef, alphaTestRef); } } float CShaderLib::GetAlphaTestRef() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); return ms_alphaTestRef[g_RenderThreadIndex]; } void CShaderLib::SetGlobalEmissiveScale(float emissiveScale, bool ignoreDisable) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if( !ignoreDisable && CRenderer::GetDisableArtificialLights() ) { emissiveScale = GetOverridesEmissiveScale(); } if (ms_gCurrentScalarGlobals[g_RenderThreadIndex].w!=emissiveScale DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(3, (u32)(emissiveScale * 255.0f), emissiveScale); grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } float CShaderLib::GetGlobalEmissiveScale() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); return ms_gCurrentScalarGlobals[g_RenderThreadIndex].w; } void CShaderLib::SetGlobalNaturalAmbientScale(float ambScale) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentScalarGlobals[g_RenderThreadIndex].z!=ambScale DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(2, (u32)(ambScale * 255.0f), ambScale); grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } float CShaderLib::GetGlobalNaturalAmbientScale() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); return ms_gCurrentScalarGlobals[g_RenderThreadIndex].z; } void CShaderLib::SetGlobalArtificialAmbientScale(float ambScale) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentScalarGlobals[g_RenderThreadIndex].y!=ambScale DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant(1, (u32)(ambScale * 255.0f), ambScale); grcEffect::SetGlobalVar(ms_globalScalarsID, (Vec4V&)(ms_gCurrentScalarGlobals[g_RenderThreadIndex])); } } float CShaderLib::GetGlobalArtificialAmbientScale() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); return ms_gCurrentScalarGlobals[g_RenderThreadIndex].y; } void CShaderLib::SetGlobalTimer(float time) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentScalarGlobals2[g_RenderThreadIndex].x != time DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant2(0, time); grcEffect::SetGlobalVar(ms_globalScalars2ID, (Vec4V&)(ms_gCurrentScalarGlobals2[g_RenderThreadIndex])); } } void CShaderLib::SetGlobalInInterior(bool inInterior) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); float inInteriorf = (inInterior) ? 1.0f : 0.0f; SetScalarGlobalConstant2(2, inInteriorf); grcEffect::SetGlobalVar(ms_globalScalars2ID, (Vec4V&)(ms_gCurrentScalarGlobals2[g_RenderThreadIndex])); } bool CShaderLib::GetGlobalInInterior() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); return (ms_gCurrentScalarGlobals2[g_RenderThreadIndex].z == 1.0f); } void CShaderLib::SetGlobalAmbientOcclusionEffect(const Vector4 &ambEffect) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentAOEffectScale[g_RenderThreadIndex].x!=ambEffect.x || ms_gCurrentAOEffectScale[g_RenderThreadIndex].y!=ambEffect.y || ms_gCurrentAOEffectScale[g_RenderThreadIndex].z!=ambEffect.z || ms_gCurrentAOEffectScale[g_RenderThreadIndex].w!=ambEffect.w DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetCurrentAOEffectScale(ambEffect); grcEffect::SetGlobalVar(globalAOEffectScaleID, (Vec4V&)(ms_gCurrentAOEffectScale[g_RenderThreadIndex])); } } void CShaderLib::SetGlobalPedRimLightScale(float rimScale) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentScalarGlobals2[g_RenderThreadIndex].w!=rimScale DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetScalarGlobalConstant2(3, rimScale); grcEffect::SetGlobalVar(ms_globalScalars2ID, (Vec4V&)(ms_gCurrentScalarGlobals2[g_RenderThreadIndex])); } } void CShaderLib::SetGlobalToneMapScalers(const Vector4& scalers) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); SetScalarGlobalConstant3(scalers); grcEffect::SetGlobalVar(ms_globalScalars3ID, (Vec4V&)(ms_gCurrentScalarGlobals3[g_RenderThreadIndex])); } Vector4 CShaderLib::GetGlobalToneMapScalers() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); return ms_gCurrentScalarGlobals3[g_RenderThreadIndex].asVector4(); } void CShaderLib::SetGlobalScreenSize(const Vector2& screenSize) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); if (ms_gCurrentScreenSize[g_RenderThreadIndex].x!=screenSize.x || ms_gCurrentScreenSize[g_RenderThreadIndex].y!=screenSize.y DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetCurrentScreenSize(screenSize); grcEffect::SetGlobalVar(globalScreenSizeID, (Vec4V&)(ms_gCurrentScreenSize[g_RenderThreadIndex])); } } void CShaderLib::SetPlayerFeetPos(const Vector4& LFootPos, const Vector4& RFootPos) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); const u8 rtIdx = g_RenderThreadIndex; if (ms_gCurrentPlayerLFootPos[rtIdx].x!=LFootPos.x || ms_gCurrentPlayerLFootPos[rtIdx].y!=LFootPos.y || ms_gCurrentPlayerLFootPos[rtIdx].z!=LFootPos.z DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetCurrentPlayerLFootPos(LFootPos); grcEffect::SetGlobalVar(globalPlayerLFootPosID, (Vec4V&)(ms_gCurrentPlayerLFootPos[rtIdx])); } if (ms_gCurrentPlayerRFootPos[rtIdx].x!=RFootPos.x || ms_gCurrentPlayerRFootPos[rtIdx].y!=RFootPos.y || ms_gCurrentPlayerRFootPos[rtIdx].z!=RFootPos.z DEV_ONLY(||ms_gDisableShaderVarCaching)) { SetCurrentPlayerRFootPos(RFootPos); grcEffect::SetGlobalVar(globalPlayerRFootPosID, (Vec4V&)(ms_gCurrentPlayerRFootPos[rtIdx])); } } #if SHADERLIB_USE_MSAA_PARAMS void CShaderLib::SetMSAAParams(const grcDevice::MSAAMode &mode, bool colorDecoding) { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); #if DEVICE_EQAA if (mode.m_uFragments == 1) { colorDecoding = false; // nothing to decode } // modePure is the one of Gbuffers[1,2,3], // required to compute a secondary fragment shift grcDevice::MSAAMode modePure = mode; if (GBUFFER_REDUCED_COVERAGE) { modePure.DisableCoverage(); } const IntVector AAParams = { mode.m_uSamples, mode.m_uFragments, colorDecoding*mode.GetFmaskShift(), colorDecoding*modePure.GetFmaskShift() }; #else (void)colorDecoding; const IntVector AAParams = {mode,mode,0,0}; #endif //DEVICE_EQAA grcEffect::SetGlobalVar(globalTargetAAParamsID, AAParams); #if !RSG_ORBIS && !RSG_DURANGO const Vec4V vectorFadeMask(1.0f, 1.0f, 1.0f, 1.0f); ms_FadeMask16 = 0xFFFF; grcEffect::SetGlobalVar(ms_globalFadeID,vectorFadeMask); #endif // !RSG_ORBIS #if USE_TRANSPARENCYAA grcEffect::SetGlobalVar(globalTransparencyAASamples, useTransparencyAA ? (float)GRCDEVICE.GetMSAA() : 0.0f); #endif } #endif // SHADERLIB_USE_MSAA_PARAMS void CShaderLib::SetTreesParams() { #if DEVICE_MSAA && RSG_PC grcEffect::SetGlobalVar(globalTreesUseDiscardId, UsesStippleFades()); #endif } void CShaderLib::SetUseFogRay(bool bUse) { grcEffect::SetGlobalVar(globalUseFogRayId, bUse); } void CShaderLib::UpdateGlobalDevScreenSize() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); Vector2 screenSize=Vector2(GRCDEVICE.GetWidth()*1.0f, GRCDEVICE.GetHeight()*1.0f); CShaderLib::SetGlobalScreenSize(screenSize); } void CShaderLib::UpdateGlobalGameScreenSize() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); Vector2 screenSize=Vector2(VideoResManager::GetSceneWidth()*1.0f, VideoResManager::GetSceneHeight()*1.0f); CShaderLib::SetGlobalScreenSize(screenSize); } void CShaderLib::DisableGlobalFogAndDepthFx() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); Assert(ms_fogDepthFxEnabled[g_RenderThreadIndex]==true); CFogParams fogParams; fogParams.vFogParams[0].Setf(1000.0f, 2000.0f, 0.0f, ms_facingBackwards[g_RenderThreadIndex] ? 1.f : 0.f); fogParams.vFogParams[1].Setf(0,0,0,0); fogParams.vFogParams[2].Setf(0.f, 0.f, 0.f, 0.0f); // Send setting for no-fog, but maintain the original settings. grcEffect::SetGlobalVar(gFogParamsID, (Vec4V*)&fogParams, sizeof(CFogParams)/sizeof(Vec4V)); #if LINEAR_PIECEWISE_FOG LinearPiecewiseFog_ShaderParams linearParams; // Default is off. SetLinearPiecewiseFogParams(linearParams); #endif // LINEAR_PIECEWISE_FOG if(!g_IsSubRenderThread) for(int i=0; i(ms_gDeferredMaterial[g_RenderThreadIndex]); #if MSAA_EDGE_PROCESS_FADING if(!reset) { ref |= grcStateBlock::ActiveStencilRef & EDGE_FLAG; } #endif grcStateBlock::SetDepthStencilState(grcStateBlock::DSS_Active, ref); } }; void CShaderLib::SetGlobalDeferredMaterialBit(u32 bit, bool forceSetMaterial) { bit &= 0xFF; // max size is 8 bits ms_gDeferredMaterialORMask[g_RenderThreadIndex] |= (bit); if(!g_IsSubRenderThread) { for(int i=0; iGetBoneIndexFromBoneTag(BONETAG_L_FOOT); const s32 rightFootBoneIdx = pPlayerPed->GetBoneIndexFromBoneTag(BONETAG_R_FOOT); if (leftFootBoneIdx != -1 && rightFootBoneIdx != -1) { Matrix34 leftFootMat; Matrix34 rightFootMat; pPlayerPed->GetGlobalMtx(leftFootBoneIdx, leftFootMat); pPlayerPed->GetGlobalMtx(rightFootBoneIdx, rightFootMat); // move positions forward, so fur collision circle better encircles both feet: const Vector3 vecForward(1,0,0); Vector3 LForward, RForward; leftFootMat.Transform3x3(vecForward, LForward); rightFootMat.Transform3x3(vecForward, RForward); static dev_float scaleLFwdX = 0.1f; static dev_float scaleLFwdY = 0.1f; static dev_float scaleLFwdZ = 0.0f; const Vector3 vecScaleFwd(scaleLFwdX, scaleLFwdY, scaleLFwdZ); Vector4 lFootPos(leftFootMat.d + LForward*vecScaleFwd); Vector4 rFootPos(rightFootMat.d + RForward*vecScaleFwd); lFootPos.w = rFootPos.w = 0.0f; ms_PlayerLFootPos[bufIdx] = lFootPos; ms_PlayerRFootPos[bufIdx] = rFootPos; } } } // // // // void CShaderLib::SetGlobalShaderVariables() { Assert(CSystem::IsThisThreadId(SYS_THREAD_RENDER)); const u32 bufIdx = gRenderThreadInterface.GetRenderBuffer(); SetPlayerFeetPos(ms_PlayerLFootPos[bufIdx], ms_PlayerRFootPos[bufIdx]); #if RSG_PC grcEffect::SetGlobalVar(globalShaderQualityID, ms_ShaderQuality[bufIdx]); #endif }