summaryrefslogtreecommitdiff
path: root/servers/rendering/rasterizer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/rasterizer_rd')
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp113
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h5
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp37
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_effects_rd.h10
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp91
-rw-r--r--servers/rendering/rasterizer_rd/rasterizer_storage_rd.h6
-rw-r--r--servers/rendering/rasterizer_rd/shaders/copy.glsl28
7 files changed, 246 insertions, 44 deletions
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
index 28674b118c..b268db5989 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
@@ -1102,28 +1102,36 @@ RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_
return uniform_set;
}
-void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights) {
+void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
- RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
-
- Vector<Color> clear_colors;
+ RID framebuffer;
+ RID fb_uniform_set;
bool clear = false;
- if (storage->render_target_is_clear_requested(p_to_render_target)) {
- clear = true;
- clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
- storage->render_target_disable_clear_request(p_to_render_target);
- }
+ Vector<Color> clear_colors;
+
+ if (p_to_backbuffer) {
+ framebuffer = storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
+ fb_uniform_set = storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
+ } else {
+ framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
+
+ if (storage->render_target_is_clear_requested(p_to_render_target)) {
+ clear = true;
+ clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
+ storage->render_target_disable_clear_request(p_to_render_target);
+ }
#ifndef _MSC_VER
#warning TODO obtain from framebuffer format eventually when this is implemented
#endif
- RID fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+ fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+ }
if (fb_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fb_uniform_set)) {
- fb_uniform_set = _create_base_uniform_set(p_to_render_target, false);
+ fb_uniform_set = _create_base_uniform_set(p_to_render_target, p_to_backbuffer);
}
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
@@ -1152,10 +1160,16 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
}
}
- if (ci->material != prev_material) {
+ RID material = ci->material;
+
+ if (material.is_null() && ci->canvas_group != nullptr) {
+ material = default_canvas_group_material;
+ }
+
+ if (material != prev_material) {
MaterialData *material_data = nullptr;
- if (ci->material.is_valid()) {
- material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
+ if (material.is_valid()) {
+ material_data = (MaterialData *)storage->material_get_data(material, RasterizerStorageRD::SHADER_TYPE_2D);
}
if (material_data) {
@@ -1174,7 +1188,7 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
_render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
- prev_material = ci->material;
+ prev_material = material;
}
RD::get_singleton()->draw_list_end();
@@ -1306,8 +1320,10 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ Item *canvas_group_owner = nullptr;
+
while (ci) {
- if (ci->copy_back_buffer) {
+ if (ci->copy_back_buffer && canvas_group_owner == nullptr) {
backbuffer_copy = true;
if (ci->copy_back_buffer->full) {
@@ -1320,7 +1336,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
if (ci->material.is_valid()) {
MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
if (md && md->shader_data->valid) {
- if (md->shader_data->uses_screen_texture) {
+ if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
@@ -1338,12 +1354,44 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
}
+ if (ci->canvas_group_owner != nullptr) {
+ if (canvas_group_owner == nullptr) {
+ //Canvas group begins here, render until before this item
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
+ item_count = 0;
+
+ Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
+
+ if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+ storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+ } else {
+ storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
+ }
+
+ backbuffer_copy = false;
+ canvas_group_owner = ci->canvas_group_owner; //continue until owner found
+ }
+
+ ci->canvas_group_owner = nullptr; //must be cleared
+ }
+
+ if (ci == canvas_group_owner) {
+ _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true);
+ item_count = 0;
+
+ if (ci->canvas_group->blur_mipmaps) {
+ storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
+ }
+
+ canvas_group_owner = nullptr;
+ }
+
if (backbuffer_copy) {
//render anything pending, including clearing if no items
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect);
+ storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
@@ -1672,10 +1720,11 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
} break;
case BLEND_MODE_MIX: {
attachment.enable_blend = true;
- attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.color_blend_op = RD::BLEND_OP_ADD;
attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ attachment.alpha_blend_op = RD::BLEND_OP_ADD;
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
@@ -2013,6 +2062,20 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
shader.default_version = shader.canvas_shader.version_create();
shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD);
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineColorBlendState::Attachment blend_attachment;
+
+ blend_attachment.enable_blend = true;
+ blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
+ blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
+ blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ blend_state.attachments.push_back(blend_attachment);
+
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
@@ -2054,7 +2117,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
};
RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0);
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
}
}
}
@@ -2260,6 +2323,13 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
state.time = 0;
+ {
+ default_canvas_group_shader = storage->shader_create();
+ storage->shader_set_code(default_canvas_group_shader, "shader_type canvas_item; \nvoid fragment() {\n\tvec4 c = textureLod(SCREEN_TEXTURE,SCREEN_UV,0.0); if (c.a > 0.0001) c.rgb/=c.a; COLOR *= c; \n}\n");
+ default_canvas_group_material = storage->material_create();
+ storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
+ }
+
static_assert(sizeof(PushConstant) == 128);
}
@@ -2307,6 +2377,9 @@ void RasterizerCanvasRD::set_shadow_texture_size(int p_size) {
RasterizerCanvasRD::~RasterizerCanvasRD() {
//canvas state
+ storage->free(default_canvas_group_material);
+ storage->free(default_canvas_group_shader);
+
{
if (state.canvas_state_buffer.is_valid()) {
RD::get_singleton()->free(state.canvas_state_buffer);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
index 5791efa4e5..4a79134c24 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
@@ -391,6 +391,9 @@ class RasterizerCanvasRD : public RasterizerCanvas {
RID default_canvas_texture;
+ RID default_canvas_group_shader;
+ RID default_canvas_group_material;
+
RS::CanvasItemTextureFilter default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
@@ -398,7 +401,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead.
void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
- void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights);
+ void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
index 409cfdfecf..d669db1b4b 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
@@ -246,7 +246,7 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr
RD::get_singleton()->draw_list_end();
}
-void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst) {
+void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) {
zeromem(&copy.push_constant, sizeof(CopyPushConstant));
if (p_flip_y) {
copy.push_constant.flags |= COPY_FLAG_FLIP_Y;
@@ -260,6 +260,10 @@ void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_textu
copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE;
}
+ if (p_alpha_to_one) {
+ copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
+ }
+
copy.push_constant.section[0] = 0;
copy.push_constant.section[1] = 0;
copy.push_constant.section[2] = p_rect.size.width;
@@ -354,6 +358,31 @@ void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest
RD::get_singleton()->compute_list_end();
}
+void RasterizerEffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) {
+ zeromem(&copy.push_constant, sizeof(CopyPushConstant));
+
+ copy.push_constant.section[0] = 0;
+ copy.push_constant.section[1] = 0;
+ copy.push_constant.section[2] = p_region.size.width;
+ copy.push_constant.section[3] = p_region.size.height;
+ copy.push_constant.target[0] = p_region.position.x;
+ copy.push_constant.target[1] = p_region.position.y;
+ copy.push_constant.set_color[0] = p_color.r;
+ copy.push_constant.set_color[1] = p_color.g;
+ copy.push_constant.set_color[2] = p_color.b;
+ copy.push_constant.set_color[3] = p_color.a;
+
+ int32_t x_groups = (p_region.size.width - 1) / 8 + 1;
+ int32_t y_groups = (p_region.size.height - 1) / 8 + 1;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
zeromem(&copy.push_constant, sizeof(CopyPushConstant));
@@ -369,7 +398,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture,
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3);
copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
@@ -380,7 +409,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture,
//VERTICAL
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3);
copy.push_constant.flags = base_flags;
RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy.push_constant, sizeof(CopyPushConstant));
@@ -1346,6 +1375,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() {
copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n");
copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n");
+ copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n");
copy_modes.push_back("\n#define MODE_MIPMAP\n");
copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n");
copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n");
diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
index 679263fbf6..a0bdd59fd2 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
@@ -66,6 +66,8 @@ class RasterizerEffectsRD {
COPY_MODE_SIMPLY_COPY,
COPY_MODE_SIMPLY_COPY_8BIT,
COPY_MODE_SIMPLY_COPY_DEPTH,
+ COPY_MODE_SET_COLOR,
+ COPY_MODE_SET_COLOR_8BIT,
COPY_MODE_MIPMAP,
COPY_MODE_LINEARIZE_DEPTH,
COPY_MODE_CUBE_TO_PANORAMA,
@@ -83,7 +85,8 @@ class RasterizerEffectsRD {
COPY_FLAG_FLIP_Y = (1 << 5),
COPY_FLAG_FORCE_LUMINANCE = (1 << 6),
COPY_FLAG_ALL_SOURCE = (1 << 7),
- COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8)
+ COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8),
+ COPY_FLAG_ALPHA_TO_ONE = (1 << 9),
};
struct CopyPushConstant {
@@ -105,6 +108,8 @@ class RasterizerEffectsRD {
float camera_z_far;
float camera_z_near;
uint32_t pad2[2];
+ //SET color
+ float set_color[4];
};
struct Copy {
@@ -603,12 +608,13 @@ class RasterizerEffectsRD {
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);
+ 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);
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far);
void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false);
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 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);
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
index b47d724147..10c9293d67 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -6131,12 +6131,18 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
tf.width = rt->size.width;
tf.height = rt->size.height;
tf.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.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
tf.mipmaps = mipmaps_required;
rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
+ {
+ Vector<RID> fb_tex;
+ fb_tex.push_back(rt->backbuffer_mipmap0);
+ rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+
if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
//the new one will require the backbuffer.
RD::get_singleton()->free(rt->framebuffer_uniform_set);
@@ -6245,6 +6251,17 @@ RID RasterizerStorageRD::render_target_get_rd_backbuffer(RID p_render_target) {
return rt->backbuffer;
}
+RID RasterizerStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ return rt->backbuffer_fb;
+}
+
void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
@@ -6283,21 +6300,30 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
rt->clear_requested = false;
}
-void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region) {
+void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
}
- Rect2i region = p_region;
- if (region == Rect2i()) {
+ Rect2i region;
+ if (p_region == Rect2i()) {
region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).clip(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
}
//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(rt->color, rt->backbuffer_fb, blur_region);
+ //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);
+
+ if (!p_gen_mipmaps) {
+ return;
+ }
//then mipmap blur
RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
@@ -6314,6 +6340,59 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target,
}
}
+void RasterizerStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).clip(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //single texture copy for backbuffer
+ effects.set_color(rt->backbuffer_mipmap0, p_color, region, true);
+}
+
+void RasterizerStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
+ RenderTarget *rt = render_target_owner.getornull(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).clip(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //then mipmap blur
+ RID prev_texture = rt->backbuffer_mipmap0;
+
+ for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ 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);
+ prev_texture = mm.mipmap;
+ }
+}
+
RID RasterizerStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
index 7caafca2e0..321bff9fdd 100644
--- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
@@ -989,6 +989,7 @@ private:
bool flags[RENDER_TARGET_FLAG_MAX];
RID backbuffer; //used for effects
+ RID backbuffer_fb;
RID backbuffer_mipmap0;
struct BackbufferMipmap {
@@ -1916,7 +1917,9 @@ public:
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
bool render_target_was_used(RID p_render_target);
void render_target_set_as_unused(RID p_render_target);
- void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region);
+ void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
+ void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
+ void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
@@ -1930,6 +1933,7 @@ public:
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
RID render_target_get_rd_backbuffer(RID p_render_target);
+ RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
RID render_target_get_framebuffer_uniform_set(RID p_render_target);
RID render_target_get_backbuffer_uniform_set(RID p_render_target);
diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl
index 355a2b9d75..cdd35dfb3f 100644
--- a/servers/rendering/rasterizer_rd/shaders/copy.glsl
+++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl
@@ -15,6 +15,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define FLAG_FORCE_LUMINANCE (1 << 6)
#define FLAG_COPY_ALL_SOURCE (1 << 7)
#define FLAG_HIGH_QUALITY_GLOW (1 << 8)
+#define FLAG_ALPHA_TO_ONE (1 << 9)
layout(push_constant, binding = 1, std430) uniform Params {
ivec4 section;
@@ -35,6 +36,8 @@ layout(push_constant, binding = 1, std430) uniform Params {
float camera_z_far;
float camera_z_near;
uint pad2[2];
+
+ vec4 set_color;
}
params;
@@ -42,7 +45,7 @@ params;
layout(set = 0, binding = 0) uniform samplerCubeArray source_color;
#elif defined(MODE_CUBEMAP_TO_PANORAMA)
layout(set = 0, binding = 0) uniform samplerCube source_color;
-#else
+#elif !defined(MODE_SET_COLOR)
layout(set = 0, binding = 0) uniform sampler2D source_color;
#endif
@@ -203,25 +206,24 @@ void main() {
}
color = textureLod(source_color, uv, 0.0);
- if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
- color.rgb = vec3(max(max(color.r, color.g), color.b));
- }
- imageStore(dest_buffer, pos + params.target, color);
-
} else {
color = texelFetch(source_color, pos + params.section.xy, 0);
- if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
- color.rgb = vec3(max(max(color.r, color.g), color.b));
- }
-
if (bool(params.flags & FLAG_FLIP_Y)) {
pos.y = params.section.w - pos.y - 1;
}
+ }
- imageStore(dest_buffer, pos + params.target, color);
+ if (bool(params.flags & FLAG_FORCE_LUMINANCE)) {
+ color.rgb = vec3(max(max(color.r, color.g), color.b));
+ }
+
+ if (bool(params.flags & FLAG_ALPHA_TO_ONE)) {
+ color.a = 1.0;
}
+ imageStore(dest_buffer, pos + params.target, color);
+
#endif
#ifdef MODE_SIMPLE_COPY_DEPTH
@@ -270,4 +272,8 @@ void main() {
#endif
imageStore(dest_buffer, pos + params.target, color);
#endif
+
+#ifdef MODE_SET_COLOR
+ imageStore(dest_buffer, pos + params.target, params.set_color);
+#endif
}