Combined the DOF far and DOF near passes
This commit is contained in:
parent
40b57319e2
commit
39658b4e07
5 changed files with 131 additions and 330 deletions
|
@ -126,7 +126,7 @@
|
|||
The length of the transition between the no-blur area and far blur.
|
||||
</member>
|
||||
<member name="dof_blur_near_amount" type="float" setter="set_dof_blur_near_amount" getter="get_dof_blur_near_amount" default="0.1">
|
||||
The amount of near blur for the depth-of-field effect.
|
||||
The amount of near blur for the depth-of-field effect. [member dof_blur_far_amount] is used if both far and near DOF are enabled.
|
||||
</member>
|
||||
<member name="dof_blur_near_distance" type="float" setter="set_dof_blur_near_distance" getter="get_dof_blur_near_distance" default="2.0">
|
||||
Distance from the camera where the near blur effect affects the rendering.
|
||||
|
@ -135,7 +135,7 @@
|
|||
If [code]true[/code], enables the depth-of-field near blur effect.
|
||||
</member>
|
||||
<member name="dof_blur_near_quality" type="int" setter="set_dof_blur_near_quality" getter="get_dof_blur_near_quality" enum="Environment.DOFBlurQuality" default="1">
|
||||
The depth-of-field near blur's quality. Higher values can mitigate the visible banding effect seen at higher strengths, but are much slower.
|
||||
The depth-of-field near blur's quality. Higher values can mitigate the visible banding effect seen at higher strengths, but are much slower. [member dof_blur_far_quality] is used if both far and near DOF are enabled.
|
||||
</member>
|
||||
<member name="dof_blur_near_transition" type="float" setter="set_dof_blur_near_transition" getter="get_dof_blur_near_transition" default="1.0">
|
||||
The length of the transition between the near blur and no-blur area.
|
||||
|
|
|
@ -2989,23 +2989,36 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
|
|||
|
||||
// DOF Blur
|
||||
|
||||
if (env && env->dof_blur_far_enabled) {
|
||||
if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) {
|
||||
int vp_h = storage->frame.current_rt->height;
|
||||
int vp_w = storage->frame.current_rt->width;
|
||||
|
||||
// If both near and far are used, we use the far quality and amount settings.
|
||||
// We should just have one setting like in Godot 4 but that would be a serious breaking change.
|
||||
// This is defendable.
|
||||
float dof_blur_amount = env->dof_blur_far_enabled ? env->dof_blur_far_amount : env->dof_blur_near_amount;
|
||||
VS::EnvironmentDOFBlurQuality quality = env->dof_blur_far_enabled ? env->dof_blur_far_quality : env->dof_blur_near_quality;
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_FAR_BLUR, true);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_FAR_BLUR, env->dof_blur_far_enabled);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_BLUR, env->dof_blur_near_enabled);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
|
||||
|
||||
state.effect_blur_shader.bind();
|
||||
int qsteps[3] = { 4, 10, 20 };
|
||||
|
||||
float radius = (env->dof_blur_far_amount * env->dof_blur_far_amount) / qsteps[env->dof_blur_far_quality];
|
||||
float radius = (dof_blur_amount * dof_blur_amount) / qsteps[quality];
|
||||
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_BEGIN, env->dof_blur_far_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_END, env->dof_blur_far_distance + env->dof_blur_far_transition);
|
||||
if (env->dof_blur_far_enabled) {
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_FAR_BEGIN, env->dof_blur_far_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_FAR_END, env->dof_blur_far_distance + env->dof_blur_far_transition);
|
||||
}
|
||||
if (env->dof_blur_near_enabled) {
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_NEAR_BEGIN, env->dof_blur_near_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_NEAR_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
|
||||
}
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(1, 0));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_RADIUS, radius);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
|
||||
|
@ -3039,97 +3052,12 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p
|
|||
storage->_copy_screen();
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_FAR_BLUR, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, false);
|
||||
}
|
||||
|
||||
if (env && env->dof_blur_near_enabled) {
|
||||
//convert texture to RGBA format if not already
|
||||
if (!storage->frame.current_rt->used_dof_blur_near) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
}
|
||||
|
||||
int vp_h = storage->frame.current_rt->height;
|
||||
int vp_w = storage->frame.current_rt->width;
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_BLUR, true);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, true);
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
|
||||
|
||||
state.effect_blur_shader.bind();
|
||||
int qsteps[3] = { 4, 10, 20 };
|
||||
|
||||
float radius = (env->dof_blur_near_amount * env->dof_blur_near_amount) / qsteps[env->dof_blur_near_quality];
|
||||
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_BEGIN, env->dof_blur_near_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(1, 0));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_RADIUS, radius);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far());
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (storage->frame.current_rt->mip_maps[0].color) {
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].color);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->mip_maps[0].sizes[0].color);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first
|
||||
|
||||
storage->_copy_screen();
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, false);
|
||||
state.effect_blur_shader.bind();
|
||||
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_BEGIN, env->dof_blur_near_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_DIR, Vector2(0, 1));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::DOF_RADIUS, radius);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES2::CAMERA_Z_FAR, p_cam_projection.get_z_far());
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->mip_maps[0].sizes[0].fbo); // copy to base level
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
storage->_copy_screen();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_BLUR, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, false);
|
||||
storage->frame.current_rt->used_dof_blur_near = true;
|
||||
}
|
||||
|
||||
if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) {
|
||||
//these needed to disable filtering, reenamble
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (storage->frame.current_rt->mip_maps[0].color) {
|
||||
|
|
|
@ -105,8 +105,10 @@ const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.0
|
|||
#endif
|
||||
|
||||
uniform sampler2D dof_source_depth; //texunit:1
|
||||
uniform float dof_begin;
|
||||
uniform float dof_end;
|
||||
uniform float dof_far_begin;
|
||||
uniform float dof_far_end;
|
||||
uniform float dof_near_begin;
|
||||
uniform float dof_near_end;
|
||||
uniform vec2 dof_dir;
|
||||
uniform float dof_radius;
|
||||
|
||||
|
@ -210,7 +212,7 @@ void main() {
|
|||
#endif
|
||||
#endif //!USE_GLES_OVER_GL
|
||||
|
||||
#ifdef DOF_FAR_BLUR
|
||||
#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR)
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
|
@ -222,79 +224,59 @@ void main() {
|
|||
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
|
||||
float amount = smoothstep(dof_begin, dof_end, depth);
|
||||
float k_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
float tap_depth = texture2D(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
// Combine near and far, our depth is unlikely to be in both ranges
|
||||
float amount = 1.0;
|
||||
#ifdef DOF_FAR_BLUR
|
||||
amount *= 1.0 - smoothstep(dof_far_begin, dof_far_end, depth);
|
||||
#endif
|
||||
float tap_amount = int_ofs == 0 ? 1.0 : smoothstep(dof_begin, dof_end, tap_depth);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
vec4 tap_color = texture2DLod(source_color, tap_uv, 0.0) * tap_k;
|
||||
|
||||
k_accum += tap_k * tap_amount;
|
||||
color_accum += tap_color * tap_amount;
|
||||
}
|
||||
|
||||
if (k_accum > 0.0) {
|
||||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
gl_FragColor = color_accum; ///k_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DOF_NEAR_BLUR
|
||||
amount *= smoothstep(dof_near_end, dof_near_begin, depth);
|
||||
#endif
|
||||
amount = 1.0 - amount;
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
if (amount > 0.0) {
|
||||
float k_accum = 0.0;
|
||||
|
||||
float max_accum = 0.0;
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius;
|
||||
float ofs_influence = max(0.0, 1.0 - abs(float(int_ofs)) / float(dof_kernel_from));
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
vec4 tap_color = texture2DLod(source_color, tap_uv, 0.0);
|
||||
|
||||
float tap_depth = texture2D(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
float tap_depth = texture2D(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
float tap_amount = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
#ifdef DOF_NEAR_FIRST_TAP
|
||||
|
||||
tap_color.a = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
|
||||
|
||||
float tap_amount = 1.0;
|
||||
#ifdef DOF_FAR_BLUR
|
||||
tap_amount *= int_ofs == 0 ? 0.0 : (1.0 - smoothstep(dof_far_begin, dof_far_end, tap_depth));
|
||||
#endif
|
||||
#ifdef DOF_NEAR_BLUR
|
||||
tap_amount *= int_ofs == 0 ? 0.0 : (smoothstep(dof_near_end, dof_near_begin, tap_depth));
|
||||
#endif
|
||||
tap_amount = 1.0 - tap_amount;
|
||||
|
||||
max_accum = max(max_accum, tap_amount * ofs_influence);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
color_accum += tap_color * tap_k;
|
||||
vec4 tap_color = texture2DLod(source_color, tap_uv, 0.0) * tap_k;
|
||||
|
||||
k_accum += tap_k * tap_amount;
|
||||
color_accum += tap_color * tap_amount;
|
||||
}
|
||||
|
||||
if (k_accum > 0.0) {
|
||||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
gl_FragColor = color_accum; ///k_accum;
|
||||
} else {
|
||||
// We're in focus, no need to waste time sampling the same UV a bunch of times...
|
||||
gl_FragColor = texture2DLod(source_color, uv_interp, 0.0);
|
||||
}
|
||||
|
||||
color_accum.a = max(color_accum.a, sqrt(max_accum));
|
||||
|
||||
gl_FragColor = color_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_FIRST_PASS
|
||||
|
|
|
@ -3535,26 +3535,39 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
|
|||
|
||||
GLuint composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
|
||||
|
||||
if (env && env->dof_blur_far_enabled) {
|
||||
if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) {
|
||||
//blur diffuse into effect mipmaps using separatable convolution
|
||||
//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
|
||||
|
||||
int vp_h = storage->frame.current_rt->height;
|
||||
int vp_w = storage->frame.current_rt->width;
|
||||
|
||||
// If both near and far are used, we use the far quality and amount settings.
|
||||
// We should just have one setting like in Godot 4 but that would be a serious breaking change.
|
||||
// This is defendable.
|
||||
float dof_blur_amount = env->dof_blur_far_enabled ? env->dof_blur_far_amount : env->dof_blur_near_amount;
|
||||
VS::EnvironmentDOFBlurQuality quality = env->dof_blur_far_enabled ? env->dof_blur_far_quality : env->dof_blur_near_quality;
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, true);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, env->dof_blur_far_enabled);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, env->dof_blur_near_enabled);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
|
||||
|
||||
state.effect_blur_shader.bind();
|
||||
int qsteps[3] = { 4, 10, 20 };
|
||||
|
||||
float radius = (env->dof_blur_far_amount * env->dof_blur_far_amount) / qsteps[env->dof_blur_far_quality];
|
||||
float radius = (dof_blur_amount * dof_blur_amount) / qsteps[quality];
|
||||
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_far_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_far_distance + env->dof_blur_far_transition);
|
||||
if (env->dof_blur_far_enabled) {
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_FAR_BEGIN, env->dof_blur_far_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_FAR_END, env->dof_blur_far_distance + env->dof_blur_far_transition);
|
||||
}
|
||||
if (env->dof_blur_near_enabled) {
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_NEAR_BEGIN, env->dof_blur_near_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_NEAR_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
|
||||
}
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(1, 0));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
|
||||
|
@ -3582,101 +3595,14 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
|
|||
_copy_screen();
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false);
|
||||
|
||||
composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
|
||||
}
|
||||
|
||||
if (env && env->dof_blur_near_enabled) {
|
||||
//blur diffuse into effect mipmaps using separatable convolution
|
||||
//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
|
||||
|
||||
int vp_h = storage->frame.current_rt->height;
|
||||
int vp_w = storage->frame.current_rt->width;
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal());
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, true);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, true);
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_LOW);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH);
|
||||
|
||||
state.effect_blur_shader.bind();
|
||||
int qsteps[3] = { 4, 10, 20 };
|
||||
|
||||
float radius = (env->dof_blur_near_amount * env->dof_blur_near_amount) / qsteps[env->dof_blur_near_quality];
|
||||
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_near_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(1, 0));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, composite_from);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //copy to front first
|
||||
|
||||
_copy_screen();
|
||||
//manually do the blend if this is the first operation resolving from the diffuse buffer
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE, composite_from == storage->frame.current_rt->buffers.diffuse);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, false);
|
||||
state.effect_blur_shader.bind();
|
||||
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN, env->dof_blur_near_distance);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END, env->dof_blur_near_distance - env->dof_blur_near_transition);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR, Vector2(0, 1));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS, radius);
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h));
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_NEAR, p_cam_projection.get_z_near());
|
||||
state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR, p_cam_projection.get_z_far());
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
|
||||
|
||||
if (composite_from != storage->frame.current_rt->buffers.diffuse) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
} else {
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->buffers.diffuse);
|
||||
}
|
||||
|
||||
_copy_screen(true);
|
||||
|
||||
if (composite_from != storage->frame.current_rt->buffers.diffuse) {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false);
|
||||
state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_ORTHOGONAL_PROJECTION, false);
|
||||
|
||||
composite_from = storage->frame.current_rt->effects.mip_maps[0].color;
|
||||
}
|
||||
|
||||
if (env && (env->dof_blur_near_enabled || env->dof_blur_far_enabled)) {
|
||||
//these needed to disable filtering, reenamble
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
|
||||
|
|
|
@ -77,16 +77,13 @@ const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.0
|
|||
#endif
|
||||
|
||||
uniform sampler2D dof_source_depth; //texunit:1
|
||||
uniform float dof_begin;
|
||||
uniform float dof_end;
|
||||
uniform float dof_far_begin;
|
||||
uniform float dof_far_end;
|
||||
uniform float dof_near_begin;
|
||||
uniform float dof_near_end;
|
||||
uniform vec2 dof_dir;
|
||||
uniform float dof_radius;
|
||||
|
||||
#ifdef DOF_NEAR_BLUR_MERGE
|
||||
|
||||
uniform sampler2D source_dof_original; //texunit:2
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_FIRST_PASS
|
||||
|
@ -161,7 +158,7 @@ void main() {
|
|||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifdef DOF_FAR_BLUR
|
||||
#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR)
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
|
@ -173,89 +170,57 @@ void main() {
|
|||
depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
|
||||
float amount = smoothstep(dof_begin, dof_end, depth);
|
||||
float k_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
// Combine near and far, our depth is unlikely to be in both ranges
|
||||
float amount = 1.0;
|
||||
#ifdef DOF_FAR_BLUR
|
||||
amount *= 1.0 - smoothstep(dof_far_begin, dof_far_end, depth);
|
||||
#endif
|
||||
float tap_amount = mix(smoothstep(dof_begin, dof_end, tap_depth), 1.0, int_ofs == 0);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
vec4 tap_color = textureLod(source_color, tap_uv, 0.0) * tap_k;
|
||||
|
||||
k_accum += tap_k * tap_amount;
|
||||
color_accum += tap_color * tap_amount;
|
||||
}
|
||||
|
||||
if (k_accum > 0.0) {
|
||||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
frag_color = color_accum; ///k_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DOF_NEAR_BLUR
|
||||
amount *= smoothstep(dof_near_end, dof_near_begin, depth);
|
||||
#endif
|
||||
amount = 1.0 - amount;
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
if (amount > 0.0) {
|
||||
float k_accum = 0.0;
|
||||
|
||||
float max_accum = 0.0;
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius;
|
||||
float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
vec4 tap_color = textureLod(source_color, tap_uv, 0.0);
|
||||
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
#ifdef USE_ORTHOGONAL_PROJECTION
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0;
|
||||
#else
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
|
||||
#endif
|
||||
float tap_amount = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
#ifdef DOF_NEAR_FIRST_TAP
|
||||
|
||||
tap_color.a = 1.0 - smoothstep(dof_end, dof_begin, tap_depth);
|
||||
|
||||
float tap_amount = 1.0;
|
||||
#ifdef DOF_FAR_BLUR
|
||||
tap_amount *= mix(1.0 - smoothstep(dof_far_begin, dof_far_end, tap_depth), 0.0, int_ofs == 0);
|
||||
#endif
|
||||
#ifdef DOF_NEAR_BLUR
|
||||
tap_amount *= mix(smoothstep(dof_near_end, dof_near_begin, tap_depth), 0.0, int_ofs == 0);
|
||||
#endif
|
||||
tap_amount = 1.0 - tap_amount;
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
max_accum = max(max_accum, tap_amount * ofs_influence);
|
||||
vec4 tap_color = textureLod(source_color, tap_uv, 0.0) * tap_k;
|
||||
|
||||
color_accum += tap_color * tap_k;
|
||||
k_accum += tap_k * tap_amount;
|
||||
color_accum += tap_color * tap_amount;
|
||||
}
|
||||
|
||||
if (k_accum > 0.0) {
|
||||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
frag_color = color_accum; ///k_accum;
|
||||
} else {
|
||||
// We're in focus, no need to waste time sampling the same UV a bunch of times...
|
||||
frag_color = textureLod(source_color, uv_interp, 0.0);
|
||||
}
|
||||
|
||||
color_accum.a = max(color_accum.a, sqrt(max_accum));
|
||||
|
||||
#ifdef DOF_NEAR_BLUR_MERGE
|
||||
|
||||
vec4 original = textureLod(source_dof_original, uv_interp, 0.0);
|
||||
color_accum = mix(original, color_accum, color_accum.a);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef DOF_NEAR_FIRST_TAP
|
||||
//color_accum=vec4(vec3(color_accum.a),1.0);
|
||||
#endif
|
||||
frag_color = color_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_FIRST_PASS
|
||||
|
|
Loading…
Reference in a new issue