Skip to content

Commit

Permalink
2D shadows respect z_index
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielKauss committed Jul 3, 2024
1 parent f0d15bb commit e13cdf4
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 81 deletions.
3 changes: 3 additions & 0 deletions doc/classes/CanvasItem.xml
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,9 @@
<constant name="NOTIFICATION_WORLD_2D_CHANGED" value="36">
The [CanvasItem]'s active [World2D] changed.
</constant>
<constant name="NOTIFICATION_Z_INDEX_CHANGED" value="37">
The [CanvasItem]'s z_index changed.
</constant>
<constant name="TEXTURE_FILTER_PARENT_NODE" value="0" enum="TextureFilter">
The [CanvasItem] will inherit the filter from its parent.
</constant>
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,14 @@
Sets a light occluder's [Transform2D].
</description>
</method>
<method name="canvas_light_occluder_set_z_index">
<return type="void" />
<param index="0" name="occluder" type="RID" />
<param index="1" name="z_index" type="int" />
<description>
Sets a light occluder's z_index.
</description>
</method>
<method name="canvas_light_occluder_transform_physics_interpolation">
<return type="void" />
<param index="0" name="occluder" type="RID" />
Expand Down
40 changes: 31 additions & 9 deletions drivers/gles3/rasterizer_canvas_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,36 @@ void RasterizerCanvasGLES3::_update_transform_to_mat4(const Transform3D &p_trans
p_mat4[15] = 1;
}

void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info) {
void RasterizerCanvasGLES3::update_shadow_map(Light *p_lights, Light *p_directional_lights, LightOccluderInstance *p_occluders, const Rect2 &p_clip_rect, int p_z_end) {
RENDER_TIMESTAMP("Render Shadow Map");
glClear(state.shadow_texture);

int shadow_index = 0;
RendererCanvasRender::Light *light = p_lights;
while (light) {
if (light->use_shadow) {
light_update_shadow(light->light_internal, shadow_index++, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, p_z_end, p_occluders);
}
light = light->next_ptr;
}

RendererCanvasRender::Light *dir_light = p_directional_lights;
while (dir_light) {
if (dir_light->use_shadow) {
light_update_directional_shadow(dir_light->light_internal, shadow_index++, dir_light->xform_cache, dir_light->item_shadow_mask, dir_light->directional_distance, p_clip_rect, p_z_end, p_occluders);
}
dir_light = dir_light->next_ptr;
}
}

void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, LightOccluderInstance *p_occluders, const Transform2D &p_canvas_transform, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
GLES3::MeshStorage *mesh_storage = GLES3::MeshStorage::get_singleton();

Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse();

// Clear out any state that may have been left from the 3D pass.
update_shadow_map(p_light_list, p_directional_light_list, p_occluders, p_clip_rect, -1000);
reset_canvas();

if (state.canvas_instance_data_buffers[state.current_data_buffer_index].fence != GLsync()) {
Expand Down Expand Up @@ -468,7 +490,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
update_skeletons = false;
}
// Canvas group begins here, render until before this item
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false, r_render_info);
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_clip_rect, p_light_list, p_directional_light_list, p_occluders, r_sdf_used, false, r_render_info);
item_count = 0;

if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
Expand Down Expand Up @@ -499,7 +521,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
mesh_storage->update_mesh_instances();
update_skeletons = false;
}
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, true, r_render_info);
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_clip_rect, p_light_list, p_directional_light_list, p_occluders, r_sdf_used, true, r_render_info);
item_count = 0;

if (ci->canvas_group->blur_mipmaps) {
Expand All @@ -523,7 +545,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
}
//render anything pending, including clearing if no items

_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, false, r_render_info);
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_clip_rect, p_light_list, p_directional_light_list, p_occluders, r_sdf_used, false, r_render_info);
item_count = 0;

texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
Expand Down Expand Up @@ -553,7 +575,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
mesh_storage->update_mesh_instances();
update_skeletons = false;
}
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, r_sdf_used, canvas_group_owner != nullptr, r_render_info);
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_clip_rect, p_light_list, p_directional_light_list, p_occluders, r_sdf_used, canvas_group_owner != nullptr, r_render_info);
//then reset
item_count = 0;
}
Expand All @@ -573,7 +595,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state.current_instance_buffer_index = 0;
}

void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer, RenderingMethod::RenderInfo *r_render_info) {
void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, const Rect2 &p_clip_rect, Light *p_lights, Light *p_directional_lights, LightOccluderInstance *p_occluders, bool &r_sdf_used, bool p_to_backbuffer, RenderingMethod::RenderInfo *r_render_info, int p_start_index) {
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();

canvas_begin(p_to_render_target, p_to_backbuffer);
Expand Down Expand Up @@ -1619,7 +1641,7 @@ void RasterizerCanvasGLES3::light_set_use_shadow(RID p_rid, bool p_enable) {
cl->shadow.enabled = p_enable;
}

void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) {
void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, int p_z_end, LightOccluderInstance *p_occluders) {
GLES3::Config *config = GLES3::Config::get_singleton();

CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
Expand Down Expand Up @@ -1723,7 +1745,7 @@ void RasterizerCanvasGLES3::light_update_shadow(RID p_rid, int p_shadow_index, c
glDisable(GL_SCISSOR_TEST);
}

void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) {
void RasterizerCanvasGLES3::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, int p_z_end, LightOccluderInstance *p_occluders) {
GLES3::Config *config = GLES3::Config::get_singleton();

CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
Expand Down
9 changes: 5 additions & 4 deletions drivers/gles3/rasterizer_canvas_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,9 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
RID light_create() override;
void light_set_texture(RID p_rid, RID p_texture) override;
void light_set_use_shadow(RID p_rid, bool p_enable) override;
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override;
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override;
void update_shadow_map(Light *p_lights, Light *p_directional_lights, LightOccluderInstance *p_occluders, const Rect2 &p_clip_rect, int p_z_end) override;
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, int p_z_end, LightOccluderInstance *p_occluders) override;
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, int p_z_end, LightOccluderInstance *p_occluders) override;

void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override;
RID occluder_polygon_create() override;
Expand All @@ -360,8 +361,8 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
void _bind_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat);
void _prepare_canvas_texture(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, uint32_t &r_index, Size2 &r_texpixel_size);

void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) override;
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, LightOccluderInstance *p_occluders, const Transform2D &p_canvas_transform, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) override;
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, const Rect2 &p_clip_rect, Light *p_lights, Light *p_directional_lights, LightOccluderInstance *p_occluders, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr, int p_start_index = 0);
void _record_item_commands(const Item *p_item, RID p_render_target, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, GLES3::CanvasShaderData::BlendMode p_blend_mode, Light *p_lights, uint32_t &r_index, bool &r_break_batch, bool &r_sdf_used, const Point2 &p_offset);
void _render_batch(Light *p_lights, uint32_t p_index, RenderingMethod::RenderInfo *r_render_info = nullptr);
bool _bind_material(GLES3::CanvasMaterialData *p_material_data, CanvasShaderGLES3::ShaderVariant p_variant, uint64_t p_specialization);
Expand Down
6 changes: 6 additions & 0 deletions scene/2d/light_occluder_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,18 @@ void LightOccluder2D::_notification(int p_what) {
RS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform());
RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree());
RS::get_singleton()->canvas_light_occluder_set_z_index(occluder, get_effective_z_index());
} break;

case NOTIFICATION_TRANSFORM_CHANGED: {
RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform());
} break;

case NOTIFICATION_Z_INDEX_CHANGED: {
int effective_z_index = get_effective_z_index();
RS::get_singleton()->canvas_light_occluder_set_z_index(occluder, effective_z_index);
} break;

case NOTIFICATION_VISIBILITY_CHANGED: {
RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree());
} break;
Expand Down
13 changes: 13 additions & 0 deletions scene/main/canvas_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,8 @@ void CanvasItem::set_z_index(int p_z) {
z_index = p_z;
RS::get_singleton()->canvas_item_set_z_index(canvas_item, z_index);
update_configuration_warnings();

_notify_z_index();
}

void CanvasItem::set_z_as_relative(bool p_enabled) {
Expand Down Expand Up @@ -946,6 +948,16 @@ void CanvasItem::_notify_transform_deferred() {
}
}

void CanvasItem::_notify_z_index() {
notification(NOTIFICATION_Z_INDEX_CHANGED);
for (CanvasItem *ci : children_items) {
if (ci->top_level) {
continue;
}
ci->_notify_z_index();
}
}

void CanvasItem::_notify_transform(CanvasItem *p_node) {
/* This check exists to avoid re-propagating the transform
* notification down the tree on dirty nodes. It provides
Expand Down Expand Up @@ -1308,6 +1320,7 @@ void CanvasItem::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_ENTER_CANVAS);
BIND_CONSTANT(NOTIFICATION_EXIT_CANVAS);
BIND_CONSTANT(NOTIFICATION_WORLD_2D_CHANGED);
BIND_CONSTANT(NOTIFICATION_Z_INDEX_CHANGED);

BIND_ENUM_CONSTANT(TEXTURE_FILTER_PARENT_NODE);
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST);
Expand Down
3 changes: 3 additions & 0 deletions scene/main/canvas_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class CanvasItem : public Node {

void _window_visibility_changed();

void _notify_z_index();

void _notify_transform(CanvasItem *p_node);

virtual void _physics_interpolated_changed() override;
Expand Down Expand Up @@ -191,6 +193,7 @@ class CanvasItem : public Node {
NOTIFICATION_EXIT_CANVAS = 33,
NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 35,
NOTIFICATION_WORLD_2D_CHANGED = 36,
NOTIFICATION_Z_INDEX_CHANGED = 37,
};

/* EDITOR */
Expand Down
7 changes: 4 additions & 3 deletions servers/rendering/dummy/rasterizer_canvas_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ class RasterizerCanvasDummy : public RendererCanvasRender {
PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override { return 0; }
void free_polygon(PolygonID p_polygon) override {}

void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) override {}
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, LightOccluderInstance *p_occluders, const Transform2D &p_canvas_transform, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used, RenderingMethod::RenderInfo *r_render_info = nullptr) override {}

RID light_create() override { return RID(); }
void light_set_texture(RID p_rid, RID p_texture) override {}
void light_set_use_shadow(RID p_rid, bool p_enable) override {}
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override {}
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override {}
void update_shadow_map(Light *p_lights, Light *p_directional_lights, LightOccluderInstance *p_occluders, const Rect2 &p_clip_rect, int p_z_end) override {}
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, int p_z_end, LightOccluderInstance *p_occluders) override {}
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, int p_z_end, LightOccluderInstance *p_occluders) override {}

void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override {}
RID occluder_polygon_create() override { return RID(); }
Expand Down
Loading

0 comments on commit e13cdf4

Please sign in to comment.