Various fixes and documentation for CanvasGroup
Properly apply custom materials with CanvasGroups in the GLES3 backend Properly blur backbuffer when using a partial rect in forward_plus and gl_compatibility renderers Properly set fit_margin when clear_margin is set Fix shader error during backbuffer clear in mobile renderer
This commit is contained in:
parent
ba4bd7f009
commit
bdd4001ef0
9 changed files with 42 additions and 19 deletions
|
@ -5,16 +5,33 @@
|
|||
</brief_description>
|
||||
<description>
|
||||
Child [CanvasItem] nodes of a [CanvasGroup] are drawn as a single object. It allows to e.g. draw overlapping translucent 2D nodes without blending (set [member CanvasItem.self_modulate] property of [CanvasGroup] to achieve this effect).
|
||||
[b]Note:[/b] The [CanvasGroup] uses a custom shader to read from the backbuffer to draw its children. Assigning a [Material] to the [CanvasGroup] overrides the builtin shader. To duplicate the behavior of the builtin shader in a custom [Shader] use the following:
|
||||
[codeblock]
|
||||
shader_type canvas_item;
|
||||
|
||||
void fragment() {
|
||||
vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
|
||||
|
||||
if (c.a > 0.0001) {
|
||||
c.rgb /= c.a;
|
||||
}
|
||||
|
||||
COLOR *= c;
|
||||
}
|
||||
[/codeblock]
|
||||
[b]Note:[/b] Since [CanvasGroup] and [member CanvasItem.clip_children] both utilize the backbuffer, children of a [CanvasGroup] who have their [member CanvasItem.clip_children] set to anything other than [constant CanvasItem.CLIP_CHILDREN_DISABLED] will not function correctly.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="clear_margin" type="float" setter="set_clear_margin" getter="get_clear_margin" default="10.0">
|
||||
Sets the size of the margin used to expand the clearing rect of this [CanvasGroup]. This expands the area of the backbuffer that will be used by the [CanvasGroup]. A smaller margin will reduce the area of the backbuffer used which can increase performance, however if [member use_mipmaps] is enabled, a small margin may result in mipmap errors at the edge of the [CanvasGroup]. Accordingly, this should be left as small as possible, but should be increased if artifacts appear along the edges of the canvas group.
|
||||
</member>
|
||||
<member name="fit_margin" type="float" setter="set_fit_margin" getter="get_fit_margin" default="10.0">
|
||||
Sets the size of a margin used to expand the drawable rect of this [CanvasGroup]. The size of the [CanvasGroup] is determined by fitting a rect around its children then expanding that rect by [member fit_margin]. This increases both the backbuffer area used and the area covered by the [CanvasGroup] both of which can reduce performance. This should be kept as small as possible and should only be expanded when an increased size is needed (e.g. for custom shader effects).
|
||||
</member>
|
||||
<member name="use_mipmaps" type="bool" setter="set_use_mipmaps" getter="is_using_mipmaps" default="false">
|
||||
If [code]true[/code], calculates mipmaps for the backbuffer before drawing the [CanvasGroup] so that mipmaps can be used in a custom [ShaderMaterial] attached to the [CanvasGroup]. Generating mipmaps has a performance cost so this should not be enabled unless required.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
||||
|
|
|
@ -148,8 +148,8 @@ void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, con
|
|||
dest_region.size.y = MAX(1, dest_region.size.y >> 1);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffers[i % 2]);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_source_texture, i);
|
||||
glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.size.x, source_region.size.y,
|
||||
dest_region.position.x, dest_region.position.y, dest_region.size.x, dest_region.size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBlitFramebuffer(source_region.position.x, source_region.position.y, source_region.position.x + source_region.size.x, source_region.position.y + source_region.size.y,
|
||||
dest_region.position.x, dest_region.position.y, dest_region.position.x + dest_region.size.x, dest_region.position.y + dest_region.size.y, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffers[i % 2]);
|
||||
source_region = dest_region;
|
||||
}
|
||||
|
|
|
@ -588,10 +588,12 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
|
|||
material = default_clip_children_material;
|
||||
}
|
||||
} else {
|
||||
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
|
||||
material = default_clip_children_material;
|
||||
} else {
|
||||
material = default_canvas_group_material;
|
||||
if (material.is_null()) {
|
||||
if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
|
||||
material = default_clip_children_material;
|
||||
} else {
|
||||
material = default_canvas_group_material;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ void CanvasGroup::set_clear_margin(real_t p_clear_margin) {
|
|||
ERR_FAIL_COND(p_clear_margin < 0.0);
|
||||
|
||||
clear_margin = p_clear_margin;
|
||||
RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CANVAS_GROUP_MODE_TRANSPARENT, clear_margin, true, clear_margin, use_mipmaps);
|
||||
RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CANVAS_GROUP_MODE_TRANSPARENT, clear_margin, true, fit_margin, use_mipmaps);
|
||||
|
||||
queue_redraw();
|
||||
}
|
||||
|
|
|
@ -628,7 +628,7 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
|
|||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst) {
|
||||
void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, 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.");
|
||||
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
|
@ -640,8 +640,10 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
|
|||
|
||||
copy.push_constant.section[0] = p_region.position.x;
|
||||
copy.push_constant.section[1] = p_region.position.y;
|
||||
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.section[2] = p_size.width;
|
||||
copy.push_constant.section[3] = p_size.height;
|
||||
|
||||
// setup our uniforms
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
|
|
@ -331,7 +331,7 @@ public:
|
|||
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 copy_raster(RID p_source_texture, RID p_dest_framebuffer);
|
||||
|
||||
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
|
||||
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst = false);
|
||||
void gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_region, const Size2i &p_size);
|
||||
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_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
|
||||
void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, 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_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
|
||||
|
|
|
@ -93,7 +93,7 @@ void main() {
|
|||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
|
||||
// First pass copy texture into 16x16 local memory for every 8x8 thread block
|
||||
vec2 quad_center_uv = clamp(vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
|
||||
vec2 quad_center_uv = clamp(vec2(params.section.xy + gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw));
|
||||
uint dest_index = gl_LocalInvocationID.x * 2 + gl_LocalInvocationID.y * 2 * 16;
|
||||
|
||||
#ifdef MODE_GLOW
|
||||
|
|
|
@ -88,6 +88,7 @@ layout(push_constant, std430) uniform Params {
|
|||
}
|
||||
params;
|
||||
|
||||
#ifndef MODE_SET_COLOR
|
||||
#ifdef MULTIVIEW
|
||||
layout(location = 0) in vec3 uv_interp;
|
||||
#else
|
||||
|
@ -106,6 +107,7 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
|
|||
layout(set = 1, binding = 0) uniform sampler2D source_color2;
|
||||
#endif /* MODE_TWO_SOURCES */
|
||||
#endif /* MULTIVIEW */
|
||||
#endif /* !SET_COLOR */
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
|
|
|
@ -3140,13 +3140,13 @@ void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, cons
|
|||
region.position.y >>= 1;
|
||||
region.size.x = MAX(1, region.size.x >> 1);
|
||||
region.size.y = MAX(1, region.size.y >> 1);
|
||||
texture_size.x = MAX(1, texture_size.x >> 1);
|
||||
texture_size.y = MAX(1, texture_size.y >> 1);
|
||||
|
||||
RID mipmap = rt->backbuffer_mipmaps[i];
|
||||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
|
||||
} else {
|
||||
texture_size.x = MAX(1, texture_size.x >> 1);
|
||||
texture_size.y = MAX(1, texture_size.y >> 1);
|
||||
copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
|
||||
}
|
||||
prev_texture = mipmap;
|
||||
|
@ -3179,7 +3179,7 @@ void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const
|
|||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
|
||||
} else {
|
||||
copy_effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
|
||||
copy_effects->set_color_raster(rt->backbuffer_mipmap0, p_color, region);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3213,14 +3213,14 @@ void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target,
|
|||
region.position.y >>= 1;
|
||||
region.size.x = MAX(1, region.size.x >> 1);
|
||||
region.size.y = MAX(1, region.size.y >> 1);
|
||||
texture_size.x = MAX(1, texture_size.x >> 1);
|
||||
texture_size.y = MAX(1, texture_size.y >> 1);
|
||||
|
||||
RID mipmap = rt->backbuffer_mipmaps[i];
|
||||
|
||||
if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, true);
|
||||
copy_effects->gaussian_blur(prev_texture, mipmap, region, texture_size, true);
|
||||
} else {
|
||||
texture_size.x = MAX(1, texture_size.x >> 1);
|
||||
texture_size.y = MAX(1, texture_size.y >> 1);
|
||||
copy_effects->gaussian_blur_raster(prev_texture, mipmap, region, texture_size);
|
||||
}
|
||||
prev_texture = mipmap;
|
||||
|
|
Loading…
Reference in a new issue