diff --git a/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli b/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli index 50ef0f240..453ca48f7 100644 --- a/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli +++ b/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli @@ -32,7 +32,7 @@ StructuredBuffer lights : register(t17); StructuredBuffer lightList : register(t18); //MAX_CLUSTER_LIGHTS * 16^3 StructuredBuffer lightGrid : register(t19); //16^3 -#if !defined(SCREEN_SPACE_SHADOWS) +#if !defined(SCREEN_SPACE_SHADOWS) && !defined(EFFECT) Texture2D TexDepthSampler : register(t20); #endif // SCREEN_SPACE_SHADOWS diff --git a/package/Shaders/Effect.hlsl b/package/Shaders/Effect.hlsl index d37ff13ae..2d498abbd 100644 --- a/package/Shaders/Effect.hlsl +++ b/package/Shaders/Effect.hlsl @@ -1,3 +1,5 @@ +#define EFFECT + struct VS_INPUT { float4 Position : POSITION0; @@ -28,6 +30,7 @@ struct VS_OUTPUT { float4 Position : SV_POSITION0; float4 TexCoord0 : TEXCOORD0; + float4 WorldPosition : POSITION1; #if defined(VC) float4 Color : COLOR0; #endif @@ -61,7 +64,6 @@ struct VS_OUTPUT # if !(defined(MEMBRANE) && (defined(SKINNED) || defined(NORMALS))) float3 ScreenSpaceNormal : TEXCOORD7; # endif - float4 WorldPosition : POSITION1; float4 PreviousWorldPosition : POSITION2; # if (defined(MEMBRANE) && defined(SKINNED) && !defined(NORMALS)) float3 ScreenSpaceNormal : TEXCOORD7; @@ -399,8 +401,8 @@ VS_OUTPUT main(VS_INPUT input) vsout.TBN1.xyz = MatProj[2].xyz; # endif -# if defined(MOTIONVECTORS_NORMALS) vsout.WorldPosition = worldPosition; +# if defined(MOTIONVECTORS_NORMALS) vsout.PreviousWorldPosition = previousWorldPosition; # endif @@ -410,8 +412,16 @@ VS_OUTPUT main(VS_INPUT input) typedef VS_OUTPUT PS_INPUT; SamplerState SampBaseSampler : register(s0); +SamplerState SampNormalSampler : register(s1); +SamplerState SampNoiseSampler : register(s2); +SamplerState SampDepthSampler : register(s3); +SamplerState SampGrayscaleSampler : register(s4); Texture2D TexBaseSampler : register(t0); +Texture2D TexNormalSampler : register(t1); +Texture2D TexNoiseSampler : register(t2); +Texture2D TexDepthSampler : register(t3); +Texture2D TexGrayscaleSampler : register(t4); struct PS_OUTPUT { @@ -426,20 +436,28 @@ struct PS_OUTPUT }; #ifdef PSHADER -cbuffer PerFrame : register(b12) -{ - row_major float4x4 ScreenProj : packoffset(c12); - row_major float4x4 PreviousScreenProj : packoffset(c16); -}; + +# include "Common/Color.hlsl" +# include "Common/FrameBuffer.hlsl" +# include "Common/MotionBlur.hlsl" +# include "Common/Permutation.hlsl" cbuffer AlphaTestRefBuffer : register(b11) { - float AlphaTestRef : packoffset(c0); + float AlphaTestRef1 : packoffset(c0); } +cbuffer PerTechnique : register(b0) +{ + float4 CameraData : packoffset(c0); + float2 VPOSOffset : packoffset(c1); + float2 FilteringParam : packoffset(c1.z); +}; + cbuffer PerMaterial : register(b1) { float4 BaseColor : packoffset(c0); + float4 BaseColorScale : packoffset(c1); float4 LightingInfluence : packoffset(c2); }; @@ -454,25 +472,29 @@ cbuffer PerGeometry : register(b2) float4 PLightColorB : packoffset(c6); float4 DLightColor : packoffset(c7); float4 PropertyColor : packoffset(c8); + float4 AlphaTestRef : packoffset(c9); + float4 MembraneRimColor : packoffset(c10); + float4 MembraneVars : packoffset(c11); }; +# if defined(MEMBRANE) || !defined(LIGHTING) +# undef LIGHT_LIMIT_FIX +# endif + +# if defined(LIGHT_LIMIT_FIX) +# include "LightLimitFix/LightLimitFix.hlsli" +# endif + # if defined(LIGHTING) float3 GetLightingColor(float3 msPosition) { - float4 lightDistX = PLightPositionX - msPosition.xxxx; - float4 lightDistXSquared = lightDistX * lightDistX; - float4 lightDistY = PLightPositionY - msPosition.yyyy; - float4 lightDistYSquared = lightDistY * lightDistY; - float4 lightDistZ = PLightPositionZ - msPosition.zzzz; - float4 lightDistZSquared = lightDistZ * lightDistZ; - - float4 lightDistanceSquared = lightDistXSquared + lightDistYSquared + lightDistZSquared; + float4 lightDistanceSquared = (PLightPositionY - msPosition.yyyy) * (PLightPositionY - msPosition.yyyy) + (PLightPositionX - msPosition.xxxx) * (PLightPositionX - msPosition.xxxx) + (PLightPositionZ - msPosition.zzzz) * (PLightPositionZ - msPosition.zzzz); float4 lightFadeMul = 1.0.xxxx - saturate(PLightingRadiusInverseSquared * lightDistanceSquared); - float3 color; - color.x = DLightColor.x + dot(PLightColorR * lightFadeMul, 1.0.xxxx); - color.y = DLightColor.y + dot(PLightColorG * lightFadeMul, 1.0.xxxx); - color.z = DLightColor.z + dot(PLightColorB * lightFadeMul, 1.0.xxxx); + float3 color = DLightColor.xyz; + color.x += dot(PLightColorR * lightFadeMul, 1.0.xxxx); + color.z += dot(PLightColorB * lightFadeMul, 1.0.xxxx); + color.y += dot(PLightColorG * lightFadeMul, 1.0.xxxx); return color; } @@ -482,36 +504,143 @@ PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; + float4 fogMul = float4(input.FogAlpha.xxx, 1); + +# if defined(MEMBRANE) + float noiseAlpha = TexNoiseSampler.Sample(SampNoiseSampler, input.TexCoord0.zw).w; +# if defined(VC) + noiseAlpha *= input.Color.w; +# endif + if (noiseAlpha - AlphaTestRef.x < 0) { + discard; + } +# if defined(ALPHA_TEST) +# endif + +# if defined(NORMALS) + float3 normal = input.TBN0; +# else + float3 normal = TexNormalSampler.Sample(SampNormalSampler, input.TexCoord0.zw).xzy * 2 - 1; +# if defined(SKINNED) + normal = mul(normal, transpose(float3x3(input.TBN0, input.TBN1, input.TBN2))); +# endif +# endif + float NdotV = dot(normal, input.ViewVector.xyz); + float membraneColorMul = pow(saturate(1 - NdotV), MembraneVars.x); + float4 membraneColor = MembraneRimColor * membraneColorMul; +# endif + + float softMul = 1; +# if defined(SOFT) + float depth = TexDepthSampler.Load(int3(input.Position.xy, 0)).x; + softMul = saturate(-input.TexCoord0.w + LightingInfluence.y / ((1 - depth) * CameraData.z + CameraData.y)); +# endif + +# if defined(MEMBRANE) + float4 baseColorMul = float4(1, 1, 1, 1); +# else float4 baseColorMul = BaseColor; -# if defined(VC) +# if defined(VC) baseColorMul *= input.Color; +# endif # endif + float4 baseTexColor = float4(1, 1, 1, 1); float4 baseColor = float4(1, 1, 1, 1); # if defined(TEXTURE) - baseColor *= TexBaseSampler.Sample(SampBaseSampler, input.TexCoord0.xy); + baseTexColor = TexBaseSampler.Sample(SampBaseSampler, input.TexCoord0.xy); + baseColor *= baseTexColor; +# if defined(IGNORE_TEX_ALPHA) || defined(GRAYSCALE_TO_ALPHA) + baseColor.w = 1; +# endif # endif +# if defined(MEMBRANE) + baseColor.w *= input.ViewVector.w; +# else baseColor.w *= input.TexCoord0.z; +# endif baseColor *= baseColorMul; + baseColor.w *= softMul; -# if !defined(MOTIONVECTORS_NORMALS) - if (PropertyColor.w * baseColor.w - AlphaTestRef < 0) { +# if defined(SOFT) + if (baseColor.w - 0.003 < 0) { discard; } # endif + float lightingInfluence = LightingInfluence.x; float3 propertyColor = PropertyColor.xyz; # if defined(LIGHTING) propertyColor = GetLightingColor(input.MSPosition); + +# if defined(LIGHT_LIMIT_FIX) + uint eyeIndex = 0; + uint lightCount = 0; + if (LightingInfluence.x > 0.0) { + float3 viewPosition = mul(CameraView[eyeIndex], float4(input.WorldPosition.xyz, 1)).xyz; + float2 screenUV = ViewToUV(viewPosition, true, eyeIndex); + + uint clusterIndex = 0; + if (perPassLLF[0].EnableGlobalLights && GetClusterIndex(screenUV, viewPosition.z, clusterIndex)) { + lightCount = lightGrid[clusterIndex].lightCount; + uint lightOffset = lightGrid[clusterIndex].offset; + [loop] for (uint i = 0; i < lightCount; i++) + { + uint light_index = lightList[lightOffset + i]; + StructuredLight light = lights[light_index]; + float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WorldPosition.xyz; + float lightDist = length(lightDirection); + float intensityFactor = saturate(lightDist / light.radius); + float intensityMultiplier = 1 - intensityFactor * intensityFactor; + float3 lightColor = light.color.xyz * intensityMultiplier; + propertyColor += lightColor; + } + } + } +# endif +# elif defined(MEMBRANE) + propertyColor *= 0; + lightingInfluence = 0; +# endif + +# if defined(GRAYSCALE_TO_COLOR) + baseColor.xyz = BaseColorScale.x * TexGrayscaleSampler.Sample(SampGrayscaleSampler, float2(baseTexColor.y, baseColorMul.x)).xyz; +# endif + + float alpha = PropertyColor.w * baseColor.w; + +# if defined(GRAYSCALE_TO_ALPHA) + alpha = TexGrayscaleSampler.Sample(SampGrayscaleSampler, float2(baseTexColor.w, alpha)).w; # endif - float3 lightColor = lerp(baseColor.xyz, propertyColor * baseColor.xyz, LightingInfluence.xxx); +# if defined(BLOOD) + baseColor.w = baseColor.y; + float deltaY = saturate(baseColor.y - AlphaTestRef.x); + float bloodMul = baseColor.z; + if (deltaY < AlphaTestRef.y) { + bloodMul *= (deltaY / AlphaTestRef.y); + } + baseColor.xyz = saturate(float3(2, 1, 1) - bloodMul.xxx) * (-bloodMul * AlphaTestRef.z + 1); +# endif + +# if defined(MEMBRANE) + baseColor.xyz = (PropertyColor.xyz + baseColor.xyz) * alpha + membraneColor.xyz * membraneColor.w; + alpha += membraneColor.w; +# endif + + float3 lightColor = lerp(baseColor.xyz, propertyColor * baseColor.xyz, lightingInfluence.xxx); + +# if !defined(MOTIONVECTORS_NORMALS) + if (alpha * fogMul.w - AlphaTestRef1 < 0) { + discard; + } +# endif # if !defined(MOTIONVECTORS_NORMALS) # if defined(ADDBLEND) float3 blendedColor = lightColor * (1 - input.FogParam.www); -# elif defined(MULTBLEND) +# elif defined(MULTBLEND) || defined(MULTBLEND_DECAL) float3 blendedColor = lerp(lightColor, 1.0.xxx, saturate(1.5 * input.FogParam.w).xxx); # else float3 blendedColor = lerp(lightColor, input.FogParam.xyz, input.FogParam.www); @@ -520,22 +649,36 @@ PS_OUTPUT main(PS_INPUT input) float3 blendedColor = lightColor.xyz; # endif - float4 finalColor = float4(blendedColor, PropertyColor.w * baseColor.w); -# if !defined(MULTBLEND) - finalColor *= float4(input.FogAlpha.xxx, 1); + float4 finalColor = float4(blendedColor, alpha); +# if defined(MULTBLEND_DECAL) + finalColor.xyz *= alpha; +# elif !defined(MULTBLEND) + finalColor *= fogMul; # endif psout.Color = finalColor; +# if defined(LIGHT_LIMIT_FIX) && defined(LLFDEBUG) + if (perPassLLF[0].EnableLightsVisualisation) { + if (perPassLLF[0].LightsVisualisationMode == 0) { + psout.Color.xyz = TurboColormap(0.0); + } else if (perPassLLF[0].LightsVisualisationMode == 1) { + psout.Color.xyz = TurboColormap(0.0); + } else { + psout.Color.xyz = TurboColormap((float)lightCount / 128.0); + } + } +# endif # if defined(MOTIONVECTORS_NORMALS) - float4 screenPosition = mul(ScreenProj, input.WorldPosition); - screenPosition.xy = screenPosition.xy / screenPosition.ww; - float4 previousScreenPosition = mul(PreviousScreenProj, input.PreviousWorldPosition); - previousScreenPosition.xy = previousScreenPosition.xy / previousScreenPosition.ww; - float2 screenMotionVector = float2(-0.5, 0.5) * (screenPosition.xy - previousScreenPosition.xy); + float2 screenMotionVector = GetSSMotionVector(input.WorldPosition, input.PreviousWorldPosition, 0); psout.MotionVectors = screenMotionVector; +# if (defined(MEMBRANE) && (defined(SKINNED) || defined(NORMALS))) + float3 screenSpaceNormal = normalize(input.TBN0); +# else float3 screenSpaceNormal = normalize(input.ScreenSpaceNormal); +# endif + screenSpaceNormal.z = max(0.001, sqrt(8 + -8 * screenSpaceNormal.z)); screenSpaceNormal.xy /= screenSpaceNormal.zz; psout.ScreenSpaceNormals.xy = screenSpaceNormal.xy + 0.5.xx; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 1d909f25f..b5306ebe4 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1332,15 +1332,13 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif // SNOW # endif // LANDSCAPE -# if !defined(LANDSCAPE) - float4 backLightColor = 1.0; - if (shaderDescriptors[0].PixelShaderDescriptor & _BackLighting) - backLightColor = TexBackLightSampler.Sample(SampBackLightSampler, uv); +# if defined(BACK_LIGHTING) + float4 backLightColor = TexBackLightSampler.Sample(SampBackLightSampler, uv); +# endif // BACK_LIGHTING - float4 rimSoftLightColor = 1.0; - if ((shaderDescriptors[0].PixelShaderDescriptor & _SoftLighting) || (shaderDescriptors[0].PixelShaderDescriptor & _RimLighting)) - rimSoftLightColor = TexRimSoftLightWorldMapOverlaySampler.Sample(SampRimSoftLightWorldMapOverlaySampler, uv); -# endif // !defined (LANDSCAPE) +# if defined(RIM_LIGHTING) || defined(SOFT_LIGHTING) + float4 rimSoftLightColor = TexRimSoftLightWorldMapOverlaySampler.Sample(SampRimSoftLightWorldMapOverlaySampler, uv); +# endif // RIM_LIGHTING || SOFT_LIGHTING float numLights = min(7, NumLightNumShadowLight.x); float numShadowLights = min(4, NumLightNumShadowLight.y); @@ -1356,15 +1354,11 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif // defined (MODELSPACENORMALS) && !defined (SKINNED) float2 baseShadowUV = 1.0.xx; - float4 shadowColor; - if (shaderDescriptors[0].PixelShaderDescriptor & _DefShadow) { - if ((shaderDescriptors[0].PixelShaderDescriptor & _ShadowDir) || numShadowLights > 0) { - baseShadowUV = input.Position.xy * DynamicResolutionParams2.xy; - float2 shadowUV = min(float2(DynamicResolutionParams2.z, DynamicResolutionParams1.y), max(0.0.xx, DynamicResolutionParams1.xy * (baseShadowUV * VPOSOffset.xy + VPOSOffset.zw))); - shadowColor = TexShadowMaskSampler.Sample(SampShadowMaskSampler, shadowUV); - } else { - shadowColor = 1.0.xxxx; - } + float4 shadowColor = 1.0; + if (shaderDescriptors[0].PixelShaderDescriptor & _DefShadow && (shaderDescriptors[0].PixelShaderDescriptor & _ShadowDir) || numShadowLights > 0) { + baseShadowUV = input.Position.xy * DynamicResolutionParams2.xy; + float2 shadowUV = min(float2(DynamicResolutionParams2.z, DynamicResolutionParams1.y), max(0.0.xx, DynamicResolutionParams1.xy * (baseShadowUV * VPOSOffset.xy + VPOSOffset.zw))); + shadowColor = TexShadowMaskSampler.Sample(SampShadowMaskSampler, shadowUV); } float texProjTmp = 0; @@ -1383,9 +1377,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace texProjTmp += (-0.5 + input.Color.w) * 2.5; # endif // LODOBJECTSHD # if defined(SPARKLE) - if (texProjTmp < 0) { + if (texProjTmp < 0) discard; - } modelNormal.xyz = projectedNormal; # if defined(SNOW) @@ -1543,8 +1536,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif # if (!defined(DRAW_IN_WORLDSPACE)) - if (!input.WorldSpace) - normalizedDirLightDirectionWS = normalize(mul(input.World[eyeIndex], float4(normalizedDirLightDirectionWS, 0))); + normalizedDirLightDirectionWS = lerp(normalize(mul(input.World[eyeIndex], float4(DirLightDirection, 0))), normalizedDirLightDirectionWS, input.WorldSpace); # endif # endif @@ -1561,10 +1553,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace cellInt = round(cellF); uint waterTile = (uint)clamp(cellInt.x + (cellInt.y * 5), 0, 24); // remap xy to 0-24 - float waterHeight = -2147483648; // lowest 32-bit integer - - if (cellInt.x < 5 && cellInt.x >= 0 && cellInt.y < 5 && cellInt.y >= 0) - waterHeight = lightingData[0].WaterHeight[waterTile]; + float waterHeight = lerp(-2147483648, lightingData[0].WaterHeight[waterTile], cellInt.x < 5 && cellInt.x >= 0 && cellInt.y < 5 && cellInt.y >= 0); # endif # if defined(WETNESS_EFFECTS) @@ -1599,11 +1588,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace puddle = FBM(puddleCoords, 3, 1.0) * 0.5 + 0.5; puddle = lerp(0.2, 1.0, puddle); puddle *= wetness; - if (shaderDescriptors[0].PixelShaderDescriptor & _DefShadow) { - if (shaderDescriptors[0].PixelShaderDescriptor & _ShadowDir) { - float upAngle = saturate(dot(float3(0, 0, 1), normalizedDirLightDirectionWS.xyz)); - puddle *= lerp(1.0, shadowColor.x, upAngle * 0.2); - } + if (shaderDescriptors[0].PixelShaderDescriptor & _DefShadow && shaderDescriptors[0].PixelShaderDescriptor & _ShadowDir) { + float upAngle = saturate(dot(float3(0, 0, 1), normalizedDirLightDirectionWS.xyz)); + puddle *= lerp(1.0, shadowColor.x, upAngle * 0.2); } } @@ -1627,8 +1614,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float wetnessGlossinessSpecular = puddle; # if !defined(LOD) - if (input.WorldPosition.z < waterHeight) - wetnessGlossinessSpecular *= shoreFactor; + wetnessGlossinessSpecular = lerp(wetnessGlossinessSpecular, wetnessGlossinessSpecular * shoreFactor, input.WorldPosition.z < waterHeight); # endif # if !defined(MODELSPACENORMALS) @@ -1681,9 +1667,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 normalizedLightDirection = normalize(lightDirection); float3 normalizedLightDirectionWS = normalizedLightDirection; # if (defined(SKINNED) || !defined(MODELSPACENORMALS)) && !defined(DRAW_IN_WORLDSPACE) - if (!input.WorldSpace) { - normalizedLightDirectionWS = normalize(mul(input.World[eyeIndex], float4(normalizedLightDirection, 0))); - } + normalizedLightDirectionWS = lerp(normalize(mul(input.World[eyeIndex], float4(normalizedLightDirection, 0))), normalizedLightDirectionWS, input.WorldSpace); # endif # if defined(LIGHT_LIMIT_FIX) @@ -1702,10 +1686,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace if (perPassParallax[0].EnableShadows) { float3 lightDirectionTS = mul(normalizedLightDirection, tbn).xyz; - bool lightIsLit = true; - - if (shadowComponent.x == 0) - lightIsLit = false; + bool lightIsLit = shadowComponent.x > 0.0; # if defined(PARALLAX) if (perPassParallax[0].EnableParallax) @@ -1755,92 +1736,90 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace if (perPassLLF[0].EnableGlobalLights && GetClusterIndex(screenUV, viewPosition.z, clusterIndex)) { lightCount = lightGrid[clusterIndex].lightCount; - if (lightCount) { - uint lightOffset = lightGrid[clusterIndex].offset; - float shadowQualityScale = saturate(1.0 - ((float)lightCount / 128.0)); + uint lightOffset = lightGrid[clusterIndex].offset; + float shadowQualityScale = saturate(1.0 - ((float)lightCount / 128.0)); # if defined(ANISO_LIGHTING) - input.TBN0.z = worldSpaceVertexNormal[0]; - input.TBN1.z = worldSpaceVertexNormal[1]; - input.TBN2.z = worldSpaceVertexNormal[2]; + input.TBN0.z = worldSpaceVertexNormal[0]; + input.TBN1.z = worldSpaceVertexNormal[1]; + input.TBN2.z = worldSpaceVertexNormal[2]; # endif - [loop] for (uint i = 0; i < lightCount; i++) - { - uint light_index = lightList[lightOffset + i]; - StructuredLight light = lights[light_index]; - - float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WorldPosition.xyz; - float lightDist = length(lightDirection); - float intensityFactor = saturate(lightDist / light.radius); - if (intensityFactor == 1) - continue; - - float intensityMultiplier = 1 - intensityFactor * intensityFactor; - float3 lightColor = light.color.xyz * intensityMultiplier; - float3 nsLightColor = lightColor; - float3 normalizedLightDirection = normalize(lightDirection); - - if (!FrameParams.z && FrameParams.y) { - float3 normalizedLightDirectionVS = WorldToView(normalizedLightDirection, true, eyeIndex); - if (light.firstPersonShadow || perPassLLF[0].EnableContactShadows) { - float radius = light.firstPersonShadow ? light.radius : 0.0; - float contactShadow = ContactShadows(viewPosition, screenUV, screenNoise, normalizedLightDirectionVS, shadowQualityScale, radius, eyeIndex); - if (light.firstPersonShadow) { - lightColor *= contactShadow; - } else { + [loop] for (uint i = 0; i < lightCount; i++) + { + uint light_index = lightList[lightOffset + i]; + StructuredLight light = lights[light_index]; + + float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WorldPosition.xyz; + float lightDist = length(lightDirection); + float intensityFactor = saturate(lightDist / light.radius); + if (intensityFactor == 1) + continue; + + float intensityMultiplier = 1 - intensityFactor * intensityFactor; + float3 lightColor = light.color.xyz * intensityMultiplier; + float3 nsLightColor = lightColor; + float3 normalizedLightDirection = normalize(lightDirection); + + if (!FrameParams.z && FrameParams.y) { + float3 normalizedLightDirectionVS = WorldToView(normalizedLightDirection, true, eyeIndex); + if (light.firstPersonShadow || perPassLLF[0].EnableContactShadows) { + float radius = light.firstPersonShadow ? light.radius : 0.0; + float contactShadow = ContactShadows(viewPosition, screenUV, screenNoise, normalizedLightDirectionVS, shadowQualityScale, radius, eyeIndex); + if (light.firstPersonShadow) { + lightColor *= contactShadow; + } else { # if !defined(MODELSPACENORMALS) - float shadowIntensityFactor = saturate(dot(worldSpaceVertexNormal, normalizedLightDirection.xyz) * PI); - lightColor *= lerp(lerp(1.0, contactShadow, shadowIntensityFactor), 1.0, !frontFace * 0.2); + float shadowIntensityFactor = saturate(dot(worldSpaceVertexNormal, normalizedLightDirection.xyz) * PI); + lightColor *= lerp(lerp(1.0, contactShadow, shadowIntensityFactor), 1.0, !frontFace * 0.2); # else - lightColor *= lerp(contactShadow, 1.0, !frontFace * 0.2); + lightColor *= lerp(contactShadow, 1.0, !frontFace * 0.2); # endif - } } } + } # if defined(CPM_AVAILABLE) - if (perPassParallax[0].EnableShadows) { - float3 lightDirectionTS = mul(normalizedLightDirection, tbn).xyz; + if (perPassParallax[0].EnableShadows) { + float3 lightDirectionTS = mul(normalizedLightDirection, tbn).xyz; # if defined(PARALLAX) - if (perPassParallax[0].EnableParallax) - lightColor *= GetParallaxSoftShadowMultiplier(uv, mipLevel, lightDirectionTS, sh0, TexParallaxSampler, SampParallaxSampler, 0, parallaxShadowQuality); + if (perPassParallax[0].EnableParallax) + lightColor *= GetParallaxSoftShadowMultiplier(uv, mipLevel, lightDirectionTS, sh0, TexParallaxSampler, SampParallaxSampler, 0, parallaxShadowQuality); # elif defined(LANDSCAPE) - if (perPassParallax[0].EnableTerrainParallax) - lightColor *= GetParallaxSoftShadowMultiplierTerrain(input, terrainUVs, mipLevel, lightDirectionTS, sh0, parallaxShadowQuality); + if (perPassParallax[0].EnableTerrainParallax) + lightColor *= GetParallaxSoftShadowMultiplierTerrain(input, terrainUVs, mipLevel, lightDirectionTS, sh0, parallaxShadowQuality); # elif defined(ENVMAP) - if (complexMaterialParallax) - lightColor *= GetParallaxSoftShadowMultiplier(uv, mipLevel, lightDirectionTS, sh0, TexEnvMaskSampler, SampEnvMaskSampler, 3, parallaxShadowQuality); + if (complexMaterialParallax) + lightColor *= GetParallaxSoftShadowMultiplier(uv, mipLevel, lightDirectionTS, sh0, TexEnvMaskSampler, SampEnvMaskSampler, 3, parallaxShadowQuality); # endif - } + } # endif - float lightAngle = dot(worldSpaceNormal.xyz, normalizedLightDirection.xyz); - float3 lightDiffuseColor = lightColor * saturate(lightAngle.xxx); + float lightAngle = dot(worldSpaceNormal.xyz, normalizedLightDirection.xyz); + float3 lightDiffuseColor = lightColor * saturate(lightAngle.xxx); # if defined(SOFT_LIGHTING) - lightDiffuseColor += nsLightColor * GetSoftLightMultiplier(dot(worldSpaceNormal.xyz, lightDirection.xyz)) * rimSoftLightColor.xyz; + lightDiffuseColor += nsLightColor * GetSoftLightMultiplier(dot(worldSpaceNormal.xyz, lightDirection.xyz)) * rimSoftLightColor.xyz; # endif # if defined(RIM_LIGHTING) - lightDiffuseColor += nsLightColor * GetRimLightMultiplier(normalizedLightDirection, viewDirection, worldSpaceNormal.xyz) * rimSoftLightColor.xyz; + lightDiffuseColor += nsLightColor * GetRimLightMultiplier(normalizedLightDirection, viewDirection, worldSpaceNormal.xyz) * rimSoftLightColor.xyz; # endif # if defined(BACK_LIGHTING) - lightDiffuseColor += (saturate(-lightAngle) * backLightColor.xyz) * nsLightColor; + lightDiffuseColor += (saturate(-lightAngle) * backLightColor.xyz) * nsLightColor; # endif # if defined(SPECULAR) || (defined(SPARKLE) && !defined(SNOW)) - lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldSpaceNormal.xyz, lightColor, shininess, uv); + lightsSpecularColor += GetLightSpecularInput(input, normalizedLightDirection, viewDirection, worldSpaceNormal.xyz, lightColor, shininess, uv); # endif - lightsDiffuseColor += lightDiffuseColor; + lightsDiffuseColor += lightDiffuseColor; # if defined(WETNESS_EFFECTS) - if (waterRoughnessSpecular < 1.0) - wetnessSpecular += GetWetnessSpecular(wetnessNormal, normalizedLightDirection, worldSpaceViewDirection, lightColor, waterRoughnessSpecular); + if (waterRoughnessSpecular < 1.0) + wetnessSpecular += GetWetnessSpecular(wetnessNormal, normalizedLightDirection, worldSpaceViewDirection, lightColor, waterRoughnessSpecular); # endif - } } } # endif diff --git a/package/Shaders/Water.hlsl b/package/Shaders/Water.hlsl index c969cc50c..ef2c85616 100644 --- a/package/Shaders/Water.hlsl +++ b/package/Shaders/Water.hlsl @@ -2,6 +2,8 @@ #include "Common/MotionBlur.hlsl" #include "Common/Permutation.hlsl" +#define WATER + struct VS_INPUT { #if defined(SPECULAR) || defined(UNDERWATER) || defined(STENCIL) || defined(SIMPLE) @@ -402,7 +404,7 @@ float3 GetWaterSpecularColor(PS_INPUT input, float3 normal, float3 viewDirection } # if defined(DEPTH) -float GetScreenDepth(float2 screenPosition) +float GetScreenDepthWater(float2 screenPosition) { float depth = DepthTex.Load(float3(screenPosition, 0)).x; return (CameraData.w / (-depth * CameraData.z + CameraData.x)); @@ -443,9 +445,9 @@ float3 GetWaterDiffuseColor(PS_INPUT input, float3 normal, float3 viewDirection, float2(refractionNormal.x, refractionNormal.w - refractionNormal.y) / refractionNormal.ww; # if defined(DEPTH) - float depth = GetScreenDepth(DynamicResolutionParams1.xy * (DynamicResolutionParams2.xy * input.HPosition.xy)); + float depth = GetScreenDepthWater(DynamicResolutionParams1.xy * (DynamicResolutionParams2.xy * input.HPosition.xy)); float refractionDepth = - GetScreenDepth(DynamicResolutionParams1.xy * (refractionUvRaw / VPOSOffset.xy)); + GetScreenDepthWater(DynamicResolutionParams1.xy * (refractionUvRaw / VPOSOffset.xy)); float refractionDepthMul = length( float3((refractionDepth * ((VPOSOffset.zw + refractionUvRaw) * 2 - 1)) / ProjData.xy, @@ -501,6 +503,10 @@ float3 GetSunColor(float3 normal, float3 viewDirection) # include "WaterBlending/WaterBlending.hlsli" # endif +# if defined(LIGHT_LIMIT_FIX) +# include "LightLimitFix/LightLimitFix.hlsli" +# endif + PS_OUTPUT main(PS_INPUT input) { PS_OUTPUT psout; @@ -521,7 +527,7 @@ PS_OUTPUT main(PS_INPUT input) # else distanceMul = 0; - float depth = GetScreenDepth( + float depth = GetScreenDepthWater( DynamicResolutionParams1.xy * (DynamicResolutionParams2.xy * input.HPosition.xy)); float2 depthOffset = DynamicResolutionParams2.xy * input.HPosition.xy * VPOSOffset.xy + VPOSOffset.zw; @@ -574,6 +580,42 @@ PS_OUTPUT main(PS_INPUT input) float3 diffuseColor = GetWaterDiffuseColor(input, normal, viewDirection, distanceMul, depthControl.y, fresnel); + float3 specularLighting = 0; + +# if defined(LIGHT_LIMIT_FIX) + uint eyeIndex = 0; + uint lightCount = 0; + + float3 viewPosition = mul(CameraView[eyeIndex], float4(input.WPosition.xyz, 1)).xyz; + float2 screenUV = ViewToUV(viewPosition, true, eyeIndex); + + uint clusterIndex = 0; + if (perPassLLF[0].EnableGlobalLights && GetClusterIndex(screenUV, viewPosition.z, clusterIndex)) { + lightCount = lightGrid[clusterIndex].lightCount; + uint lightOffset = lightGrid[clusterIndex].offset; + [loop] for (uint i = 0; i < lightCount; i++) + { + uint light_index = lightList[lightOffset + i]; + StructuredLight light = lights[light_index]; + + float3 lightDirection = light.positionWS[eyeIndex].xyz - input.WPosition.xyz; + float lightDist = length(lightDirection); + float intensityFactor = saturate(lightDist / light.radius); + + float intensityMultiplier = 1 - intensityFactor * intensityFactor; + + float3 normalizedLightDirection = normalize(lightDirection); + + float3 H = normalize(normalizedLightDirection - viewDirection); + float HdotN = saturate(dot(H, normal)); + + float3 lightColor = light.color.xyz * pow(HdotN, FresnelRI.z); + specularLighting += lightColor * intensityMultiplier; + } + } + specularColor += specularLighting * 3; +# endif + # if defined(UNDERWATER) float3 finalSpecularColor = lerp(ShallowColor.xyz, specularColor, 0.5); float3 finalColor = saturate(1 - input.WPosition.w * 0.002) * @@ -582,9 +624,7 @@ PS_OUTPUT main(PS_INPUT input) # else float3 sunColor = GetSunColor(normal, viewDirection); float specularFraction = lerp(1, fresnel * depthControl.x, distanceFactor); - - float3 finalColorPreFog = - lerp(diffuseColor, specularColor, specularFraction) + sunColor * depthControl.w; + float3 finalColorPreFog = lerp(diffuseColor, specularColor, specularFraction) + sunColor * depthControl.w; float3 finalColor = lerp(finalColorPreFog, input.FogParam.xyz, input.FogParam.w); # endif # endif diff --git a/src/Features/LightLimitFix.cpp b/src/Features/LightLimitFix.cpp index fb834f001..fa458dc10 100644 --- a/src/Features/LightLimitFix.cpp +++ b/src/Features/LightLimitFix.cpp @@ -607,21 +607,14 @@ enum class GrassShaderTechniques RenderDepth = 8, }; -void LightLimitFix::Draw(const RE::BSShader* shader, const uint32_t descriptor) +void LightLimitFix::Draw(const RE::BSShader* shader, const uint32_t) { switch (shader->shaderType.get()) { case RE::BSShader::Type::Lighting: - { - Bind(); - } - break; case RE::BSShader::Type::Grass: - { - const auto technique = descriptor & 0b1111; - if (technique != static_cast(GrassShaderTechniques::RenderDepth)) { - Bind(); - } - } + case RE::BSShader::Type::Effect: + case RE::BSShader::Type::Water: + Bind(); break; } } @@ -1027,6 +1020,9 @@ bool LightLimitFix::HasShaderDefine(RE::BSShader::Type shaderType) case RE::BSShader::Type::Lighting: case RE::BSShader::Type::Grass: return true; + case RE::BSShader::Type::Effect: + case RE::BSShader::Type::Water: + return !REL::Module::IsVR(); default: return false; } diff --git a/src/Features/LightLimitFix.h b/src/Features/LightLimitFix.h index 9f881d3ae..34821e475 100644 --- a/src/Features/LightLimitFix.h +++ b/src/Features/LightLimitFix.h @@ -187,7 +187,7 @@ struct LightLimitFix : Feature { static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light) { - return func(a_property, a_light) && (!netimmerse_cast(a_property) || (a_light->portalStrict || !a_light->portalGraph || skyrim_cast(a_light))); + return func(a_property, a_light) && ((REL::Module::IsVR() && !netimmerse_cast(a_property)) || (a_light->portalStrict || !a_light->portalGraph || skyrim_cast(a_light))); } static inline REL::Relocation func; }; @@ -196,7 +196,7 @@ struct LightLimitFix : Feature { static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light) { - return func(a_property, a_light) && (!netimmerse_cast(a_property) || (a_light->portalStrict || !a_light->portalGraph || skyrim_cast(a_light))); + return func(a_property, a_light) && ((REL::Module::IsVR() && !netimmerse_cast(a_property)) || (a_light->portalStrict || !a_light->portalGraph || skyrim_cast(a_light))); } static inline REL::Relocation func; }; @@ -205,7 +205,7 @@ struct LightLimitFix : Feature { static bool thunk(RE::BSShaderProperty* a_property, RE::BSLight* a_light) { - return func(a_property, a_light) && (!netimmerse_cast(a_property) || (a_light->portalStrict || !a_light->portalGraph || skyrim_cast(a_light))); + return func(a_property, a_light) && ((REL::Module::IsVR() && !netimmerse_cast(a_property)) || (a_light->portalStrict || !a_light->portalGraph || skyrim_cast(a_light))); } static inline REL::Relocation func; }; diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index 2b12cd080..c6481d8dd 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -287,119 +287,121 @@ namespace SIE defines[lastIndex] = { nullptr, nullptr }; } - enum class EffectShaderFlags - { - Vc = 1 << 0, - TexCoord = 1 << 1, - TexCoordIndex = 1 << 2, - Skinned = 1 << 3, - Normals = 1 << 4, - BinormalTangent = 1 << 5, - Texture = 1 << 6, - IndexedTexture = 1 << 7, - Falloff = 1 << 8, - AddBlend = 1 << 10, - MultBlend = 1 << 11, - Particles = 1 << 12, - StripParticles = 1 << 13, - Blood = 1 << 14, - Membrane = 1 << 15, - Lighting = 1 << 16, - ProjectedUv = 1 << 17, - Soft = 1 << 18, - GrayscaleToColor = 1 << 19, - GrayscaleToAlpha = 1 << 20, - IgnoreTexAlpha = 1 << 21, - MultBlendDecal = 1 << 22, - AlphaTest = 1 << 23, - SkyObject = 1 << 24, - MsnSpuSkinned = 1 << 25, - MotionVectorsNormals = 1 << 26, - }; - static void GetEffectShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) { - int lastIndex = 0; - if (descriptor & static_cast(EffectShaderFlags::Vc)) { - defines[lastIndex++] = { "VC", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Vc)) { + defines[0] = { "VC", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::TexCoord)) { - defines[lastIndex++] = { "TEXCOORD", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::TexCoord)) { + defines[0] = { "TEXCOORD", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::TexCoordIndex)) { - defines[lastIndex++] = { "TEXCOORD_INDEX", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::TexCoordIndex)) { + defines[0] = { "TEXCOORD_INDEX", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Skinned)) { - defines[lastIndex++] = { "SKINNED", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Skinned)) { + defines[0] = { "SKINNED", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Normals)) { - defines[lastIndex++] = { "NORMALS", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Normals)) { + defines[0] = { "NORMALS", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::BinormalTangent)) { - defines[lastIndex++] = { "BINORMAL_TANGENT", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::BinormalTangent)) { + defines[0] = { "BINORMAL_TANGENT", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Texture)) { - defines[lastIndex++] = { "TEXTURE", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Texture)) { + defines[0] = { "TEXTURE", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::IndexedTexture)) { - defines[lastIndex++] = { "INDEXED_TEXTURE", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::IndexedTexture)) { + defines[0] = { "INDEXED_TEXTURE", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Falloff)) { - defines[lastIndex++] = { "FALLOFF", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Falloff)) { + defines[0] = { "FALLOFF", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::AddBlend)) { - defines[lastIndex++] = { "ADDBLEND", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::AddBlend)) { + defines[0] = { "ADDBLEND", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::MultBlend)) { - defines[lastIndex++] = { "MULTBLEND", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::MultBlend)) { + defines[0] = { "MULTBLEND", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Particles)) { - defines[lastIndex++] = { "PARTICLES", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Particles)) { + defines[0] = { "PARTICLES", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::StripParticles)) { - defines[lastIndex++] = { "STRIP_PARTICLES", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::StripParticles)) { + defines[0] = { "STRIP_PARTICLES", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Blood)) { - defines[lastIndex++] = { "BLOOD", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Blood)) { + defines[0] = { "BLOOD", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Membrane)) { - defines[lastIndex++] = { "MEMBRANE", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Membrane)) { + defines[0] = { "MEMBRANE", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Lighting)) { - defines[lastIndex++] = { "LIGHTING", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Lighting)) { + defines[0] = { "LIGHTING", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::ProjectedUv)) { - defines[lastIndex++] = { "PROJECTED_UV", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::ProjectedUv)) { + defines[0] = { "PROJECTED_UV", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::Soft)) { - defines[lastIndex++] = { "SOFT", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::Soft)) { + defines[0] = { "SOFT", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::GrayscaleToColor)) { - defines[lastIndex++] = { "GRAYSCALE_TO_COLOR", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::GrayscaleToColor)) { + defines[0] = { "GRAYSCALE_TO_COLOR", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::GrayscaleToAlpha)) { - defines[lastIndex++] = { "GRAYSCALE_TO_ALPHA", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::GrayscaleToAlpha)) { + defines[0] = { "GRAYSCALE_TO_ALPHA", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::IgnoreTexAlpha)) { - defines[lastIndex++] = { "IGNORE_TEX_ALPHA", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::IgnoreTexAlpha)) { + defines[0] = { "IGNORE_TEX_ALPHA", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::MultBlendDecal)) { - defines[lastIndex++] = { "MULTBLEND_DECAL", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::MultBlendDecal)) { + defines[0] = { "MULTBLEND_DECAL", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::AlphaTest)) { - defines[lastIndex++] = { "ALPHA_TEST", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::AlphaTest)) { + defines[0] = { "ALPHA_TEST", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::SkyObject)) { - defines[lastIndex++] = { "SKY_OBJECT", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::SkyObject)) { + defines[0] = { "SKY_OBJECT", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::MsnSpuSkinned)) { - defines[lastIndex++] = { "MSN_SPU_SKINNED", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::MsnSpuSkinned)) { + defines[0] = { "MSN_SPU_SKINNED", nullptr }; + ++defines; } - if (descriptor & static_cast(EffectShaderFlags::MotionVectorsNormals)) { - defines[lastIndex++] = { "MOTIONVECTORS_NORMALS", nullptr }; + if (descriptor & static_cast(ShaderCache::EffectShaderFlags::MotionVectorsNormals)) { + defines[0] = { "MOTIONVECTORS_NORMALS", nullptr }; + ++defines; } - defines[lastIndex] = { nullptr, nullptr }; + for (auto* feature : Feature::GetFeatureList()) { + if (feature->loaded && feature->HasShaderDefine(RE::BSShader::Type::Effect)) { + defines[0] = { feature->GetShaderDefineName().data(), nullptr }; + ++defines; + } + } + + defines[0] = { nullptr, nullptr }; } static void GetWaterShaderDefines(uint32_t descriptor, D3D_SHADER_MACRO* defines) @@ -492,6 +494,9 @@ namespace SIE case RE::BSShader::Type::Particle: GetParticleShaderDefines(descriptor, defines); break; + case RE::BSShader::Type::Effect: + GetEffectShaderDefines(descriptor, defines); + break; } } diff --git a/src/ShaderCache.h b/src/ShaderCache.h index 1719bfee0..2dd1ebeb7 100644 --- a/src/ShaderCache.h +++ b/src/ShaderCache.h @@ -102,7 +102,8 @@ namespace SIE type == RE::BSShader::Type::Sky || type == RE::BSShader::Type::Grass || type == RE::BSShader::Type::Particle || - type == RE::BSShader::Type::Water; + type == RE::BSShader::Type::Water || + type == RE::BSShader::Type::Effect; return type == RE::BSShader::Type::Lighting || type == RE::BSShader::Type::Grass; } @@ -230,6 +231,36 @@ namespace SIE BlendNormals = 1 << 10, }; + enum class EffectShaderFlags + { + Vc = 1 << 0, + TexCoord = 1 << 1, + TexCoordIndex = 1 << 2, + Skinned = 1 << 3, + Normals = 1 << 4, + BinormalTangent = 1 << 5, + Texture = 1 << 6, + IndexedTexture = 1 << 7, + Falloff = 1 << 8, + AddBlend = 1 << 10, + MultBlend = 1 << 11, + Particles = 1 << 12, + StripParticles = 1 << 13, + Blood = 1 << 14, + Membrane = 1 << 15, + Lighting = 1 << 16, + ProjectedUv = 1 << 17, + Soft = 1 << 18, + GrayscaleToColor = 1 << 19, + GrayscaleToAlpha = 1 << 20, + IgnoreTexAlpha = 1 << 21, + MultBlendDecal = 1 << 22, + AlphaTest = 1 << 23, + SkyObject = 1 << 24, + MsnSpuSkinned = 1 << 25, + MotionVectorsNormals = 1 << 26, + }; + uint blockedKeyIndex = (uint)-1; // index in shaderMap; negative value indicates disabled std::string blockedKey = ""; std::vector blockedIDs; // more than one descriptor could be blocked based on shader hash