I have found a shader that I like here: https://www.shadertoy.com/view/4dyXWy
The code for the fragment shader from the link above is:
#define DITHER //Dithering toggle
#define QUALITY 0 //0- low, 1- medium, 2- high
#define DECAY .974
#define EXPOSURE .24
#if (QUALITY==2)
#define SAMPLES 64
#define DENSITY .97
#define WEIGHT .25
#else
#if (QUALITY==1)
#define SAMPLES 32
#define DENSITY .95
#define WEIGHT .25
#else
#define SAMPLES 16
#define DENSITY .93
#define WEIGHT .36
#endif
#endif
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
vec2 coord = uv;
vec2 lightpos = texture(iChannel0, uv).zw;
float occ = texture(iChannel0, uv).x; //light
float obj = texture(iChannel0, uv).y; //objects
float dither = texture(iChannel1, fragCoord/iChannelResolution[1].xy).r;
vec2 dtc = (coord - lightpos) * (1. / float(SAMPLES) * DENSITY);
float illumdecay = 1.;
for(int i=0; i<SAMPLES; i++)
{
coord -= dtc;
#ifdef DITHER
float s = texture(iChannel0, coord+(dtc*dither)).x;
#else
float s = texture(iChannel0, coord).x;
#endif
s *= illumdecay * WEIGHT;
occ += s;
illumdecay *= DECAY;
}
fragColor = vec4(vec3(0., 0., obj*.333)+occ*EXPOSURE,1.0);
}
That is in GLSL, but I am using DirectX 11. I've been able to port it across quite easily, but I feel like I have some knowledge gaps that are making it hard for me to get correct. For example, I don't understand the difference between texture(iChannel0, uv).x
and texture(iChannel0, uv).r
if someone wouldn't mind explaining ( I understand sampling the colour channels but xyz while sampling?).
I also do not understand the channel resolution. Is it the dimensions of the 2D texture that I'm rendering to? Or perhaps the ratio of the texture?
Here is what I have come up with so far, just the bare minimum of changes to get it working:
SamplerState g_samSampler : register( s0 );
Texture2D g_texInfo : register( t0 );
#define DITHER
#define DECAY 0.974f
#define EXPOSURE 0.24f
#define SAMPLES 64
#define DENSITY 0.97f
#define WEIGHT 0.25f
struct PixelInput
{
float4 vPosition : SV_POSITION;
float2 vTexCoord : TEXCOORD0;
};
float4 PS( PixelInput input ) : SV_TARGET
{
float2 uv = input.vTexCoord;
float2 coord = uv;
float2 lightpos = g_texInfo.Sample( g_samSampler, uv ).zw; //TAKE NOTE OF THIS LINE
float occ = g_texInfo.Sample( g_samSampler, input.vTexCoord ).g; //light
float obj = g_texInfo.Sample( g_samSampler, input.vTexCoord ).b; //objects
float dither = g_texInfo.Sample( g_samSampler, uv/float2( 4.f, 3.f ) ).x;
float2 dtc = (coord - lightpos) * (1.f / float(SAMPLES) * DENSITY);
float illumdecay = 1.;
for(int i=0; i<SAMPLES; i++)
{
coord -= dtc;
#ifdef DITHER
float s = g_texInfo.Sample( g_samSampler, coord+(dtc*dither) ).g;
#else
float s = g_texInfo.Sample( g_samSampler, input.vTexCoord ).g;
#endif
s *= illumdecay * WEIGHT;
occ += s;
illumdecay *= DECAY;
}
return float4(float3(0.f, 0.f, obj*.333f)+occ*EXPOSURE,1.f);
}
Please note that my green channel of the passed in texture g_texInfo
stores the light texture (the white circle for the sun) and the blue channel stores the light occluders.
I am doing this as a post processing effect on a screen quad. (Is this correct?)
My suspicion is the line float2 lightpos = g_texInfo.Sample( g_samSampler, uv ).zw;
is causing the trouble - I don't really understand this part - how can I find the position of the sun?
Here's what I'm receiving from my current shader, it appears that the light rays are being emitted in the wrong direction.
When I shift the camera so that the sun is in the top left, it gives the correct effect, it is also occluded properly when putting an object in the way.