146 lines
5.7 KiB
HLSL
146 lines
5.7 KiB
HLSL
// expects first normal to be unpacked already
|
|
half3 UnpackAndBlendNormals(fixed3 n1, fixed4 n2, fixed4 n3) {
|
|
half3 normal;
|
|
#if defined(UNITY_NO_DXT5nm)
|
|
normal = normalize( n1 + (n2.xyz * 2 - 1) + (n3.xyz * 2 - 1) );
|
|
#else
|
|
normal.xy = n1.xy;
|
|
normal.xy += (n2.ag * 2 - 1) * _BumpScale.y;
|
|
normal.xy += (n3.ag * 2 - 1) * _BumpScale.z;
|
|
normal.z = sqrt(1.0 - saturate( normal.x * normal.x + normal.y * normal.y));
|
|
normal = normalize(normal);
|
|
#endif
|
|
return normal;
|
|
}
|
|
|
|
half3 WorldNormal(half3 t0, half3 t1, half3 t2, half3 normal) {
|
|
// normalize is done once in the fragment shader
|
|
return /*normalize*/( half3( dot(t0, normal), dot(t1, normal), dot(t2, normal) ) );
|
|
}
|
|
|
|
float2 rotate2D(float2 v, float a) {
|
|
float s = sin(a);
|
|
float c = cos(a);
|
|
float2x2 m = float2x2(c, -s, s, c);
|
|
return mul(m, v);
|
|
}
|
|
|
|
// Shadow Helpers -------------------------------------------------
|
|
|
|
UNITY_DECLARE_SHADOWMAP(_LuxParticles_CascadedShadowMap);
|
|
|
|
float computeShadowFadeDistance(float3 wpos, float z) {
|
|
float sphereDist = distance(wpos, unity_ShadowFadeCenterAndType.xyz);
|
|
return lerp(z, sphereDist, unity_ShadowFadeCenterAndType.w);
|
|
}
|
|
half computeShadowFade(float fadeDist) {
|
|
return saturate(fadeDist * _LightShadowData.z + _LightShadowData.w);
|
|
}
|
|
|
|
inline fixed4 getCascadeWeights_splitSpheres(float3 wpos) {
|
|
float3 fromCenter0 = wpos.xyz - unity_ShadowSplitSpheres[0].xyz;
|
|
float3 fromCenter1 = wpos.xyz - unity_ShadowSplitSpheres[1].xyz;
|
|
float3 fromCenter2 = wpos.xyz - unity_ShadowSplitSpheres[2].xyz;
|
|
float3 fromCenter3 = wpos.xyz - unity_ShadowSplitSpheres[3].xyz;
|
|
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
|
|
fixed4 weights = float4(distances2 < unity_ShadowSplitSqRadii);
|
|
weights.yzw = saturate(weights.yzw - weights.xyz);
|
|
return weights;
|
|
}
|
|
|
|
inline float4 getShadowCoord(float4 wpos, fixed4 cascadeWeights) {
|
|
float3 sc0 = mul(unity_WorldToShadow[0], wpos).xyz;
|
|
float3 sc1 = mul(unity_WorldToShadow[1], wpos).xyz;
|
|
float3 sc2 = mul(unity_WorldToShadow[2], wpos).xyz;
|
|
float3 sc3 = mul(unity_WorldToShadow[3], wpos).xyz;
|
|
float4 shadowMapCoordinate = float4(sc0 * cascadeWeights[0] + sc1 * cascadeWeights[1] + sc2 * cascadeWeights[2] + sc3 * cascadeWeights[3], 1);
|
|
#if defined(UNITY_REVERSED_Z)
|
|
float noCascadeWeights = 1 - dot(cascadeWeights, float4(1, 1, 1, 1));
|
|
shadowMapCoordinate.z += noCascadeWeights;
|
|
#endif
|
|
return shadowMapCoordinate;
|
|
}
|
|
|
|
float GetLightAttenuation(float3 wpos) {
|
|
// Directional Lights only
|
|
float atten = 1;
|
|
fixed4 cascadeWeights = getCascadeWeights_splitSpheres(wpos);
|
|
float4 coord = getShadowCoord(float4(wpos, 1), cascadeWeights);
|
|
atten = UNITY_SAMPLE_SHADOW(_LuxParticles_CascadedShadowMap, coord.xyz);
|
|
// Fade out shadows
|
|
float zDist = dot(_WorldSpaceCameraPos - wpos, UNITY_MATRIX_V[2].xyz);
|
|
float fadeDist = computeShadowFadeDistance(wpos, zDist);
|
|
half realtimeShadowFade = computeShadowFade(fadeDist);
|
|
atten = lerp (_LightShadowData.r, 1.0f, saturate(atten + realtimeShadowFade));
|
|
return atten;
|
|
}
|
|
|
|
// https://forum.unity.com/threads/fixing-screen-space-directional-shadows-and-anti-aliasing.379902/
|
|
// Thanks bgolus once more!
|
|
float MSSADepth(float fragDepth, float sceneDepth, float depth_raw, float2 screenUV) {
|
|
|
|
// this is good far distances but bad at close distances
|
|
// screenUV.xy = (screenUV.xy * (_CameraDepthTexture_TexelSize.zw - 1.0) + 0.5f) * _CameraDepthTexture_TexelSize.xy;
|
|
// this is bad too
|
|
// screenUV = (floor(screenUV * _CameraDepthTexture_TexelSize.zw) + 0.5) / _CameraDepthTexture_TexelSize.zw;
|
|
// Testing, testing, testing - and finding a good compromise...
|
|
// screenUV.x -= _CameraDepthTexture_TexelSize.x;
|
|
|
|
float depthDiff = abs(fragDepth - sceneDepth); //LinearEyeDepth(depth_raw));
|
|
|
|
// The if does not safe much but stabilizes results (jittering)
|
|
if (depthDiff < 20.0) {
|
|
// Would help the 0,1 offsets
|
|
//screenUV.x -= 0.975 * _CameraDepthTexture_TexelSize.x;
|
|
|
|
float2 texelSize = _CameraDepthTexture_TexelSize.xy;
|
|
float4 offsetDepths = 0;
|
|
|
|
// https://github.com/TheRealMJP/MSAAFilter/blob/master/MSAAFilter/Resolve.hlsl
|
|
// These offsets are not very stable
|
|
#define FACTOR 1.0f
|
|
float2 uvOffsetsX[5] = {
|
|
float2(-0.125f, -0.375f) * FACTOR * texelSize,
|
|
float2(0.375f, -0.125f) * FACTOR * texelSize,
|
|
float2(-0.375f, 0.125f) * FACTOR * texelSize,
|
|
float2(0.125f, 0.375f) * FACTOR * texelSize,
|
|
float2(0.0, 0.0)
|
|
};
|
|
|
|
// These offsets create strange jagged artifacts
|
|
float2 uvOffsets[5] = {
|
|
float2(1.0, 0.0) * texelSize,
|
|
float2(-1.0, 0.0) * texelSize,
|
|
float2(0.0, 1.0) * texelSize,
|
|
float2(0.0, -1.0) * texelSize,
|
|
float2(0.0, 0.0)
|
|
};
|
|
|
|
offsetDepths.x = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(screenUV + uvOffsets[0], 0, 0));
|
|
offsetDepths.y = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(screenUV + uvOffsets[1], 0, 0));
|
|
offsetDepths.z = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(screenUV + uvOffsets[2], 0, 0));
|
|
offsetDepths.w = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(screenUV + uvOffsets[3], 0, 0));
|
|
|
|
float4 offsetDiffs = abs(fragDepth - offsetDepths);
|
|
float diffs[4] = { offsetDiffs.x, offsetDiffs.y, offsetDiffs.z, offsetDiffs.w };
|
|
|
|
int lowest = 0;
|
|
float tempDiff = depthDiff;
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
// TODO: why is it flipped - at least when using perspective?
|
|
#if defined(UNITY_REVERSED_Z)
|
|
if (diffs[i] > tempDiff) { // DX11
|
|
#else
|
|
if (diffs[i] < tempDiff) { // OpenGL
|
|
#endif
|
|
tempDiff = diffs[i];
|
|
lowest = i;
|
|
}
|
|
}
|
|
return SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(screenUV + uvOffsets[lowest], 0, 0));
|
|
}
|
|
else {
|
|
return depth_raw;
|
|
}
|
|
} |