Skip to content

Instantly share code, notes, and snippets.

@antonkudin
Last active January 9, 2024 05:55
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antonkudin/ce2728800afd269ea6b58bf377a423b7 to your computer and use it in GitHub Desktop.
Save antonkudin/ce2728800afd269ea6b58bf377a423b7 to your computer and use it in GitHub Desktop.
Spherical fog unity shader
// 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"
}
@antonkudin
Copy link
Author

antonkudin commented Oct 4, 2023

Screenshot 2023-10-05 at 00 58 41

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/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment