Last active
February 8, 2025 10:19
-
-
Save antonkudin/ce2728800afd269ea6b58bf377a423b7 to your computer and use it in GitHub Desktop.
Spherical fog unity shader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// original from https://forum.unity3d.com/threads/share-volume-fog-shader.147323/ | |
Shader "Effect/SphereFog" { | |
Properties { | |
_FogColor ("Fog Color", Color) = (1,1,1,1) | |
[space] | |
_Density ("Density", Float) = 1 | |
_Power ("Power/gamma", Float) = 4 | |
_Offset ("Offset", Range(-.1,.1)) = -0.003 | |
[space] | |
_NearbyOffset ("Nearby Offset", Float) = -1 | |
_NearbyFade ("Nearby Fade", Float) = .6 | |
[space] | |
_Steps ("CalcSteps", Range(1, 50)) = 10 | |
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 1 | |
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend", Float) = 1 | |
} | |
Category { | |
Tags { "Queue"="Transparent+99" "IgnoreProjector"="True" "RenderType"="Transparent" } | |
Blend [_SrcBlend] [_DstBlend] | |
Cull Off Lighting Off ZWrite Off | |
ZTest Always | |
SubShader { | |
Pass { | |
CGPROGRAM | |
#pragma target 3.0 | |
#pragma vertex vert | |
#pragma fragment frag | |
#include "UnityCG.cginc" | |
uniform fixed _Steps; | |
inline float CalcVolumeFogIntensity(float3 sphereCenter, float sphereRadius, float3 cameraPosition, float3 viewDirection, float backDepth, float maxDistance) | |
{ | |
// Local is the cam position in local space of the sphere. | |
float3 local = cameraPosition - sphereCenter; | |
// Calculate ray-sphere intersection | |
float fA = dot(viewDirection, viewDirection); | |
float fB = 2 * dot(viewDirection, local); | |
float fC = dot(local, local) - sphereRadius * sphereRadius; | |
float fD = fB * fB - 4 * fA * fC; | |
float dist; | |
if (fD == 0.0f) | |
dist = backDepth; | |
else { | |
float DSqrt = sqrt(fD); | |
dist = (-fB - DSqrt) * .5; | |
} | |
dist = min(dist, maxDistance); | |
backDepth = min(backDepth, maxDistance); | |
float sample = dist; | |
float fog = 0; | |
float step_distance = ( backDepth - dist ) / _Steps; | |
for ( int seg = 0; seg < _Steps; seg++ ) | |
{ | |
float3 position = cameraPosition + viewDirection * sample; | |
fog += 1 - saturate( length( sphereCenter - position ) / sphereRadius ); | |
sample += step_distance; | |
} | |
fog /= _Steps; | |
return fog; | |
} | |
uniform fixed4 _FogColor; | |
uniform float _Density; | |
uniform float _Power; | |
uniform float _NearbyFade, _NearbyOffset; | |
uniform float _Offset; | |
uniform sampler2D _CameraDepthTexture; | |
struct appdat { | |
float4 vertex : POSITION; | |
fixed4 color : COLOR; | |
}; | |
struct v2f { | |
float4 pos : SV_POSITION; | |
float3 view : TEXCOORD0; | |
float4 projPos : TEXCOORD1; | |
float4 centerSize : TEXCOORD2; | |
fixed4 color : COLOR; | |
}; | |
v2f vert (appdat v) | |
{ | |
v2f o; | |
float4 wPos = mul (unity_ObjectToWorld, v.vertex); | |
o.pos = UnityObjectToClipPos (v.vertex); | |
o.view = wPos.xyz - _WorldSpaceCameraPos; | |
o.projPos = ComputeScreenPos (o.pos); | |
half3x3 m = (half3x3)UNITY_MATRIX_M; | |
half objectScale = length(half3(m[0][0], m[1][0], m[2][0])); | |
o.centerSize = mul(unity_ObjectToWorld, float4(0,0,0,1)); | |
o.centerSize.w = objectScale/2; | |
o.color = v.color * _FogColor; | |
return o; | |
} | |
half4 frag (v2f i) : COLOR | |
{ | |
i.projPos.xyz /= i.projPos.w; | |
float depth = LinearEyeDepth(tex2D(_CameraDepthTexture, i.projPos.xy).r); | |
float3 viewDir = normalize(i.view); | |
// fix by @yetmania | |
float3 vpos = mul(unity_WorldToCamera, float4(viewDir, 0.0)); | |
depth = length(vpos * depth / vpos.z); | |
float backDist = 0;//length(i.view); | |
float fog = CalcVolumeFogIntensity(i.centerSize.xyz, i.centerSize.w, _WorldSpaceCameraPos, viewDir, backDist, depth) * _Density; | |
fog = saturate(pow(fog+_Offset, _Power)); | |
// fade out if camera is close to far side of sphere | |
// probably would be better if it was incorporated into the fog intensity function | |
if(_NearbyFade>0){ | |
float dist = length(i.view)+_NearbyOffset; | |
float fade = saturate(dist/_NearbyFade); | |
fog *= fade; | |
} | |
return float4((_FogColor.rgb * i.color.rgb) * fog, 1); | |
} | |
ENDCG | |
} | |
} | |
} | |
Fallback "VertexLit" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Spherical fog shader.
Supports vertex color. Supply with sphere mesh (might even work with quad or cube).
Scale transform and fog radius will change (only uses X scale value).
Fixed and adapted from original: https://forum.unity.com/threads/share-volume-fog-shader.147323/