Use fragment shader instead of compute shader for effects for mobile renderer
This commit is contained in:
parent
54b598ffe4
commit
1f69582835
12 changed files with 843 additions and 38 deletions
|
@ -383,6 +383,8 @@ void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i
|
|||
}
|
||||
|
||||
void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
|
||||
|
||||
memset(©.push_constant, 0, sizeof(CopyPushConstant));
|
||||
|
||||
uint32_t base_flags = 0;
|
||||
|
@ -416,6 +418,8 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
|
|||
}
|
||||
|
||||
void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
|
||||
|
||||
memset(©.push_constant, 0, sizeof(CopyPushConstant));
|
||||
|
||||
CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
|
||||
|
@ -449,6 +453,57 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the fragment version of the gaussian glow with the clustered renderer.");
|
||||
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
|
||||
BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
|
||||
uint32_t base_flags = 0;
|
||||
|
||||
blur_raster.push_constant.pixel_size[0] = p_pixel_size.x;
|
||||
blur_raster.push_constant.pixel_size[1] = p_pixel_size.y;
|
||||
|
||||
blur_raster.push_constant.glow_strength = p_strength;
|
||||
blur_raster.push_constant.glow_bloom = p_bloom;
|
||||
blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
|
||||
blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
|
||||
blur_raster.push_constant.glow_exposure = p_exposure;
|
||||
blur_raster.push_constant.glow_white = 0; //actually unused
|
||||
blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
|
||||
|
||||
blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
|
||||
|
||||
//HORIZONTAL
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, 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_framebuffer_half)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||
if (p_auto_exposure.is_valid() && p_first_pass) {
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
|
||||
}
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
|
||||
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();
|
||||
|
||||
blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
|
||||
|
||||
//VERTICAL
|
||||
draw_list = RD::get_singleton()->draw_list_begin(p_dest_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, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
blur_raster.push_constant.flags = base_flags;
|
||||
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::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
|
@ -736,6 +791,8 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
|
|||
}
|
||||
|
||||
void EffectsRD::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) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
|
||||
|
||||
luminance_reduce.push_constant.source_size[0] = p_source_size.x;
|
||||
luminance_reduce.push_constant.source_size[1] = p_source_size.y;
|
||||
luminance_reduce.push_constant.max_luminance = p_max_luminance;
|
||||
|
@ -774,7 +831,41 @@ void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::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) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use fragment version of luminance reduction with the clustered renderer.");
|
||||
ERR_FAIL_COND_MSG(p_reduce.size() != p_fb.size(), "Incorrect frame buffer account for luminance reduction.");
|
||||
|
||||
luminance_reduce_raster.push_constant.max_luminance = p_max_luminance;
|
||||
luminance_reduce_raster.push_constant.min_luminance = p_min_luminance;
|
||||
luminance_reduce_raster.push_constant.exposure_adjust = p_adjust;
|
||||
|
||||
for (int i = 0; i < p_reduce.size(); i++) {
|
||||
luminance_reduce_raster.push_constant.source_size[0] = i == 0 ? p_source_size.x : luminance_reduce_raster.push_constant.dest_size[0];
|
||||
luminance_reduce_raster.push_constant.source_size[1] = i == 0 ? p_source_size.y : luminance_reduce_raster.push_constant.dest_size[1];
|
||||
luminance_reduce_raster.push_constant.dest_size[0] = MAX(luminance_reduce_raster.push_constant.source_size[0] / 8, 1);
|
||||
luminance_reduce_raster.push_constant.dest_size[1] = MAX(luminance_reduce_raster.push_constant.source_size[1] / 8, 1);
|
||||
|
||||
bool final = !p_set && (luminance_reduce_raster.push_constant.dest_size[0] == 1) && (luminance_reduce_raster.push_constant.dest_size[1] == 1);
|
||||
LuminanceReduceRasterMode mode = final ? LUMINANCE_REDUCE_FRAGMENT_FINAL : (i == 0 ? LUMINANCE_REDUCE_FRAGMENT_FIRST : LUMINANCE_REDUCE_FRAGMENT);
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb[i], 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, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_fb[i])));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(i == 0 ? p_source_texture : p_reduce[i - 1]), 0);
|
||||
if (final) {
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_prev_luminance), 1);
|
||||
}
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &luminance_reduce_raster.push_constant, sizeof(LuminanceReduceRasterPushConstant));
|
||||
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
|
||||
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
|
||||
|
@ -924,6 +1015,78 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
|
|||
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) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer.");
|
||||
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
|
||||
BlurRasterMode blur_mode;
|
||||
int qsteps[4] = { 4, 4, 10, 20 };
|
||||
uint32_t base_flags = p_cam_orthogonal ? BLUR_FLAG_USE_ORTHOGONAL_PROJECTION : 0;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//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);
|
||||
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, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
|
||||
|
||||
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);
|
||||
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, &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);
|
||||
if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
|
||||
|
@ -1464,7 +1627,35 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
|
|||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
EffectsRD::EffectsRD() {
|
||||
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
prefer_raster_effects = p_prefer_raster_effects;
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
// init blur shader (on compute use copy shader)
|
||||
|
||||
Vector<String> blur_modes;
|
||||
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_raster.shader.initialize(blur_modes);
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
blur_raster.shader_version = blur_raster.shader.version_create();
|
||||
|
||||
for (int i = 0; i < BLUR_MODE_MAX; i++) {
|
||||
blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
// not used in clustered
|
||||
for (int i = 0; i < BLUR_MODE_MAX; i++) {
|
||||
blur_raster.pipelines[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
{ // Initialize copy
|
||||
Vector<String> copy_modes;
|
||||
copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
|
||||
|
@ -1483,10 +1674,21 @@ EffectsRD::EffectsRD() {
|
|||
|
||||
copy.shader.initialize(copy_modes);
|
||||
memset(©.push_constant, 0, sizeof(CopyPushConstant));
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
// disable shaders we can't use
|
||||
copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY, false);
|
||||
copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY_8BIT, false);
|
||||
copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW, false);
|
||||
copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, false);
|
||||
}
|
||||
|
||||
copy.shader_version = copy.shader.version_create();
|
||||
|
||||
for (int i = 0; i < COPY_MODE_MAX; i++) {
|
||||
copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
|
||||
if (copy.shader.is_variant_enabled(i)) {
|
||||
copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
|
@ -1551,7 +1753,20 @@ EffectsRD::EffectsRD() {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (prefer_raster_effects) {
|
||||
Vector<String> luminance_reduce_modes;
|
||||
luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
|
||||
luminance_reduce_modes.push_back("\n"); // LUMINANCE_REDUCE_FRAGMENT
|
||||
luminance_reduce_modes.push_back("\n#define FINAL_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FINAL
|
||||
|
||||
luminance_reduce_raster.shader.initialize(luminance_reduce_modes);
|
||||
memset(&luminance_reduce_raster.push_constant, 0, sizeof(LuminanceReduceRasterPushConstant));
|
||||
luminance_reduce_raster.shader_version = luminance_reduce_raster.shader.version_create();
|
||||
|
||||
for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
|
||||
luminance_reduce_raster.pipelines[i].setup(luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
|
||||
}
|
||||
} else {
|
||||
// Initialize luminance_reduce
|
||||
Vector<String> luminance_reduce_modes;
|
||||
luminance_reduce_modes.push_back("\n#define READ_TEXTURE\n");
|
||||
|
@ -1565,6 +1780,10 @@ EffectsRD::EffectsRD() {
|
|||
for (int i = 0; i < LUMINANCE_REDUCE_MAX; i++) {
|
||||
luminance_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
|
||||
luminance_reduce_raster.pipelines[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1583,7 +1802,9 @@ EffectsRD::EffectsRD() {
|
|||
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");
|
||||
|
@ -1974,13 +2195,18 @@ EffectsRD::~EffectsRD() {
|
|||
RD::get_singleton()->free(ssao.gather_constants_buffer);
|
||||
RD::get_singleton()->free(ssao.importance_map_load_counter);
|
||||
|
||||
bokeh.shader.version_free(bokeh.shader_version);
|
||||
if (prefer_raster_effects) {
|
||||
blur_raster.shader.version_free(blur_raster.shader_version);
|
||||
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
|
||||
} else {
|
||||
bokeh.shader.version_free(bokeh.shader_version);
|
||||
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
|
||||
}
|
||||
copy.shader.version_free(copy.shader_version);
|
||||
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
|
||||
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
|
||||
cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
|
||||
filter.shader.version_free(filter.shader_version);
|
||||
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
|
||||
resolve.shader.version_free(resolve.shader_version);
|
||||
roughness.shader.version_free(roughness.shader_version);
|
||||
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "core/math/camera_matrix.h"
|
||||
#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/copy.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h"
|
||||
|
@ -60,6 +62,63 @@
|
|||
#include "servers/rendering_server.h"
|
||||
|
||||
class EffectsRD {
|
||||
enum BlurRasterMode {
|
||||
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_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
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 {
|
||||
float pixel_size[2];
|
||||
uint32_t flags;
|
||||
uint32_t pad;
|
||||
|
||||
//glow
|
||||
float glow_strength;
|
||||
float glow_bloom;
|
||||
float glow_hdr_threshold;
|
||||
float glow_hdr_scale;
|
||||
|
||||
float glow_exposure;
|
||||
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 {
|
||||
BlurRasterPushConstant push_constant;
|
||||
BlurRasterShaderRD shader;
|
||||
RID shader_version;
|
||||
PipelineCacheRD pipelines[BLUR_MODE_MAX];
|
||||
} blur_raster;
|
||||
|
||||
enum CopyMode {
|
||||
COPY_MODE_GAUSSIAN_COPY,
|
||||
COPY_MODE_GAUSSIAN_COPY_8BIT,
|
||||
|
@ -239,6 +298,29 @@ class EffectsRD {
|
|||
RID pipelines[LUMINANCE_REDUCE_MAX];
|
||||
} luminance_reduce;
|
||||
|
||||
enum LuminanceReduceRasterMode {
|
||||
LUMINANCE_REDUCE_FRAGMENT_FIRST,
|
||||
LUMINANCE_REDUCE_FRAGMENT,
|
||||
LUMINANCE_REDUCE_FRAGMENT_FINAL,
|
||||
LUMINANCE_REDUCE_FRAGMENT_MAX
|
||||
};
|
||||
|
||||
struct LuminanceReduceRasterPushConstant {
|
||||
int32_t source_size[2];
|
||||
int32_t dest_size[2];
|
||||
float exposure_adjust;
|
||||
float min_luminance;
|
||||
float max_luminance;
|
||||
float pad[1];
|
||||
};
|
||||
|
||||
struct LuminanceReduceFragment {
|
||||
LuminanceReduceRasterPushConstant push_constant;
|
||||
LuminanceReduceRasterShaderRD shader;
|
||||
RID shader_version;
|
||||
PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
|
||||
} luminance_reduce_raster;
|
||||
|
||||
struct CopyToDPPushConstant {
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
@ -656,6 +738,8 @@ class EffectsRD {
|
|||
RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
|
||||
RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
|
||||
|
||||
bool prefer_raster_effects;
|
||||
|
||||
public:
|
||||
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
|
||||
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
|
||||
|
@ -666,12 +750,16 @@ public:
|
|||
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
|
||||
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
|
||||
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
||||
void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
||||
|
||||
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
|
||||
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
|
||||
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip);
|
||||
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 TonemapSettings {
|
||||
bool use_glow = false;
|
||||
|
@ -751,7 +839,7 @@ public:
|
|||
|
||||
void sort_buffer(RID p_uniform_set, int p_size);
|
||||
|
||||
EffectsRD();
|
||||
EffectsRD(bool p_prefer_raster_effects);
|
||||
~EffectsRD();
|
||||
};
|
||||
|
||||
|
|
|
@ -96,10 +96,6 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
|||
RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
|
||||
|
||||
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
|
||||
if (color_format == RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32) {
|
||||
// @TODO add a second color buffer for alpha as this format is RGB only
|
||||
}
|
||||
|
||||
Vector<RID> fb;
|
||||
fb.push_back(p_color_buffer);
|
||||
fb.push_back(depth);
|
||||
|
@ -165,15 +161,12 @@ bool RenderForwardMobile::free(RID p_rid) {
|
|||
|
||||
RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() {
|
||||
// Using 32bit buffers enables AFBC on mobile devices which should have a definate performance improvement (MALI G710 and newer support this on 64bit RTs)
|
||||
// NO ALPHA and unsigned float.
|
||||
// @TODO No alpha is an issue, recommendation here is to add a second RT for alpha
|
||||
return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
}
|
||||
|
||||
bool RenderForwardMobile::_render_buffers_can_be_storage() {
|
||||
// Using 32bit buffers enables AFBC on mobile devices which should have a definate performance improvement (MALI G710 and newer support this on 64bit RTs)
|
||||
// NO ALPHA and unsigned float.
|
||||
// @TODO No alpha is an issue, recommendation here is to add a second RT for alpha
|
||||
// Doesn't support storage
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -280,6 +280,9 @@ RendererCompositorRD::RendererCompositorRD() {
|
|||
// default to our high end renderer
|
||||
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
|
||||
}
|
||||
|
||||
// now we're ready to create our effects,
|
||||
storage->init_effects(!scene->_render_buffers_can_be_storage());
|
||||
}
|
||||
|
||||
RendererCompositorRD::~RendererCompositorRD() {
|
||||
|
|
|
@ -1383,12 +1383,20 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
|||
|
||||
uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH);
|
||||
|
||||
// TODO make sure texture_create_shared_from_slice works for multiview
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.width = rb->width;
|
||||
tf.height = rb->height;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
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;
|
||||
if (_render_buffers_can_be_storage()) {
|
||||
tf.usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
} else {
|
||||
tf.usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
tf.mipmaps = mipmaps_required;
|
||||
|
||||
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
@ -1408,11 +1416,40 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
|
|||
mm.width = base_width;
|
||||
mm.height = base_height;
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(mm.texture);
|
||||
|
||||
mm.fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
}
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
// and half texture, this is an intermediate result so just allocate a texture, is this good enough?
|
||||
tf.width = MAX(1, base_width >> 1);
|
||||
tf.height = base_height;
|
||||
tf.mipmaps = 1; // 1 or 0?
|
||||
|
||||
mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
Vector<RID> half_fb;
|
||||
half_fb.push_back(mm.half_texture);
|
||||
mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
|
||||
}
|
||||
|
||||
rb->blur[0].mipmaps.push_back(mm);
|
||||
|
||||
if (i > 0) {
|
||||
mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(mm.texture);
|
||||
|
||||
mm.fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
|
||||
// We can re-use the half texture here as it is an intermediate result
|
||||
}
|
||||
|
||||
rb->blur[1].mipmaps.push_back(mm);
|
||||
}
|
||||
|
||||
|
@ -1435,26 +1472,48 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
|
|||
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
|
||||
tf.width = w;
|
||||
tf.height = h;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
bool final = w == 1 && h == 1;
|
||||
|
||||
if (final) {
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
if (_render_buffers_can_be_storage()) {
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
if (final) {
|
||||
tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
}
|
||||
} else {
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
}
|
||||
|
||||
RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
rb->luminance.reduce.push_back(texture);
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(texture);
|
||||
|
||||
rb->luminance.fb.push_back(RD::get_singleton()->framebuffer_create(fb));
|
||||
}
|
||||
|
||||
if (final) {
|
||||
rb->luminance.current = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(rb->luminance.current);
|
||||
|
||||
rb->luminance.current_fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
|
||||
if (rb->texture_fb.is_valid()) {
|
||||
RD::get_singleton()->free(rb->texture_fb);
|
||||
rb->texture_fb = RID();
|
||||
}
|
||||
|
||||
if (rb->texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->texture);
|
||||
rb->texture = RID();
|
||||
|
@ -1466,19 +1525,43 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
|
||||
// do we free the texture slice here? or is it enough to free the main texture?
|
||||
|
||||
// do free the mobile extra stuff
|
||||
if (rb->blur[i].mipmaps[m].fb.is_valid()) {
|
||||
RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb);
|
||||
}
|
||||
if (rb->blur[i].mipmaps[m].half_fb.is_valid()) {
|
||||
RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb);
|
||||
}
|
||||
if (rb->blur[i].mipmaps[m].half_texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture);
|
||||
}
|
||||
}
|
||||
rb->blur[i].mipmaps.clear();
|
||||
|
||||
if (rb->blur[i].texture.is_valid()) {
|
||||
RD::get_singleton()->free(rb->blur[i].texture);
|
||||
rb->blur[i].texture = RID();
|
||||
rb->blur[i].mipmaps.clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rb->luminance.fb.size(); i++) {
|
||||
RD::get_singleton()->free(rb->luminance.fb[i]);
|
||||
}
|
||||
rb->luminance.fb.clear();
|
||||
|
||||
for (int i = 0; i < rb->luminance.reduce.size(); i++) {
|
||||
RD::get_singleton()->free(rb->luminance.reduce[i]);
|
||||
}
|
||||
|
||||
rb->luminance.reduce.clear();
|
||||
|
||||
if (rb->luminance.current_fb.is_valid()) {
|
||||
RD::get_singleton()->free(rb->luminance.current_fb);
|
||||
rb->luminance.current_fb = RID();
|
||||
}
|
||||
|
||||
if (rb->luminance.current.is_valid()) {
|
||||
RD::get_singleton()->free(rb->luminance.current);
|
||||
rb->luminance.current = RID();
|
||||
|
@ -1750,17 +1833,27 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
CameraEffects *camfx = camera_effects_owner.getornull(p_render_data->camera_effects);
|
||||
|
||||
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
|
||||
bool can_use_storage = _render_buffers_can_be_storage();
|
||||
|
||||
// @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
|
||||
|
||||
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
|
||||
RD::get_singleton()->draw_command_begin_label("DOF");
|
||||
if (rb->blur[0].texture.is_null()) {
|
||||
_allocate_blur_textures(rb);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
} 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);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
if (can_use_effects && env && env->auto_exposure) {
|
||||
RD::get_singleton()->draw_command_begin_label("Auto exposure");
|
||||
if (rb->luminance.current.is_null()) {
|
||||
_allocate_luminance_textures(rb);
|
||||
}
|
||||
|
@ -1769,16 +1862,26 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
rb->auto_exposure_version = env->auto_exposure_version;
|
||||
|
||||
double step = env->auto_exp_speed * time_step;
|
||||
storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
|
||||
if (can_use_storage) {
|
||||
storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
} else {
|
||||
storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
|
||||
}
|
||||
//swap final reduce with prev luminance
|
||||
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
|
||||
if (!can_use_storage) {
|
||||
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
|
||||
}
|
||||
|
||||
RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
int max_glow_level = -1;
|
||||
|
||||
if (can_use_effects && env && env->glow_enabled) {
|
||||
RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
|
||||
|
||||
/* see that blur textures are allocated */
|
||||
|
||||
if (rb->blur[1].texture.is_null()) {
|
||||
|
@ -1804,14 +1907,26 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
if (env->auto_exposure && rb->luminance.current.is_valid()) {
|
||||
luminance_texture = rb->luminance.current;
|
||||
}
|
||||
storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
if (can_use_storage) {
|
||||
storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
} else {
|
||||
storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
|
||||
}
|
||||
} else {
|
||||
storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
|
||||
if (can_use_storage) {
|
||||
storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
|
||||
} else {
|
||||
storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
{
|
||||
RD::get_singleton()->draw_command_begin_label("Tonemap");
|
||||
|
||||
//tonemap
|
||||
EffectsRD::TonemapSettings tonemap;
|
||||
|
||||
|
@ -1870,6 +1985,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
tonemap.view_count = p_render_data->view_count;
|
||||
|
||||
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
storage->render_target_disable_clear_request(rb->render_target);
|
||||
|
@ -2197,6 +2314,14 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
|||
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
}
|
||||
|
||||
if (!_render_buffers_can_be_storage()) {
|
||||
// ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
|
||||
Vector<RID> fb;
|
||||
fb.push_back(rb->texture);
|
||||
|
||||
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
|
||||
}
|
||||
|
||||
rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count);
|
||||
|
||||
if (is_clustered_enabled()) {
|
||||
|
|
|
@ -446,6 +446,7 @@ private:
|
|||
|
||||
RID texture; //main texture for rendering to, must be filled after done rendering
|
||||
RID depth_texture; //main depth texture
|
||||
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
|
||||
|
||||
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
|
||||
VolumetricFog *volumetric_fog = nullptr;
|
||||
|
@ -461,6 +462,11 @@ private:
|
|||
RID texture;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// only used on mobile renderer
|
||||
RID fb;
|
||||
RID half_texture;
|
||||
RID half_fb;
|
||||
};
|
||||
|
||||
Vector<Mipmap> mipmaps;
|
||||
|
@ -471,6 +477,10 @@ private:
|
|||
struct Luminance {
|
||||
Vector<RID> reduce;
|
||||
RID current;
|
||||
|
||||
// used only on mobile renderer
|
||||
Vector<RID> fb;
|
||||
RID current_fb;
|
||||
} luminance;
|
||||
|
||||
struct SSAO {
|
||||
|
|
|
@ -4962,7 +4962,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
|
|||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
effects.sort_buffer(particles->particles_sort_uniform_set, particles->amount);
|
||||
effects->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
|
||||
}
|
||||
|
||||
copy_push_constant.total_particles *= copy_push_constant.total_particles;
|
||||
|
@ -7538,7 +7538,7 @@ void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, c
|
|||
|
||||
//single texture copy for backbuffer
|
||||
//RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
|
||||
effects.copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
|
||||
effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
|
||||
|
||||
if (!p_gen_mipmaps) {
|
||||
return;
|
||||
|
@ -7554,7 +7554,7 @@ void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, c
|
|||
region.size.y = MAX(1, region.size.y >> 1);
|
||||
|
||||
const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
|
||||
effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
|
||||
effects->gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
|
||||
prev_texture = mm.mipmap;
|
||||
}
|
||||
}
|
||||
|
@ -7577,7 +7577,7 @@ void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, con
|
|||
}
|
||||
|
||||
//single texture copy for backbuffer
|
||||
effects.set_color(rt->backbuffer_mipmap0, p_color, region, true);
|
||||
effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
|
||||
}
|
||||
|
||||
void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
|
||||
|
@ -7607,7 +7607,7 @@ void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_targe
|
|||
region.size.y = MAX(1, region.size.y >> 1);
|
||||
|
||||
const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
|
||||
effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
|
||||
effects->gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
|
||||
prev_texture = mm.mipmap;
|
||||
}
|
||||
}
|
||||
|
@ -7928,14 +7928,14 @@ void RendererStorageRD::_update_decal_atlas() {
|
|||
while ((K = decal_atlas.textures.next(K))) {
|
||||
DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
|
||||
Texture *src_tex = texture_owner.getornull(*K);
|
||||
effects.copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
|
||||
effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
prev_texture = mm.texture;
|
||||
} else {
|
||||
effects.copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
|
||||
effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
|
||||
prev_texture = mm.texture;
|
||||
}
|
||||
} else {
|
||||
|
@ -8807,8 +8807,13 @@ bool RendererStorageRD::free(RID p_rid) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void RendererStorageRD::init_effects(bool p_prefer_raster_effects) {
|
||||
effects = memnew(EffectsRD(p_prefer_raster_effects));
|
||||
}
|
||||
|
||||
EffectsRD *RendererStorageRD::get_effects() {
|
||||
return &effects;
|
||||
ERR_FAIL_NULL_V_MSG(effects, nullptr, "Effects haven't been initialised yet.");
|
||||
return effects;
|
||||
}
|
||||
|
||||
void RendererStorageRD::capture_timestamps_begin() {
|
||||
|
@ -9532,4 +9537,9 @@ RendererStorageRD::~RendererStorageRD() {
|
|||
if (decal_atlas.texture.is_valid()) {
|
||||
RD::get_singleton()->free(decal_atlas.texture);
|
||||
}
|
||||
|
||||
if (effects) {
|
||||
memdelete(effects);
|
||||
effects = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1290,7 +1290,7 @@ private:
|
|||
void _update_global_variables();
|
||||
/* EFFECTS */
|
||||
|
||||
EffectsRD effects;
|
||||
EffectsRD *effects = NULL;
|
||||
|
||||
public:
|
||||
virtual bool can_create_resources_async() const;
|
||||
|
@ -2374,6 +2374,7 @@ public:
|
|||
|
||||
static RendererStorageRD *base_singleton;
|
||||
|
||||
void init_effects(bool p_prefer_raster_effects);
|
||||
EffectsRD *get_effects();
|
||||
|
||||
RendererStorageRD();
|
||||
|
|
228
servers/rendering/renderer_rd/shaders/blur_raster.glsl
Normal file
228
servers/rendering/renderer_rd/shaders/blur_raster.glsl
Normal file
|
@ -0,0 +1,228 @@
|
|||
/* clang-format off */
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "blur_raster_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 "blur_raster_inc.glsl"
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
|
||||
#ifdef GLOW_USE_AUTO_EXPOSURE
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size);
|
||||
color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size);
|
||||
color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size);
|
||||
color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size);
|
||||
frag_color = color / 4.0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
|
||||
//Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
|
||||
|
||||
if (bool(blur.flags & FLAG_HORIZONTAL)) {
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
pix_size *= 0.5; //reading from larger buffer, so use more samples
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
|
||||
color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
|
||||
color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
|
||||
color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
|
||||
color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
|
||||
color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
|
||||
color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
|
||||
frag_color = color;
|
||||
} else {
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
|
||||
frag_color = color;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_GLOW
|
||||
|
||||
//Glow uses larger sigma 1 for a more rounded blur effect
|
||||
|
||||
#define GLOW_ADD(m_ofs, m_mult) \
|
||||
{ \
|
||||
vec2 ofs = uv_interp + m_ofs * pix_size; \
|
||||
vec4 c = texture(source_color, ofs) * m_mult; \
|
||||
if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \
|
||||
c *= 0.0; \
|
||||
} \
|
||||
color += c; \
|
||||
}
|
||||
|
||||
if (bool(blur.flags & FLAG_HORIZONTAL)) {
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
pix_size *= 0.5; //reading from larger buffer, so use more samples
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
|
||||
GLOW_ADD(vec2(1.0, 0.0), 0.165569);
|
||||
GLOW_ADD(vec2(2.0, 0.0), 0.140367);
|
||||
GLOW_ADD(vec2(3.0, 0.0), 0.106595);
|
||||
GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
|
||||
GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
|
||||
GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
|
||||
color *= blur.glow_strength;
|
||||
frag_color = color;
|
||||
} else {
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
|
||||
GLOW_ADD(vec2(0.0, 1.0), 0.233062);
|
||||
GLOW_ADD(vec2(0.0, 2.0), 0.122581);
|
||||
GLOW_ADD(vec2(0.0, -1.0), 0.233062);
|
||||
GLOW_ADD(vec2(0.0, -2.0), 0.122581);
|
||||
color *= blur.glow_strength;
|
||||
frag_color = color;
|
||||
}
|
||||
|
||||
#undef GLOW_ADD
|
||||
|
||||
if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
|
||||
#ifdef GLOW_USE_AUTO_EXPOSURE
|
||||
|
||||
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
|
||||
#endif
|
||||
frag_color *= blur.glow_exposure;
|
||||
|
||||
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
|
||||
float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
|
||||
|
||||
frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
36
servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
Normal file
36
servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
Normal file
|
@ -0,0 +1,36 @@
|
|||
#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;
|
||||
uint flags;
|
||||
uint pad;
|
||||
|
||||
// Glow.
|
||||
float glow_strength;
|
||||
float glow_bloom;
|
||||
float glow_hdr_threshold;
|
||||
float glow_hdr_scale;
|
||||
|
||||
float glow_exposure;
|
||||
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;
|
|
@ -0,0 +1,74 @@
|
|||
/* clang-format off */
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "luminance_reduce_raster_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 "luminance_reduce_raster_inc.glsl"
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_exposure;
|
||||
|
||||
#ifdef FINAL_PASS
|
||||
layout(set = 1, binding = 0) uniform sampler2D prev_luminance;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out highp float luminance;
|
||||
|
||||
void main() {
|
||||
ivec2 dest_pos = ivec2(uv_interp * settings.dest_size);
|
||||
ivec2 src_pos = ivec2(uv_interp * settings.source_size);
|
||||
|
||||
ivec2 next_pos = (dest_pos + ivec2(1)) * settings.source_size / settings.dest_size;
|
||||
next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel
|
||||
|
||||
highp vec3 source_color = vec3(0.0);
|
||||
for (int i = src_pos.x; i < next_pos.x; i++) {
|
||||
for (int j = src_pos.y; j < next_pos.y; j++) {
|
||||
source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb;
|
||||
}
|
||||
}
|
||||
|
||||
source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y));
|
||||
|
||||
#ifdef FIRST_PASS
|
||||
luminance = max(source_color.r, max(source_color.g, source_color.b));
|
||||
|
||||
// This formula should be more "accurate" but gave an overexposed result when testing.
|
||||
// Leaving it here so we can revisit it if we want.
|
||||
// luminance = source_color.r * 0.21 + source_color.g * 0.71 + source_color.b * 0.07;
|
||||
#else
|
||||
luminance = source_color.r;
|
||||
#endif
|
||||
|
||||
#ifdef FINAL_PASS
|
||||
// Obtain our target luminance
|
||||
luminance = clamp(luminance, settings.min_luminance, settings.max_luminance);
|
||||
|
||||
// Now smooth to our transition
|
||||
highp float prev_lum = texelFetch(prev_luminance, ivec2(0, 0), 0).r; //1 pixel previous luminance
|
||||
luminance = prev_lum + (luminance - prev_lum) * clamp(settings.exposure_adjust, 0.0, 1.0);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
layout(push_constant, binding = 1, std430) uniform PushConstant {
|
||||
ivec2 source_size;
|
||||
ivec2 dest_size;
|
||||
|
||||
float exposure_adjust;
|
||||
float min_luminance;
|
||||
float max_luminance;
|
||||
float pad;
|
||||
}
|
||||
settings;
|
Loading…
Reference in a new issue