1 | /**************************************************************************/ |
2 | /* renderer_canvas_cull.h */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #ifndef RENDERER_CANVAS_CULL_H |
32 | #define RENDERER_CANVAS_CULL_H |
33 | |
34 | #include "core/templates/paged_allocator.h" |
35 | #include "renderer_compositor.h" |
36 | #include "renderer_viewport.h" |
37 | |
38 | class RendererCanvasCull { |
39 | public: |
40 | struct Item : public RendererCanvasRender::Item { |
41 | RID parent; // canvas it belongs to |
42 | List<Item *>::Element *E; |
43 | int z_index; |
44 | bool z_relative; |
45 | bool sort_y; |
46 | Color modulate; |
47 | Color self_modulate; |
48 | bool use_parent_material; |
49 | int index; |
50 | bool children_order_dirty; |
51 | int ysort_children_count; |
52 | Color ysort_modulate; |
53 | Transform2D ysort_xform; |
54 | Vector2 ysort_pos; |
55 | int ysort_index; |
56 | int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting. |
57 | uint32_t visibility_layer = 0xffffffff; |
58 | |
59 | Vector<Item *> child_items; |
60 | |
61 | struct VisibilityNotifierData { |
62 | Rect2 area; |
63 | Callable enter_callable; |
64 | Callable exit_callable; |
65 | bool just_visible = false; |
66 | uint64_t visible_in_frame = 0; |
67 | SelfList<VisibilityNotifierData> visible_element; |
68 | VisibilityNotifierData() : |
69 | visible_element(this) { |
70 | } |
71 | }; |
72 | |
73 | VisibilityNotifierData *visibility_notifier = nullptr; |
74 | |
75 | Item() { |
76 | children_order_dirty = true; |
77 | E = nullptr; |
78 | z_index = 0; |
79 | modulate = Color(1, 1, 1, 1); |
80 | self_modulate = Color(1, 1, 1, 1); |
81 | sort_y = false; |
82 | use_parent_material = false; |
83 | z_relative = true; |
84 | index = 0; |
85 | ysort_children_count = -1; |
86 | ysort_xform = Transform2D(); |
87 | ysort_pos = Vector2(); |
88 | ysort_index = 0; |
89 | ysort_parent_abs_z_index = 0; |
90 | } |
91 | }; |
92 | |
93 | struct ItemIndexSort { |
94 | _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { |
95 | return p_left->index < p_right->index; |
96 | } |
97 | }; |
98 | |
99 | struct ItemPtrSort { |
100 | _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { |
101 | if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) { |
102 | return p_left->ysort_index < p_right->ysort_index; |
103 | } |
104 | |
105 | return p_left->ysort_pos.y < p_right->ysort_pos.y; |
106 | } |
107 | }; |
108 | |
109 | struct LightOccluderPolygon { |
110 | bool active; |
111 | Rect2 aabb; |
112 | RS::CanvasOccluderPolygonCullMode cull_mode; |
113 | RID occluder; |
114 | HashSet<RendererCanvasRender::LightOccluderInstance *> owners; |
115 | |
116 | LightOccluderPolygon() { |
117 | active = false; |
118 | cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; |
119 | } |
120 | }; |
121 | |
122 | RID_Owner<LightOccluderPolygon, true> canvas_light_occluder_polygon_owner; |
123 | |
124 | RID_Owner<RendererCanvasRender::LightOccluderInstance, true> canvas_light_occluder_owner; |
125 | |
126 | struct Canvas : public RendererViewport::CanvasBase { |
127 | HashSet<RID> viewports; |
128 | struct ChildItem { |
129 | Point2 mirror; |
130 | Item *item = nullptr; |
131 | bool operator<(const ChildItem &p_item) const { |
132 | return item->index < p_item.item->index; |
133 | } |
134 | }; |
135 | |
136 | HashSet<RendererCanvasRender::Light *> lights; |
137 | HashSet<RendererCanvasRender::Light *> directional_lights; |
138 | |
139 | HashSet<RendererCanvasRender::LightOccluderInstance *> occluders; |
140 | |
141 | bool children_order_dirty; |
142 | Vector<ChildItem> child_items; |
143 | Color modulate; |
144 | RID parent; |
145 | float parent_scale; |
146 | |
147 | int find_item(Item *p_item) { |
148 | for (int i = 0; i < child_items.size(); i++) { |
149 | if (child_items[i].item == p_item) { |
150 | return i; |
151 | } |
152 | } |
153 | return -1; |
154 | } |
155 | void erase_item(Item *p_item) { |
156 | int idx = find_item(p_item); |
157 | if (idx >= 0) { |
158 | child_items.remove_at(idx); |
159 | } |
160 | } |
161 | |
162 | Canvas() { |
163 | modulate = Color(1, 1, 1, 1); |
164 | children_order_dirty = true; |
165 | parent_scale = 1.0; |
166 | } |
167 | }; |
168 | |
169 | mutable RID_Owner<Canvas, true> canvas_owner; |
170 | RID_Owner<Item, true> canvas_item_owner; |
171 | RID_Owner<RendererCanvasRender::Light, true> canvas_light_owner; |
172 | |
173 | bool disable_scale; |
174 | bool sdf_used = false; |
175 | bool snapping_2d_transforms_to_pixel = false; |
176 | |
177 | PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator; |
178 | SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list; |
179 | |
180 | _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform); |
181 | |
182 | private: |
183 | void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask); |
184 | void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask); |
185 | |
186 | static constexpr int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; |
187 | |
188 | RendererCanvasRender::Item **z_list; |
189 | RendererCanvasRender::Item **z_last_list; |
190 | |
191 | public: |
192 | void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask); |
193 | |
194 | bool was_sdf_used(); |
195 | |
196 | RID canvas_allocate(); |
197 | void canvas_initialize(RID p_rid); |
198 | |
199 | void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring); |
200 | void canvas_set_modulate(RID p_canvas, const Color &p_color); |
201 | void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale); |
202 | void canvas_set_disable_scale(bool p_disable); |
203 | |
204 | RID canvas_item_allocate(); |
205 | void canvas_item_initialize(RID p_rid); |
206 | |
207 | void canvas_item_set_parent(RID p_item, RID p_parent); |
208 | |
209 | void canvas_item_set_visible(RID p_item, bool p_visible); |
210 | void canvas_item_set_light_mask(RID p_item, int p_mask); |
211 | |
212 | void canvas_item_set_visibility_layer(RID p_item, uint32_t p_layer); |
213 | uint32_t canvas_item_get_visibility_layer(RID p_item); |
214 | |
215 | void canvas_item_set_transform(RID p_item, const Transform2D &p_transform); |
216 | void canvas_item_set_clip(RID p_item, bool p_clip); |
217 | void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); |
218 | void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()); |
219 | void canvas_item_set_modulate(RID p_item, const Color &p_color); |
220 | void canvas_item_set_self_modulate(RID p_item, const Color &p_color); |
221 | |
222 | void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable); |
223 | |
224 | void canvas_item_set_update_when_visible(RID p_item, bool p_update); |
225 | |
226 | void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false); |
227 | void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false); |
228 | void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0); |
229 | void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); |
230 | void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); |
231 | void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); |
232 | void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); |
233 | void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0); |
234 | void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); |
235 | void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); |
236 | void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture); |
237 | void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()); |
238 | void canvas_item_add_triangle_array(RID p_item, 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>(), RID p_texture = RID(), int p_count = -1); |
239 | void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID()); |
240 | void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID()); |
241 | void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture); |
242 | void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); |
243 | void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); |
244 | void canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset); |
245 | |
246 | void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); |
247 | void canvas_item_set_z_index(RID p_item, int p_z); |
248 | void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); |
249 | void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect); |
250 | void canvas_item_attach_skeleton(RID p_item, RID p_skeleton); |
251 | |
252 | void canvas_item_clear(RID p_item); |
253 | void canvas_item_set_draw_index(RID p_item, int p_index); |
254 | |
255 | void canvas_item_set_material(RID p_item, RID p_material); |
256 | |
257 | void canvas_item_set_use_parent_material(RID p_item, bool p_enable); |
258 | |
259 | void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable); |
260 | |
261 | void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false); |
262 | |
263 | RID canvas_light_allocate(); |
264 | void canvas_light_initialize(RID p_rid); |
265 | |
266 | void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode); |
267 | void canvas_light_attach_to_canvas(RID p_light, RID p_canvas); |
268 | void canvas_light_set_enabled(RID p_light, bool p_enabled); |
269 | void canvas_light_set_texture_scale(RID p_light, float p_scale); |
270 | void canvas_light_set_transform(RID p_light, const Transform2D &p_transform); |
271 | void canvas_light_set_texture(RID p_light, RID p_texture); |
272 | void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset); |
273 | void canvas_light_set_color(RID p_light, const Color &p_color); |
274 | void canvas_light_set_height(RID p_light, float p_height); |
275 | void canvas_light_set_energy(RID p_light, float p_energy); |
276 | void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z); |
277 | void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer); |
278 | void canvas_light_set_item_cull_mask(RID p_light, int p_mask); |
279 | void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask); |
280 | void canvas_light_set_directional_distance(RID p_light, float p_distance); |
281 | |
282 | void canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode); |
283 | |
284 | void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); |
285 | void canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter); |
286 | void canvas_light_set_shadow_color(RID p_light, const Color &p_color); |
287 | void canvas_light_set_shadow_smooth(RID p_light, float p_smooth); |
288 | |
289 | RID canvas_light_occluder_allocate(); |
290 | void canvas_light_occluder_initialize(RID p_rid); |
291 | |
292 | void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas); |
293 | void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled); |
294 | void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon); |
295 | void canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable); |
296 | void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform); |
297 | void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask); |
298 | |
299 | RID canvas_occluder_polygon_allocate(); |
300 | void canvas_occluder_polygon_initialize(RID p_rid); |
301 | |
302 | void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed); |
303 | |
304 | void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode); |
305 | |
306 | void canvas_set_shadow_texture_size(int p_size); |
307 | |
308 | RID canvas_texture_allocate(); |
309 | void canvas_texture_initialize(RID p_rid); |
310 | |
311 | void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture); |
312 | void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess); |
313 | |
314 | void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); |
315 | void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); |
316 | |
317 | void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); |
318 | void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); |
319 | |
320 | void update_visibility_notifiers(); |
321 | |
322 | bool free(RID p_rid); |
323 | RendererCanvasCull(); |
324 | ~RendererCanvasCull(); |
325 | }; |
326 | |
327 | #endif // RENDERER_CANVAS_CULL_H |
328 | |