diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-05-12 01:58:53 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-05-13 00:28:55 +0300 |
commit | f9cfb221d64a8f7b5bb89ee36d5ac594d6da34ff (patch) | |
tree | adad1f71d8df8de99e58631a3cca088c64044a3a | |
parent | 74a08cf12854308af166742f7dcaa5c7c227fcd4 (diff) |
Eevee: Depth of field: Smooth out bokeh shape.
Due to the scatter operation being done at half resolution, undersampling
is visible at bokeh shape edges (because of the hard cut).
This commit adds a smoothing function to minimize the problem.
Also optimize the bokeh shape parametrization by precomputing a lot of
constants.
4 files changed, 51 insertions, 23 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index c17378a48e3..f4d534c4ccc 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -162,10 +162,15 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v effects->dof_params[0] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled)); effects->dof_params[1] = -focus_dist; effects->dof_params[2] = viewport_size[0] / sensor_scaled; - effects->dof_bokeh[0] = blades; - effects->dof_bokeh[1] = rotation; - effects->dof_bokeh[2] = ratio; - effects->dof_bokeh[3] = BKE_collection_engine_property_value_get_float(props, "bokeh_max_size"); + effects->dof_bokeh[0] = rotation; + effects->dof_bokeh[1] = ratio; + effects->dof_bokeh[2] = BKE_collection_engine_property_value_get_float(props, "bokeh_max_size"); + + /* Precompute values to save instructions in fragment shader. */ + effects->dof_bokeh_sides[0] = blades; + effects->dof_bokeh_sides[1] = 2.0f * M_PI / blades; + effects->dof_bokeh_sides[2] = blades / (2.0f * M_PI); + effects->dof_bokeh_sides[3] = cosf(M_PI / blades); return EFFECT_DOF | EFFECT_POST_BUFFER; } @@ -219,7 +224,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->unf_source_buffer); DRW_shgroup_uniform_texture_ref(grp, "cocBuffer", &effects->dof_coc); DRW_shgroup_uniform_vec2(grp, "layerSelection", effects->dof_layer_select, 1); - DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 1); + DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 2); psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index e8ad25527d7..d76ecea4e43 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -546,6 +546,7 @@ typedef struct EEVEE_EffectsInfo { float dof_near_far[2]; float dof_params[3]; float dof_bokeh[4]; + float dof_bokeh_sides[4]; float dof_layer_select[2]; int dof_target_size[2]; struct GPUTexture *dof_down_near; /* Textures from pool */ diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl index 14ddf10f2d8..3ec36c95dfa 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl @@ -10,12 +10,12 @@ uniform vec3 dofParams; #define dof_distance dofParams.y #define dof_invsensorsize dofParams.z -uniform vec4 bokehParams; +uniform vec4 bokehParams[2]; -#define bokeh_sides bokehParams.x /* Polygon Bokeh shape number of sides */ -#define bokeh_rotation bokehParams.y -#define bokeh_ratio bokehParams.z -#define bokeh_maxsize bokehParams.w +#define bokeh_rotation bokehParams[0].x +#define bokeh_ratio bokehParams[0].y +#define bokeh_maxsize bokehParams[0].z +#define bokeh_sides bokehParams[1] /* Polygon Bokeh shape number of sides (with precomputed vars) */ uniform vec2 nearFar; /* Near & far view depths values */ @@ -130,6 +130,7 @@ void main(void) #elif defined(STEP_SCATTER) flat in vec4 color; +flat in float smoothFac; /* coordinate used for calculating radius */ in vec2 particlecoord; @@ -139,28 +140,42 @@ out vec4 fragColor; void main(void) { /* Early out */ - float dist_sqrd = dot(particlecoord, particlecoord); + float dist_sqr = dot(particlecoord, particlecoord); /* Circle Dof */ - if (dist_sqrd > 1.0) { + if (dist_sqr > 1.0) { discard; } + float dist = sqrt(dist_sqr); + /* Regular Polygon Dof */ - if (bokeh_sides > 0.0) { + if (bokeh_sides.x > 0.0) { /* Circle parametrization */ float theta = atan(particlecoord.y, particlecoord.x) + bokeh_rotation; - float r; - r = cos(M_PI / bokeh_sides) / - (cos(theta - (M_2PI / bokeh_sides) * floor((bokeh_sides * theta + M_PI) / M_2PI))); + /* Optimized version of : + * float denom = theta - (M_2PI / bokeh_sides) * floor((bokeh_sides * theta + M_PI) / M_2PI); + * float r = cos(M_PI / bokeh_sides) / cos(denom); */ + float denom = theta - bokeh_sides.y * floor(bokeh_sides.z * theta + 0.5); + float r = bokeh_sides.w / max(1e-8, cos(denom)); + + /* Divide circle radial coord by the shape radius for angle theta. + * Giving us the new linear radius to the shape edge. */ + dist /= r; - if (dist_sqrd > r * r) { + if (dist > 1.0) { discard; } } fragColor = color; + + /* Smooth the edges a bit. This effectively reduce the bokeh shape + * but does fade out the undersampling artifacts. */ + if (smoothFac < 1.0) { + fragColor *= smoothstep(1.0, smoothFac, dist); + } } #elif defined(STEP_RESOLVE) diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl index dc34f2bd1fc..e28c957d58d 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl @@ -1,17 +1,17 @@ uniform vec2 layerSelection; -uniform vec4 bokehParams; +uniform vec4 bokehParams[2]; -#define bokeh_sides bokehParams.x /* Polygon Bokeh shape number of sides */ -#define bokeh_rotation bokehParams.y -#define bokeh_ratio bokehParams.z -#define bokeh_maxsize bokehParams.w +#define bokeh_rotation bokehParams[0].x +#define bokeh_ratio bokehParams[0].y +#define bokeh_maxsize bokehParams[0].z -uniform sampler2D colorBuffer; uniform sampler2D cocBuffer; +uniform sampler2D colorBuffer; flat out vec4 color; +flat out float smoothFac; out vec2 particlecoord; #define M_PI 3.1415926535897932384626433832795 @@ -78,4 +78,11 @@ void main() gl_Position.xy -= 1.0 - 0.5 * texel_size; /* NDC Bottom left */ gl_Position.xy += (0.5 + vec2(texelco) * 2.0) * texel_size; + /* don't do smoothing for small sprites */ + if (coc > 3.0) { + smoothFac = 1.0 - 1.5 / coc; + } + else { + smoothFac = 1.0; + } } |