Skip to content

Instantly share code, notes, and snippets.

@HAliss
Created January 13, 2025 08:03
Show Gist options
  • Save HAliss/f84e3c482ea2ac9664a3048fa734093c to your computer and use it in GitHub Desktop.
Save HAliss/f84e3c482ea2ac9664a3048fa734093c to your computer and use it in GitHub Desktop.
A simple volumetric fog shader
Shader "Tutorial/VolumetricFog"
{
Properties
{
_Color("Color", Color) = (1, 1, 1, 1)
_MaxDistance("Max distance", float) = 100
_StepSize("Step size", Range(0.1, 20)) = 1
_DensityMultiplier("Density multiplier", Range(0, 10)) = 1
_NoiseOffset("Noise offset", float) = 0
_FogNoise("Fog noise", 3D) = "white" {}
_NoiseTiling("Noise tiling", float) = 1
_DensityThreshold("Density threshold", Range(0, 1)) = 0.1
[HDR]_LightContribution("Light contribution", Color) = (1, 1, 1, 1)
_LightScattering("Light scattering", Range(0, 1)) = 0.2
}
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
float4 _Color;
float _MaxDistance;
float _DensityMultiplier;
float _StepSize;
float _NoiseOffset;
TEXTURE3D(_FogNoise);
float _DensityThreshold;
float _NoiseTiling;
float4 _LightContribution;
float _LightScattering;
float henyey_greenstein(float angle, float scattering)
{
return (1.0 - angle * angle) / (4.0 * PI * pow(1.0 + scattering * scattering - (2.0 * scattering) * angle, 1.5f));
}
float get_density(float3 worldPos)
{
float4 noise = _FogNoise.SampleLevel(sampler_TrilinearRepeat, worldPos * 0.01 * _NoiseTiling, 0);
float density = dot(noise, noise);
density = saturate(density - _DensityThreshold) * _DensityMultiplier;
return density;
}
half4 frag(Varyings IN) : SV_Target
{
float4 col = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, IN.texcoord);
float depth = SampleSceneDepth(IN.texcoord);
float3 worldPos = ComputeWorldSpacePosition(IN.texcoord, depth, UNITY_MATRIX_I_VP);
float3 entryPoint = _WorldSpaceCameraPos;
float3 viewDir = worldPos - _WorldSpaceCameraPos;
float viewLength = length(viewDir);
float3 rayDir = normalize(viewDir);
float2 pixelCoords = IN.texcoord * _BlitTexture_TexelSize.zw;
float distLimit = min(viewLength, _MaxDistance);
float distTravelled = InterleavedGradientNoise(pixelCoords, (int)(_Time.y / max(HALF_EPS, unity_DeltaTime.x))) * _NoiseOffset;
float transmittance = 1;
float4 fogCol = _Color;
while(distTravelled < distLimit)
{
float3 rayPos = entryPoint + rayDir * distTravelled;
float density = get_density(rayPos);
if (density > 0)
{
Light mainLight = GetMainLight(TransformWorldToShadowCoord(rayPos));
fogCol.rgb += mainLight.color.rgb * _LightContribution.rgb * henyey_greenstein(dot(rayDir, mainLight.direction), _LightScattering) * density * mainLight.shadowAttenuation * _StepSize;
transmittance *= exp(-density * _StepSize);
}
distTravelled += _StepSize;
}
return lerp(col, fogCol, 1.0 - saturate(transmittance));
}
ENDHLSL
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment