Sun shafts via postprocess artefacts

Started by
6 comments, last by AndreyVK_D3D 6 years, 2 months ago

Hi all!

I try to use the Sun shafts effects via post process in my 3DEngine, but i have some artefacts on final image(Please see attached images).

The effect contains the following passes:

1) Depth scene pass;

2) "Shafts pass" Using DepthPass Texture + RGBA BackBuffer texture.

3) Shafts pass texture +  RGBA BackBuffer texture.

Shafts shader for 2 pass:


//
uniform sampler2D FullSampler; // RGBA Back Buffer
uniform sampler2D DepthSampler;

varying vec2 tex;

#ifndef saturate
float saturate(float val)
{
    return clamp(val, 0.0, 1.0);
}
#endif

void main(void)
{
    vec2 uv = tex;
    float sceneDepth = texture2D(DepthSampler, uv.xy).r;
    vec4  scene        = texture2D(FullSampler, tex);
    float fShaftsMask     = (1.0 - sceneDepth);
    gl_FragColor = vec4( scene.xyz * saturate(sceneDepth), fShaftsMask );
}

final shader:


//
uniform sampler2D FullSampler; // RGBA Back Buffer
uniform sampler2D BlurSampler; // shafts sampler
varying vec4 Sun_pos;
const vec4    ShaftParams = vec4(0.1,2.0,0.1,2.0);

varying vec2 Tex_UV;

#ifndef saturate 
float saturate(float val)
{
    return clamp(val, 0.0, 1.0);
}
#endif

vec4 blendSoftLight(vec4 a, vec4 b)
{
  vec4 c = 2.0 * a * b + a * a * (1.0 - 2.0 * b);
  vec4 d = sqrt(a) * (2.0 * b - 1.0) + 2.0 * a * (1.0 - b);
   
  // TODO: To look in Crysis what it the shit???
  //return ( b < 0.5 )? c : d;
  return any(lessThan(b, vec4(0.5,0.5,0.5,0.5)))? c : d;
}

void main(void)
{
    vec4 sun_pos = Sun_pos;
    vec2    sunPosProj = sun_pos.xy;
    //float    sign = sun_pos.w;
    float    sign = 1.0;

    vec2    sunVec = sunPosProj.xy - (Tex_UV.xy - vec2(0.5, 0.5));
    float    sunDist = saturate(sign) * saturate( 1.0 - saturate(length(sunVec) * ShaftParams.y ));

    sunVec *= ShaftParams.x * sign;

    vec4 accum;
    vec2 tc = Tex_UV.xy;

    tc += sunVec;
    accum = texture2D(BlurSampler, tc);
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.875;
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.75;
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.625;
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.5;
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.375;
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.25;
    tc += sunVec;
    accum += texture2D(BlurSampler, tc) * 0.125;

    accum  *= 0.25 * vec4(sunDist, sunDist, sunDist, 1.0);
    
     accum.w += 1.0 - saturate(saturate(sign * 0.1 + 0.9));

    vec4    cScreen = texture2D(FullSampler, Tex_UV.xy);      
    vec4    cSunShafts = accum;

    float fShaftsMask = saturate(1.00001 - cSunShafts.w) * ShaftParams.z * 2.0;
        
    float fBlend = cSunShafts.w;

    vec4 sunColor = vec4(0.9, 0.8, 0.6, 1.0);

    accum =  cScreen + cSunShafts.xyzz * ShaftParams.w * sunColor * (1.0 - cScreen);
    accum = blendSoftLight(accum, sunColor * fShaftsMask * 0.5 + 0.5);

    gl_FragColor = accum;
}

Demo project:

Demo Project

Shaders for postprocess Shaders/SunShaft/

What i do wrong ?

Thanks!
 

sun_shafts.png

sun_shafts2.png

3DGraphics,Direct3D12,Vulkan,OpenCL,Algorithms

Advertisement

It looks like its working correctly, you just need more samples to get it smoother I think...

From those images it seem to work correctly, but you should either take more samples or blur the result after the radial blur. You can also do the radial blur pass in a lower resolution which can help with performance and the banding as well. I couldn't really understand your process as you explained so here is what I do:

1.) Draw the sun against scene depth buffer to a render target, depth test on to discard occluded sun pixels

2.) Radial blur on a low-res (0.5x) texture

3.) Draw the result on top with additive blending

8 hours ago, Matt_Aufderheide said:

It looks like its working correctly, you just need more samples to get it smoother I think...

 

6 hours ago, turanszkij said:

but you should either take more samples or blur the result after the radial blur.

Matt_Aufderheide, turanszkij Thanks! But how to calculate of the correct number of samples ? i think we can use the dimension of Render Target for calculation of number of samples.

 

6 hours ago, turanszkij said:

From those images it seem to work correctly, but you should either take more samples or blur the result after the radial blur. You can also do the radial blur pass in a lower resolution which can help with performance and the banding as well. I couldn't really understand your process as you explained so here is what I do:

1.) Draw the sun against scene depth buffer to a render target, depth test on to discard occluded sun pixels

2.) Radial blur on a low-res (0.5x) texture

3.) Draw the result on top with additive blending

Yes, but this is other Sun shafts technique? I think this technique are described there: herehere, also here ?

3DGraphics,Direct3D12,Vulkan,OpenCL,Algorithms

5 hours ago, Andrey OGL_D3D said:

Matt_Aufderheide, turanszkij Thanks! But how to calculate of the correct number of samples ? i think we can use the dimension of Render Target for calculation of number of samples.

You don't have to calculate the correct number of samples, just tweak it until it looks good. I am using 35 samples, but rendering to half-resolution. This gives great results, but probably should take less samples. Also make sure you are using a linear texture filter when sampling.

5 hours ago, Andrey OGL_D3D said:

Yes, but this is other Sun shafts technique? I think this technique are described there: herehere, also here ?

It is the same technique, but for some reason all of them say to draw the scene depth buffer after the sun, but you probably already have a depth buffer by the time you are doing this effect, so best to just reuse that. By the radial blur I meant the shader that calculates vector from pixel to sun and samples along the direction.

43 minutes ago, turanszkij said:

You don't have to calculate the correct number of samples, just tweak it until it looks good. I am using 35 samples, but rendering to half-resolution. This gives great results, but probably should take less samples. Also make sure you are using a linear texture filter when sampling.

Ok, Thanks again. I will try it and check linear filter.

44 minutes ago, turanszkij said:

It is the same technique, but for some reason all of them say to draw the scene depth buffer after the sun, but you probably already have a depth buffer by the time you are doing this effect, so best to just reuse that. By the radial blur I meant the shader that calculates vector from pixel to sun and samples along the direction

Yes, i have separate depth scene pass without Sun, now i understand, thanks

3DGraphics,Direct3D12,Vulkan,OpenCL,Algorithms

Hi all!

After some modiifcation of shader i have the result for 16 samples:

image.thumb.png.5f35d407bc2589104f73b92d9640431c.png

the result for 32 samples:

image.thumb.png.7e1ae09735a907dd12598ad41c3d88a8.png

also i try to change ShaftParams:


const vec4    ShaftParams = vec4(0.05, 1.0, 0.1, 2.0);

But i have still some artefacts.

May be i should use additive blend + blur in low resolution, from turanszkij post, but can be simple to fix this implemenation.

I attached the new shader.

shaftsCryPS.glsl

3DGraphics,Direct3D12,Vulkan,OpenCL,Algorithms

This topic is closed to new replies.

Advertisement