Implemented raster versions of bokeh shaders to replace broken gaussian implementation
This commit is contained in:
parent
a98589a449
commit
07fd559478
@ -928,7 +928,7 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
void EffectsRD::bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer.");
|
||||
|
||||
bokeh.push_constant.blur_far_active = p_dof_far;
|
||||
@ -957,22 +957,22 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
||||
// The alpha channel of the source color texture is filled with the expected circle size
|
||||
// If used for DOF far, the size is positive, if used for near, its negative.
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BLUR_SIZE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_texture), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.depth_texture), 1);
|
||||
|
||||
bokeh.push_constant.size[0] = p_base_texture_size.x;
|
||||
bokeh.push_constant.size[1] = p_base_texture_size.y;
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
|
||||
//second pass
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]);
|
||||
|
||||
static const int quality_samples[4] = { 6, 12, 12, 24 };
|
||||
|
||||
@ -981,18 +981,18 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
|
||||
|
||||
bokeh.push_constant.size[0] = p_base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_base_texture_size.y >> 1;
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
|
||||
bokeh.push_constant.half_size = true;
|
||||
bokeh.push_constant.blur_size *= 0.5;
|
||||
|
||||
} else {
|
||||
//medium and high quality use full size
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.secondary_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
@ -1004,11 +1004,11 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
||||
bokeh.push_constant.second_pass = true;
|
||||
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture2), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[1]), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.secondary_texture), 1);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
@ -1019,25 +1019,25 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
//forth pass, upscale for low quality
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture2), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[1]), 1);
|
||||
|
||||
bokeh.push_constant.size[0] = p_base_texture_size.x;
|
||||
bokeh.push_constant.size[1] = p_base_texture_size.y;
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
|
||||
bokeh.push_constant.half_size = false;
|
||||
bokeh.push_constant.second_pass = false;
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
|
||||
}
|
||||
} else {
|
||||
//circle
|
||||
|
||||
//second pass
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
|
||||
|
||||
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
|
||||
|
||||
@ -1046,11 +1046,11 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
||||
|
||||
//circle always runs in half size, otherwise too expensive
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.half_texture[0]), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.base_texture), 1);
|
||||
|
||||
bokeh.push_constant.size[0] = p_base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_base_texture_size.y >> 1;
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
|
||||
bokeh.push_constant.half_size = true;
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
@ -1062,95 +1062,197 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
||||
|
||||
// upscale
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_buffers.base_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_buffers.half_texture[0]), 1);
|
||||
|
||||
bokeh.push_constant.size[0] = p_base_texture_size.x;
|
||||
bokeh.push_constant.size[1] = p_base_texture_size.y;
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y;
|
||||
bokeh.push_constant.half_size = false;
|
||||
bokeh.push_constant.second_pass = false;
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_base_texture_size.x, p_base_texture_size.y, 1);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::blur_dof_raster(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_base_fb, RID p_secondary_texture, RID p_secondary_fb, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
void EffectsRD::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer.");
|
||||
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
|
||||
|
||||
BlurRasterMode blur_mode;
|
||||
int qsteps[4] = { 4, 4, 10, 20 };
|
||||
uint32_t base_flags = p_cam_orthogonal ? BLUR_FLAG_USE_ORTHOGONAL_PROJECTION : 0;
|
||||
bokeh.push_constant.orthogonal = p_cam_orthogonal;
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.width;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.height;
|
||||
bokeh.push_constant.z_far = p_cam_zfar;
|
||||
bokeh.push_constant.z_near = p_cam_znear;
|
||||
|
||||
Vector2 pixel_size = Vector2(1.0 / p_base_texture_size.width, 1.0 / p_base_texture_size.height);
|
||||
|
||||
blur_raster.push_constant.dof_radius = (p_dof_blur_amount * p_dof_blur_amount) / qsteps[p_quality];
|
||||
blur_raster.push_constant.pixel_size[0] = pixel_size.x;
|
||||
blur_raster.push_constant.pixel_size[1] = pixel_size.y;
|
||||
blur_raster.push_constant.camera_z_far = p_cam_zfar;
|
||||
blur_raster.push_constant.camera_z_near = p_cam_znear;
|
||||
bokeh.push_constant.second_pass = false;
|
||||
bokeh.push_constant.half_size = false;
|
||||
bokeh.push_constant.blur_size = p_dof_blur_amount;
|
||||
|
||||
if (p_dof_far || p_dof_near) {
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_HIGH) {
|
||||
blur_mode = BLUR_MODE_DOF_HIGH;
|
||||
} else if (p_quality == RS::DOF_BLUR_QUALITY_MEDIUM) {
|
||||
blur_mode = BLUR_MODE_DOF_MEDIUM;
|
||||
} else { // for LOW or VERYLOW we use LOW
|
||||
blur_mode = BLUR_MODE_DOF_LOW;
|
||||
}
|
||||
|
||||
if (p_dof_far) {
|
||||
base_flags |= BLUR_FLAG_DOF_FAR;
|
||||
blur_raster.push_constant.dof_far_begin = p_dof_far_begin;
|
||||
blur_raster.push_constant.dof_far_end = p_dof_far_begin + p_dof_far_size;
|
||||
bokeh.push_constant.blur_far_active = true;
|
||||
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
|
||||
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
|
||||
}
|
||||
|
||||
if (p_dof_near) {
|
||||
base_flags |= BLUR_FLAG_DOF_NEAR;
|
||||
blur_raster.push_constant.dof_near_begin = p_dof_near_begin;
|
||||
blur_raster.push_constant.dof_near_end = p_dof_near_begin - p_dof_near_size;
|
||||
bokeh.push_constant.blur_near_active = true;
|
||||
bokeh.push_constant.blur_near_begin = p_dof_near_begin;
|
||||
bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
|
||||
}
|
||||
|
||||
//HORIZONTAL
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_secondary_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_secondary_fb)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_depth_texture), 1);
|
||||
{
|
||||
// generate our depth data
|
||||
RID framebuffer = p_buffers.base_weight_fb;
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.depth_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL;
|
||||
blur_raster.push_constant.dof_dir[0] = 1.0;
|
||||
blur_raster.push_constant.dof_dir[1] = 0.0;
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
|
||||
// double pass approach
|
||||
BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
|
||||
|
||||
if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
|
||||
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
|
||||
bokeh.push_constant.half_size = true;
|
||||
bokeh.push_constant.blur_size *= 0.5;
|
||||
}
|
||||
|
||||
static const int quality_samples[4] = { 6, 12, 12, 24 };
|
||||
bokeh.push_constant.blur_scale = 0.5;
|
||||
bokeh.push_constant.steps = quality_samples[p_quality];
|
||||
|
||||
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
|
||||
|
||||
// Pass 1
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
//VERTICAL
|
||||
draw_list = RD::get_singleton()->draw_list_begin(p_base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_base_fb)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_depth_texture), 1);
|
||||
// Pass 2
|
||||
if (!bokeh.push_constant.half_size) {
|
||||
// do not output weight, we're writing back into our base buffer
|
||||
mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
|
||||
}
|
||||
bokeh.push_constant.second_pass = true;
|
||||
|
||||
framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[1] : p_buffers.base_fb;
|
||||
RID texture = bokeh.push_constant.half_size ? p_buffers.half_texture[0] : p_buffers.secondary_texture;
|
||||
RID weight = bokeh.push_constant.half_size ? p_buffers.weight_texture[2] : p_buffers.weight_texture[1];
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(weight), 1);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
blur_raster.push_constant.flags = base_flags;
|
||||
blur_raster.push_constant.dof_dir[0] = 0.0;
|
||||
blur_raster.push_constant.dof_dir[1] = 1.0;
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
if (bokeh.push_constant.half_size) {
|
||||
// Compose pass
|
||||
mode = BOKEH_COMPOSITE;
|
||||
framebuffer = p_buffers.base_fb;
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[1]), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[3]), 1);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
} else {
|
||||
// circular is a single pass approach
|
||||
BokehMode mode = BOKEH_GEN_BOKEH_CIRCULAR;
|
||||
|
||||
{
|
||||
// circle always runs in half size, otherwise too expensive (though the code below does support making this optional)
|
||||
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
|
||||
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
|
||||
bokeh.push_constant.half_size = true;
|
||||
// bokeh.push_constant.blur_size *= 0.5;
|
||||
}
|
||||
|
||||
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
|
||||
bokeh.push_constant.blur_scale = quality_scale[p_quality];
|
||||
bokeh.push_constant.steps = 0.0;
|
||||
|
||||
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.base_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 1);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
if (bokeh.push_constant.half_size) {
|
||||
// Compose
|
||||
mode = BOKEH_COMPOSITE;
|
||||
framebuffer = p_buffers.base_fb;
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.half_texture[0]), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[2]), 1);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.weight_texture[0]), 2);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &bokeh.push_constant, sizeof(BokehPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
} else {
|
||||
// Just copy it back (we use our blur raster shader here)..
|
||||
draw_list = RD::get_singleton()->draw_list_begin(p_buffers.base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_buffers.base_fb)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_buffers.secondary_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
|
||||
@ -1774,9 +1876,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
|
||||
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
|
||||
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
|
||||
blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_LOW\n"); // BLUR_MODE_DOF_LOW
|
||||
blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_MEDIUM\n"); // BLUR_MODE_DOF_MEDIUM
|
||||
blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_HIGH\n"); // BLUR_MODE_DOF_HIGH
|
||||
blur_modes.push_back("\n#define MODE_COPY\n"); // BLUR_MODE_COPY
|
||||
|
||||
blur_raster.shader.initialize(blur_modes);
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
@ -1956,23 +2056,40 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
|
||||
}
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
// not supported
|
||||
} else {
|
||||
// Initialize bokeh
|
||||
Vector<String> bokeh_modes;
|
||||
bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
|
||||
bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n#define OUTPUT_WEIGHT\n");
|
||||
bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n");
|
||||
bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n#define OUTPUT_WEIGHT\n");
|
||||
bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n");
|
||||
bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n");
|
||||
bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n#define OUTPUT_WEIGHT\n");
|
||||
bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n");
|
||||
if (prefer_raster_effects) {
|
||||
bokeh.raster_shader.initialize(bokeh_modes);
|
||||
|
||||
bokeh.shader.initialize(bokeh_modes);
|
||||
bokeh.shader_version = bokeh.raster_shader.version_create();
|
||||
|
||||
bokeh.shader_version = bokeh.shader.version_create();
|
||||
const int att_count[BOKEH_MAX] = { 1, 2, 1, 2, 1, 2, 1 };
|
||||
for (int i = 0; i < BOKEH_MAX; i++) {
|
||||
RD::PipelineColorBlendState blend_state = (i == BOKEH_COMPOSITE) ? RD::PipelineColorBlendState::create_blend(att_count[i]) : RD::PipelineColorBlendState::create_disabled(att_count[i]);
|
||||
bokeh.raster_pipelines[i].setup(bokeh.raster_shader.version_get_shader(bokeh.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
|
||||
}
|
||||
} else {
|
||||
bokeh.compute_shader.initialize(bokeh_modes);
|
||||
|
||||
bokeh.shader_version = bokeh.compute_shader.version_create();
|
||||
bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_BOX_NOWEIGHT, false);
|
||||
bokeh.compute_shader.set_variant_enabled(BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT, false);
|
||||
|
||||
for (int i = 0; i < BOKEH_MAX; i++) {
|
||||
bokeh.pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.shader.version_get_shader(bokeh.shader_version, i));
|
||||
if (bokeh.compute_shader.is_variant_enabled(i)) {
|
||||
bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < BOKEH_MAX; i++) {
|
||||
bokeh.raster_pipelines[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2173,12 +2290,13 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
filter.raster_shader.initialize(cubemap_filter_modes);
|
||||
filter.shader_version = filter.raster_shader.version_create();
|
||||
|
||||
// array variants are not supported in raster
|
||||
filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false);
|
||||
filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false);
|
||||
|
||||
filter.shader_version = filter.raster_shader.version_create();
|
||||
|
||||
for (int i = 0; i < FILTER_MODE_MAX; i++) {
|
||||
if (filter.raster_shader.is_variant_enabled(i)) {
|
||||
filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
@ -2390,12 +2508,13 @@ EffectsRD::~EffectsRD() {
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
blur_raster.shader.version_free(blur_raster.shader_version);
|
||||
bokeh.raster_shader.version_free(blur_raster.shader_version);
|
||||
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
|
||||
roughness.raster_shader.version_free(roughness.shader_version);
|
||||
cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
|
||||
filter.raster_shader.version_free(filter.shader_version);
|
||||
} else {
|
||||
bokeh.shader.version_free(bokeh.shader_version);
|
||||
bokeh.compute_shader.version_free(bokeh.shader_version);
|
||||
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
|
||||
roughness.compute_shader.version_free(roughness.shader_version);
|
||||
cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h"
|
||||
@ -72,10 +73,7 @@ private:
|
||||
BLUR_MODE_GAUSSIAN_BLUR,
|
||||
BLUR_MODE_GAUSSIAN_GLOW,
|
||||
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
|
||||
|
||||
BLUR_MODE_DOF_LOW,
|
||||
BLUR_MODE_DOF_MEDIUM,
|
||||
BLUR_MODE_DOF_HIGH,
|
||||
BLUR_MODE_COPY,
|
||||
|
||||
BLUR_MODE_MAX
|
||||
};
|
||||
@ -84,8 +82,6 @@ private:
|
||||
BLUR_FLAG_HORIZONTAL = (1 << 0),
|
||||
BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
|
||||
BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
|
||||
BLUR_FLAG_DOF_FAR = (1 << 3),
|
||||
BLUR_FLAG_DOF_NEAR = (1 << 4),
|
||||
};
|
||||
|
||||
struct BlurRasterPushConstant {
|
||||
@ -103,19 +99,6 @@ private:
|
||||
float glow_white;
|
||||
float glow_luminance_cap;
|
||||
float glow_auto_exposure_grey;
|
||||
|
||||
//dof
|
||||
float dof_far_begin;
|
||||
float dof_far_end;
|
||||
float dof_near_begin;
|
||||
float dof_near_end;
|
||||
|
||||
float dof_radius;
|
||||
float dof_pad[3];
|
||||
|
||||
float dof_dir[2];
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
};
|
||||
|
||||
struct BlurRaster {
|
||||
@ -252,29 +235,29 @@ private:
|
||||
};
|
||||
|
||||
struct TonemapPushConstant {
|
||||
float bcs[3];
|
||||
uint32_t use_bcs;
|
||||
float bcs[3]; // 12 - 12
|
||||
uint32_t use_bcs; // 4 - 16
|
||||
|
||||
uint32_t use_glow;
|
||||
uint32_t use_auto_exposure;
|
||||
uint32_t use_color_correction;
|
||||
uint32_t tonemapper;
|
||||
uint32_t use_glow; // 4 - 20
|
||||
uint32_t use_auto_exposure; // 4 - 24
|
||||
uint32_t use_color_correction; // 4 - 28
|
||||
uint32_t tonemapper; // 4 - 32
|
||||
|
||||
uint32_t glow_texture_size[2];
|
||||
float glow_intensity;
|
||||
uint32_t pad3;
|
||||
uint32_t glow_texture_size[2]; // 8 - 40
|
||||
float glow_intensity; // 4 - 44
|
||||
uint32_t pad3; // 4 - 48
|
||||
|
||||
uint32_t glow_mode;
|
||||
float glow_levels[7];
|
||||
uint32_t glow_mode; // 4 - 52
|
||||
float glow_levels[7]; // 28 - 80
|
||||
|
||||
float exposure;
|
||||
float white;
|
||||
float auto_exposure_grey;
|
||||
uint32_t pad2;
|
||||
float exposure; // 4 - 84
|
||||
float white; // 4 - 88
|
||||
float auto_exposure_grey; // 4 - 92
|
||||
uint32_t pad2; // 4 - 96
|
||||
|
||||
float pixel_size[2];
|
||||
uint32_t use_fxaa;
|
||||
uint32_t use_debanding;
|
||||
float pixel_size[2]; // 8 - 104
|
||||
uint32_t use_fxaa; // 4 - 108
|
||||
uint32_t use_debanding; // 4 - 112
|
||||
};
|
||||
|
||||
/* tonemap actually writes to a framebuffer, which is
|
||||
@ -375,7 +358,9 @@ private:
|
||||
enum BokehMode {
|
||||
BOKEH_GEN_BLUR_SIZE,
|
||||
BOKEH_GEN_BOKEH_BOX,
|
||||
BOKEH_GEN_BOKEH_BOX_NOWEIGHT,
|
||||
BOKEH_GEN_BOKEH_HEXAGONAL,
|
||||
BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT,
|
||||
BOKEH_GEN_BOKEH_CIRCULAR,
|
||||
BOKEH_COMPOSITE,
|
||||
BOKEH_MAX
|
||||
@ -383,9 +368,11 @@ private:
|
||||
|
||||
struct Bokeh {
|
||||
BokehPushConstant push_constant;
|
||||
BokehDofShaderRD shader;
|
||||
BokehDofShaderRD compute_shader;
|
||||
BokehDofRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID pipelines[BOKEH_MAX];
|
||||
RID compute_pipelines[BOKEH_MAX];
|
||||
PipelineCacheRD raster_pipelines[BOKEH_MAX];
|
||||
} bokeh;
|
||||
|
||||
enum SSAOMode {
|
||||
@ -784,8 +771,26 @@ public:
|
||||
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
|
||||
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
|
||||
|
||||
void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||
void blur_dof_raster(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_base_fb, RID p_secondary_texture, RID p_secondary_fb, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||
struct BokehBuffers {
|
||||
// bokeh buffers
|
||||
|
||||
// textures
|
||||
Size2i base_texture_size;
|
||||
RID base_texture;
|
||||
RID depth_texture;
|
||||
RID secondary_texture;
|
||||
RID half_texture[2];
|
||||
|
||||
// raster only
|
||||
RID base_fb;
|
||||
RID secondary_fb; // with weights
|
||||
RID half_fb[2]; // with weights
|
||||
RID base_weight_fb;
|
||||
RID weight_texture[4];
|
||||
};
|
||||
|
||||
void bokeh_dof(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||
void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||
|
||||
struct TonemapSettings {
|
||||
bool use_glow = false;
|
||||
|
@ -1464,6 +1464,53 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
||||
base_width = MAX(1, base_width >> 1);
|
||||
base_height = MAX(1, base_height >> 1);
|
||||
}
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
// create 4 weight textures, 2 full size, 2 half size
|
||||
|
||||
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
|
||||
tf.array_layers = rb->view_count;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
tf.mipmaps = 1;
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
// associated blur texture
|
||||
RID texture;
|
||||
if (i == 0) {
|
||||
texture = rb->texture;
|
||||
} else if (i == 1) {
|
||||
texture = rb->blur[0].mipmaps[0].texture;
|
||||
} else if (i == 2) {
|
||||
texture = rb->blur[1].mipmaps[0].texture;
|
||||
} else if (i == 3) {
|
||||
texture = rb->blur[0].mipmaps[1].texture;
|
||||
}
|
||||
|
||||
// create weight texture
|
||||
rb->weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
// create frame buffer
|
||||
Vector<RID> fb;
|
||||
fb.push_back(texture);
|
||||
fb.push_back(rb->weight_buffers[i].weight);
|
||||
rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
|
||||
if (i == 1) {
|
||||
// next 2 are half size
|
||||
tf.width = MAX(1, tf.width >> 1);
|
||||
tf.height = MAX(1, tf.height >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// and finally an FB for just our base weights
|
||||
Vector<RID> fb;
|
||||
fb.push_back(rb->weight_buffers[0].weight);
|
||||
rb->base_weight_fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
|
||||
@ -1851,11 +1898,34 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
||||
_allocate_blur_textures(rb);
|
||||
}
|
||||
|
||||
if (can_use_storage) {
|
||||
EffectsRD::BokehBuffers buffers;
|
||||
|
||||
// textures we use
|
||||
buffers.base_texture_size = Size2i(rb->width, rb->height);
|
||||
buffers.base_texture = rb->texture;
|
||||
buffers.depth_texture = rb->depth_texture;
|
||||
buffers.secondary_texture = rb->blur[0].mipmaps[0].texture;
|
||||
buffers.half_texture[0] = rb->blur[1].mipmaps[0].texture;
|
||||
buffers.half_texture[1] = rb->blur[0].mipmaps[1].texture;
|
||||
|
||||
float bokeh_size = camfx->dof_blur_amount * 64.0;
|
||||
storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
|
||||
if (can_use_storage) {
|
||||
storage->get_effects()->bokeh_dof(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
|
||||
} else {
|
||||
storage->get_effects()->blur_dof_raster(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->texture_fb, rb->blur[0].mipmaps[0].texture, rb->blur[0].mipmaps[0].fb, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, camfx->dof_blur_amount, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
|
||||
// set framebuffers
|
||||
buffers.base_fb = rb->texture_fb;
|
||||
buffers.secondary_fb = rb->weight_buffers[1].fb;
|
||||
buffers.half_fb[0] = rb->weight_buffers[2].fb;
|
||||
buffers.half_fb[1] = rb->weight_buffers[3].fb;
|
||||
buffers.weight_texture[0] = rb->weight_buffers[0].weight;
|
||||
buffers.weight_texture[1] = rb->weight_buffers[1].weight;
|
||||
buffers.weight_texture[2] = rb->weight_buffers[2].weight;
|
||||
buffers.weight_texture[3] = rb->weight_buffers[3].weight;
|
||||
|
||||
// set weight buffers
|
||||
buffers.base_weight_fb = rb->base_weight_fb;
|
||||
|
||||
storage->get_effects()->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
@ -483,6 +483,15 @@ private:
|
||||
|
||||
Blur blur[2]; //the second one starts from the first mipmap
|
||||
|
||||
struct WeightBuffers {
|
||||
RID weight;
|
||||
RID fb; // FB with both texture and weight
|
||||
};
|
||||
|
||||
// 2 full size, 2 half size
|
||||
WeightBuffers weight_buffers[4]; // Only used in raster
|
||||
RID base_weight_fb; // base buffer for weight
|
||||
|
||||
struct Luminance {
|
||||
Vector<RID> reduce;
|
||||
RID current;
|
||||
|
@ -37,32 +37,6 @@ layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
//DOF
|
||||
#ifdef MODE_DOF_BLUR
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
|
||||
|
||||
#ifdef DOF_QUALITY_LOW
|
||||
const int dof_kernel_size = 5;
|
||||
const int dof_kernel_from = 2;
|
||||
const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_MEDIUM
|
||||
const int dof_kernel_size = 11;
|
||||
const int dof_kernel_from = 5;
|
||||
const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_HIGH
|
||||
const int dof_kernel_size = 21;
|
||||
const int dof_kernel_from = 10;
|
||||
const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_MIPMAP
|
||||
|
||||
@ -155,74 +129,8 @@ void main() {
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DOF_BLUR
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
float depth = texture(dof_source_depth, uv_interp, 0.0).r;
|
||||
depth = depth * 2.0 - 1.0;
|
||||
|
||||
if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
|
||||
depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
|
||||
}
|
||||
|
||||
// mix near and far blur amount
|
||||
float amount = 1.0;
|
||||
if (bool(blur.flags & FLAG_DOF_FAR)) {
|
||||
amount *= 1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, depth);
|
||||
}
|
||||
if (bool(blur.flags & FLAG_DOF_NEAR)) {
|
||||
amount *= smoothstep(blur.dof_near_end, blur.dof_near_begin, depth);
|
||||
}
|
||||
amount = 1.0 - amount;
|
||||
|
||||
if (amount > 0.0) {
|
||||
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 + blur.dof_dir * float(int_ofs) * amount * blur.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;
|
||||
|
||||
if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
|
||||
tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
|
||||
} else {
|
||||
tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
|
||||
}
|
||||
|
||||
// mix near and far blur amount
|
||||
float tap_amount = 1.0;
|
||||
if (bool(blur.flags & FLAG_DOF_FAR)) {
|
||||
tap_amount *= mix(1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, tap_depth), 0.0, int_ofs == 0);
|
||||
}
|
||||
if (bool(blur.flags & FLAG_DOF_NEAR)) {
|
||||
tap_amount *= mix(smoothstep(blur.dof_near_end, blur.dof_near_begin, tap_depth), 0.0, int_ofs == 0);
|
||||
}
|
||||
tap_amount = 1.0 - tap_amount;
|
||||
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
vec4 tap_color = texture(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;
|
||||
} else {
|
||||
// we are in focus, don't waste time
|
||||
frag_color = texture(source_color, uv_interp, 0.0);
|
||||
}
|
||||
|
||||
#ifdef MODE_COPY
|
||||
vec4 color = textureLod(source_color, uv_interp, 0.0);
|
||||
frag_color = color;
|
||||
#endif
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
#define FLAG_HORIZONTAL (1 << 0)
|
||||
#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
|
||||
#define FLAG_GLOW_FIRST_PASS (1 << 2)
|
||||
#define FLAG_DOF_FAR (1 << 3)
|
||||
#define FLAG_DOF_NEAR (1 << 4)
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Blur {
|
||||
vec2 pixel_size;
|
||||
@ -19,18 +17,5 @@ layout(push_constant, binding = 1, std430) uniform Blur {
|
||||
float glow_white;
|
||||
float glow_luminance_cap;
|
||||
float glow_auto_exposure_grey;
|
||||
|
||||
// DOF.
|
||||
float dof_far_begin;
|
||||
float dof_far_end;
|
||||
float dof_near_begin;
|
||||
float dof_near_end;
|
||||
|
||||
float dof_radius;
|
||||
float dof_pad[3];
|
||||
|
||||
vec2 dof_dir;
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
}
|
||||
blur;
|
||||
|
@ -25,34 +25,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
|
||||
|
||||
// based on https://www.shadertoy.com/view/Xd3GDl
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
ivec2 size;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
bool orthogonal;
|
||||
float blur_size;
|
||||
float blur_scale;
|
||||
int blur_steps;
|
||||
|
||||
bool blur_near_active;
|
||||
float blur_near_begin;
|
||||
float blur_near_end;
|
||||
bool blur_far_active;
|
||||
|
||||
float blur_far_begin;
|
||||
float blur_far_end;
|
||||
bool second_pass;
|
||||
bool half_size;
|
||||
|
||||
bool use_jitter;
|
||||
float jitter_seed;
|
||||
uint pad[2];
|
||||
}
|
||||
params;
|
||||
|
||||
//used to work around downsampling filter
|
||||
#define DEPTH_GAP 0.0
|
||||
#include "bokeh_dof_inc.glsl"
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
|
||||
@ -80,15 +53,6 @@ float get_blur_size(float depth) {
|
||||
|
||||
#endif
|
||||
|
||||
const float GOLDEN_ANGLE = 2.39996323;
|
||||
|
||||
//note: uniform pdf rand [0;1[
|
||||
float hash12n(vec2 p) {
|
||||
p = fract(p * vec2(5.3987, 5.4421));
|
||||
p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
|
||||
return fract(p.x * p.y * 95.4307);
|
||||
}
|
||||
|
||||
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
|
||||
|
||||
vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
|
||||
|
37
servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl
Normal file
37
servers/rendering/renderer_rd/shaders/bokeh_dof_inc.glsl
Normal file
@ -0,0 +1,37 @@
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
ivec2 size;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
bool orthogonal;
|
||||
float blur_size;
|
||||
float blur_scale;
|
||||
int blur_steps;
|
||||
|
||||
bool blur_near_active;
|
||||
float blur_near_begin;
|
||||
float blur_near_end;
|
||||
bool blur_far_active;
|
||||
|
||||
float blur_far_begin;
|
||||
float blur_far_end;
|
||||
bool second_pass;
|
||||
bool half_size;
|
||||
|
||||
bool use_jitter;
|
||||
float jitter_seed;
|
||||
uint pad[2];
|
||||
}
|
||||
params;
|
||||
|
||||
//used to work around downsampling filter
|
||||
#define DEPTH_GAP 0.0
|
||||
|
||||
const float GOLDEN_ANGLE = 2.39996323;
|
||||
|
||||
//note: uniform pdf rand [0;1[
|
||||
float hash12n(vec2 p) {
|
||||
p = fract(p * vec2(5.3987, 5.4421));
|
||||
p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
|
||||
return fract(p.x * p.y * 95.4307);
|
||||
}
|
253
servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
Normal file
253
servers/rendering/renderer_rd/shaders/bokeh_dof_raster.glsl
Normal file
@ -0,0 +1,253 @@
|
||||
/* clang-format off */
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "bokeh_dof_inc.glsl"
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
|
||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
#[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "bokeh_dof_inc.glsl"
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
layout(location = 0) out float weight;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_depth;
|
||||
#else
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
#ifdef OUTPUT_WEIGHT
|
||||
layout(location = 1) out float weight;
|
||||
#endif
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_weight;
|
||||
#ifdef MODE_COMPOSITE_BOKEH
|
||||
layout(set = 2, binding = 0) uniform sampler2D original_weight;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//DOF
|
||||
// Bokeh single pass implementation based on http://tuxedolabs.blogspot.com/2018/05/bokeh-depth-of-field-in-single-pass.html
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
|
||||
float get_depth_at_pos(vec2 uv) {
|
||||
float depth = textureLod(source_depth, uv, 0.0).x;
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
float get_blur_size(float depth) {
|
||||
if (params.blur_near_active && depth < params.blur_near_begin) {
|
||||
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
|
||||
}
|
||||
|
||||
if (params.blur_far_active && depth > params.blur_far_begin) {
|
||||
return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
|
||||
|
||||
vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
|
||||
dir *= pixel_size;
|
||||
vec4 color = texture(source_color, uv);
|
||||
color.a = texture(source_weight, uv).r;
|
||||
|
||||
vec4 accum = color;
|
||||
float total = 1.0;
|
||||
|
||||
float blur_scale = params.blur_size / float(params.blur_steps);
|
||||
|
||||
if (params.use_jitter) {
|
||||
uv += dir * (hash12n(uv + params.jitter_seed) - 0.5);
|
||||
}
|
||||
|
||||
for (int i = -params.blur_steps; i <= params.blur_steps; i++) {
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
float radius = float(i) * blur_scale;
|
||||
vec2 suv = uv + dir * radius;
|
||||
radius = abs(radius);
|
||||
|
||||
vec4 sample_color = texture(source_color, suv);
|
||||
sample_color.a = texture(source_weight, suv).r;
|
||||
float limit;
|
||||
|
||||
if (sample_color.a < color.a) {
|
||||
limit = abs(sample_color.a);
|
||||
} else {
|
||||
limit = abs(color.a);
|
||||
}
|
||||
|
||||
limit -= DEPTH_GAP;
|
||||
|
||||
float m = smoothstep(radius - 0.5, radius + 0.5, limit);
|
||||
|
||||
accum += mix(color, sample_color, m);
|
||||
|
||||
total += 1.0;
|
||||
}
|
||||
|
||||
return accum / total;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec2 pixel_size = 1.0 / vec2(params.size);
|
||||
vec2 uv = uv_interp;
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
uv += pixel_size * 0.5;
|
||||
float center_depth = get_depth_at_pos(uv);
|
||||
weight = get_blur_size(center_depth);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_BOKEH_BOX
|
||||
//pixel_size*=0.5; //resolution is doubled
|
||||
if (params.second_pass || !params.half_size) {
|
||||
uv += pixel_size * 0.5; //half pixel to read centers
|
||||
} else {
|
||||
uv += pixel_size * 0.25; //half pixel to read centers from full res
|
||||
}
|
||||
|
||||
float alpha = texture(source_color, uv).a; // retain this
|
||||
vec2 dir = (params.second_pass ? vec2(0.0, 1.0) : vec2(1.0, 0.0));
|
||||
|
||||
vec4 color = weighted_filter_dir(dir, uv, pixel_size);
|
||||
|
||||
frag_color = color;
|
||||
frag_color.a = alpha; // attempt to retain this in case we have a transparent background, ignored if half_size
|
||||
#ifdef OUTPUT_WEIGHT
|
||||
weight = color.a;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_BOKEH_HEXAGONAL
|
||||
|
||||
//pixel_size*=0.5; //resolution is doubled
|
||||
if (params.second_pass || !params.half_size) {
|
||||
uv += pixel_size * 0.5; //half pixel to read centers
|
||||
} else {
|
||||
uv += pixel_size * 0.25; //half pixel to read centers from full res
|
||||
}
|
||||
|
||||
float alpha = texture(source_color, uv).a; // retain this
|
||||
|
||||
vec2 dir = (params.second_pass ? normalize(vec2(1.0, 0.577350269189626)) : vec2(0.0, 1.0));
|
||||
|
||||
vec4 color = weighted_filter_dir(dir, uv, pixel_size);
|
||||
|
||||
if (params.second_pass) {
|
||||
dir = normalize(vec2(-1.0, 0.577350269189626));
|
||||
|
||||
vec4 color2 = weighted_filter_dir(dir, uv, pixel_size);
|
||||
|
||||
color.rgb = min(color.rgb, color2.rgb);
|
||||
color.a = (color.a + color2.a) * 0.5;
|
||||
}
|
||||
|
||||
frag_color = color;
|
||||
frag_color.a = alpha; // attempt to retain this in case we have a transparent background, ignored if half_size
|
||||
#ifdef OUTPUT_WEIGHT
|
||||
weight = color.a;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_BOKEH_CIRCULAR
|
||||
if (params.half_size) {
|
||||
pixel_size *= 0.5; //resolution is doubled
|
||||
}
|
||||
|
||||
uv += pixel_size * 0.5; //half pixel to read centers
|
||||
|
||||
vec4 color = texture(source_color, uv);
|
||||
float alpha = color.a; // retain this
|
||||
color.a = texture(source_weight, uv).r;
|
||||
|
||||
vec4 color_accum = color;
|
||||
float accum = 1.0;
|
||||
|
||||
float radius = params.blur_scale;
|
||||
for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) {
|
||||
vec2 uv_adj = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;
|
||||
|
||||
vec4 sample_color = texture(source_color, uv_adj);
|
||||
sample_color.a = texture(source_weight, uv_adj).r;
|
||||
|
||||
float limit;
|
||||
|
||||
if (sample_color.a < color.a) {
|
||||
limit = abs(sample_color.a);
|
||||
} else {
|
||||
limit = abs(color.a);
|
||||
}
|
||||
|
||||
limit -= DEPTH_GAP;
|
||||
|
||||
float m = smoothstep(radius - 0.5, radius + 0.5, limit);
|
||||
color_accum += mix(color_accum / accum, sample_color, m);
|
||||
accum += 1.0;
|
||||
|
||||
radius += params.blur_scale / radius;
|
||||
}
|
||||
|
||||
color_accum = color_accum / accum;
|
||||
|
||||
frag_color.rgb = color_accum.rgb;
|
||||
frag_color.a = alpha; // attempt to retain this in case we have a transparent background, ignored if half_size
|
||||
#ifdef OUTPUT_WEIGHT
|
||||
weight = color_accum.a;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_COMPOSITE_BOKEH
|
||||
frag_color.rgb = texture(source_color, uv).rgb;
|
||||
|
||||
float center_weigth = texture(source_weight, uv).r;
|
||||
float sample_weight = texture(original_weight, uv).r;
|
||||
|
||||
float mix_amount;
|
||||
if (sample_weight < center_weigth) {
|
||||
mix_amount = min(1.0, max(0.0, max(abs(center_weigth), abs(sample_weight)) - DEPTH_GAP));
|
||||
} else {
|
||||
mix_amount = min(1.0, max(0.0, abs(center_weigth) - DEPTH_GAP));
|
||||
}
|
||||
|
||||
// let alpha blending take care of mixing
|
||||
frag_color.a = mix_amount;
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue
Block a user