diff options
4 files changed, 85 insertions, 28 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 e51fb2fd1d7..c36e8601d25 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -56,23 +56,32 @@ static struct { /* Depth Of Field */ - struct GPUShader *dof_downsample_sh; - struct GPUShader *dof_scatter_sh; - struct GPUShader *dof_resolve_sh; + struct GPUShader *dof_downsample_sh[2]; + struct GPUShader *dof_scatter_sh[2]; + struct GPUShader *dof_resolve_sh[2]; } e_data = {NULL}; /* Engine data */ extern char datatoc_effect_dof_vert_glsl[]; extern char datatoc_effect_dof_frag_glsl[]; -static void eevee_create_shader_depth_of_field(void) +static void eevee_create_shader_depth_of_field(const bool use_alpha) { - e_data.dof_downsample_sh = DRW_shader_create_fullscreen( - datatoc_effect_dof_frag_glsl, "#define STEP_DOWNSAMPLE\n"); - e_data.dof_scatter_sh = DRW_shader_create( + e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen( + datatoc_effect_dof_frag_glsl, use_alpha ? + "#define USE_ALPHA_DOF\n" + "#define STEP_DOWNSAMPLE\n" : + "#define STEP_DOWNSAMPLE\n"); + e_data.dof_scatter_sh[use_alpha] = DRW_shader_create( datatoc_effect_dof_vert_glsl, NULL, - datatoc_effect_dof_frag_glsl, "#define STEP_SCATTER\n"); - e_data.dof_resolve_sh = DRW_shader_create_fullscreen( - datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n"); + datatoc_effect_dof_frag_glsl, use_alpha ? + "#define USE_ALPHA_DOF\n" + "#define STEP_SCATTER\n" : + "#define STEP_SCATTER\n"); + e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen( + datatoc_effect_dof_frag_glsl, use_alpha ? + "#define USE_ALPHA_DOF\n" + "#define STEP_RESOLVE\n" : + "#define STEP_RESOLVE\n"); } int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera) @@ -86,9 +95,10 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v if (scene_eval->eevee.flag & SCE_EEVEE_DOF_ENABLED) { RegionView3D *rv3d = draw_ctx->rv3d; + const bool use_alpha = !DRW_state_draw_background(); - if (!e_data.dof_downsample_sh) { - eevee_create_shader_depth_of_field(); + if (!e_data.dof_downsample_sh[use_alpha]) { + eevee_create_shader_depth_of_field(use_alpha); } if (camera) { @@ -101,9 +111,11 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2}; - effects->dof_down_near = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], GPU_R11F_G11F_B10F, + GPUTextureFormat down_format = DRW_state_draw_background() ? GPU_R11F_G11F_B10F : GPU_RGBA16F; + + effects->dof_down_near = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], down_format, &draw_engine_eevee_type); - effects->dof_down_far = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], GPU_R11F_G11F_B10F, + effects->dof_down_far = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], down_format, &draw_engine_eevee_type); effects->dof_coc = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], GPU_RG16F, &draw_engine_eevee_type); @@ -120,11 +132,18 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v effects->dof_blur = DRW_texture_pool_query_2D(buffer_size[0] * 2, buffer_size[1], fb_format, &draw_engine_eevee_type); + GPU_framebuffer_ensure_config(&fbl->dof_scatter_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->dof_blur), }); + if (!DRW_state_draw_background()) { + effects->dof_blur_alpha = DRW_texture_pool_query_2D(buffer_size[0] * 2, buffer_size[1], GPU_R32F, + &draw_engine_eevee_type); + GPU_framebuffer_texture_attach(fbl->dof_scatter_fb, effects->dof_blur_alpha, 1, 0); + } + /* Parameters */ /* TODO UI Options */ float fstop = cam->gpu_dof.fstop; @@ -193,10 +212,11 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ **/ DRWShadingGroup *grp; struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + const bool use_alpha = !DRW_state_draw_background(); psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_create(e_data.dof_downsample_sh, psl->dof_down); + grp = DRW_shgroup_create(e_data.dof_downsample_sh[use_alpha], psl->dof_down); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1); @@ -209,8 +229,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ * by the vertex shader 0.4ms against 6ms with instancing */ const float *viewport_size = DRW_viewport_size_get(); const int sprite_len = ((int)viewport_size[0] / 2) * ((int)viewport_size[1] / 2); /* brackets matters */ - grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh, psl->dof_scatter, sprite_len); - + grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh[use_alpha], psl->dof_scatter, sprite_len); DRW_shgroup_uniform_texture_ref(grp, "nearBuffer", &effects->dof_down_near); DRW_shgroup_uniform_texture_ref(grp, "farBuffer", &effects->dof_down_far); DRW_shgroup_uniform_texture_ref(grp, "cocBuffer", &effects->dof_coc); @@ -218,13 +237,17 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_create(e_data.dof_resolve_sh, psl->dof_resolve); + grp = DRW_shgroup_create(e_data.dof_resolve_sh[use_alpha], psl->dof_resolve); DRW_shgroup_uniform_texture_ref(grp, "scatterBuffer", &effects->dof_blur); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1); DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1); DRW_shgroup_call_add(grp, quad, NULL); + + if (use_alpha) { + DRW_shgroup_uniform_texture_ref(grp, "scatterAlphaBuffer", &effects->dof_blur_alpha); + } } } @@ -258,7 +281,9 @@ void EEVEE_depth_of_field_draw(EEVEE_Data *vedata) void EEVEE_depth_of_field_free(void) { - DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh); - DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh); - DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh); + for (int i = 0; i < 2; ++i) { + DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh[i]); + } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 35a1211ba4a..c5d184e1a84 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -578,6 +578,7 @@ typedef struct EEVEE_EffectsInfo { struct GPUTexture *dof_down_far; struct GPUTexture *dof_coc; struct GPUTexture *dof_blur; + struct GPUTexture *dof_blur_alpha; /* Other */ float prev_persmat[4][4]; /* Bloom */ 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 d816d72c1e3..27517ebd86e 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl @@ -77,6 +77,14 @@ void main(void) vec4 near_weights = step(THRESHOLD, coc_near) * clamp(1.0 - abs(cocData.x - coc_near), 0.0, 1.0); vec4 far_weights = step(THRESHOLD, coc_far) * clamp(1.0 - abs(cocData.y - coc_far), 0.0, 1.0); +# ifdef USE_ALPHA_DOF + /* Premult */ + color1.rgb *= color1.a; + color2.rgb *= color2.a; + color3.rgb *= color3.a; + color4.rgb *= color4.a; +# endif + /* now write output to weighted buffers. */ nearColor = weighted_sum(color1, color2, color3, color4, near_weights); farColor = weighted_sum(color1, color2, color3, color4, far_weights); @@ -85,12 +93,16 @@ void main(void) #elif defined(STEP_SCATTER) flat in vec4 color; +flat in float weight; flat in float smoothFac; flat in ivec2 edge; /* coordinate used for calculating radius */ in vec2 particlecoord; -out vec4 fragColor; +layout(location = 0) out vec4 fragColor; +# ifdef USE_ALPHA_DOF +layout(location = 1) out float fragAlpha; +# endif /* accumulate color in the near/far blur buffers */ void main(void) @@ -130,9 +142,14 @@ void main(void) /* 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); - } + float shape = smoothstep(1.0, min(0.999, smoothFac), dist); + + fragColor *= shape; + +# ifdef USE_ALPHA_DOF + fragAlpha = fragColor.a; + fragColor.a = weight * shape; +# endif } #elif defined(STEP_RESOLVE) @@ -140,6 +157,7 @@ void main(void) #define MERGE_THRESHOLD 4.0 uniform sampler2D scatterBuffer; +uniform sampler2D scatterAlphaBuffer; in vec4 uvcoordsvar; out vec4 fragColor; @@ -203,9 +221,21 @@ void main(void) float far_w = far_col.a; float near_w = near_col.a; float focus_w = 1.0 - smoothstep(1.0, MERGE_THRESHOLD, abs(coc_signed)); + float inv_weight_sum = 1.0 / (near_w + focus_w + far_w); + focus_col *= focus_w; /* Premul */ - fragColor = (far_col + near_col + focus_col) / (near_w + focus_w + far_w); +# ifdef USE_ALPHA_DOF + near_col.a = upsample_filter(scatterAlphaBuffer, near_uv, texelSize).r; + far_col.a = upsample_filter(scatterAlphaBuffer, far_uv, texelSize).r; +# endif + + fragColor = (far_col + near_col + focus_col) * inv_weight_sum; + +# ifdef USE_ALPHA_DOF + /* Unpremult */ + fragColor.rgb /= (fragColor.a > 0.0) ? fragColor.a : 1.0; +# endif } #endif 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 ec8b474b431..92fd36f684a 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl @@ -10,6 +10,7 @@ uniform sampler2D farBuffer; uniform sampler2D cocBuffer; flat out vec4 color; +flat out float weight; flat out float smoothFac; flat out ivec2 edge; out vec2 particlecoord; @@ -49,8 +50,8 @@ void main() /* find the area the pixel will cover and divide the color by it */ /* HACK: 4.0 out of nowhere (I suppose it's 4 pixels footprint for coc 0?) * Makes near in focus more closer to 1.0 alpha. */ - color.a = 4.0 / (coc * coc * M_PI); - color.rgb *= color.a; + weight = 4.0 / (coc * coc * M_PI); + color *= weight; /* Compute edge to discard fragment that does not belong to the other layer. */ edge.x = (is_near) ? 1 : -1; |