|
|
|
|
|
|
#define ATMOSPHERICS_DBG_RAYLEIGH 4 |
|
|
|
#define ATMOSPHERICS_DBG_MIE 5 |
|
|
|
#define ATMOSPHERICS_DBG_HEIGHT 6 |
|
|
|
uniform int _AtmosphericsDebugMode; |
|
|
|
|
|
|
|
uniform int _AtmosphericsDebugMode; |
|
|
|
|
|
|
|
uniform float3 _SunDirection; |
|
|
|
|
|
|
|
|
|
|
uniform float _OcclusionDepthThreshold; |
|
|
|
TEXTURE2D(_OcclusionTexture); |
|
|
|
|
|
|
|
uniform sampler2D _CameraDepthTexture; |
|
|
|
|
|
|
|
uniform float _WorldScaleExponent; |
|
|
|
uniform float _WorldNormalDistanceRcp; |
|
|
|
|
|
|
uniform float3 _MieColorO00; |
|
|
|
uniform float3 _MieColorP20; |
|
|
|
uniform float3 _MieColorP45; |
|
|
|
|
|
|
|
|
|
|
|
uniform float _HeightNormalDistanceRcp; |
|
|
|
uniform float _HeightNearScatterPush; |
|
|
|
uniform float _HeightRayleighDensity; |
|
|
|
|
|
|
|
|
|
|
uniform float4 _HeightRayleighColor; |
|
|
|
|
|
|
|
SAMPLER2D(sampler_CameraDepthTexture) |
|
|
|
#define SRL_BilinearSampler sampler_CameraDepthTexture // Used for all textures |
|
|
|
|
|
|
|
TEXTURE2D(_CameraDepthTexture); |
|
|
|
TEXTURE2D(_OcclusionTexture); |
|
|
|
|
|
|
|
float HenyeyGreensteinPhase(float g, float cosTheta) { |
|
|
|
float gSqr = g * g; |
|
|
|
float a1 = (1.f - gSqr); |
|
|
|
|
|
|
return (a1 / a2) * (b1 / b2); |
|
|
|
return (a1 / a2) * (b1 / b2); |
|
|
|
} |
|
|
|
|
|
|
|
float RayleighPhase(float cosTheta) { |
|
|
|
|
|
|
const float3 worldDir = worldVec / worldVecLen; |
|
|
|
|
|
|
|
const float3 worldDirUnscaled = normalize(worldPos - _WorldSpaceCameraPos.xyz); |
|
|
|
|
|
|
|
|
|
|
|
const float viewSunCos = dot(worldDirUnscaled, _SunDirection); |
|
|
|
const float rayleighPh = min(1.f, RayleighPhase(viewSunCos) * 12.f); |
|
|
|
const float miePh = MiePhase(viewSunCos, _MiePhaseAnisotropy); |
|
|
|
|
|
|
const float angleY = worldDir.y * saturate(worldVecLen / 250.0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float3 mieColor; |
|
|
|
if(angleY >= 0.f) mieColor = lerp(_MieColorO00, _MieColorP20, saturate(angleY / angle20)); |
|
|
|
else mieColor = lerp(_MieColorM20, _MieColorO00, saturate((angleY + angle20) / angle20)); |
|
|
|
|
|
|
|
|
|
|
rayleighColor = lerp(Luminance(rayleighColor).rrr, rayleighColor, saturate(pushedDistance * _WorldNormalDistanceRcp)); |
|
|
|
float3 heightRayleighColor = lerp(Luminance(_HeightRayleighColor.xyz).rrr, _HeightRayleighColor.xyz, saturate(pushedHeightDistance * _HeightNormalDistanceRcp)); |
|
|
|
|
|
|
|
|
|
|
|
coords1.rgb = rayleighScatter * rayleighColor; |
|
|
|
coords1.a = rayleighScatter; |
|
|
|
|
|
|
|
|
|
|
void VolundTransferScatter(float3 scaledWorldPos, out float4 coords1) { |
|
|
|
float4 c1, c2, c3; |
|
|
|
VolundTransferScatter(scaledWorldPos, c1, c2, c3); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef IS_RENDERING_SKY |
|
|
|
coords1.rgb = c3.rgb; |
|
|
|
coords1.a = max(0.f, 1.f - c3.a * _HeightExtinctionFactor); |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
float2 UVFromPos(float2 pos) { |
|
|
|
#if defined(UNITY_PASS_FORWARDBASE) |
|
|
|
return pos; |
|
|
|
#else |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
float3 VolundApplyScatter(float4 coords1, float2 pos, float3 color) { |
|
|
|
|
|
|
void VolundTransferScatterOcclusion(float3 scaledWorldPos, out float4 coords1, out float3 coords2) { |
|
|
|
float4 c1, c2, c3; |
|
|
|
VolundTransferScatter(scaledWorldPos, c1, c2, c3); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
coords2.rgb = c3.rgb + c1.rgb * _RayleighInScatterPct.y; |
|
|
|
|
|
|
|
#ifdef ATMOSPHERICS_DEBUG |
|
|
|
|
|
|
float VolundSampleScatterOcclusion(float2 pos) { |
|
|
|
#if defined(ATMOSPHERICS_OCCLUSION) |
|
|
|
float2 uv = UVFromPos(pos); |
|
|
|
#if defined(ATMOSPHERICS_OCCLUSION_EDGE_FIXUP) && defined(SHADER_API_D3D11) && SHADER_TARGET > 40 |
|
|
|
#if defined(ATMOSPHERICS_OCCLUSION_EDGE_FIXUP) |
|
|
|
float cDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, baseUV); |
|
|
|
float cDepth = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV, 0.f).r; |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.zy; xDepth.x = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, baseUV); |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.xy; xDepth.y = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, baseUV); |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.xw; xDepth.z = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, baseUV); |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.zw; xDepth.w = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, baseUV); |
|
|
|
|
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.zy; xDepth.x = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.xy; xDepth.y = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.xw; xDepth.z = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|
|
|
baseUV.xy = uv + _DepthTextureScaledTexelSize.zw; xDepth.w = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return _OcclusionTexture.SampleLevel(sampler_OcclusionTexture, uv, 0.f); |
|
|
|
return SAMPLE_TEXTURE2D_LOD(_OcclusionTexture, SRL_BilinearSampler, uv, 0.f).r; |
|
|
|
float4 occ = _OcclusionTexture.Gather(sampler_OcclusionTexture, uv); |
|
|
|
|
|
|
|
float4 occ = GATHER_TEXTURE2D(_OcclusionTexture, SRL_BilinearSampler, uv); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
return UNITY_SAMPLE_TEX2D(_OcclusionTexture, uv).r; |
|
|
|
#endif |
|
|
|
#else //defined(ATMOSPHERICS_OCCLUSION) |
|
|
|
return 1.f; |
|
|
|
#endif //defined(ATMOSPHERICS_OCCLUSION) |
|
|
|
|
|
|
float occlusion = VolundSampleScatterOcclusion(pos); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef ATMOSPHERICS_DEBUG |
|
|
|
if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_SCATTERING) |
|
|
|
return coords1.rgb + coords2.rgb; |
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
color.rgb = color.rgb * coords1.a + coords1.rgb * min(1.f, occlusion + _ShadowBias) + coords2.rgb * min(1.f, occlusion + _ShadowBiasIndirect); |
|
|
|
|
|
|
|
|
|
|
|
float cloudOcclusion = min(1.f, occlusion + _ShadowBiasClouds); |
|
|
|
color.a *= cloudOcclusion; |
|
|
|
|
|
|
|
|
|
|
#define VOLUND_TRANSFER_SCATTER(pos, o) VolundTransferScatter(pos, o.scatterCoords1) |
|
|
|
#define VOLUND_APPLY_SCATTER(i, color) color = VolundApplyScatter(i.scatterCoords1, i.pos.xy, color) |
|
|
|
#define VOLUND_CLOUD_SCATTER(i, color) color = VolundApplyCloudScatter(i.scatterCoords1, color) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
// Surface shader macros (specifically do nothing for deferred as that needs post-support) |
|
|
|
#if defined(ATMOSPHERICS) |
|
|
|
#if defined(UNITY_PASS_FORWARDBASE) && defined(ATMOSPHERICS_OCCLUSION) |
|
|
|
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float4 scatterCoords1; float3 scatterCoords2; |
|
|
|
#define SURFACE_SCATTER_TRANSFER(pos, o) VolundTransferScatterOcclusion(pos, o.scatterCoords1, o.scatterCoords2) |
|
|
|
/* we can't fit screenPos interpolator, so calculate per-pixel. if only we had vpos available.. */ |
|
|
|
#define SURFACE_SCATTER_APPLY(i, color) { \ |
|
|
|
float4 scatterPos = ComputeScreenPos(mul(UNITY_MATRIX_VP, float4(i.scaledWorldPos, 1.f))); \ |
|
|
|
color = VolundApplyScatterOcclusion(i.scatterCoords1, i.scatterCoords2, scatterPos.xy / scatterPos.w, color); \ |
|
|
|
} |
|
|
|
#elif defined(UNITY_PASS_FORWARDBASE) |
|
|
|
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float4 scatterCoords1; float scatterCoords2; |
|
|
|
#define SURFACE_SCATTER_TRANSFER(pos, o) VolundTransferScatter(pos, o.scatterCoords1) |
|
|
|
#define SURFACE_SCATTER_APPLY(i, color) { \ |
|
|
|
float4 scatterPos = ComputeScreenPos(mul(UNITY_MATRIX_VP, float4(i.scaledWorldPos, 1.f))); \ |
|
|
|
color = VolundApplyScatter(i.scatterCoords1, scatterPos.xy / scatterPos.w, color); \ |
|
|
|
} |
|
|
|
#elif defined(UNITY_PASS_FORWARDADD) |
|
|
|
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float scatterCoords1; float scatterCoords2; |
|
|
|
#define SURFACE_SCATTER_TRANSFER(pos, o) { float4 scatterCoords; VolundTransferScatter(pos, scatterCoords); o.scatterCoords1 = scatterCoords.a; } |
|
|
|
#define SURFACE_SCATTER_APPLY(i, color) color = VolundApplyScatterAdd(i.scatterCoords1, color) |
|
|
|
#endif |
|
|
|
#elif defined(ATMOSPHERICS_PER_PIXEL) |
|
|
|
#if defined(UNITY_PASS_FORWARDBASE) && defined(ATMOSPHERICS_OCCLUSION) |
|
|
|
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float scatterCoords1; float scatterCoords2; |
|
|
|
#define SURFACE_SCATTER_TRANSFER(pos, o) |
|
|
|
#define SURFACE_SCATTER_APPLY(i, color) { \ |
|
|
|
float4 scatterPos = ComputeScreenPos(mul(UNITY_MATRIX_VP, float4(i.scaledWorldPos, 1.f))); \ |
|
|
|
float4 scatterCoords1; float3 scatterCoords2; VolundTransferScatterOcclusion(i.scaledWorldPos, scatterCoords1, scatterCoords2); \ |
|
|
|
color = VolundApplyScatterOcclusion(scatterCoords1, scatterCoords2, scatterPos.xy / scatterPos.w, color); \ |
|
|
|
} |
|
|
|
#elif defined(UNITY_PASS_FORWARDBASE) |
|
|
|
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float scatterCoords1; float scatterCoords2; |
|
|
|
#define SURFACE_SCATTER_TRANSFER(pos, o) |
|
|
|
#define SURFACE_SCATTER_APPLY(i, color) { \ |
|
|
|
float4 scatterCoords1; VolundTransferScatter(i.scaledWorldPos, scatterCoords1); \ |
|
|
|
float4 scatterPos = ComputeScreenPos(mul(UNITY_MATRIX_VP, float4(i.scaledWorldPos, 1.f))); \ |
|
|
|
color = VolundApplyScatter(scatterCoords1, scatterPos.xy / scatterPos.w, color); \ |
|
|
|
} |
|
|
|
#elif defined(UNITY_PASS_FORWARDADD) |
|
|
|
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float scatterCoords1; float scatterCoords2; |
|
|
|
#define SURFACE_SCATTER_TRANSFER(pos, o) |
|
|
|
#define SURFACE_SCATTER_APPLY(i, color) { \ |
|
|
|
float4 scatterCoords1; VolundTransferScatter(i.scaledWorldPos, scatterCoords1); \ |
|
|
|
color = VolundApplyScatterAdd(scatterCoords1.a, color); \ |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|