Preventing sunshaft banding

Recently I was making a scene with the sun shining from behind some mountains and got a lot of sunshaft banding. I wasn’t able to see any set of CVAR controls that would keep the fidelity I wanted but without the banding. I ended up jumping into the Sunshafts.cfx shader to increase the sampling to get the fidelity I wanted.

To modify the shader so you can control the number of samples, open Sunshafts.cfx, comment out the current sampling code (8 samples) in SunShaftsGenPS and add a loop that lets you control the samples and range like this:

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 1.0);      
//accum += depth * (1.0-1.0/8.0);

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 2.0);      
//accum += depth * (1.0-2.0/8.0);

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 3.0);      
//accum += depth * (1.0-3.0/8.0);

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 4.0);      
//accum += depth * (1.0-4.0/8.0);

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 5.0);      
//accum += depth * (1.0-5.0/8.0);

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 6.0);      
//accum += depth * (1.0-6.0/8.0);

//depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * 7.0);      
//accum += depth * (1.0-7.0/8.0);

//accum /= 8.0;

half samples = 16.0;
half range = 0.5;
for (half current_sample = 1; current_sample <= samples; ++current_sample)
{
	depth = tex2D(_tex0, IN.baseTC.xy + sunDir.xy * current_sample * range);
	accum += depth * (1.0 - current_sample / samples);
}

accum /= samples;

This will cost more in terms of performance, but is worth it when taking screenshots or in cut-scenes

7 Likes