To elaborate, screen space sun shafts are imho kinda easy for both 2D and 3D, you generally need projection from 3D space to screen anyway (I mean, you are rendering objects, we are talking three multiplication of three matrices here and some screen data).
Issue comes in if you want to do it right way which means rendering screenshaft even if you are not looking at source, great examples there are GTA V and Lords of Fallen, which actually made pretty good presentation on that topic:
I know that´s not what you want, I just want that this technique is more spread and we are slowly moving in direction of removing old school screen space light shafts where it makes sense.
But, so I am not here just to preach....
from your git:
float2 TexCoord = texCoord - halfPixel;
DeltaTexCoord = DeltaTexCoord ;
You shouldnt need halfPixel correction here, what you need tho is position of source, thus:
float4 PixelShaderFunction(float4 position : SV_Position, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
// Calculate vector from pixel to light source in screen space.
float2 deltaTexCoord = (texCoord - ScreenLightPos.xy);
// Divide by number of samples and scale by control factor.
deltaTexCoord *= 1.0f / NUM_SAMPLES * Density;
// Store initial sample.
float3 base = tex2D(TextureSampler, texCoord);
// Set up illumination decay factor.
float illuminationDecay = 1.0f;
// Evaluate summation from Equation 3 NUM_SAMPLES iterations.
for (int i = 0; i < NUM_SAMPLES; i++)
// Step sample location along ray.
texCoord -= deltaTexCoord;
// Retrieve sample at new location.
sample = tex2D(TextureSampler, texCoord).rgb;
// Apply sample attenuation scale/decay factors.
sample *= illuminationDecay * Weight;
// Accumulate combined color.
base += sample;
// Update exponential decay factor.
illuminationDecay *= Decay;
base = clamp(base, 0, Max); //You dont need this if you dont want to clamp max intensity, it can be useful, tho I recommend HDR tone mapping as well if you are using bloom or LS when composing your postprocessing in last step
return float4(base * Exposure, 1);