diff options
Diffstat (limited to 'servers/rendering')
84 files changed, 1751 insertions, 1037 deletions
diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h index 5531e2a5d0..10aa242060 100644 --- a/servers/rendering/dummy/environment/fog.h +++ b/servers/rendering/dummy/environment/fog.h @@ -44,7 +44,7 @@ public: virtual void fog_volume_free(RID p_rid) override {} virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {} - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {} + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override {} virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override {} virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); } virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; } diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h index 99329055a8..b9e8bcc6f1 100644 --- a/servers/rendering/dummy/storage/light_storage.h +++ b/servers/rendering/dummy/storage/light_storage.h @@ -80,6 +80,7 @@ public: virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; } virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; } virtual uint64_t light_get_version(RID p_light) const override { return 0; } + virtual uint32_t light_get_cull_mask(RID p_light) const override { return 0; } /* LIGHT INSTANCE API */ @@ -101,7 +102,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {} virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {} virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {} - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {} + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override {} virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {} virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {} virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {} @@ -114,7 +115,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); } virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; } virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; } - virtual Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); } + virtual Vector3 reflection_probe_get_size(RID p_probe) const override { return Vector3(); } virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); } virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; } virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; } diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 2d66c225e8..aba362c956 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -126,6 +126,7 @@ public: virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {} virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {} virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {} + virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override {} virtual void update_mesh_instances() override {} /* MULTIMESH API */ diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 62e1eb326d..67661ce821 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -134,7 +134,7 @@ public: virtual void decal_initialize(RID p_rid) override {} virtual void decal_free(RID p_rid) override{}; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {} + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override {} virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {} virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {} virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {} @@ -145,6 +145,7 @@ public: virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {} virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); } + virtual uint32_t decal_get_cull_mask(RID p_decal) const override { return 0; } virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {} @@ -154,6 +155,7 @@ public: virtual RID decal_instance_create(RID p_decal) override { return RID(); } virtual void decal_instance_free(RID p_decal_instance) override {} virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {} + virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override {} /* RENDER TARGET */ diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h index ac56791711..f5c4134d14 100644 --- a/servers/rendering/environment/renderer_fog.h +++ b/servers/rendering/environment/renderer_fog.h @@ -44,7 +44,7 @@ public: virtual void fog_volume_free(RID p_rid) = 0; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) = 0; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0; virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0; diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 3510b415d8..b9e3c4f303 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -597,7 +597,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, Vector2 end_left; Vector2 end_right; - if (p_width > 1.001) { + if (p_width >= 0.0) { begin_left = p_from + t; begin_right = p_from - t; end_left = p_to + t; @@ -628,7 +628,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, // This value is empirically determined to provide good antialiasing quality // while not making lines appear too soft. float border_size = 1.25f; - if (p_width < 1.0f) { + if (0.0f <= p_width && p_width < 1.0f) { border_size *= p_width; } Vector2 dir2 = diff.normalized(); @@ -769,6 +769,49 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, } } +static Vector2 compute_polyline_segment_dir(const Vector<Point2> &p_points, int p_index, const Vector2 &p_prev_segment_dir) { + int point_count = p_points.size(); + + bool is_last_point = (p_index == point_count - 1); + + Vector2 segment_dir; + + if (is_last_point) { + segment_dir = p_prev_segment_dir; + } else { + segment_dir = (p_points[p_index + 1] - p_points[p_index]).normalized(); + + if (segment_dir.is_zero_approx()) { + segment_dir = p_prev_segment_dir; + } + } + + return segment_dir; +} + +static Vector2 compute_polyline_edge_offset_clamped(const Vector2 &p_segment_dir, const Vector2 &p_prev_segment_dir) { + Vector2 bisector; + float length = 1.0f; + + bisector = (p_prev_segment_dir * p_segment_dir.length() - p_segment_dir * p_prev_segment_dir.length()).normalized(); + + float angle = atan2f(bisector.cross(p_prev_segment_dir), bisector.dot(p_prev_segment_dir)); + float sin_angle = sinf(angle); + + if (!Math::is_zero_approx(sin_angle) && !p_segment_dir.is_equal_approx(p_prev_segment_dir)) { + length = 1.0f / sin_angle; + length = CLAMP(length, -3.0f, 3.0f); + } else { + bisector = p_segment_dir.orthogonal(); + } + + if (bisector.is_zero_approx()) { + bisector = p_segment_dir.orthogonal(); + } + + return bisector * length; +} + void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) { ERR_FAIL_COND(p_points.size() < 2); Item *canvas_item = canvas_item_owner.get_or_null(p_item); @@ -777,20 +820,68 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point Color color = Color(1, 1, 1, 1); Vector<int> indices; - int pc = p_points.size(); - int pc2 = pc * 2; - - Vector2 prev_t; - int j2; + int point_count = p_points.size(); Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline); + if (p_width < 0) { + if (p_antialiased) { + WARN_PRINT("Antialiasing is not supported for thin polylines drawn using line strips (`p_width < 0`)."); + } + + pline->primitive = RS::PRIMITIVE_LINE_STRIP; + + if (p_colors.size() == 1 || p_colors.size() == point_count) { + pline->polygon.create(indices, p_points, p_colors); + } else { + Vector<Color> colors; + if (p_colors.is_empty()) { + colors.push_back(color); + } else { + colors.resize(point_count); + Color *colors_ptr = colors.ptrw(); + for (int i = 0; i < point_count; i++) { + if (i < p_colors.size()) { + color = p_colors[i]; + } + colors_ptr[i] = color; + } + } + pline->polygon.create(indices, p_points, colors); + } + return; + } + + int polyline_point_count = point_count * 2; + + bool loop = p_points[0].is_equal_approx(p_points[point_count - 1]); + Vector2 first_segment_dir; + Vector2 last_segment_dir; + + // Search for first non-zero vector between two segments. + for (int i = 1; i < point_count; i++) { + first_segment_dir = (p_points[i] - p_points[i - 1]).normalized(); + + if (!first_segment_dir.is_zero_approx()) { + break; + } + } + + // Search for last non-zero vector between two segments. + for (int i = point_count - 1; i >= 1; i--) { + last_segment_dir = (p_points[i] - p_points[i - 1]).normalized(); + + if (!last_segment_dir.is_zero_approx()) { + break; + } + } + PackedColorArray colors; PackedVector2Array points; - colors.resize(pc2); - points.resize(pc2); + colors.resize(polyline_point_count); + points.resize(polyline_point_count); Vector2 *points_ptr = points.ptrw(); Color *colors_ptr = colors.ptrw(); @@ -845,14 +936,14 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point PackedColorArray colors_left; PackedVector2Array points_left; - colors_left.resize(pc2); - points_left.resize(pc2); + colors_left.resize(polyline_point_count); + points_left.resize(polyline_point_count); PackedColorArray colors_right; PackedVector2Array points_right; - colors_right.resize(pc2); - points_right.resize(pc2); + colors_right.resize(polyline_point_count); + points_right.resize(polyline_point_count); Item::CommandPolygon *pline_begin = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline_begin); @@ -898,79 +989,81 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point Color *colors_left_ptr = colors_left.ptrw(); Color *colors_right_ptr = colors_right.ptrw(); - for (int i = 0, j = 0; i < pc; i++, j += 2) { - bool is_begin = i == 0; - bool is_end = i == pc - 1; + Vector2 prev_segment_dir; + for (int i = 0; i < point_count; i++) { + bool is_first_point = (i == 0); + bool is_last_point = (i == point_count - 1); - Vector2 t; - Vector2 end_border; - Vector2 begin_border; - if (is_end) { - t = prev_t; - end_border = (p_points[i] - p_points[i - 1]).normalized() * border_size; - } else { - t = (p_points[i + 1] - p_points[i]).normalized().orthogonal(); - if (is_begin) { - prev_t = t; - begin_border = (p_points[i] - p_points[i + 1]).normalized() * border_size; - } + Vector2 segment_dir = compute_polyline_segment_dir(p_points, i, prev_segment_dir); + if (is_first_point && loop) { + prev_segment_dir = last_segment_dir; + } else if (is_last_point && loop) { + prev_segment_dir = first_segment_dir; } - j2 = j + 1; + Vector2 base_edge_offset; + if (is_first_point && !loop) { + base_edge_offset = first_segment_dir.orthogonal(); + } else if (is_last_point && !loop) { + base_edge_offset = last_segment_dir.orthogonal(); + } else { + base_edge_offset = compute_polyline_edge_offset_clamped(segment_dir, prev_segment_dir); + } - Vector2 dir = (t + prev_t).normalized(); - Vector2 tangent = dir * p_width * 0.5; - Vector2 border = dir * border_size; + Vector2 edge_offset = base_edge_offset * (p_width * 0.5f); + Vector2 border = base_edge_offset * border_size; Vector2 pos = p_points[i]; - points_ptr[j] = pos + tangent; - points_ptr[j2] = pos - tangent; + points_ptr[i * 2 + 0] = pos + edge_offset; + points_ptr[i * 2 + 1] = pos - edge_offset; - points_left_ptr[j] = pos + tangent + border; - points_left_ptr[j2] = pos + tangent; + points_left_ptr[i * 2 + 0] = pos + edge_offset + border; + points_left_ptr[i * 2 + 1] = pos + edge_offset; - points_right_ptr[j] = pos - tangent; - points_right_ptr[j2] = pos - tangent - border; + points_right_ptr[i * 2 + 0] = pos - edge_offset; + points_right_ptr[i * 2 + 1] = pos - edge_offset - border; if (i < p_colors.size()) { color = p_colors[i]; color2 = Color(color.r, color.g, color.b, 0); } - colors_ptr[j] = color; - colors_ptr[j2] = color; + colors_ptr[i * 2 + 0] = color; + colors_ptr[i * 2 + 1] = color; + + colors_left_ptr[i * 2 + 0] = color2; + colors_left_ptr[i * 2 + 1] = color; - colors_left_ptr[j] = color2; - colors_left_ptr[j2] = color; + colors_right_ptr[i * 2 + 0] = color; + colors_right_ptr[i * 2 + 1] = color2; - colors_right_ptr[j] = color; - colors_right_ptr[j2] = color2; + if (is_first_point) { + Vector2 begin_border = loop ? Vector2() : -segment_dir * border_size; - if (is_begin) { - points_begin_ptr[0] = pos + tangent + begin_border; - points_begin_ptr[1] = pos - tangent + begin_border; - points_begin_ptr[2] = pos + tangent; - points_begin_ptr[3] = pos - tangent; + points_begin_ptr[0] = pos + edge_offset + begin_border; + points_begin_ptr[1] = pos - edge_offset + begin_border; + points_begin_ptr[2] = pos + edge_offset; + points_begin_ptr[3] = pos - edge_offset; colors_begin_ptr[0] = color2; colors_begin_ptr[1] = color2; colors_begin_ptr[2] = color; colors_begin_ptr[3] = color; - points_begin_left_corner_ptr[0] = pos - tangent - border; - points_begin_left_corner_ptr[1] = pos - tangent + begin_border - border; - points_begin_left_corner_ptr[2] = pos - tangent; - points_begin_left_corner_ptr[3] = pos - tangent + begin_border; + points_begin_left_corner_ptr[0] = pos - edge_offset - border; + points_begin_left_corner_ptr[1] = pos - edge_offset + begin_border - border; + points_begin_left_corner_ptr[2] = pos - edge_offset; + points_begin_left_corner_ptr[3] = pos - edge_offset + begin_border; colors_begin_left_corner_ptr[0] = color2; colors_begin_left_corner_ptr[1] = color2; colors_begin_left_corner_ptr[2] = color; colors_begin_left_corner_ptr[3] = color2; - points_begin_right_corner_ptr[0] = pos + tangent + begin_border; - points_begin_right_corner_ptr[1] = pos + tangent + begin_border + border; - points_begin_right_corner_ptr[2] = pos + tangent; - points_begin_right_corner_ptr[3] = pos + tangent + border; + points_begin_right_corner_ptr[0] = pos + edge_offset + begin_border; + points_begin_right_corner_ptr[1] = pos + edge_offset + begin_border + border; + points_begin_right_corner_ptr[2] = pos + edge_offset; + points_begin_right_corner_ptr[3] = pos + edge_offset + border; colors_begin_right_corner_ptr[0] = color2; colors_begin_right_corner_ptr[1] = color2; @@ -978,31 +1071,33 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point colors_begin_right_corner_ptr[3] = color2; } - if (is_end) { - points_end_ptr[0] = pos + tangent + end_border; - points_end_ptr[1] = pos - tangent + end_border; - points_end_ptr[2] = pos + tangent; - points_end_ptr[3] = pos - tangent; + if (is_last_point) { + Vector2 end_border = loop ? Vector2() : prev_segment_dir * border_size; + + points_end_ptr[0] = pos + edge_offset + end_border; + points_end_ptr[1] = pos - edge_offset + end_border; + points_end_ptr[2] = pos + edge_offset; + points_end_ptr[3] = pos - edge_offset; colors_end_ptr[0] = color2; colors_end_ptr[1] = color2; colors_end_ptr[2] = color; colors_end_ptr[3] = color; - points_end_left_corner_ptr[0] = pos - tangent - border; - points_end_left_corner_ptr[1] = pos - tangent + end_border - border; - points_end_left_corner_ptr[2] = pos - tangent; - points_end_left_corner_ptr[3] = pos - tangent + end_border; + points_end_left_corner_ptr[0] = pos - edge_offset - border; + points_end_left_corner_ptr[1] = pos - edge_offset + end_border - border; + points_end_left_corner_ptr[2] = pos - edge_offset; + points_end_left_corner_ptr[3] = pos - edge_offset + end_border; colors_end_left_corner_ptr[0] = color2; colors_end_left_corner_ptr[1] = color2; colors_end_left_corner_ptr[2] = color; colors_end_left_corner_ptr[3] = color2; - points_end_right_corner_ptr[0] = pos + tangent + end_border; - points_end_right_corner_ptr[1] = pos + tangent + end_border + border; - points_end_right_corner_ptr[2] = pos + tangent; - points_end_right_corner_ptr[3] = pos + tangent + border; + points_end_right_corner_ptr[0] = pos + edge_offset + end_border; + points_end_right_corner_ptr[1] = pos + edge_offset + end_border + border; + points_end_right_corner_ptr[2] = pos + edge_offset; + points_end_right_corner_ptr[3] = pos + edge_offset + border; colors_end_right_corner_ptr[0] = color2; colors_end_right_corner_ptr[1] = color2; @@ -1010,7 +1105,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point colors_end_right_corner_ptr[3] = color2; } - prev_t = t; + prev_segment_dir = segment_dir; } pline_begin->primitive = RS::PRIMITIVE_TRIANGLE_STRIP; @@ -1039,33 +1134,41 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point } else { // Makes a single triangle strip for drawing the line. - for (int i = 0, j = 0; i < pc; i++, j += 2) { - Vector2 t; - if (i == pc - 1) { - t = prev_t; - } else { - t = (p_points[i + 1] - p_points[i]).normalized().orthogonal(); - if (i == 0) { - prev_t = t; - } + Vector2 prev_segment_dir; + for (int i = 0; i < point_count; i++) { + bool is_first_point = (i == 0); + bool is_last_point = (i == point_count - 1); + + Vector2 segment_dir = compute_polyline_segment_dir(p_points, i, prev_segment_dir); + if (is_first_point && loop) { + prev_segment_dir = last_segment_dir; + } else if (is_last_point && loop) { + prev_segment_dir = first_segment_dir; } - j2 = j + 1; + Vector2 base_edge_offset; + if (is_first_point && !loop) { + base_edge_offset = first_segment_dir.orthogonal(); + } else if (is_last_point && !loop) { + base_edge_offset = last_segment_dir.orthogonal(); + } else { + base_edge_offset = compute_polyline_edge_offset_clamped(segment_dir, prev_segment_dir); + } - Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + Vector2 edge_offset = base_edge_offset * (p_width * 0.5f); Vector2 pos = p_points[i]; - points_ptr[j] = pos + tangent; - points_ptr[j2] = pos - tangent; + points_ptr[i * 2 + 0] = pos + edge_offset; + points_ptr[i * 2 + 1] = pos - edge_offset; if (i < p_colors.size()) { color = p_colors[i]; } - colors_ptr[j] = color; - colors_ptr[j2] = color; + colors_ptr[i * 2 + 0] = color; + colors_ptr[i * 2 + 1] = color; - prev_t = t; + prev_segment_dir = segment_dir; } } @@ -1077,7 +1180,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin ERR_FAIL_COND(p_points.size() < 2); // TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out. - if (p_width <= 1) { + if (p_width < 0) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_COND(!canvas_item); @@ -1133,20 +1236,23 @@ void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, static const int circle_points = 64; points.resize(circle_points); + Vector2 *points_ptr = points.ptrw(); const real_t circle_point_step = Math_TAU / circle_points; for (int i = 0; i < circle_points; i++) { float angle = i * circle_point_step; - points.write[i].x = Math::cos(angle) * p_radius; - points.write[i].y = Math::sin(angle) * p_radius; - points.write[i] += p_pos; + points_ptr[i].x = Math::cos(angle) * p_radius; + points_ptr[i].y = Math::sin(angle) * p_radius; + points_ptr[i] += p_pos; } + indices.resize((circle_points - 2) * 3); + int *indices_ptr = indices.ptrw(); for (int i = 0; i < circle_points - 2; i++) { - indices.write[i * 3 + 0] = 0; - indices.write[i * 3 + 1] = i + 1; - indices.write[i * 3 + 2] = i + 2; + indices_ptr[i * 3 + 0] = 0; + indices_ptr[i * 3 + 1] = i + 1; + indices_ptr[i * 3 + 2] = i + 2; } Vector<Color> color; @@ -1313,7 +1419,7 @@ void RendererCanvasCull::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_r style->axis_y = p_y_axis_mode; } -void RendererCanvasCull::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, float p_width) { +void RendererCanvasCull::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) { uint32_t pc = p_points.size(); ERR_FAIL_COND(pc == 0 || pc > 4); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 4d0be48cc0..1106fc4f1e 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -221,9 +221,9 @@ public: void canvas_item_set_update_when_visible(RID p_item, bool p_update); - 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); - 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); - void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); + 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); + 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); + void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); 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); @@ -231,7 +231,7 @@ public: 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); 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)); 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)); - 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, float p_width = 1.0); + 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); 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()); 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); 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()); diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 73a0c652a4..959a752fba 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -74,7 +74,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() { cluster_debug.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_debug.shader); } - { // SPHERE + { // Sphere mesh data. static const uint32_t icosphere_vertex_count = 42; static const float icosphere_vertices[icosphere_vertex_count * 3] = { 0, 0, -1, 0.7236073, -0.5257253, -0.4472195, -0.276388, -0.8506492, -0.4472199, -0.8944262, 0, -0.4472156, -0.276388, 0.8506492, -0.4472199, 0.7236073, 0.5257253, -0.4472195, 0.276388, -0.8506492, 0.4472199, -0.7236073, -0.5257253, 0.4472195, -0.7236073, 0.5257253, 0.4472195, 0.276388, 0.8506492, 0.4472199, 0.8944262, 0, 0.4472156, 0, 0, 1, -0.1624555, -0.4999952, -0.8506544, 0.4253227, -0.3090114, -0.8506542, 0.2628688, -0.8090116, -0.5257377, 0.8506479, 0, -0.5257359, 0.4253227, 0.3090114, -0.8506542, -0.5257298, 0, -0.8506517, -0.6881894, -0.4999969, -0.5257362, -0.1624555, 0.4999952, -0.8506544, -0.6881894, 0.4999969, -0.5257362, 0.2628688, 0.8090116, -0.5257377, 0.9510579, -0.3090126, 0, 0.9510579, 0.3090126, 0, 0, -1, 0, 0.5877856, -0.8090167, 0, -0.9510579, -0.3090126, 0, -0.5877856, -0.8090167, 0, -0.5877856, 0.8090167, 0, -0.9510579, 0.3090126, 0, 0.5877856, 0.8090167, 0, 0, 1, 0, 0.6881894, -0.4999969, 0.5257362, -0.2628688, -0.8090116, 0.5257377, -0.8506479, 0, 0.5257359, -0.2628688, 0.8090116, 0.5257377, 0.6881894, 0.4999969, 0.5257362, 0.1624555, -0.4999952, 0.8506544, 0.5257298, 0, 0.8506517, -0.4253227, -0.3090114, 0.8506542, -0.4253227, 0.3090114, 0.8506542, 0.1624555, 0.4999952, 0.8506544 @@ -118,7 +118,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() { sphere_overfit = 1.0 / min_d; } - { // CONE + { // Cone mesh data. static const uint32_t cone_vertex_count = 99; static const float cone_vertices[cone_vertex_count * 3] = { 0, 1, -1, 0.1950903, 0.9807853, -1, 0.3826835, 0.9238795, -1, 0.5555703, 0.8314696, -1, 0.7071068, 0.7071068, -1, 0.8314697, 0.5555702, -1, 0.9238795, 0.3826834, -1, 0.9807853, 0.1950903, -1, 1, 0, -1, 0.9807853, -0.1950902, -1, 0.9238796, -0.3826833, -1, 0.8314697, -0.5555702, -1, 0.7071068, -0.7071068, -1, 0.5555702, -0.8314697, -1, 0.3826833, -0.9238796, -1, 0.1950901, -0.9807853, -1, -3.25841e-7, -1, -1, -0.1950907, -0.9807852, -1, -0.3826839, -0.9238793, -1, -0.5555707, -0.8314693, -1, -0.7071073, -0.7071063, -1, -0.83147, -0.5555697, -1, -0.9238799, -0.3826827, -1, 0, 0, 0, -0.9807854, -0.1950894, -1, -1, 9.65599e-7, -1, -0.9807851, 0.1950913, -1, -0.9238791, 0.3826845, -1, -0.8314689, 0.5555713, -1, -0.7071059, 0.7071077, -1, -0.5555691, 0.8314704, -1, -0.3826821, 0.9238801, -1, -0.1950888, 0.9807856, -1 @@ -172,7 +172,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() { cone_overfit = 1.0 / min_d; } - { // BOX + { // Box mesh data. static const uint32_t box_vertex_count = 8; static const float box_vertices[box_vertex_count * 3] = { -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1 @@ -219,8 +219,9 @@ ClusterBuilderSharedDataRD::~ClusterBuilderSharedDataRD() { void ClusterBuilderRD::_clear() { if (cluster_buffer.is_null()) { - return; //nothing to clear + return; } + RD::get_singleton()->free(cluster_buffer); RD::get_singleton()->free(cluster_render_buffer); RD::get_singleton()->free(element_buffer); @@ -254,7 +255,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID cluster_screen_size.height = (p_screen_size.height - 1) / cluster_size + 1; max_elements_by_type = p_max_elements; - if (max_elements_by_type % 32) { //need to be 32 aligned + if (max_elements_by_type % 32) { // Needs to be aligned to 32. max_elements_by_type += 32 - (max_elements_by_type % 32); } @@ -264,7 +265,8 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID uint32_t element_tag_bits_size = render_element_max / 32; uint32_t element_tag_depth_bits_size = render_element_max; - cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // tag bits (element was used) and tag depth (depth range in which it was used) + + cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // Tag bits (element was used) and tag depth (depth range in which it was used). cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size); cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size); @@ -379,9 +381,9 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projecti projection = p_cam_projection; z_near = projection.get_z_near(); z_far = projection.get_z_far(); - orthogonal = p_cam_projection.is_orthogonal(); + camera_orthogonal = p_cam_projection.is_orthogonal(); adjusted_projection = projection; - if (!orthogonal) { + if (!camera_orthogonal) { adjusted_projection.adjust_perspective_znear(0.0001); } @@ -390,7 +392,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projecti projection = correction * projection; adjusted_projection = correction * adjusted_projection; - //reset counts + // Reset counts. render_element_count = 0; for (uint32_t i = 0; i < ELEMENT_TYPE_MAX; i++) { cluster_count_by_type[i] = 0; @@ -402,14 +404,14 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_command_begin_label("Bake Light Cluster"); - //clear cluster buffer + // Clear cluster buffer. RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); if (render_element_count > 0) { - //clear render buffer + // Clear render buffer. RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, RD::BARRIER_MASK_RASTER); - { //fill state uniform + { // Fill state uniform. StateUniform state; @@ -425,13 +427,13 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); } - //update instances + // Update instances. RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); RENDER_TIMESTAMP("Render 3D Cluster Elements"); - //render elements + // Render elements. { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {}; @@ -447,8 +449,16 @@ void ClusterBuilderRD::bake_cluster() { RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array); } break; case ELEMENT_TYPE_SPOT_LIGHT: { - RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array); - RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array); + // If the spot angle is above a certain threshold, use a sphere instead of a cone for building the clusters + // since the cone gets too flat/large (spot angle close to 90 degrees) or + // can't even cover the affected area of the light (spot angle above 90 degrees). + if (render_elements[i].has_wide_spot_angle) { + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->sphere_vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array); + } else { + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array); + } } break; case ELEMENT_TYPE_DECAL: case ELEMENT_TYPE_REFLECTION_PROBE: { @@ -465,7 +475,7 @@ void ClusterBuilderRD::bake_cluster() { } RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE); } - //store elements + // Store elements. RENDER_TIMESTAMP("Pack 3D Cluster Elements"); { @@ -509,7 +519,7 @@ void ClusterBuilderRD::debug(ElementType p_element) { push_constant.cluster_screen_size[1] = cluster_screen_size.y; push_constant.cluster_shift = get_shift_from_power_of_2(cluster_size); push_constant.cluster_type = p_element; - push_constant.orthogonal = orthogonal; + push_constant.orthogonal = camera_orthogonal; push_constant.z_far = z_far; push_constant.z_near = z_near; push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index 0b20a5d7ee..3ca7af70ca 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -43,13 +43,13 @@ class ClusterBuilderSharedDataRD { RID sphere_vertex_array; RID sphere_index_buffer; RID sphere_index_array; - float sphere_overfit = 0.0; //because an icosphere is not a perfect sphere, we need to enlarge it to cover the sphere area + float sphere_overfit = 0.0; // Because an icosphere is not a perfect sphere, we need to enlarge it to cover the sphere area. RID cone_vertex_buffer; RID cone_vertex_array; RID cone_index_buffer; RID cone_index_array; - float cone_overfit = 0.0; //because an cone mesh is not a perfect sphere, we need to enlarge it to cover the actual cone area + float cone_overfit = 0.0; // Because an cone mesh is not a perfect cone, we need to enlarge it to cover the actual cone area. RID box_vertex_buffer; RID box_vertex_array; @@ -73,6 +73,7 @@ class ClusterBuilderSharedDataRD { ClusterRenderShaderRD cluster_render_shader; RID shader_version; RID shader; + enum PipelineVersion { PIPELINE_NORMAL, PIPELINE_MSAA, @@ -85,10 +86,11 @@ class ClusterBuilderSharedDataRD { struct ClusterStore { struct PushConstant { uint32_t cluster_render_data_size; // how much data for a single cluster takes - uint32_t max_render_element_count_div_32; //divided by 32 + uint32_t max_render_element_count_div_32; // divided by 32 uint32_t cluster_screen_size[2]; - uint32_t render_element_count_div_32; //divided by 32 - uint32_t max_cluster_element_count_div_32; //divided by 32 + uint32_t render_element_count_div_32; // divided by 32 + uint32_t max_cluster_element_count_div_32; // divided by 32 + uint32_t pad1; uint32_t pad2; }; @@ -111,6 +113,7 @@ class ClusterBuilderSharedDataRD { uint32_t orthogonal; uint32_t max_cluster_element_count_div_32; + uint32_t pad1; uint32_t pad2; }; @@ -128,6 +131,8 @@ public: class ClusterBuilderRD { public: + static constexpr float WIDE_SPOT_ANGLE_THRESHOLD_DEG = 60.0f; + enum LightType { LIGHT_TYPE_OMNI, LIGHT_TYPE_SPOT @@ -144,21 +149,20 @@ public: ELEMENT_TYPE_DECAL, ELEMENT_TYPE_REFLECTION_PROBE, ELEMENT_TYPE_MAX, - }; private: ClusterBuilderSharedDataRD *shared = nullptr; struct RenderElementData { - uint32_t type; //0-4 + uint32_t type; // 0-4 uint32_t touches_near; uint32_t touches_far; uint32_t original_index; - float transform_inv[12]; //transposed transform for less space + float transform_inv[12]; // Transposed transform for less space. float scale[3]; - uint32_t pad; - }; + uint32_t has_wide_spot_angle; + }; // Keep aligned to 32 bytes. uint32_t cluster_count_by_type[ELEMENT_TYPE_MAX] = {}; uint32_t max_elements_by_type = 0; @@ -172,7 +176,7 @@ private: Projection projection; float z_far = 0; float z_near = 0; - bool orthogonal = false; + bool camera_orthogonal = false; enum Divisor { DIVISOR_1, @@ -188,26 +192,27 @@ private: Size2i cluster_screen_size; RID framebuffer; - RID cluster_render_buffer; //used for creating - RID cluster_buffer; //used for rendering - RID element_buffer; //used for storing, to hint element touches far plane or near plane + RID cluster_render_buffer; // Used for creating. + RID cluster_buffer; // Used for rendering. + RID element_buffer; // Used for storing, to hint element touches far plane or near plane. uint32_t cluster_render_buffer_size = 0; uint32_t cluster_buffer_size = 0; RID cluster_render_uniform_set; RID cluster_store_uniform_set; - //persistent data + // Persistent data. void _clear(); struct StateUniform { float projection[16]; float inv_z_far; - uint32_t screen_to_clusters_shift; // shift to obtain coordinates in block indices - uint32_t cluster_screen_width; // - uint32_t cluster_data_size; // how much data for a single cluster takes + uint32_t screen_to_clusters_shift; // Shift to obtain coordinates in block indices. + uint32_t cluster_screen_width; + uint32_t cluster_data_size; // How much data is needed for a single cluster. uint32_t cluster_depth_offset; + uint32_t pad0; uint32_t pad1; uint32_t pad2; @@ -224,10 +229,10 @@ public: _FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) { if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) { - return; //max number elements reached + return; // Max number elements reached. } if (p_type == LIGHT_TYPE_SPOT && cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT] == max_elements_by_type) { - return; //max number elements reached + return; // Max number elements reached. } RenderElementData &e = render_elements[render_element_count]; @@ -242,15 +247,14 @@ public: radius *= p_radius; if (p_type == LIGHT_TYPE_OMNI) { - radius *= shared->sphere_overfit; // overfit icosphere + radius *= shared->sphere_overfit; // Overfit icosphere. - //omni float depth = -xform.origin.z; - if (orthogonal) { + if (camera_orthogonal) { e.touches_near = (depth - radius) < z_near; } else { - //contains camera inside light - float radius2 = radius * shared->sphere_overfit; // overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex) + // Contains camera inside light. + float radius2 = radius * shared->sphere_overfit; // Overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex) e.touches_near = xform.origin.length_squared() < radius2 * radius2; } @@ -265,12 +269,11 @@ public: cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++; - } else { - //spot - radius *= shared->cone_overfit; // overfit icosphere + } else /*LIGHT_TYPE_SPOT */ { + radius *= shared->cone_overfit; // Overfit icosphere real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius; - //approximate, probably better to use a cone support function + // Approximate, probably better to use a cone support function. float max_d = -1e20; float min_d = 1e20; #define CONE_MINMAX(m_x, m_y) \ @@ -285,14 +288,13 @@ public: CONE_MINMAX(-1, -1); CONE_MINMAX(1, -1); - if (orthogonal) { + if (camera_orthogonal) { e.touches_near = min_d < z_near; } else { - //contains camera inside light Plane base_plane(-xform.basis.get_column(Vector3::AXIS_Z), xform.origin); float dist = base_plane.distance_to(Vector3()); if (dist >= 0 && dist < radius) { - //inside, check angle + // Contains camera inside light, check angle. float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z)))); e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit } else { @@ -302,12 +304,23 @@ public: e.touches_far = max_d > z_far; - e.scale[0] = len * shared->cone_overfit; - e.scale[1] = len * shared->cone_overfit; - e.scale[2] = radius; + // If the spot angle is above the threshold, use a sphere instead of a cone for building the clusters + // since the cone gets too flat/large (spot angle close to 90 degrees) or + // can't even cover the affected area of the light (spot angle above 90 degrees). + if (p_spot_aperture > WIDE_SPOT_ANGLE_THRESHOLD_DEG) { + e.scale[0] = radius; + e.scale[1] = radius; + e.scale[2] = radius; + e.has_wide_spot_angle = true; + } else { + e.scale[0] = len * shared->cone_overfit; + e.scale[1] = len * shared->cone_overfit; + e.scale[2] = radius; + e.has_wide_spot_angle = false; + } e.type = ELEMENT_TYPE_SPOT_LIGHT; - e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index + e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; // Use omni light since they share index. RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv); @@ -317,19 +330,19 @@ public: render_element_count++; } - _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_extents) { + _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_size) { if (p_box_type == BOX_TYPE_DECAL && cluster_count_by_type[ELEMENT_TYPE_DECAL] == max_elements_by_type) { - return; //max number elements reached + return; // Max number elements reached. } if (p_box_type == BOX_TYPE_REFLECTION_PROBE && cluster_count_by_type[ELEMENT_TYPE_REFLECTION_PROBE] == max_elements_by_type) { - return; //max number elements reached + return; // Max number elements reached. } RenderElementData &e = render_elements[render_element_count]; Transform3D xform = view_xform * p_transform; - //extract scale and scale the matrix by it, makes things simpler - Vector3 scale = p_half_extents; + // Extract scale and scale the matrix by it, makes things simpler. + Vector3 scale = p_half_size; for (uint32_t i = 0; i < 3; i++) { float s = xform.basis.rows[i].length(); scale[i] *= s; @@ -339,10 +352,10 @@ public: float box_depth = Math::abs(xform.basis.xform_inv(Vector3(0, 0, -1)).dot(scale)); float depth = -xform.origin.z; - if (orthogonal) { + if (camera_orthogonal) { e.touches_near = depth - box_depth < z_near; } else { - //contains camera inside box + // Contains camera inside box. Vector3 inside = xform.xform_inv(Vector3(0, 0, 0)).abs(); e.touches_near = inside.x < scale.x && inside.y < scale.y && inside.z < scale.z; } diff --git a/servers/rendering/renderer_rd/effects/luminance.cpp b/servers/rendering/renderer_rd/effects/luminance.cpp new file mode 100644 index 0000000000..7462282932 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/luminance.cpp @@ -0,0 +1,255 @@ +/**************************************************************************/ +/* luminance.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "luminance.h" +#include "../framebuffer_cache_rd.h" +#include "../uniform_set_cache_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" + +using namespace RendererRD; + +Luminance::Luminance(bool p_prefer_raster_effects) { + prefer_raster_effects = p_prefer_raster_effects; + + 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); + 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"); + luminance_reduce_modes.push_back("\n"); + luminance_reduce_modes.push_back("\n#define WRITE_LUMINANCE\n"); + + luminance_reduce.shader.initialize(luminance_reduce_modes); + luminance_reduce.shader_version = luminance_reduce.shader.version_create(); + + 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(); + } + } +} + +Luminance::~Luminance() { + if (prefer_raster_effects) { + luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version); + } else { + luminance_reduce.shader.version_free(luminance_reduce.shader_version); + } +} + +void Luminance::LuminanceBuffers::set_prefer_raster_effects(bool p_prefer_raster_effects) { + prefer_raster_effects = p_prefer_raster_effects; +} + +void Luminance::LuminanceBuffers::configure(RenderSceneBuffersRD *p_render_buffers) { + Size2i internal_size = p_render_buffers->get_internal_size(); + int w = internal_size.x; + int h = internal_size.y; + + while (true) { + w = MAX(w / 8, 1); + h = MAX(h / 8, 1); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = w; + tf.height = h; + + bool final = w == 1 && h == 1; + + if (prefer_raster_effects) { + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + } else { + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + if (final) { + tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT; + } + } + + RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + reduce.push_back(texture); + + if (final) { + current = RD::get_singleton()->texture_create(tf, RD::TextureView()); + break; + } + } +} + +void Luminance::LuminanceBuffers::free_data() { + for (int i = 0; i < reduce.size(); i++) { + RD::get_singleton()->free(reduce[i]); + } + reduce.clear(); + + if (current.is_valid()) { + RD::get_singleton()->free(current); + current = RID(); + } +} + +Ref<Luminance::LuminanceBuffers> Luminance::get_luminance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers) { + if (p_render_buffers->has_custom_data(RB_LUMINANCE_BUFFERS)) { + return p_render_buffers->get_custom_data(RB_LUMINANCE_BUFFERS); + } + + Ref<LuminanceBuffers> buffers; + buffers.instantiate(); + buffers->set_prefer_raster_effects(prefer_raster_effects); + buffers->configure(p_render_buffers.ptr()); + + p_render_buffers->set_custom_data(RB_LUMINANCE_BUFFERS, buffers); + + return buffers; +} + +RID Luminance::get_current_luminance_buffer(Ref<RenderSceneBuffersRD> p_render_buffers) { + if (p_render_buffers->has_custom_data(RB_LUMINANCE_BUFFERS)) { + Ref<LuminanceBuffers> buffers = p_render_buffers->get_custom_data(RB_LUMINANCE_BUFFERS); + return buffers->current; + } + + return RID(); +} + +void Luminance::luminance_reduction(RID p_source_texture, const Size2i p_source_size, Ref<LuminanceBuffers> p_luminance_buffers, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + if (prefer_raster_effects) { + LuminanceReduceRasterPushConstant push_constant; + memset(&push_constant, 0, sizeof(LuminanceReduceRasterPushConstant)); + + push_constant.max_luminance = p_max_luminance; + push_constant.min_luminance = p_min_luminance; + push_constant.exposure_adjust = p_adjust; + + for (int i = 0; i < p_luminance_buffers->reduce.size(); i++) { + push_constant.source_size[0] = i == 0 ? p_source_size.x : push_constant.dest_size[0]; + push_constant.source_size[1] = i == 0 ? p_source_size.y : push_constant.dest_size[1]; + push_constant.dest_size[0] = MAX(push_constant.source_size[0] / 8, 1); + push_constant.dest_size[1] = MAX(push_constant.source_size[1] / 8, 1); + + bool final = !p_set && (push_constant.dest_size[0] == 1) && (push_constant.dest_size[1] == 1); + LuminanceReduceRasterMode mode = final ? LUMINANCE_REDUCE_FRAGMENT_FINAL : (i == 0 ? LUMINANCE_REDUCE_FRAGMENT_FIRST : LUMINANCE_REDUCE_FRAGMENT); + RID shader = luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, mode); + + RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_luminance_buffers->reduce[i]); + + RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, i == 0 ? p_source_texture : p_luminance_buffers->reduce[i - 1] })); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); + if (final) { + RD::Uniform u_current_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_luminance_buffers->current })); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_current_texture), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(LuminanceReduceRasterPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + } + } else { + LuminanceReducePushConstant push_constant; + memset(&push_constant, 0, sizeof(LuminanceReducePushConstant)); + + push_constant.source_size[0] = p_source_size.x; + push_constant.source_size[1] = p_source_size.y; + push_constant.max_luminance = p_max_luminance; + push_constant.min_luminance = p_min_luminance; + push_constant.exposure_adjust = p_adjust; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + for (int i = 0; i < p_luminance_buffers->reduce.size(); i++) { + RID shader; + + if (i == 0) { + shader = luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, LUMINANCE_REDUCE_READ); + RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); + } else { + RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done + + if (i == p_luminance_buffers->reduce.size() - 1 && !p_set) { + shader = luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, LUMINANCE_REDUCE_WRITE); + RD::Uniform u_current_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_luminance_buffers->current })); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_WRITE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_current_texture), 2); + } else { + shader = luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, LUMINANCE_REDUCE); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE]); + } + + RD::Uniform u_source_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_luminance_buffers->reduce[i - 1]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0); + } + + RD::Uniform u_reduce_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_luminance_buffers->reduce[i]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_reduce_texture), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(LuminanceReducePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.source_size[0], push_constant.source_size[1], 1); + + push_constant.source_size[0] = MAX(push_constant.source_size[0] / 8, 1); + push_constant.source_size[1] = MAX(push_constant.source_size[1] / 8, 1); + } + + RD::get_singleton()->compute_list_end(); + } + + SWAP(p_luminance_buffers->current, p_luminance_buffers->reduce.write[p_luminance_buffers->reduce.size() - 1]); +} diff --git a/servers/rendering/renderer_rd/effects/luminance.h b/servers/rendering/renderer_rd/effects/luminance.h new file mode 100644 index 0000000000..0f343fceab --- /dev/null +++ b/servers/rendering/renderer_rd/effects/luminance.h @@ -0,0 +1,120 @@ +/**************************************************************************/ +/* luminance.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef LUMINANCE_RD_H +#define LUMINANCE_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +#define RB_LUMINANCE_BUFFERS SNAME("luminance_buffers") + +namespace RendererRD { + +class Luminance { +private: + bool prefer_raster_effects; + + enum LuminanceReduceMode { + LUMINANCE_REDUCE_READ, + LUMINANCE_REDUCE, + LUMINANCE_REDUCE_WRITE, + LUMINANCE_REDUCE_MAX + }; + + struct LuminanceReducePushConstant { + int32_t source_size[2]; + float max_luminance; + float min_luminance; + float exposure_adjust; + float pad[3]; + }; + + struct LuminanceReduce { + LuminanceReduceShaderRD shader; + RID shader_version; + 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; + uint32_t pad1; + }; + + struct LuminanceReduceFragment { + LuminanceReduceRasterShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX]; + } luminance_reduce_raster; + +public: + class LuminanceBuffers : public RenderBufferCustomDataRD { + GDCLASS(LuminanceBuffers, RenderBufferCustomDataRD); + + private: + bool prefer_raster_effects; + + public: + Vector<RID> reduce; + RID current; + + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; + virtual void free_data() override; + + void set_prefer_raster_effects(bool p_prefer_raster_effects); + }; + + Ref<LuminanceBuffers> get_luminance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers); + RID get_current_luminance_buffer(Ref<RenderSceneBuffersRD> p_render_buffers); + void luminance_reduction(RID p_source_texture, const Size2i p_source_size, Ref<LuminanceBuffers> p_luminance_buffers, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); + + Luminance(bool p_prefer_raster_effects); + ~Luminance(); +}; + +} // namespace RendererRD + +#endif // LUMINANCE_RD_H diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 6d15d5c77b..b7a1396f9c 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -55,36 +55,13 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) { u.append_id(p_image); uniforms.push_back(u); //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0), 1); image_to_uniform_set_cache[p_image] = uniform_set; return uniform_set; } -RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { - if (texture_to_uniform_set_cache.has(p_texture)) { - RID uniform_set = texture_to_uniform_set_cache[p_texture]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.append_id(p_texture); - uniforms.push_back(u); - // anything with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0); - - texture_to_uniform_set_cache[p_texture] = uniform_set; - - return uniform_set; -} - RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { if (texture_to_compute_uniform_set_cache.has(p_texture)) { RID uniform_set = texture_to_compute_uniform_set_cache[p_texture]; @@ -101,86 +78,13 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m u.append_id(p_texture); uniforms.push_back(u); //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0), 0); texture_to_compute_uniform_set_cache[p_texture] = uniform_set; return uniform_set; } -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; - luminance_reduce.push_constant.min_luminance = p_min_luminance; - luminance_reduce.push_constant.exposure_adjust = p_adjust; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - for (int i = 0; i < p_reduce.size(); i++) { - if (i == 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_texture), 0); - } else { - RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done - - if (i == p_reduce.size() - 1 && !p_set) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_WRITE]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_prev_luminance), 2); - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE]); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i - 1]), 0); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i]), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &luminance_reduce.push_constant, sizeof(LuminanceReducePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, luminance_reduce.push_constant.source_size[0], luminance_reduce.push_constant.source_size[1], 1); - - luminance_reduce.push_constant.source_size[0] = MAX(luminance_reduce.push_constant.source_size[0] / 8, 1); - luminance_reduce.push_constant.source_size[1] = MAX(luminance_reduce.push_constant.source_size[1] / 8, 1); - } - - 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 raster 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::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { roughness_limiter.push_constant.screen_size[0] = p_size.x; roughness_limiter.push_constant.screen_size[1] = p_size.y; @@ -270,39 +174,6 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) { EffectsRD::EffectsRD(bool p_prefer_raster_effects) { prefer_raster_effects = p_prefer_raster_effects; - 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"); - luminance_reduce_modes.push_back("\n"); - luminance_reduce_modes.push_back("\n#define WRITE_LUMINANCE\n"); - - luminance_reduce.shader.initialize(luminance_reduce_modes); - - luminance_reduce.shader_version = luminance_reduce.shader.version_create(); - - 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(); - } - } - if (!prefer_raster_effects) { // Initialize roughness limiter Vector<String> shader_modes; @@ -368,11 +239,6 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(default_mipmap_sampler); RD::get_singleton()->free(index_buffer); //array gets freed as dependency - if (prefer_raster_effects) { - luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version); - } else { - luminance_reduce.shader.version_free(luminance_reduce.shader_version); - } if (!prefer_raster_effects) { roughness_limiter.shader.version_free(roughness_limiter.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index bbe240b241..45198e5fc5 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -33,8 +33,6 @@ #include "core/math/projection.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.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/roughness_limiter.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" @@ -45,51 +43,6 @@ class EffectsRD { private: bool prefer_raster_effects; - enum LuminanceReduceMode { - LUMINANCE_REDUCE_READ, - LUMINANCE_REDUCE, - LUMINANCE_REDUCE_WRITE, - LUMINANCE_REDUCE_MAX - }; - - struct LuminanceReducePushConstant { - int32_t source_size[2]; - float max_luminance; - float min_luminance; - float exposure_adjust; - float pad[3]; - }; - - struct LuminanceReduce { - LuminanceReducePushConstant push_constant; - LuminanceReduceShaderRD shader; - RID shader_version; - 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; - uint32_t pad1; - }; - - struct LuminanceReduceFragment { - LuminanceReduceRasterPushConstant push_constant; - LuminanceReduceRasterShaderRD shader; - RID shader_version; - PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX]; - } luminance_reduce_raster; - struct RoughnessLimiterPushConstant { int32_t screen_size[2]; float curve; @@ -164,15 +117,11 @@ private: RBMap<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; RID _get_uniform_set_from_image(RID p_texture); - RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); public: bool get_prefer_raster_effects(); - 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 roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); void sort_buffer(RID p_uniform_set, int p_size); diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 2787693aeb..4253ea8610 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -82,11 +82,11 @@ void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } -void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { +void Fog::fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); ERR_FAIL_COND(!fog_volume); - fog_volume->extents = p_extents; + fog_volume->size = p_size; fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } @@ -120,8 +120,8 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { case RS::FOG_VOLUME_SHAPE_CYLINDER: case RS::FOG_VOLUME_SHAPE_BOX: { AABB aabb; - aabb.position = -fog_volume->extents; - aabb.size = fog_volume->extents * 2; + aabb.position = -fog_volume->size / 2; + aabb.size = fog_volume->size; return aabb; } default: { @@ -131,10 +131,10 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { } } -Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { +Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const { const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); ERR_FAIL_COND_V(!fog_volume, Vector3()); - return fog_volume->extents; + return fog_volume->size; } //////////////////////////////////////////////////////////////////////////////// @@ -210,7 +210,7 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay actions.renames["WORLD_POSITION"] = "world.xyz"; actions.renames["OBJECT_POSITION"] = "params.position"; actions.renames["UVW"] = "uvw"; - actions.renames["EXTENTS"] = "params.extents"; + actions.renames["SIZE"] = "params.size"; actions.renames["ALBEDO"] = "albedo"; actions.renames["DENSITY"] = "density"; actions.renames["EMISSION"] = "emission"; @@ -643,7 +643,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P Vector3 position = fog_volume_instance->transform.get_origin(); RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); - Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); + Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2; if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { // Local fog volume. @@ -683,9 +683,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P push_constant.position[0] = position.x; push_constant.position[1] = position.y; push_constant.position[2] = position.z; - push_constant.extents[0] = extents.x; - push_constant.extents[1] = extents.y; - push_constant.extents[2] = extents.z; + push_constant.size[0] = extents.x * 2; + push_constant.size[1] = extents.y * 2; + push_constant.size[2] = extents.z * 2; push_constant.corner[0] = min.x; push_constant.corner[1] = min.y; push_constant.corner[2] = min.z; diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index eb0a2fc7b5..0b6bcc29fb 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -53,7 +53,7 @@ private: struct FogVolume { RID material; - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX; @@ -83,7 +83,7 @@ private: float position[3]; float pad; - float extents[3]; + float size[3]; float pad2; int32_t corner[3]; @@ -239,12 +239,12 @@ public: Dependency *fog_volume_get_dependency(RID p_fog_volume) const; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; + virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override; virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override; virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; RID fog_volume_get_material(RID p_fog_volume) const; virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; - Vector3 fog_volume_get_extents(RID p_fog_volume) const; + Vector3 fog_volume_get_size(RID p_fog_volume) const; /* FOG VOLUMES INSTANCE */ diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index a52716cd78..08133bf8d6 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -540,9 +540,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re occlusion_texture = RD::get_singleton()->texture_create_shared(tv, occlusion_data); } - for (uint32_t i = 0; i < cascades.size(); i++) { - SDFGI::Cascade &cascade = cascades[i]; - + for (SDFGI::Cascade &cascade : cascades) { /* 3D Textures */ cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView()); @@ -743,9 +741,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re } //direct light - for (uint32_t i = 0; i < cascades.size(); i++) { - SDFGI::Cascade &cascade = cascades[i]; - + for (SDFGI::Cascade &cascade : cascades) { Vector<RD::Uniform> uniforms; { RD::Uniform u; @@ -1134,8 +1130,7 @@ void GI::SDFGI::free_data() { } GI::SDFGI::~SDFGI() { - for (uint32_t i = 0; i < cascades.size(); i++) { - const SDFGI::Cascade &c = cascades[i]; + for (const SDFGI::Cascade &c : cascades) { RD::get_singleton()->free(c.light_data); RD::get_singleton()->free(c.light_aniso_0_tex); RD::get_singleton()->free(c.light_aniso_1_tex); @@ -1198,8 +1193,7 @@ void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) { int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2; - for (uint32_t i = 0; i < cascades.size(); i++) { - SDFGI::Cascade &cascade = cascades[i]; + for (SDFGI::Cascade &cascade : cascades) { cascade.dirty_regions = Vector3i(); Vector3 probe_half_size = Vector3(1, 1, 1) * cascade.cell_size * float(cascade_size / SDFGI::PROBE_DIVISOR) * 0.5; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 863e8d6c15..7fff349b3c 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -347,7 +347,10 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo tf.texture_type = RD::TEXTURE_TYPE_CUBE; tf.array_layers = 6; tf.mipmaps = p_low_quality ? 7 : mipmaps - 1; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; + } downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap"); @@ -571,7 +574,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; // half res if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { + if (reflection.layers.size() && reflection.layers[0].views.size() >= 2 && reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { u.append_id(reflection.layers[0].views[1]); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); @@ -591,7 +594,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; // quarter res if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { + if (reflection.layers.size() && reflection.layers[0].views.size() >= 3 && reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { u.append_id(reflection.layers[0].views[2]); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); @@ -1085,8 +1088,8 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con sky->reflection.dirty = true; } + sky_scene_state.ubo.directional_light_count = 0; if (shader_data->uses_light) { - sky_scene_state.ubo.directional_light_count = 0; // Run through the list of lights in the scene and pick out the Directional Lights. // This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called // after the depth prepass, but this runs before the depth prepass @@ -1320,7 +1323,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, // Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader. - if (shader_data->uses_quarter_res) { + if (shader_data->uses_quarter_res && roughness_layers >= 3) { RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap"); PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; @@ -1337,9 +1340,11 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); + } else if (shader_data->uses_quarter_res && roughness_layers < 3) { + ERR_PRINT_ED("Cannot use quarter res buffer in sky shader when roughness layers is less than 3. Please increase rendering/reflections/sky_reflections/roughness_layers."); } - if (shader_data->uses_half_res) { + if (shader_data->uses_half_res && roughness_layers >= 2) { RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap"); PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES]; @@ -1356,6 +1361,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); + } else if (shader_data->uses_half_res && roughness_layers < 2) { + ERR_PRINT_ED("Cannot use half res buffer in sky shader when roughness layers is less than 2. Please increase rendering/reflections/sky_reflections/roughness_layers."); } RD::DrawListID cubemap_draw_list; @@ -1627,7 +1634,10 @@ void SkyRD::update_dirty_skys() { tf.mipmaps = mipmaps; tf.width = w; tf.height = h; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; + } sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -1642,7 +1652,10 @@ void SkyRD::update_dirty_skys() { tf.mipmaps = MIN(mipmaps, layers); tf.width = w; tf.height = h; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) { + tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; + } sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 85b5ef5e09..59e1f559c7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -667,7 +667,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { scene_state.ubo.ss_effects_flags = 0; - } else if (is_environment(p_render_data->environment)) { + } else if (p_render_data->reflection_probe.is_null() && is_environment(p_render_data->environment)) { scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment); scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment); uint32_t ss_flags = 0; @@ -1232,9 +1232,9 @@ void RenderForwardClustered::_update_volumetric_fog(Ref<RenderSceneBuffersRD> p_ /* Lighting */ -void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) { +void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) { if (current_cluster_builder != nullptr) { - current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_extents); + current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_size); } } @@ -1244,9 +1244,9 @@ void RenderForwardClustered::setup_added_light(const RS::LightType p_type, const } } -void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) { +void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) { if (current_cluster_builder != nullptr) { - current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_extents); + current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_size); } } @@ -1365,8 +1365,8 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo } //cube shadows are rendered in their own way - for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + for (const int &index : p_render_data->cube_shadows) { + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); } if (p_render_data->directional_shadows.size()) { @@ -1480,7 +1480,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo uint32_t directional_light_count = 0; uint32_t positional_light_count = 0; light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); - texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); + texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform); p_render_data->directional_light_count = directional_light_count; @@ -1550,16 +1550,18 @@ void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buf void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - Ref<RenderSceneBuffersRD> rb; + ERR_FAIL_NULL(p_render_data); + + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); Ref<RenderBufferDataForwardClustered> rb_data; - if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = p_render_data->render_buffers; - if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) { - // Our forward clustered custom data buffer will only be available when we're rendering our normal view. - // This will not be available when rendering reflection probes. - rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); - } + if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) { + // Our forward clustered custom data buffer will only be available when we're rendering our normal view. + // This will not be available when rendering reflection probes. + rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); } + bool is_reflection_probe = p_render_data->reflection_probe.is_valid(); + static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; //first of all, make a new render pass @@ -1588,18 +1590,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co p_render_data->voxel_gi_count = 0; - if (rb.is_valid()) { - if (rb->has_custom_data(RB_SCOPE_SDFGI)) { - Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); - if (sdfgi.is_valid()) { - sdfgi->update_cascades(); - sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data); - sdfgi->update_light(); - } + if (rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + if (sdfgi.is_valid()) { + sdfgi->update_cascades(); + sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data); + sdfgi->update_light(); } - - gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count); } + + gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count); } else { ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash current_cluster_builder = nullptr; @@ -1618,7 +1618,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co // check if we need motion vectors if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { p_render_data->scene_data->calculate_motion_vectors = true; - } else if (rb.is_valid() && rb->get_use_taa()) { + } else if (!is_reflection_probe && rb->get_use_taa()) { p_render_data->scene_data->calculate_motion_vectors = true; } else { p_render_data->scene_data->calculate_motion_vectors = false; @@ -1641,9 +1641,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool using_sdfgi = false; bool using_voxelgi = false; bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0; - bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); + bool using_ssil = !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; @@ -1657,7 +1657,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } reverse_cull = true; // for some reason our views are inverted - } else if (rb.is_valid()) { + } else { screen_size = rb->get_internal_size(); if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { @@ -1668,39 +1668,15 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co using_voxelgi = true; } - if (p_render_data->environment.is_null() && using_voxelgi) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; - } else if (p_render_data->environment.is_valid() && (environment_get_ssr_enabled(p_render_data->environment) || environment_get_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { + if (p_render_data->environment.is_valid()) { if (environment_get_sdfgi_enabled(p_render_data->environment)) { - depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi using_sdfgi = true; - } else { - depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } if (environment_get_ssr_enabled(p_render_data->environment)) { using_separate_specular = true; using_ssr = true; color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; } - } else if (p_render_data->environment.is_valid() && (environment_get_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; - } - - switch (depth_pass_mode) { - case PASS_MODE_DEPTH: { - depth_framebuffer = rb_data->get_depth_fb(); - } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS); - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); - } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { - depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS_VOXELGI); - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); - depth_pass_clear.push_back(Color(0, 0, 0, 0)); - } break; - default: { - }; } if (p_render_data->scene_data->view_count > 1) { @@ -1709,8 +1685,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); color_only_framebuffer = rb_data->get_color_only_fb(); - } else { - ERR_FAIL(); //bug? } p_render_data->scene_data->emissive_exposure_normalization = -1.0; @@ -1719,7 +1693,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform); _setup_voxelgis(*p_render_data->voxel_gi_instances); - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) @@ -1731,7 +1705,39 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); - bool using_sss = rb_data.is_valid() && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; + if (!is_reflection_probe) { + if (using_voxelgi) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; + } else if (p_render_data->environment.is_valid()) { + if (environment_get_ssr_enabled(p_render_data->environment) || + environment_get_sdfgi_enabled(p_render_data->environment) || + environment_get_ssao_enabled(p_render_data->environment) || + using_ssil || + get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER || + scene_state.used_normal_texture) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; + } + } + + switch (depth_pass_mode) { + case PASS_MODE_DEPTH: { + depth_framebuffer = rb_data->get_depth_fb(); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS); + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { + depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS_VOXELGI); + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + depth_pass_clear.push_back(Color(0, 0, 0, 0)); + } break; + default: { + }; + } + } + + bool using_sss = rb_data.is_valid() && !is_reflection_probe && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; if (using_sss && !using_separate_specular) { using_separate_specular = true; @@ -1764,7 +1770,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { + if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1774,7 +1780,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy_multiplier; clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; - if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { + if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear())); } @@ -1783,7 +1789,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co draw_sky = true; } break; case RS::ENV_BG_CANVAS: { - if (rb.is_valid()) { + if (!is_reflection_probe) { RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target()); copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true); } @@ -1804,7 +1810,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Setup Sky"); // Setup our sky render information for this frame/viewport - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { Vector3 eye_offset; Projection correction; correction.set_depth_correction(true); @@ -1841,7 +1847,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid(); - bool using_ssao = depth_pre_pass && rb.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); + bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); bool continue_depth = false; if (depth_pre_pass) { //depth pre pass @@ -1873,7 +1879,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi); } - if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)"); RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)"); if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) { @@ -1907,14 +1913,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count; p_render_data->scene_data->opaque_prepass_threshold = 0.0f; - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, rb.is_valid()); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true); RENDER_TIMESTAMP("Render Opaque Pass"); RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true); bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss; - bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; + bool can_continue_depth = !(scene_state.used_depth_texture || scene_state.used_normal_texture) && !using_ssr && !using_sss; { bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes); @@ -1988,7 +1994,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); } - if (rb.is_valid() && !can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (!can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass. for (uint32_t v = 0; v < rb->get_view_count(); v++) { RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v)); @@ -2000,7 +2006,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } } - if (rb.is_valid() && !can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + if (!can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { for (uint32_t v = 0; v < rb->get_view_count(); v++) { resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); } @@ -2046,7 +2052,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true); - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); { uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR); @@ -2407,8 +2413,7 @@ void RenderForwardClustered::_render_shadow_process() { void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_begin_label("Shadow Render"); - for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { - SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; + for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) { RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); } @@ -2610,8 +2615,8 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - Vector3 half_extents = p_bounds.size * 0.5; - Vector3 center = p_bounds.position + half_extents; + Vector3 half_size = p_bounds.size * 0.5; + Vector3 center = p_bounds.position + half_size; Vector<RID> sbs = { p_albedo_texture, @@ -2639,16 +2644,16 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu fb_size.x = p_size[right_axis]; fb_size.y = p_size[up_axis]; - scene_data.cam_transform.origin = center + axis * half_extents; + scene_data.cam_transform.origin = center + axis * half_size; scene_data.cam_transform.basis.set_column(0, right); scene_data.cam_transform.basis.set_column(1, up); scene_data.cam_transform.basis.set_column(2, axis); //print_line("pass: " + itos(i) + " xform " + scene_data.cam_transform); - float h_size = half_extents[right_axis]; - float v_size = half_extents[up_axis]; - float d_size = half_extents[i] * 2.0; + float h_size = half_size[right_axis]; + float v_size = half_size[up_axis]; + float d_size = half_size[i] * 2.0; scene_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size); //print_line("pass: " + itos(i) + " cam hsize: " + rtos(h_size) + " vsize: " + rtos(v_size) + " dsize " + rtos(d_size)); @@ -3368,9 +3373,7 @@ int RenderForwardClustered::sdfgi_get_pending_region_count(const Ref<RenderScene Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); int dirty_count = 0; - for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { - const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i]; - + for (const RendererRD::GI::SDFGI::Cascade &c : sdfgi->cascades) { if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) { dirty_count++; } else { @@ -3436,7 +3439,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = (p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha; + bool has_base_alpha = (p_material->shader_data->uses_alpha && (!p_material->shader_data->uses_alpha_clip || p_material->shader_data->uses_alpha_antialiasing)) || has_read_screen_alpha; bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; bool has_alpha = has_base_alpha || has_blend_alpha; @@ -3465,7 +3468,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; - if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED)) { + if ((p_material->shader_data->uses_depth_prepass_alpha || p_material->shader_data->uses_alpha_antialiasing) && !(p_material->shader_data->depth_draw == SceneShaderForwardClustered::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardClustered::ShaderData::DEPTH_TEST_DISABLED)) { flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; } @@ -3481,7 +3484,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet SceneShaderForwardClustered::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_alpha_antialiasing && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); @@ -3763,6 +3766,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D case Dependency::DEPENDENCY_CHANGED_MULTIMESH: case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); + static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata)->data->dirty_dependencies = true; } break; case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); @@ -3777,6 +3781,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D } void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); + static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata)->data->dirty_dependencies = true; } RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) { @@ -3999,11 +4004,11 @@ RenderForwardClustered::~RenderForwardClustered() { RSG::light_storage->directional_shadow_atlas_set_size(0); { - for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) { - RD::get_singleton()->free(scene_state.uniform_buffers[i]); + for (const RID &rid : scene_state.uniform_buffers) { + RD::get_singleton()->free(rid); } - for (uint32_t i = 0; i < scene_state.implementation_uniform_buffers.size(); i++) { - RD::get_singleton()->free(scene_state.implementation_uniform_buffers[i]); + for (const RID &rid : scene_state.implementation_uniform_buffers) { + RD::get_singleton()->free(rid); } RD::get_singleton()->free(scene_state.lightmap_buffer); RD::get_singleton()->free(scene_state.lightmap_capture_buffer); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 9245f1b13a..8eb17ba6f4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -640,9 +640,9 @@ public: RendererRD::SSEffects *get_ss_effects() { return ss_effects; } /* callback from updating our lighting UBOs, used to populate cluster builder */ - virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) override; + virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) override; virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) override; - virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) override; + virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) override; virtual void base_uniforms_changed() override; _FORCE_INLINE_ virtual void update_uniform_sets() override { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 9117320eab..3b3979b198 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -44,7 +44,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { valid = false; ubo_size = 0; uniforms.clear(); - uses_screen_texture = false; if (code.is_empty()) { return; //just invalid, but no error @@ -60,6 +59,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { uses_point_size = false; uses_alpha = false; uses_alpha_clip = false; + uses_alpha_antialiasing = false; uses_blend_alpha = false; uses_depth_prepass_alpha = false; uses_discard = false; @@ -72,9 +72,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { uses_position = false; uses_sss = false; uses_transmittance = false; - uses_screen_texture = false; - uses_depth_texture = false; - uses_normal_texture = false; uses_time = false; writes_modelview_or_projection = false; uses_world_coordinates = false; @@ -111,17 +108,14 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["ALPHA"] = &uses_alpha; actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; - // Use alpha clip pipeline for alpha hash/dither. - // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; + actions.usage_flag_pointers["ALPHA_ANTIALIASING_EDGE"] = &uses_alpha_antialiasing; + actions.usage_flag_pointers["ALPHA_TEXTURE_COORDINATE"] = &uses_alpha_antialiasing; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_prepass_alpha; actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; actions.usage_flag_pointers["DISCARD"] = &uses_discard; actions.usage_flag_pointers["TIME"] = &uses_time; actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; @@ -150,6 +144,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { depth_test = DepthTest(depth_testi); cull_mode = Cull(cull_modei); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; + uses_depth_texture = gen_code.uses_depth_texture; + uses_normal_texture = gen_code.uses_normal_roughness_texture; uses_vertex_time = gen_code.uses_vertex_time; uses_fragment_time = gen_code.uses_fragment_time; @@ -309,14 +306,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; - if (depth_pre_pass_enabled && casts_shadows() && !uses_depth_prepass_alpha) { - // We already have a depth from the depth pre-pass, there is no need to write it again. - // In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL. - // This way we can use the early depth test to discard transparent fragments before the fragment shader even starts. - // This cannot be used with depth_prepass_alpha as it uses a different threshold during the depth-prepass and regular drawing. - depth_stencil.depth_compare_operator = RD::COMPARE_OP_EQUAL; - depth_stencil.enable_depth_write = false; - } RD::PipelineColorBlendState blend_state; RD::PipelineMultisampleState multisample_state; @@ -338,6 +327,14 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } else { blend_state = blend_state_color_opaque; + if (depth_pre_pass_enabled) { + // We already have a depth from the depth pre-pass, there is no need to write it again. + // In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL. + // This way we can use the early depth test to discard transparent fragments before the fragment shader even starts. + depth_stencil.depth_compare_operator = RD::COMPARE_OP_EQUAL; + depth_stencil.enable_depth_write = false; + } + if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) { shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR; } @@ -356,6 +353,11 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } int variant = shader_version + shader_flags; + + if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(variant)) { + continue; + } + RID shader_variant = shader_singleton->shader.version_get_shader(version, variant); color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants); } @@ -392,7 +394,7 @@ bool SceneShaderForwardClustered::ShaderData::is_animated() const { bool SceneShaderForwardClustered::ShaderData::casts_shadows() const { bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture; - bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; + bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha; bool has_alpha = has_base_alpha || uses_blend_alpha; return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); @@ -506,7 +508,14 @@ void SceneShaderForwardClustered::init(const String p_defines) { shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false); shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, false); shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, false); - // TODO Add a way to enable/disable color pass flags + + // Disable Color Passes + for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) { + // Selectively disable any shader pass that includes Multiview. + if ((i & SHADER_COLOR_PASS_FLAG_MULTIVIEW)) { + shader.set_variant_enabled(i + SHADER_VERSION_COLOR_PASS, false); + } + } } } @@ -606,9 +615,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["POINT_COORD"] = "gl_PointCoord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "color_buffer"; - actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; actions.renames["FOG"] = "fog"; @@ -631,6 +637,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; + actions.renames["EYE_OFFSET"] = "eye_offset"; //for light actions.renames["VIEW"] = "view"; @@ -673,7 +680,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; @@ -706,10 +712,6 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps - actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]"; - actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter - actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; @@ -728,6 +730,8 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.global_buffer_array_variable = "global_shader_uniforms.data"; actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs"; + actions.check_multiview_samplers = true; // make sure we check sampling multiview textures + compiler.initialize(actions); } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index 1169ae784c..ffaf091b36 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -153,6 +153,7 @@ public: bool uses_alpha = false; bool uses_blend_alpha = false; bool uses_alpha_clip = false; + bool uses_alpha_antialiasing = false; bool uses_depth_prepass_alpha = false; bool uses_discard = false; bool uses_roughness = false; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 72857cdea7..f9529de6dd 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -251,7 +251,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe Size2i target_size = render_buffers->get_target_size(); Size2i internal_size = render_buffers->get_internal_size(); - // can't do our blit pass if resolutions don't match + // can't do our blit pass if resolutions don't match, this should already have been checked. ERR_FAIL_COND_V(target_size != internal_size, RID()); // - opaque pass @@ -579,8 +579,8 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { } //cube shadows are rendered in their own way - for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + for (const int &index : p_render_data->cube_shadows) { + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); } if (p_render_data->directional_shadows.size()) { @@ -593,12 +593,10 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size(); + //prepare shadow rendering if (render_shadows) { RENDER_TIMESTAMP("Render Shadows"); - } - //prepare shadow rendering - if (render_shadows) { _render_shadow_begin(); //render directional shadows @@ -632,7 +630,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { uint32_t directional_light_count = 0; uint32_t positional_light_count = 0; light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); - texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); + texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform); p_render_data->directional_light_count = directional_light_count; } @@ -640,16 +638,18 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - Ref<RenderSceneBuffersRD> rb; + ERR_FAIL_NULL(p_render_data); + + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); + Ref<RenderBufferDataForwardMobile> rb_data; - if (p_render_data->render_buffers.is_valid()) { - rb = p_render_data->render_buffers; - if (rb->has_custom_data(RB_SCOPE_MOBILE)) { - // Our forward mobile custom data buffer will only be available when we're rendering our normal view. - // This will not be available when rendering reflection probes. - rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); - } + if (rb->has_custom_data(RB_SCOPE_MOBILE)) { + // Our forward mobile custom data buffer will only be available when we're rendering our normal view. + // This will not be available when rendering reflection probes. + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); } + bool is_reflection_probe = p_render_data->reflection_probe.is_valid(); RENDER_TIMESTAMP("Prepare 3D Scene"); @@ -697,7 +697,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size(); } - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; @@ -715,20 +715,26 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // setup rendering to render buffer screen_size = p_render_data->render_buffers->get_internal_size(); - if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) { - // can't do blit subpass + if (rb->get_scaling_3d_mode() != RS::VIEWPORT_SCALING_3D_MODE_OFF) { + // can't do blit subpass because we're scaling using_subpass_post_process = false; } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) { - // can't do blit subpass + // can't do blit subpass because we're using post processes using_subpass_post_process = false; } if (scene_state.used_screen_texture || scene_state.used_depth_texture) { - // can't use our last two subpasses + // can't use our last two subpasses because we're reading from screen texture or depth texture using_subpass_transparent = false; using_subpass_post_process = false; } + // We do this last because our get_color_fbs creates and caches the framebuffer if we need it. + if (using_subpass_post_process && rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) { + // can't do blit subpass because we don't have all subpasses + using_subpass_post_process = false; + } + if (using_subpass_post_process) { // all as subpasses framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES); @@ -748,7 +754,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Render Setup"); _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform); - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) @@ -826,7 +832,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Setup Sky"); // Setup our sky render information for this frame/viewport - if (p_render_data->reflection_probe.is_valid()) { + if (is_reflection_probe) { Vector3 eye_offset; Projection correction; correction.set_depth_correction(true); @@ -890,7 +896,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count; - _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid()); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, p_render_data->render_buffers.is_valid()); if (using_subpass_transparent && using_subpass_post_process) { RENDER_TIMESTAMP("Render Opaque + Transparent + Tonemap"); @@ -1019,7 +1025,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } // this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation - // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); + // _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); @@ -1059,9 +1065,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _disable_clear_request(p_render_data); } - if (rb.is_valid()) { - _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); - } + _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); } /* these are being called from RendererSceneRenderRD::_pre_opaque_render */ @@ -1334,8 +1338,7 @@ void RenderForwardMobile::_render_shadow_process() { void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) { RD::get_singleton()->draw_command_begin_label("Shadow Render"); - for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { - SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; + for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) { RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER); _render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect); } @@ -1919,7 +1922,6 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { - Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers; RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID(); RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); @@ -2232,6 +2234,9 @@ RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base ginstance->data->base = p_base; ginstance->data->base_type = type; + ginstance->data->dependency_tracker.userdata = ginstance; + ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed; + ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted; ginstance->_mark_dirty(); @@ -2349,9 +2354,9 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha); + bool has_base_alpha = p_material->shader_data->uses_alpha && (!p_material->shader_data->uses_alpha_clip || p_material->shader_data->uses_alpha_antialiasing); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; - bool has_alpha = has_base_alpha || has_blend_alpha; + bool has_alpha = has_base_alpha || has_blend_alpha || has_read_screen_alpha; uint32_t flags = 0; @@ -2375,10 +2380,10 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS; } - if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED) { + if (has_alpha || p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED) { //material is only meant for alpha pass flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; - if (p_material->shader_data->uses_depth_prepass_alpha && !(p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED)) { + if ((p_material->shader_data->uses_depth_prepass_alpha || p_material->shader_data->uses_alpha_antialiasing) && !(p_material->shader_data->depth_draw == SceneShaderForwardMobile::ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == SceneShaderForwardMobile::ShaderData::DEPTH_TEST_DISABLED)) { flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; } @@ -2394,7 +2399,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI SceneShaderForwardMobile::MaterialData *material_shadow = nullptr; void *surface_shadow = nullptr; - if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip) { + if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_prepass_alpha && !p_material->shader_data->uses_alpha_clip && !p_material->shader_data->uses_alpha_antialiasing) { flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); @@ -2668,6 +2673,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe case Dependency::DEPENDENCY_CHANGED_MULTIMESH: case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); + static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata)->data->dirty_dependencies = true; } break; case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata); @@ -2682,6 +2688,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe } void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty(); + static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata)->data->dirty_dependencies = true; } /* misc */ @@ -2804,8 +2811,8 @@ RenderForwardMobile::~RenderForwardMobile() { } { - for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) { - RD::get_singleton()->free(scene_state.uniform_buffers[i]); + for (const RID &rid : scene_state.uniform_buffers) { + RD::get_singleton()->free(rid); } RD::get_singleton()->free(scene_state.lightmap_buffer); RD::get_singleton()->free(scene_state.lightmap_capture_buffer); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 2e9a33a636..cc4a7dfa47 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -46,7 +46,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { valid = false; ubo_size = 0; uniforms.clear(); - uses_screen_texture = false; if (code.is_empty()) { return; //just invalid, but no error @@ -62,6 +61,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { uses_point_size = false; uses_alpha = false; uses_alpha_clip = false; + uses_alpha_antialiasing = false; uses_blend_alpha = false; uses_depth_prepass_alpha = false; uses_discard = false; @@ -73,9 +73,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { uses_vertex = false; uses_sss = false; uses_transmittance = false; - uses_screen_texture = false; - uses_depth_texture = false; - uses_normal_texture = false; uses_time = false; writes_modelview_or_projection = false; uses_world_coordinates = false; @@ -112,17 +109,14 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { actions.usage_flag_pointers["ALPHA"] = &uses_alpha; actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip; - // Use alpha clip pipeline for alpha hash/dither. - // This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows. actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip; + actions.usage_flag_pointers["ALPHA_ANTIALIASING_EDGE"] = &uses_alpha_antialiasing; + actions.usage_flag_pointers["ALPHA_TEXTURE_COORDINATE"] = &uses_alpha_antialiasing; actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_prepass_alpha; // actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; // actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance; - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; actions.usage_flag_pointers["DISCARD"] = &uses_discard; actions.usage_flag_pointers["TIME"] = &uses_time; actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; @@ -151,6 +145,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { depth_test = DepthTest(depth_testi); uses_vertex_time = gen_code.uses_vertex_time; uses_fragment_time = gen_code.uses_fragment_time; + uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; + uses_depth_texture = gen_code.uses_depth_texture; + uses_normal_texture = gen_code.uses_normal_roughness_texture; #if 0 print_line("**compiling shader:"); @@ -338,7 +336,7 @@ bool SceneShaderForwardMobile::ShaderData::is_animated() const { bool SceneShaderForwardMobile::ShaderData::casts_shadows() const { bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture; - bool has_base_alpha = (uses_alpha && !uses_alpha_clip) || has_read_screen_alpha; + bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha; bool has_alpha = has_base_alpha || uses_blend_alpha; return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED)); @@ -497,9 +495,6 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["POINT_COORD"] = "gl_PointCoord"; actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "color_buffer"; - actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; actions.renames["FOG"] = "fog"; @@ -522,6 +517,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["VIEW_INDEX"] = "ViewIndex"; actions.renames["VIEW_MONO_LEFT"] = "0"; actions.renames["VIEW_RIGHT"] = "1"; + actions.renames["EYE_OFFSET"] = "eye_offset"; //for light actions.renames["VIEW"] = "view"; @@ -564,7 +560,6 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; @@ -615,6 +610,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs"; actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture + actions.check_multiview_samplers = true; // make sure we check sampling multiview textures compiler.initialize(actions); } diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 99f252b9ca..6f1f00cedc 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -114,6 +114,7 @@ public: bool uses_alpha = false; bool uses_blend_alpha = false; bool uses_alpha_clip = false; + bool uses_alpha_antialiasing = false; bool uses_depth_prepass_alpha = false; bool uses_discard = false; bool uses_roughness = false; @@ -127,6 +128,7 @@ public: bool uses_screen_texture = false; bool uses_depth_texture = false; bool uses_normal_texture = false; + bool uses_screen_texture_mipmaps = false; bool uses_time = false; bool uses_vertex_time = false; bool uses_fragment_time = false; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 0c6dcb553a..f102bc0650 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -455,7 +455,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend light_count++; - if (light_count == MAX_LIGHTS_PER_ITEM) { + if (light_count == MAX_LIGHTS_PER_ITEM - 1) { break; } } @@ -525,10 +525,12 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend if (rect->flags & CANVAS_RECT_FLIP_H) { src_rect.size.x *= -1; + push_constant.flags |= FLAGS_FLIP_H; } if (rect->flags & CANVAS_RECT_FLIP_V) { src_rect.size.y *= -1; + push_constant.flags |= FLAGS_FLIP_V; } if (rect->flags & CANVAS_RECT_TRANSPOSE) { @@ -1429,6 +1431,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c); if (cm->mesh_instance.is_valid()) { mesh_storage->mesh_instance_check_for_update(cm->mesh_instance); + mesh_storage->mesh_instance_set_canvas_item_transform(cm->mesh_instance, canvas_transform_inverse * ci->final_transform); update_skeletons = true; } } @@ -1547,6 +1550,9 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) { if (cl->texture == p_texture) { return; } + + ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture)); + if (cl->texture.is_valid()) { texture_storage->texture_remove_from_decal_atlas(cl->texture); } @@ -2034,7 +2040,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA); actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED); - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; actions.usage_flag_pointers["texture_sdf"] = &uses_sdf; actions.usage_flag_pointers["TIME"] = &uses_time; @@ -2046,6 +2051,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed."); uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps; + uses_screen_texture = gen_code.uses_screen_texture; if (version.is_null()) { version = canvas_singleton->shader.canvas_shader.version_create(); @@ -2423,7 +2429,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture"; actions.renames["SPECULAR_SHININESS"] = "specular_shininess"; actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "screen_texture"; actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["POINT_COORD"] = "gl_PointCoord"; @@ -2444,7 +2449,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf"; actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; @@ -2459,7 +2463,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { actions.custom_samplers["TEXTURE"] = "texture_sampler"; actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler"; actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler"; - actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; actions.texture_layout_set = MATERIAL_UNIFORM_SET; @@ -2631,9 +2634,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { // Default CanvasGroup shader. shader_type canvas_item; +render_mode unshaded; + +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); if (c.a > 0.0001) { c.rgb /= c.a; @@ -2656,9 +2662,12 @@ void fragment() { // Default clip children shader. shader_type canvas_item; +render_mode unshaded; + +uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest; void fragment() { - vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0); + vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0); COLOR.rgb = c.rgb; } )"); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 266083fc49..7dea4a1a65 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -86,6 +86,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_USE_MSDF = (1 << 28), FLAGS_USE_LCD = (1 << 29), + + FLAGS_FLIP_H = (1 << 30), + FLAGS_FLIP_V = (1 << 31), }; enum { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index d426c4fc2e..5776414b14 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -249,61 +249,15 @@ Ref<RenderSceneBuffers> RendererSceneRenderRD::render_buffers_create() { return rb; } -void RendererSceneRenderRD::_allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb) { - ERR_FAIL_COND(!rb->luminance.current.is_null()); - - Size2i internal_size = rb->get_internal_size(); - int w = internal_size.x; - int h = internal_size.y; - - while (true) { - w = MAX(w / 8, 1); - h = MAX(h / 8, 1); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = w; - tf.height = h; - - bool final = w == 1 && h == 1; - - 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::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) { Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); + if (!rb->has_internal_texture()) { + // We're likely rendering reflection probes where we can't use our backbuffers. + return; + } + RD::get_singleton()->draw_command_begin_label("Copy screen texture"); rb->allocate_blur_textures(); @@ -326,7 +280,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData for (int i = 1; i < mipmaps; i++) { RID source = dest; dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i); - Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i); + Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i); if (can_use_storage) { copy_effects->make_mipmap(source, dest, msize); @@ -343,6 +297,11 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); + if (!rb->has_depth_texture()) { + // We're likely rendering reflection probes where we can't use our backbuffers. + return; + } + RD::get_singleton()->draw_command_begin_label("Copy depth texture"); // note, this only creates our back depth texture if we haven't already created it. @@ -372,9 +331,13 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL(p_render_data); + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); + ERR_FAIL_COND_MSG(p_render_data->reflection_probe.is_valid(), "Post processes should not be applied on reflection probes."); + // Glow, auto exposure and DoF (if enabled). Size2i internal_size = rb->get_internal_size(); @@ -443,9 +406,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RENDER_TIMESTAMP("Auto exposure"); RD::get_singleton()->draw_command_begin_label("Auto exposure"); - if (rb->luminance.current.is_null()) { - _allocate_luminance_textures(rb); - } + + Ref<RendererRD::Luminance::LuminanceBuffers> luminance_buffers = luminance->get_luminance_buffers(rb); + uint64_t auto_exposure_version = RSG::camera_attributes->camera_attributes_get_auto_exposure_version(p_render_data->camera_attributes); bool set_immediate = auto_exposure_version != rb->get_auto_exposure_version(); rb->set_auto_exposure_version(auto_exposure_version); @@ -453,16 +416,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step; float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes); float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes); - if (can_use_storage) { - RendererCompositorRD::singleton->get_effects()->luminance_reduction(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); - } else { - RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); - } + luminance->luminance_reduction(internal_texture, internal_size, luminance_buffers, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, 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]); - } auto_exposure_scale = RSG::camera_attributes->camera_attributes_get_auto_exposure_scale(p_render_data->camera_attributes); @@ -492,12 +448,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende float luminance_multiplier = _render_buffers_get_luminance_multiplier(); for (uint32_t l = 0; l < rb->get_view_count(); l++) { for (int i = 0; i < (max_glow_level + 1); i++) { - Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); + Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i); if (i == 0) { RID luminance_texture; - if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) { - luminance_texture = rb->luminance.current; + if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) { + luminance_texture = luminance->get_current_luminance_buffer(rb); // this will return and empty RID if we don't have an auto exposure buffer } RID source = rb->get_internal_texture(l); RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); @@ -530,9 +486,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RendererRD::ToneMapper::TonemapSettings tonemap; - if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) { + tonemap.exposure_texture = luminance->get_current_luminance_buffer(rb); + if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && tonemap.exposure_texture.is_valid()) { tonemap.use_auto_exposure = true; - tonemap.exposure_texture = rb->luminance.current; tonemap.auto_exposure_scale = auto_exposure_scale; } else { tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); @@ -546,7 +502,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i]; } - Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0); + Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0); tonemap.glow_texture_size.x = msize.width; tonemap.glow_texture_size.y = msize.height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; @@ -597,7 +553,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.view_count = rb->get_view_count(); RID dest_fb; - if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) { + if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) { // If we use FSR to upscale we need to write our result into an intermediate buffer. // Note that this is cached so we only create the texture the first time. RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT); @@ -614,10 +570,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RD::get_singleton()->draw_command_end_label(); } - if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) { - // TODO Investigate? Does this work? We never write into our render target and we've already done so up above in our tonemapper. - // I think FSR should either work before our tonemapper or as an alternative of our tonemapper. - + if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) { RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); for (uint32_t v = 0; v < rb->get_view_count(); v++) { @@ -746,10 +699,11 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) { - if (p_render_buffers->luminance.current.is_valid()) { + RID luminance_texture = luminance->get_current_luminance_buffer(p_render_buffers); + if (luminance_texture.is_valid()) { Size2i rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(p_render_buffers->luminance.current, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true); + copy_effects->copy_to_fb_rect(luminance_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true); } } @@ -978,11 +932,9 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); // getting this here now so we can direct call a bunch of things more easily - Ref<RenderSceneBuffersRD> rb; - if (p_render_buffers.is_valid()) { - rb = p_render_buffers; // cast it... - ERR_FAIL_COND(rb.is_null()); - } + ERR_FAIL_COND(p_render_buffers.is_null()); + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND(rb.is_null()); // setup scene data RenderSceneDataRD scene_data; @@ -1334,6 +1286,7 @@ void RendererSceneRenderRD::init() { bool can_use_vrs = is_vrs_supported(); bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); + luminance = memnew(RendererRD::Luminance(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); if (can_use_vrs) { vrs = memnew(RendererRD::VRS); @@ -1354,6 +1307,9 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { if (copy_effects) { memdelete(copy_effects); } + if (luminance) { + memdelete(luminance); + } if (tone_mapper) { memdelete(tone_mapper); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 54f068c314..7c43021eb0 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -38,6 +38,7 @@ #include "servers/rendering/renderer_rd/effects/bokeh_dof.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/effects/fsr.h" +#include "servers/rendering/renderer_rd/effects/luminance.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" #include "servers/rendering/renderer_rd/effects/vrs.h" #include "servers/rendering/renderer_rd/environment/fog.h" @@ -105,6 +106,7 @@ protected: RendererRD::ForwardIDStorage *forward_id_storage = nullptr; RendererRD::BokehDOF *bokeh_dof = nullptr; RendererRD::CopyEffects *copy_effects = nullptr; + RendererRD::Luminance *luminance = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; RendererRD::FSR *fsr = nullptr; RendererRD::VRS *vrs = nullptr; @@ -180,9 +182,6 @@ private: /* RENDER BUFFERS */ - // TODO move into effects/luminance.h/cpp - void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb); - /* GI */ bool screen_space_roughness_limiter = false; float screen_space_roughness_limiter_amount = 0.25; @@ -205,9 +204,9 @@ public: /* LIGHTING */ - virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents){}; + virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size){}; virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture){}; - virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents){}; + virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size){}; /* GI */ diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index ab64ae1055..533a912a34 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -33,6 +33,7 @@ #include "core/io/compression.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/version.h" #include "renderer_compositor_rd.h" #include "servers/rendering/rendering_device.h" #include "thirdparty/misc/smolv.h" @@ -116,6 +117,10 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con } StringBuilder tohash; + tohash.append("[GodotVersionNumber]"); + tohash.append(VERSION_NUMBER); + tohash.append("[GodotVersionHash]"); + tohash.append(VERSION_HASH); tohash.append("[SpirvCacheKey]"); tohash.append(RenderingDevice::get_singleton()->shader_get_spirv_cache_key()); tohash.append("[BinaryCacheKey]"); @@ -160,8 +165,7 @@ void ShaderRD::_clear_version(Version *p_version) { } void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, const Version *p_version, const StageTemplate &p_template) { - for (uint32_t i = 0; i < p_template.chunks.size(); i++) { - const StageTemplate::Chunk &chunk = p_template.chunks[i]; + for (const StageTemplate::Chunk &chunk : p_template.chunks) { switch (chunk.type) { case StageTemplate::Chunk::TYPE_VERSION_DEFINES: { builder.append("\n"); //make sure defines begin at newline diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index eb5f68849e..1fb8b28b15 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -502,6 +502,12 @@ void main() { if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); + if (bool(draw_data.flags & FLAGS_FLIP_H)) { + normal.x = -normal.x; + } + if (bool(draw_data.flags & FLAGS_FLIP_V)) { + normal.y = -normal.y; + } normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); normal_used = true; } else { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 1b627a3e81..a904f4e0a6 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -27,6 +27,9 @@ #define FLAGS_USE_MSDF (1 << 28) #define FLAGS_USE_LCD (1 << 29) +#define FLAGS_FLIP_H (1 << 30) +#define FLAGS_FLIP_V (1 << 31) + #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 #define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 @@ -134,7 +137,7 @@ layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture; layout(set = 0, binding = 5) uniform sampler shadow_sampler; -layout(set = 0, binding = 6) uniform texture2D screen_texture; +layout(set = 0, binding = 6) uniform texture2D color_buffer; layout(set = 0, binding = 7) uniform texture2D sdf_texture; layout(set = 0, binding = 8) uniform sampler material_samplers[12]; diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl index 0ee4cf6e31..0ee4cf6e31 100644 --- a/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl index 29ebd74a90..29ebd74a90 100644 --- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl index b8860f6518..b8860f6518 100644 --- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl index 134aae5ce7..b1ff46dd3b 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl @@ -56,7 +56,7 @@ vec4 screen_space_to_view_space_depth(vec4 p_depth) { float depth_linearize_mul = params.z_near; float depth_linearize_add = params.z_far; - // Optimised version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar" + // Optimized version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar" // Set your depth_linearize_mul and depth_linearize_add to: // depth_linearize_mul = ( cameraClipFar * cameraClipNear) / ( cameraClipFar - cameraClipNear ); diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl index 2a87e273bc..ffaa6872c9 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl @@ -221,7 +221,7 @@ void SSAOTap(const int p_quality_level, inout float r_obscurance_sum, inout floa // snap to pixel center (more correct obscurance math, avoids artifacts) sample_offset = round(sample_offset); - // calculate MIP based on the sample distance from the centre, similar to as described + // calculate MIP based on the sample distance from the center, similar to as described // in http://graphics.cs.williams.edu/papers/SAOHPG12/. float mip_level = (p_quality_level < SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset); @@ -259,7 +259,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o // get this pixel's viewspace depth pix_z = valuesUL.y; - // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0) + // get left right top bottom neighboring pixels for edge detection (gets compiled out on quality_level == 0) pix_left_z = valuesUL.x; pix_top_z = valuesUL.z; pix_right_z = valuesBR.z; @@ -304,7 +304,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o float obscurance_sum = 0.0; float weight_sum = 0.0; - // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge) + // edge mask for between this and left/right/top/bottom neighbor pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge) vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0); // Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats @@ -318,7 +318,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o if (!p_adaptive_base && (p_quality_level >= SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET)) { // disable in case of quality level 4 (reference) if (p_quality_level != 4) { - //approximate neighbouring pixels positions (actually just deltas or "positions - pix_center_pos" ) + //approximate neighboring pixels positions (actually just deltas or "positions - pix_center_pos" ) vec3 normalized_viewspace_dir = vec3(pix_center_pos.xy / pix_center_pos.zz, 1.0); vec3 pixel_left_delta = vec3(-pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_left_z - pix_center_pos.z); vec3 pixel_right_delta = vec3(+pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_right_z - pix_center_pos.z); diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl index 04f98964e8..d234ab4417 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl @@ -80,7 +80,7 @@ void main() { #ifdef PROCESS_MAPA vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0; - float centre = textureLod(source_importance, uv, 0.0).x; + float center = textureLod(source_importance, uv, 0.0).x; vec2 half_pixel = params.half_screen_pixel_size; @@ -98,7 +98,7 @@ void main() { #ifdef PROCESS_MAPB vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0; - float centre = textureLod(source_importance, uv, 0.0).x; + float center = textureLod(source_importance, uv, 0.0).x; vec2 half_pixel = params.half_screen_pixel_size; diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl index f6a9a92fac..45cc62d361 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl @@ -60,8 +60,8 @@ void main() { int mx = int(pix_pos.x % 2); int my = int(pix_pos.y % 2); int index_center = mx + my * 2; // center index - int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal - int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical + int index_horizontal = (1 - mx) + my * 2; // neighboring, horizontal + int index_vertical = mx + (1 - my) * 2; // neighboring, vertical int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal vec2 center_val = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0).xy; diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl index 513791dfbf..de7b97953f 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl @@ -234,7 +234,7 @@ void SSILTap(const int p_quality_level, inout vec3 r_color_sum, inout float r_ob // snap to pixel center (more correct obscurance math, avoids artifacts) sample_offset = round(sample_offset); - // calculate MIP based on the sample distance from the centre, similar to as described + // calculate MIP based on the sample distance from the center, similar to as described // in http://graphics.cs.williams.edu/papers/SAOHPG12/. float mip_level = (p_quality_level < SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset); @@ -272,7 +272,7 @@ void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, o // get this pixel's viewspace depth pix_z = valuesUL.y; - // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0) + // get left right top bottom neighboring pixels for edge detection (gets compiled out on quality_level == 0) pix_left_z = valuesUL.x; pix_top_z = valuesUL.z; pix_right_z = valuesBR.z; @@ -318,7 +318,7 @@ void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, o float obscurance_sum = 0.0; float weight_sum = 0.0; - // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge) + // edge mask for between this and left/right/top/bottom neighbor pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge) vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0); // Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl index 47c56571f6..f48e6c4341 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl @@ -124,14 +124,14 @@ void main() { vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size; - vec4 centre = textureLod(source_ssil, uv, 0.0); + vec4 center = textureLod(source_ssil, uv, 0.0); vec4 value = textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x * 3, -half_pixel.y)), 0.0) * 0.2; value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x, -half_pixel.y * 3)), 0.0) * 0.2; value += textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x, +half_pixel.y * 3)), 0.0) * 0.2; value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x * 3, +half_pixel.y)), 0.0) * 0.2; - vec4 sampled = value + centre * 0.2; + vec4 sampled = value + center * 0.2; #else #ifdef MODE_SMART diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl index 6b6b02739d..193e3458ab 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl @@ -82,7 +82,7 @@ void main() { #ifdef PROCESS_MAPA vec2 uv = (vec2(ssC) + 0.5) * params.half_screen_pixel_size * 2.0; - float centre = textureLod(source_importance, uv, 0.0).x; + float center = textureLod(source_importance, uv, 0.0).x; vec2 half_pixel = params.half_screen_pixel_size; @@ -100,7 +100,7 @@ void main() { #ifdef PROCESS_MAPB vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0; - float centre = textureLod(source_importance, uv, 0.0).x; + float center = textureLod(source_importance, uv, 0.0).x; vec2 half_pixel = params.half_screen_pixel_size; diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl index 9e86ac0cf0..ed85b8ee4c 100644 --- a/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl @@ -62,8 +62,8 @@ void main() { int mx = int(pix_pos.x % 2); int my = int(pix_pos.y % 2); int index_center = mx + my * 2; // center index - int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal - int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical + int index_horizontal = (1 - mx) + my * 2; // neighboring, horizontal + int index_vertical = mx + (1 - my) * 2; // neighboring, vertical int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal vec4 color = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0); diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl index 9f7449b8aa..06709f65d3 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl @@ -24,7 +24,7 @@ struct ProcessVoxel { uint albedo; // rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors. uint light; // rgbe8985 encoded total saved light, extra 2 bits for neighbors. uint light_aniso; // 55555 light anisotropy, extra 2 bits for neighbors. - //total neighbours: 26 + //total neighbors: 26 }; #ifdef MODE_PROCESS_STATIC @@ -443,10 +443,10 @@ void main() { imageStore(dst_aniso1, positioni, vec4(aniso1, 0.0, 0.0)); imageStore(dst_light, positioni, uvec4(light_total_rgbe)); - //also fill neighbours, so light interpolation during the indirect pass works + //also fill neighbors, so light interpolation during the indirect pass works - //recover the neighbour list from the leftover bits - uint neighbours = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24); + //recover the neighbor list from the leftover bits + uint neighbors = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24); const uint max_neighbours = 26; const ivec3 neighbour_positions[max_neighbours] = ivec3[]( @@ -478,7 +478,7 @@ void main() { ivec3(1, 1, 1)); for (uint i = 0; i < max_neighbours; i++) { - if (bool(neighbours & (1 << i))) { + if (bool(neighbors & (1 << i))) { ivec3 neighbour_pos = positioni + neighbour_positions[i]; imageStore(dst_light, neighbour_pos, uvec4(light_total_rgbe)); imageStore(dst_aniso0, neighbour_pos, aniso0); diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl index bce98f4054..dd35ae3b73 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl @@ -102,10 +102,10 @@ dispatch_data; struct ProcessVoxel { uint position; // xyz 7 bit packed, extra 11 bits for neighbors. - uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours - uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours - uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours - //total neighbours: 26 + uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbors + uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbors + //total neighbors: 26 }; layout(set = 0, binding = 11, std430) restrict buffer writeonly ProcessVoxels { @@ -135,10 +135,10 @@ dispatch_data; struct ProcessVoxel { uint position; // xyz 7 bit packed, extra 11 bits for neighbors. - uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours - uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours - uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours - //total neighbours: 26 + uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbors + uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbors + //total neighbors: 26 }; layout(set = 0, binding = 6, std430) restrict buffer readonly ProcessVoxels { @@ -1016,14 +1016,14 @@ void main() { store_positions[index].albedo = rgb >> 1; //store as it comes (555) to avoid precision loss (and move away the alpha bit) store_positions[index].albedo |= (facing & 0x3F) << 15; // store facing in bits 15-21 - store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbours with remaining albedo - store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbours with position + store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbors with remaining albedo + store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbors with position store_positions[index].light = imageLoad(src_light, pos).r; store_positions[index].light_aniso = imageLoad(src_light_aniso, pos).r; - //add neighbours - store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbours with light - store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbours with aniso + //add neighbors + store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbors with light + store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbors with aniso } groupMemoryBarrier(); diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl index 4658afd02d..8e4f5762fd 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl @@ -37,7 +37,7 @@ layout(push_constant, std430) uniform Params { vec3 position; float pad; - vec3 extents; + vec3 size; float pad2; ivec3 corner; @@ -184,36 +184,37 @@ void main() { vec4 local_pos = params.transform * world; local_pos.xyz /= local_pos.w; + vec3 half_size = params.size / 2.0; float sdf = -1.0; if (params.shape == 0) { // Ellipsoid // https://www.shadertoy.com/view/tdS3DG - float k0 = length(local_pos.xyz / params.extents); - float k1 = length(local_pos.xyz / (params.extents * params.extents)); + float k0 = length(local_pos.xyz / half_size); + float k1 = length(local_pos.xyz / (half_size * half_size)); sdf = k0 * (k0 - 1.0) / k1; } else if (params.shape == 1) { // Cone // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm - // Compute the cone angle automatically to fit within the volume's extents. - float inv_height = 1.0 / max(0.001, params.extents.y); - float radius = 1.0 / max(0.001, (min(params.extents.x, params.extents.z) * 0.5)); + // Compute the cone angle automatically to fit within the volume's size. + float inv_height = 1.0 / max(0.001, half_size.y); + float radius = 1.0 / max(0.001, (min(half_size.x, half_size.z) * 0.5)); float hypotenuse = sqrt(radius * radius + inv_height * inv_height); float rsin = radius / hypotenuse; float rcos = inv_height / hypotenuse; vec2 c = vec2(rsin, rcos); float q = length(local_pos.xz); - sdf = max(dot(c, vec2(q, local_pos.y - params.extents.y)), -params.extents.y - local_pos.y); + sdf = max(dot(c, vec2(q, local_pos.y - half_size.y)), -half_size.y - local_pos.y); } else if (params.shape == 2) { // Cylinder // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm - vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(params.extents.x, params.extents.z), params.extents.y); + vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(half_size.x, half_size.z), half_size.y); sdf = min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); } else if (params.shape == 3) { // Box // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm - vec3 q = abs(local_pos.xyz) - params.extents; + vec3 q = abs(local_pos.xyz) - half_size; sdf = length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0); } @@ -222,7 +223,7 @@ void main() { #ifndef SDF_USED cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf); #endif - uvw = clamp((local_pos.xyz + params.extents) / (2.0 * params.extents), 0.0, 1.0); + uvw = clamp((local_pos.xyz + half_size) / params.size, 0.0, 1.0); } if (cull_mask > 0.0) { diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index be53a7ae49..21fa7fa148 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -118,9 +118,15 @@ layout(location = 10) out flat uint instance_index_interp; // !BAS! This needs to become an input once we implement our fallback! #define ViewIndex 0 #endif // has_VK_KHR_multiview +vec3 multiview_uv(vec2 uv) { + return vec3(uv, ViewIndex); +} #else // USE_MULTIVIEW // Set to zero, not supported in non stereo #define ViewIndex 0 +vec2 multiview_uv(vec2 uv) { + return uv; +} #endif //USE_MULTIVIEW invariant gl_Position; @@ -309,9 +315,11 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multime #ifdef USE_MULTIVIEW mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; #else mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; + vec3 eye_offset = vec3(0.0, 0.0, 0.0); #endif //USE_MULTIVIEW //using world coordinates @@ -544,9 +552,15 @@ layout(location = 10) in flat uint instance_index_interp; // !BAS! This needs to become an input once we implement our fallback! #define ViewIndex 0 #endif // has_VK_KHR_multiview +vec3 multiview_uv(vec2 uv) { + return vec3(uv, ViewIndex); +} #else // USE_MULTIVIEW // Set to zero, not supported in non stereo #define ViewIndex 0 +vec2 multiview_uv(vec2 uv) { + return uv; +} #endif //USE_MULTIVIEW //defines to keep compatibility with vertex @@ -710,8 +724,10 @@ void fragment_shader(in SceneData scene_data) { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; #ifdef USE_MULTIVIEW - vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz); + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; + vec3 view = -normalize(vertex_interp - eye_offset); #else + vec3 eye_offset = vec3(0.0, 0.0, 0.0); vec3 view = -normalize(vertex_interp); #endif vec3 albedo = vec3(1.0); @@ -1293,24 +1309,26 @@ void fragment_shader(in SceneData scene_data) { } if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances - uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; - vec3 ref_vec = normalize(reflect(-view, normal)); - ref_vec = mix(ref_vec, normal, roughness * roughness); + // Make vertex orientation the world one, but still align to camera. + vec3 cam_pos = mat3(scene_data.inv_view_matrix) * vertex; + vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normal; + vec3 ref_vec = mat3(scene_data.inv_view_matrix) * normalize(reflect(-view, normal)); + //find arbitrary tangent and bitangent, then build a matrix - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal)); - vec3 bitangent = normalize(cross(tangent, normal)); - mat3 normal_mat = mat3(tangent, bitangent, normal); + vec3 v0 = abs(cam_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, cam_normal)); + vec3 bitangent = normalize(cross(tangent, cam_normal)); + mat3 normal_mat = mat3(tangent, bitangent, cam_normal); vec4 amb_accum = vec4(0.0); vec4 spec_accum = vec4(0.0); - voxel_gi_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + voxel_gi_compute(index1, cam_pos, cam_normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); uint index2 = instances.data[instance_index].gi_offset >> 16; if (index2 != 0xFFFF) { - voxel_gi_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + voxel_gi_compute(index2, cam_pos, cam_normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); } if (amb_accum.a > 0.0) { @@ -1339,8 +1357,8 @@ void fragment_shader(in SceneData scene_data) { #endif // USE_MULTIVIEW for (int i = 0; i < 4; i++) { - const vec2 neighbours[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1)); - vec2 neighbour_coord = base_coord + neighbours[i] * scene_data.screen_pixel_size; + const vec2 neighbors[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1)); + vec2 neighbour_coord = base_coord + neighbors[i] * scene_data.screen_pixel_size; #ifdef USE_MULTIVIEW float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0); #else // USE_MULTIVIEW @@ -1786,7 +1804,7 @@ void fragment_shader(in SceneData scene_data) { shadow = float(shadow1 >> ((i - 4u) * 8u) & 0xFFu) / 255.0; } - shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity; + shadow = mix(1.0, shadow, directional_lights.data[i].shadow_opacity); #endif blur_shadow(shadow); @@ -2070,7 +2088,7 @@ void fragment_shader(in SceneData scene_data) { float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); - //store as 8985 to have 2 extra neighbour bits + //store as 8985 to have 2 extra neighbor bits uint light_rgbe = ((uint(sRed) & 0x1FFu) >> 1) | ((uint(sGreen) & 0x1FFu) << 8) | (((uint(sBlue) & 0x1FFu) >> 1) << 17) | ((uint(exps) & 0x1Fu) << 25); imageStore(emission_grid, grid_pos, uvec4(light_rgbe)); diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 3a45ab0059..8ff7a784dc 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -268,19 +268,23 @@ layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid; #define color_buffer shadow_atlas #define normal_roughness_buffer shadow_atlas +#define multiviewSampler sampler2D #else -layout(set = 1, binding = 10) uniform texture2D depth_buffer; -layout(set = 1, binding = 11) uniform texture2D color_buffer; - #ifdef USE_MULTIVIEW +layout(set = 1, binding = 10) uniform texture2DArray depth_buffer; +layout(set = 1, binding = 11) uniform texture2DArray color_buffer; layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer; layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer; layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer; +#define multiviewSampler sampler2DArray #else // USE_MULTIVIEW +layout(set = 1, binding = 10) uniform texture2D depth_buffer; +layout(set = 1, binding = 11) uniform texture2D color_buffer; layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer; layout(set = 1, binding = 14) uniform texture2D ambient_buffer; layout(set = 1, binding = 15) uniform texture2D reflection_buffer; +#define multiviewSampler sampler2D #endif layout(set = 1, binding = 13) uniform texture2D ao_buffer; layout(set = 1, binding = 16) uniform texture2DArray sdfgi_lightprobe_texture; diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 5e64d4e651..a8b28bbd4f 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -112,9 +112,15 @@ layout(location = 9) out highp float dp_clip; // !BAS! This needs to become an input once we implement our fallback! #define ViewIndex 0 #endif +vec3 multiview_uv(vec2 uv) { + return vec3(uv, ViewIndex); +} #else // Set to zero, not supported in non stereo #define ViewIndex 0 +vec2 multiview_uv(vec2 uv) { + return uv; +} #endif //USE_MULTIVIEW invariant gl_Position; @@ -308,9 +314,11 @@ void main() { #ifdef USE_MULTIVIEW mat4 projection_matrix = scene_data.projection_matrix_view[ViewIndex]; mat4 inv_projection_matrix = scene_data.inv_projection_matrix_view[ViewIndex]; + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; #else mat4 projection_matrix = scene_data.projection_matrix; mat4 inv_projection_matrix = scene_data.inv_projection_matrix; + vec3 eye_offset = vec3(0.0, 0.0, 0.0); #endif //USE_MULTIVIEW //using world coordinates @@ -523,9 +531,15 @@ layout(location = 9) highp in float dp_clip; // !BAS! This needs to become an input once we implement our fallback! #define ViewIndex 0 #endif +vec3 multiview_uv(vec2 uv) { + return vec3(uv, ViewIndex); +} #else // Set to zero, not supported in non stereo #define ViewIndex 0 +vec2 multiview_uv(vec2 uv) { + return uv; +} #endif //USE_MULTIVIEW //defines to keep compatibility with vertex @@ -659,8 +673,10 @@ void main() { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; #ifdef USE_MULTIVIEW - vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz); + vec3 eye_offset = scene_data.eye_offset[ViewIndex].xyz; + vec3 view = -normalize(vertex_interp - eye_offset); #else + vec3 eye_offset = vec3(0.0, 0.0, 0.0); vec3 view = -normalize(vertex_interp); #endif vec3 albedo = vec3(1.0); @@ -1515,6 +1531,8 @@ void main() { } else { shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0; } + + shadow = mix(1.0, shadow, directional_lights.data[i].shadow_opacity); #endif blur_shadow(shadow); diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 631ff0575b..78b39a356d 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -154,8 +154,15 @@ layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas; // this needs to change to providing just the lightmap we're using.. layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; +#ifdef USE_MULTIVIEW +layout(set = 1, binding = 9) uniform highp texture2DArray depth_buffer; +layout(set = 1, binding = 10) uniform mediump texture2DArray color_buffer; +#define multiviewSampler sampler2DArray +#else layout(set = 1, binding = 9) uniform highp texture2D depth_buffer; layout(set = 1, binding = 10) uniform mediump texture2D color_buffer; +#define multiviewSampler sampler2D +#endif // USE_MULTIVIEW /* Set 2 Skeleton & Instancing (can change per item) */ diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl index b30b0c8169..9dda62c28d 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -794,8 +794,13 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v float light_length = length(light_rel_vec); float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation); vec3 spot_dir = spot_lights.data[idx].direction; - float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[idx].cone_angle); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[idx].cone_angle)); + + // This conversion to a highp float is crucial to prevent light leaking + // due to precision errors in the following calculations (cone angle is mediump). + highp float cone_angle = spot_lights.data[idx].cone_angle; + float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle); + float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle)); + spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation); float light_attenuation = spot_attenuation; vec3 color = spot_lights.data[idx].color; diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index f5b233cca0..59c161548c 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -51,6 +51,15 @@ layout(push_constant, std430) uniform Params { bool normalized_blend_shapes; uint pad0; uint pad1; + + vec2 skeleton_transform_x; + vec2 skeleton_transform_y; + + vec2 skeleton_transform_offset; + vec2 inverse_transform_x; + + vec2 inverse_transform_y; + vec2 inverse_transform_offset; } params; @@ -158,8 +167,12 @@ void main() { m += mat4(bone_transforms.data[bones_23.x], bone_transforms.data[bones_23.x + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x; m += mat4(bone_transforms.data[bones_23.y], bone_transforms.data[bones_23.y + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y; - //reverse order because its transposed - vertex = (vec4(vertex, 0.0, 1.0) * m).xy; + mat4 skeleton_matrix = mat4(vec4(params.skeleton_transform_x, 0.0, 0.0), vec4(params.skeleton_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(params.skeleton_transform_offset, 0.0, 1.0)); + mat4 inverse_matrix = mat4(vec4(params.inverse_transform_x, 0.0, 0.0), vec4(params.inverse_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(params.inverse_transform_offset, 0.0, 1.0)); + + m = skeleton_matrix * transpose(m) * inverse_matrix; + + vertex = (m * vec4(vertex, 0.0, 1.0)).xy; } uint dst_offset = index * params.vertex_stride; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 673fc25595..e65d842a67 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -232,6 +232,8 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) { return; } + ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture)); + if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) { texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); } @@ -387,6 +389,13 @@ uint64_t LightStorage::light_get_version(RID p_light) const { return light->version; } +uint32_t LightStorage::light_get_cull_mask(RID p_light) const { + const Light *light = light_owner.get_or_null(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->cull_mask; +} + AABB LightStorage::light_get_aabb(RID p_light) const { const Light *light = light_owner.get_or_null(p_light); ERR_FAIL_COND_V(!light, AABB()); @@ -568,8 +577,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged r_directional_light_count = 0; r_positional_light_count = 0; - Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin); - omni_light_count = 0; spot_light_count = 0; @@ -720,7 +727,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged } Transform3D light_transform = light_instance->transform; - const real_t distance = camera_plane.distance_to(light_transform.origin); + const real_t distance = p_camera_transform.origin.distance_to(light_transform.origin); if (light->distance_fade) { const float fade_begin = light->distance_fade_begin; @@ -745,7 +752,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged } Transform3D light_transform = light_instance->transform; - const real_t distance = camera_plane.distance_to(light_transform.origin); + const real_t distance = p_camera_transform.origin.distance_to(light_transform.origin); if (light->distance_fade) { const float fade_begin = light->distance_fade_begin; @@ -787,6 +794,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT; LightInstance *light_instance = (i < omni_light_count) ? omni_light_sort[index].light_instance : spot_light_sort[index].light_instance; Light *light = (i < omni_light_count) ? omni_light_sort[index].light : spot_light_sort[index].light; + real_t distance = (i < omni_light_count) ? omni_light_sort[index].depth : spot_light_sort[index].depth; if (using_forward_ids) { forward_id_storage->map_forward_id(type == RS::LIGHT_OMNI ? RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT : RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id, index); @@ -803,7 +811,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged float fade_begin = 0.0; float fade_shadow = 0.0; float fade_length = 0.0; - real_t distance = 0.0; float fade = 1.0; float shadow_opacity_fade = 1.0; @@ -811,7 +818,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged fade_begin = light->distance_fade_begin; fade_shadow = light->distance_fade_shadow; fade_length = light->distance_fade_length; - distance = camera_plane.distance_to(light_transform.origin); // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. if (distance > fade_begin) { @@ -1067,14 +1073,14 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } -void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { +void LightStorage::reflection_probe_set_size(RID p_probe, const Vector3 &p_size) { ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); ERR_FAIL_COND(!reflection_probe); - if (reflection_probe->extents == p_extents) { + if (reflection_probe->size == p_size) { return; } - reflection_probe->extents = p_extents; + reflection_probe->size = p_size; reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } @@ -1146,8 +1152,8 @@ AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const { ERR_FAIL_COND_V(!reflection_probe, AABB()); AABB aabb; - aabb.position = -reflection_probe->extents; - aabb.size = reflection_probe->extents * 2.0; + aabb.position = -reflection_probe->size / 2; + aabb.size = reflection_probe->size; return aabb; } @@ -1166,11 +1172,11 @@ uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const { return reflection_probe->cull_mask; } -Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const { +Vector3 LightStorage::reflection_probe_get_size(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe); ERR_FAIL_COND_V(!reflection_probe, Vector3()); - return reflection_probe->extents; + return reflection_probe->size; } Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const { @@ -1467,7 +1473,6 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_ fb.push_back(atlas->depth_buffer); atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb); - atlas->render_buffers->cleanup(); atlas->render_buffers->configure_for_reflections(Size2i(atlas->size, atlas->size)); } @@ -1556,6 +1561,11 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) { if (rpi->processing_side == 6) { rpi->processing_side = 0; rpi->processing_layer++; + if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { + rpi->rendering = false; + rpi->processing_layer = 1; + return true; + } } return false; @@ -1671,7 +1681,7 @@ void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, c ReflectionData &reflection_ubo = reflections[i]; - Vector3 extents = probe->extents; + Vector3 extents = probe->size / 2; rpi->cull_mask = probe->cull_mask; diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index f7c8b8833b..c36d1ef503 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -226,7 +226,7 @@ private: Color ambient_color; float ambient_color_energy = 1.0; float max_distance = 0; - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(20, 20, 20); Vector3 origin_offset; bool interior = false; bool box_projection = false; @@ -517,13 +517,6 @@ public: return light->color; } - _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) { - const Light *light = light_owner.get_or_null(p_light); - ERR_FAIL_COND_V(!light, 0); - - return light->cull_mask; - } - _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) { const Light *light = light_owner.get_or_null(p_light); return light->distance_fade; @@ -575,6 +568,7 @@ public: virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override; virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override; virtual uint64_t light_get_version(RID p_light) const override; + virtual uint32_t light_get_cull_mask(RID p_light) const override; Dependency *light_get_dependency(RID p_light) const; @@ -791,7 +785,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) override; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override; @@ -805,7 +799,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const override; virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const override; + virtual Vector3 reflection_probe_get_size(RID p_probe) const override; virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override; virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override; virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 66ae1e8d1a..d631a89dd2 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -2685,6 +2685,14 @@ void MaterialStorage::material_free(RID p_rid) { Material *material = material_owner.get_or_null(p_rid); ERR_FAIL_COND(!material); + // Need to clear texture arrays to prevent spin locking of their RID's. + // This happens when the app is being closed. + for (KeyValue<StringName, Variant> &E : material->params) { + if (E.value.get_type() == Variant::ARRAY) { + Array(E.value).clear(); + } + } + material_set_shader(p_rid, RID()); //clean up shader material->dependency.deleted_notify(p_rid); diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 0ac5557659..ac217d9a49 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -323,13 +323,13 @@ public: // http://andrewthall.org/papers/df64_qf128.pdf #ifdef REAL_T_IS_DOUBLE - static _FORCE_INLINE_ void split_double(double a, float *ahi, float *alo) { + static _FORCE_INLINE_ void split_double(double a, float *a_hi, float *a_lo) { const double SPLITTER = (1 << 29) + 1; double t = a * SPLITTER; - double thi = t - (t - a); - double tlo = a - thi; - *ahi = (float)thi; - *alo = (float)tlo; + double t_hi = t - (t - a); + double t_lo = a - t_hi; + *a_hi = (float)t_hi; + *a_lo = (float)t_lo; } #endif diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 62da62403f..96618c3352 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -586,6 +586,8 @@ void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { Mesh *mesh = mesh_owner.get_or_null(p_mesh); ERR_FAIL_COND(!mesh); mesh->custom_aabb = p_aabb; + + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const { @@ -842,15 +844,15 @@ void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int } void MeshStorage::_mesh_instance_clear(MeshInstance *mi) { - for (uint32_t i = 0; i < mi->surfaces.size(); i++) { - if (mi->surfaces[i].versions) { - for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) { - RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array); + for (const RendererRD::MeshStorage::MeshInstance::Surface &surface : mi->surfaces) { + if (surface.versions) { + for (uint32_t j = 0; j < surface.version_count; j++) { + RD::get_singleton()->free(surface.versions[j].vertex_array); } - memfree(mi->surfaces[i].versions); + memfree(surface.versions); } - if (mi->surfaces[i].vertex_buffer.is_valid()) { - RD::get_singleton()->free(mi->surfaces[i].vertex_buffer); + if (surface.vertex_buffer.is_valid()) { + RD::get_singleton()->free(surface.vertex_buffer); } } mi->surfaces.clear(); @@ -866,8 +868,8 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) { void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) { if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) { mi->blend_weights.resize(mesh->blend_shape_count); - for (uint32_t i = 0; i < mi->blend_weights.size(); i++) { - mi->blend_weights[i] = 0; + for (float &weight : mi->blend_weights) { + weight = 0; } mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array()); mi->weights_dirty = true; @@ -930,6 +932,11 @@ void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) { } } +void MeshStorage::mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) { + MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); + mi->canvas_item_transform_2d = p_transform; +} + void MeshStorage::update_mesh_instances() { while (dirty_mesh_instance_weights.first()) { MeshInstance *mi = dirty_mesh_instance_weights.first()->self(); @@ -981,6 +988,25 @@ void MeshStorage::update_mesh_instances() { push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4; push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2; + Transform2D transform = Transform2D(); + if (sk && sk->use_2d) { + transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d; + } + push_constant.skeleton_transform_x[0] = transform.columns[0][0]; + push_constant.skeleton_transform_x[1] = transform.columns[0][1]; + push_constant.skeleton_transform_y[0] = transform.columns[1][0]; + push_constant.skeleton_transform_y[1] = transform.columns[1][1]; + push_constant.skeleton_transform_offset[0] = transform.columns[2][0]; + push_constant.skeleton_transform_offset[1] = transform.columns[2][1]; + + Transform2D inverse_transform = transform.affine_inverse(); + push_constant.inverse_transform_x[0] = inverse_transform.columns[0][0]; + push_constant.inverse_transform_x[1] = inverse_transform.columns[0][1]; + push_constant.inverse_transform_y[0] = inverse_transform.columns[1][0]; + push_constant.inverse_transform_y[1] = inverse_transform.columns[1][1]; + push_constant.inverse_transform_offset[0] = inverse_transform.columns[2][0]; + push_constant.inverse_transform_offset[1] = inverse_transform.columns[2][1]; + push_constant.blend_shape_count = mi->mesh->blend_shape_count; push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED; push_constant.pad0 = 0; @@ -1779,8 +1805,12 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible } if (multimesh->data_cache.size()) { - //there is a data cache.. + // There is a data cache, but we may need to update some sections. _multimesh_mark_all_dirty(multimesh, false, true); + int start = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + for (int i = start; i < p_visible; i++) { + _multimesh_mark_dirty(multimesh, i, true); + } } multimesh->visible_instances = p_visible; diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index b62da5fd7b..c921523941 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -178,6 +178,7 @@ private: bool weights_dirty = false; SelfList<MeshInstance> weight_update_list; SelfList<MeshInstance> array_update_list; + Transform2D canvas_item_transform_2d; MeshInstance() : weight_update_list(this), array_update_list(this) {} }; @@ -256,6 +257,14 @@ private: uint32_t normalized_blend_shapes; uint32_t pad0; uint32_t pad1; + float skeleton_transform_x[2]; + float skeleton_transform_y[2]; + + float skeleton_transform_offset[2]; + float inverse_transform_x[2]; + + float inverse_transform_y[2]; + float inverse_transform_offset[2]; }; enum { @@ -548,6 +557,7 @@ public: virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override; virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override; virtual void mesh_instance_check_for_update(RID p_mesh_instance) override; + virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override; virtual void update_mesh_instances() override; /* MULTIMESH API */ diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 6401d0f5d0..00fb8acca8 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -851,9 +851,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta collision_heightmap_texture = p_particles->sdf_collision_texture; //replace in all other history frames where used because parameters are no longer valid if screen moves - for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) { - if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) { - p_particles->frame_history[i].colliders[0] = frame_params.colliders[0]; + for (ParticlesFrameParams ¶ms : p_particles->frame_history) { + if (params.collider_count > 0 && params.colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) { + params.colliders[0] = frame_params.colliders[0]; } } } @@ -1145,7 +1145,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p return; } - if (particles->particle_buffer.is_null()) { + if (particles->particle_buffer.is_null() || particles->trail_bind_pose_uniform_set.is_null()) { return; //particles have not processed yet } @@ -1415,7 +1415,6 @@ void ParticlesStorage::update_particles() { } bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0; - bool updated = false; if (particles->clear && particles->pre_process_time > 0.0) { double frame_time; @@ -1430,7 +1429,6 @@ void ParticlesStorage::update_particles() { while (todo >= 0) { _particles_process(particles, frame_time); todo -= frame_time; - updated = true; } } @@ -1452,10 +1450,9 @@ void ParticlesStorage::update_particles() { } double todo = particles->frame_remainder + delta; - while (todo >= frame_time || (particles->clear && !updated)) { + while (todo >= frame_time || particles->clear) { _particles_process(particles, frame_time); todo -= decr; - updated = true; } particles->frame_remainder = todo; @@ -1463,16 +1460,16 @@ void ParticlesStorage::update_particles() { } else { if (zero_time_scale) { _particles_process(particles, 0.0); - updated = true; } else { _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time()); - updated = true; } } - //copy particles to instance buffer + // Ensure that memory is initialized (the code above should ensure that _particles_process is always called at least once upon clearing). + DEV_ASSERT(!particles->clear); - if (updated && particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { + // Copy particles to instance buffer. + if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) { //does not need view dependent operation, do copy here ParticlesShader::CopyPushConstant copy_push_constant; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index a953bac433..f5d6404f01 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -50,25 +50,19 @@ void RenderSceneBuffersRD::_bind_methods() { // ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture); ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture); // ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format); - ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice); - ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size); + ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice); + ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size); ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context); } void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) { ERR_FAIL_COND(p_named_texture.texture.is_null()); - uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps; - p_named_texture.sizes.resize(size); + p_named_texture.sizes.resize(p_named_texture.format.mipmaps); Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height); - for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) { - for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) { - uint32_t index = layer * p_named_texture.format.mipmaps + mipmap; - - p_named_texture.sizes.ptrw()[index] = mipmap_size; - } + p_named_texture.sizes.ptrw()[mipmap] = mipmap_size; mipmap_size.width = MAX(1, mipmap_size.width >> 1); mipmap_size.height = MAX(1, mipmap_size.height >> 1); @@ -94,31 +88,9 @@ void RenderSceneBuffersRD::cleanup() { free_named_texture(E.value); } named_textures.clear(); - - // old stuff, to be re-evaluated... - - for (int i = 0; i < luminance.fb.size(); i++) { - RD::get_singleton()->free(luminance.fb[i]); - } - luminance.fb.clear(); - - for (int i = 0; i < luminance.reduce.size(); i++) { - RD::get_singleton()->free(luminance.reduce[i]); - } - luminance.reduce.clear(); - - if (luminance.current_fb.is_valid()) { - RD::get_singleton()->free(luminance.current_fb); - luminance.current_fb = RID(); - } - - if (luminance.current.is_valid()) { - RD::get_singleton()->free(luminance.current); - luminance.current = RID(); - } } -void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { +void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -126,12 +98,7 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna target_size = p_target_size; internal_size = p_internal_size; - - // FIXME, right now we do this because only our clustered renderer supports FSR upscale - // this does mean that with linear upscale if we use subpasses, we could get into trouble. - if (!can_be_storage) { - internal_size = target_size; - } + scaling_3d_mode = p_scaling_3d_mode; if (p_use_taa) { // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. @@ -215,6 +182,7 @@ void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_s target_size = p_reflection_size; internal_size = p_reflection_size; render_target = RID(); + scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF; fsr_sharpness = 0.0; msaa_3d = RS::VIEWPORT_MSAA_DISABLED; screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; @@ -277,7 +245,7 @@ RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const Stri } RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) { - // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation. + // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimization. NTKey key(p_context, p_texture_name); @@ -350,7 +318,7 @@ const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringNam return named_textures[key].format; } -RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) { +RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps) { NTKey key(p_context, p_texture_name); // check if this is a known texture @@ -360,36 +328,41 @@ RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const S // check if we're in bounds ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID()); + ERR_FAIL_COND_V(p_layers == 0, RID()); + ERR_FAIL_COND_V(p_layer + p_layers > named_texture.format.array_layers, RID()); ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID()); + ERR_FAIL_COND_V(p_mipmaps == 0, RID()); + ERR_FAIL_COND_V(p_mipmap + p_mipmaps > named_texture.format.mipmaps, RID()); - // if we don't have multiple layers or mipmaps, we can just return our texture as is - if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) { + // asking the whole thing? just return the original + if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps) { return named_texture.texture; } - // get our index and make sure we have enough entries in our slices vector - uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap; - while (named_texture.slices.size() <= int(index)) { - named_texture.slices.push_back(RID()); + // see if we have this + NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps); + if (named_texture.slices.has(slice_key)) { + return named_texture.slices[slice_key]; } - // create our slice if we don't have it already - if (named_texture.slices[index].is_null()) { - named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap); + // create our slice + RID &slice = named_texture.slices[slice_key]; + slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers); - Array arr; - arr.push_back(p_context); - arr.push_back(p_texture_name); - arr.push_back(itos(p_layer)); - arr.push_back(itos(p_mipmap)); - RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr)); - } + Array arr; + arr.push_back(p_context); + arr.push_back(p_texture_name); + arr.push_back(itos(p_layer)); + arr.push_back(itos(p_layers)); + arr.push_back(itos(p_mipmap)); + arr.push_back(itos(p_mipmaps)); + RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}").format(arr)); // and return our slice - return named_texture.slices[index]; + return slice; } -Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) { +Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap) { NTKey key(p_context, p_texture_name); // check if this is a known texture @@ -398,14 +371,10 @@ Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i()); // check if we're in bounds - ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i()); ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i()); - // get our index - uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap; - - // and return our size - return named_texture.sizes[index]; + // return our size + return named_texture.sizes[p_mipmap]; } void RenderSceneBuffersRD::clear_context(const StringName &p_context) { @@ -516,6 +485,16 @@ Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const String // Depth texture +bool RenderSceneBuffersRD::has_depth_texture() { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RID depth = texture_storage->render_target_get_override_depth(render_target); + if (depth.is_valid()) { + return true; + } else { + return has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH); + } +} + RID RenderSceneBuffersRD::get_depth_texture() { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RID depth = texture_storage->render_target_get_override_depth(render_target); diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index 1bd542500c..9a299a3415 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -73,6 +73,7 @@ private: // The internal size of the textures we render 3D to in case we render at a lower resolution and upscale Size2i internal_size = Size2i(0, 0); + RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF; float fsr_sharpness = 0.2f; // Aliassing settings @@ -92,7 +93,6 @@ private: } static uint32_t hash(const NTKey &p_val) { - // FIXME, properly hash two stringnames together uint32_t h = p_val.context.hash(); h = hash_murmur3_one_32(p_val.buffer_name.hash(), h); return hash_fmix32(h); @@ -105,6 +105,33 @@ private: } }; + struct NTSliceKey { + uint32_t layer; + uint32_t layers; + uint32_t mipmap; + uint32_t mipmaps; + + bool operator==(const NTSliceKey &p_val) const { + return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps); + } + + static uint32_t hash(const NTSliceKey &p_val) { + uint32_t h = hash_murmur3_one_32(p_val.layer); + h = hash_murmur3_one_32(p_val.layers, h); + h = hash_murmur3_one_32(p_val.mipmap, h); + h = hash_murmur3_one_32(p_val.mipmaps, h); + return hash_fmix32(h); + } + + NTSliceKey() {} + NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) { + layer = p_layer; + layers = p_layers; + mipmap = p_mipmap; + mipmaps = p_mipmaps; + } + }; + struct NamedTexture { // Cache the data used to create our texture RD::TextureFormat format; @@ -112,7 +139,7 @@ private: // Our texture objects, slices are lazy (i.e. only created when requested). RID texture; - Vector<RID> slices; + mutable HashMap<NTSliceKey, RID, NTSliceKey> slices; Vector<Size2i> sizes; }; @@ -139,7 +166,7 @@ public: void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; } void cleanup(); - virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; + virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; void configure_for_reflections(const Size2i p_reflection_size); virtual void set_fsr_sharpness(float p_fsr_sharpness) override; virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override; @@ -153,8 +180,8 @@ public: RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView()); RID get_texture(const StringName &p_context, const StringName &p_texture_name) const; const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; - RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap); - Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap); + RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1); + Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap); void clear_context(const StringName &p_context); @@ -172,6 +199,7 @@ public: _FORCE_INLINE_ uint32_t get_view_count() const { return view_count; } _FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; } _FORCE_INLINE_ Size2i get_target_size() const { return target_size; } + _FORCE_INLINE_ RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; } _FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; } _FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; } _FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; } @@ -183,6 +211,9 @@ public: // For our internal textures we provide some easy access methods. + _FORCE_INLINE_ bool has_internal_texture() const { + return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR); + } _FORCE_INLINE_ RID get_internal_texture() const { return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR); } @@ -190,6 +221,7 @@ public: return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0); } + bool has_depth_texture(); RID get_depth_texture(); RID get_depth_texture(const uint32_t p_layer); @@ -213,15 +245,6 @@ public: // 2 full size, 2 half size WeightBuffers weight_buffers[4]; // Only used in raster - - struct Luminance { - Vector<RID> reduce; - RID current; - - // used only on mobile renderer - Vector<RID> fb; - RID current_fb; - } luminance; }; #endif // RENDER_SCENE_BUFFERS_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 06fda8fa9e..0ee9b28826 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -422,8 +422,7 @@ TextureStorage::TextureStorage() { tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT; tformat.texture_type = RD::TEXTURE_TYPE_2D; if (!RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) { - tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.format = RD::DATA_FORMAT_R8_UNORM; + tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; } Vector<uint8_t> pv; @@ -1854,10 +1853,10 @@ void TextureStorage::decal_free(RID p_rid) { decal_owner.free(p_rid); } -void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) { +void TextureStorage::decal_set_size(RID p_decal, const Vector3 &p_size) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND(!decal); - decal->extents = p_extents; + decal->size = p_size; decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } @@ -1907,7 +1906,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND(!decal); decal->cull_mask = p_layers; - decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); + decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL); } void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { @@ -1950,7 +1949,14 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND_V(!decal, AABB()); - return AABB(-decal->extents, decal->extents * 2.0); + return AABB(-decal->size / 2, decal->size); +} + +uint32_t TextureStorage::decal_get_cull_mask(RID p_decal) const { + Decal *decal = decal_owner.get_or_null(p_decal); + ERR_FAIL_COND_V(!decal, 0); + + return decal->cull_mask; } Dependency *TextureStorage::decal_get_dependency(RID p_decal) { @@ -2206,6 +2212,12 @@ void TextureStorage::decal_instance_set_transform(RID p_decal_instance, const Tr di->transform = p_transform; } +void TextureStorage::decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) { + DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); + ERR_FAIL_COND(!di); + di->sorting_offset = p_sorting_offset; +} + /* DECAL DATA API */ void TextureStorage::free_decal_data() { @@ -2233,7 +2245,7 @@ void TextureStorage::set_max_decals(const uint32_t p_max_decals) { decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size); } -void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) { +void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform) { ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton(); Transform3D uv_xform; @@ -2257,7 +2269,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D xform = decal_instance->transform; - real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; + real_t distance = p_camera_xform.origin.distance_to(xform.origin); if (decal->distance_fade) { float fade_begin = decal->distance_fade_begin; @@ -2272,7 +2284,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const decal_sort[decal_count].decal_instance = decal_instance; decal_sort[decal_count].decal = decal; - decal_sort[decal_count].depth = distance; + decal_sort[decal_count].depth = distance - decal_instance->sorting_offset; decal_count++; } @@ -2292,11 +2304,10 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const decal_instance->cull_mask = decal->cull_mask; - Transform3D xform = decal_instance->transform; float fade = 1.0; if (decal->distance_fade) { - const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z; + const real_t distance = decal_sort[i].depth + decal_instance->sorting_offset; const float fade_begin = decal->distance_fade_begin; const float fade_length = decal->distance_fade_length; @@ -2308,15 +2319,20 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const DecalData &dd = decals[i]; - Vector3 decal_extents = decal->extents; + Vector3 decal_extents = decal->size / 2; Transform3D scale_xform; scale_xform.basis.scale(decal_extents); - Transform3D to_decal_xform = (p_camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse(); + + Transform3D xform = decal_instance->transform; + + Transform3D camera_inverse_xform = p_camera_xform.affine_inverse(); + + Transform3D to_decal_xform = (camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse(); MaterialStorage::store_transform(to_decal_xform, dd.xform); Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized(); - normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine + normal = camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine dd.normal[0] = normal.x; dd.normal[1] = normal.y; @@ -2350,7 +2366,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const dd.normal_rect[2] = rect.size.x; dd.normal_rect[3] = rect.size.y; - Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized(); + Basis normal_xform = camera_inverse_xform.basis * xform.basis.orthonormalized(); MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform); } else { dd.normal_rect[0] = 0; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 1558342c3b..c16f5274ad 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -235,7 +235,7 @@ private: } decal_atlas; struct Decal { - Vector3 extents = Vector3(1, 1, 1); + Vector3 size = Vector3(2, 2, 2); RID textures[RS::DECAL_TEXTURE_MAX]; float emission_energy = 1.0; float albedo_mix = 1.0; @@ -258,6 +258,7 @@ private: struct DecalInstance { RID decal; Transform3D transform; + float sorting_offset = 0.0; uint32_t cull_mask = 0; RendererRD::ForwardID forward_id = -1; }; @@ -560,7 +561,7 @@ public: virtual void decal_initialize(RID p_decal) override; virtual void decal_free(RID p_rid) override; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override; virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override; virtual void decal_set_emission_energy(RID p_decal, float p_energy) override; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override; @@ -576,9 +577,9 @@ public: virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override; virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override; - _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) { + _FORCE_INLINE_ Vector3 decal_get_size(RID p_decal) { const Decal *decal = decal_owner.get_or_null(p_decal); - return decal->extents; + return decal->size; } _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) { @@ -637,6 +638,7 @@ public: } virtual AABB decal_get_aabb(RID p_decal) const override; + virtual uint32_t decal_get_cull_mask(RID p_decal) const override; Dependency *decal_get_dependency(RID p_decal); /* DECAL INSTANCE API */ @@ -646,6 +648,7 @@ public: virtual RID decal_instance_create(RID p_decal) override; virtual void decal_instance_free(RID p_decal_instance) override; virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override; + virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override; _FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const { DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance); @@ -677,7 +680,7 @@ public: void free_decal_data(); void set_max_decals(const uint32_t p_max_decals); RID get_decal_buffer() { return decal_buffer; } - void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform); + void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform); /* RENDER TARGET API */ diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp index d2f5e6f224..cabac4e9ee 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -286,6 +286,10 @@ bool Utilities::has_os_feature(const String &p_feature) const { return true; } + if (p_feature == "astc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + return false; } diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 2ea813aab0..7d2cd12959 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -694,6 +694,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) { instance->base_data = decal; decal->instance = RSG::texture_storage->decal_instance_create(p_base); + RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset); } break; case RS::INSTANCE_LIGHTMAP: { InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData); @@ -748,6 +749,10 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) { switch (instance->base_type) { case RS::INSTANCE_LIGHT: { InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); + if (instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + instance->scenario->dynamic_lights.erase(light->instance); + } + #ifdef DEBUG_ENABLED if (light->geometries.size()) { ERR_PRINT("BUG, indexing did not unpair geometries from light."); @@ -867,6 +872,9 @@ void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data); ERR_FAIL_NULL(geom->geometry_instance); geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center); + } else if (instance->base_type == RS::INSTANCE_DECAL && instance->base_data) { + InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data); + RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset); } } @@ -1779,6 +1787,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.pair_allocator = &pair_allocator; pair.pair_pass = pair_pass; pair.pair_mask = 0; + pair.cull_mask = 0xFFFFFFFF; if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { pair.pair_mask |= 1 << RS::INSTANCE_LIGHT; @@ -1799,12 +1808,14 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI); pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES]; } + pair.cull_mask = RSG::light_storage->light_get_cull_mask(p_instance->base); } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; } else if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (p_instance->base_type == RS::INSTANCE_DECAL)) { pair.pair_mask = RS::INSTANCE_GEOMETRY_MASK; pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; + pair.cull_mask = RSG::texture_storage->decal_get_cull_mask(p_instance->base); } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) { pair.pair_mask = (1 << RS::INSTANCE_PARTICLES); pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY]; @@ -2820,7 +2831,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data); ERR_FAIL_NULL(geom->geometry_instance); + cull_data.cull->lock.lock(); geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0); + cull_data.cull->lock.unlock(); idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY); } @@ -2887,7 +2900,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed)); } ERR_FAIL_NULL(geom->geometry_instance); + cull_data.cull->lock.lock(); geom->geometry_instance->set_lightmap_capture(sh); + cull_data.cull->lock.unlock(); idata.instance->last_frame_pass = frame_number; } @@ -2952,11 +2967,13 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c Scenario *scenario = scenario_owner.get_or_null(p_scenario); + ERR_FAIL_COND(p_render_buffers.is_null()); + render_pass++; scene_render->set_scene_pass(render_pass); - if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + if (p_reflection_probe.is_null()) { //no rendering code here, this is only to set up what needs to be done, request regions, etc. scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not) } @@ -3038,7 +3055,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c { //sdfgi cull.sdfgi.region_count = 0; - if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + if (p_reflection_probe.is_null()) { cull.sdfgi.cascade_light_count = 0; uint32_t prev_cascade = 0xFFFFFFFF; @@ -3084,15 +3101,15 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c #endif if (cull_to > thread_cull_threshold) { //multiple threads - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result_threads[i].clear(); + for (InstanceCullResult &thread : scene_cull_result_threads) { + thread.clear(); } WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances")); WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result.append_from(scene_cull_result_threads[i]); + for (InstanceCullResult &thread : scene_cull_result_threads) { + scene_cull_result.append_from(thread); } } else { @@ -3267,7 +3284,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c } } - if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) { + if (p_reflection_probe.is_null()) { sdfgi_update_data.directional_lights = &directional_lights; sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr(); sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size(); @@ -3382,13 +3399,13 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int Vector3(0, -1, 0) }; - Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base); + Vector3 probe_size = RSG::light_storage->reflection_probe_get_size(p_instance->base); Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base); float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base); - float size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); - float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size; + float atlas_size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas); + float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / atlas_size; - Vector3 edge = view_normals[p_step] * extents; + Vector3 edge = view_normals[p_step] * probe_size / 2; float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit max_distance = MAX(max_distance, distance); @@ -4122,8 +4139,8 @@ RendererSceneCull::RendererSceneCull() { scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count()); - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); + for (InstanceCullResult &thread : scene_cull_result_threads) { + thread.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool); } indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame"); @@ -4151,8 +4168,8 @@ RendererSceneCull::~RendererSceneCull() { } scene_cull_result.reset(); - for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) { - scene_cull_result_threads[i].reset(); + for (InstanceCullResult &thread : scene_cull_result_threads) { + thread.reset(); } scene_cull_result_threads.clear(); diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 2ec75b03ef..b3874ee7ae 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -485,6 +485,7 @@ public: singleton->_instance_queue_update(instance, true, false); } break; + case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: case Dependency::DEPENDENCY_CHANGED_MATERIAL: { singleton->_instance_queue_update(instance, false, true); } break; @@ -496,9 +497,6 @@ public: case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: { singleton->_instance_queue_update(instance, true, true); } break; - case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { - //ignored - } break; case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: { //requires repairing if (instance->indexer_id.is_valid()) { @@ -735,11 +733,12 @@ public: DynamicBVH *bvh2 = nullptr; //some may need to cull in two uint32_t pair_mask; uint64_t pair_pass; + uint32_t cull_mask = 0xFFFFFFFF; // Needed for decals and lights in the mobile and compatibility renderers. _FORCE_INLINE_ bool operator()(void *p_data) { Instance *p_instance = (Instance *)p_data; - if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type))) { + if (instance != p_instance && instance->transformed_aabb.intersects(p_instance->transformed_aabb) && (pair_mask & (1 << p_instance->base_type)) && (cull_mask & p_instance->layer_mask)) { //test is more coarse in indexer p_instance->pair_check = pair_pass; InstancePair *pair = pair_allocator->alloc(); diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index e2e6ea5aa2..a389e3e767 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -84,7 +84,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count Transform3D main_transform_inv = main_transform.inverse(); // 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters - Vector3 far_center = (planes[0][Projection::PLANE_FAR].center() + planes[1][Projection::PLANE_FAR].center()) * 0.5; + Vector3 far_center = (planes[0][Projection::PLANE_FAR].get_center() + planes[1][Projection::PLANE_FAR].get_center()) * 0.5; Plane far(-z, far_center); ///////////////////////////////////////////////////////////////////////////// diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 05a3fccf1c..d251a81427 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -115,9 +115,8 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { if (p_viewport->size.width == 0 || p_viewport->size.height == 0) { p_viewport->render_buffers.unref(); } else { - const float scaling_3d_scale = p_viewport->scaling_3d_scale; + float scaling_3d_scale = p_viewport->scaling_3d_scale; RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode; - bool scaling_enabled = true; if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) { // FSR is not designed for downsampling. @@ -133,7 +132,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { } if (scaling_3d_scale == 1.0) { - scaling_enabled = false; + scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF; } int width; @@ -141,36 +140,37 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { int render_width; int render_height; - if (scaling_enabled) { - switch (scaling_3d_mode) { - case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR: - // Clamp 3D rendering resolution to reasonable values supported on most hardware. - // This prevents freezing the engine or outright crashing on lower-end GPUs. - width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384); - height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384); - render_width = width; - render_height = height; - break; - case RS::VIEWPORT_SCALING_3D_MODE_FSR: - width = p_viewport->size.width; - height = p_viewport->size.height; - render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling) - render_height = MAX(height * scaling_3d_scale, 1.0); - break; - default: - // This is an unknown mode. - WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode)); - width = p_viewport->size.width; - height = p_viewport->size.height; - render_width = width; - render_height = height; - break; - } - } else { - width = p_viewport->size.width; - height = p_viewport->size.height; - render_width = width; - render_height = height; + switch (scaling_3d_mode) { + case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR: + // Clamp 3D rendering resolution to reasonable values supported on most hardware. + // This prevents freezing the engine or outright crashing on lower-end GPUs. + width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384); + height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384); + render_width = width; + render_height = height; + break; + case RS::VIEWPORT_SCALING_3D_MODE_FSR: + width = p_viewport->size.width; + height = p_viewport->size.height; + render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling) + render_height = MAX(height * scaling_3d_scale, 1.0); + break; + case RS::VIEWPORT_SCALING_3D_MODE_OFF: + width = p_viewport->size.width; + height = p_viewport->size.height; + render_width = width; + render_height = height; + break; + default: + // This is an unknown mode. + WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode)); + scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF; + scaling_3d_scale = 1.0; + width = p_viewport->size.width; + height = p_viewport->size.height; + render_width = width; + render_height = height; + break; } p_viewport->internal_size = Size2(render_width, render_height); @@ -179,7 +179,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { // to compensate for the loss of sharpness. const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias; - p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count); + p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), scaling_3d_mode, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count); } } } @@ -236,7 +236,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) { } } - if (!p_viewport->disable_2d && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) { + if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport) && RSG::scene->is_scenario(p_viewport->scenario)) { RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario); if (RSG::scene->is_environment(environment)) { scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS; @@ -844,7 +844,7 @@ void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_sca } void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) { - ERR_FAIL_COND(p_width < 0 && p_height < 0); + ERR_FAIL_COND(p_width < 0 || p_height < 0); Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); @@ -992,11 +992,21 @@ void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) { viewport->disable_2d = p_disable; } -void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) { +void RendererViewport::viewport_set_environment_mode(RID p_viewport, RS::ViewportEnvironmentMode p_mode) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); - viewport->disable_environment = p_disable; + viewport->disable_environment = p_mode; +} + +bool RendererViewport::viewport_is_environment_disabled(Viewport *viewport) { + ERR_FAIL_COND_V(!viewport, false); + + if (viewport->parent.is_valid() && viewport->disable_environment == RS::VIEWPORT_ENVIRONMENT_INHERIT) { + Viewport *parent = viewport_owner.get_or_null(viewport->parent); + return viewport_is_environment_disabled(parent); + } + return viewport->disable_environment == RS::VIEWPORT_ENVIRONMENT_DISABLED; } void RendererViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) { @@ -1138,6 +1148,7 @@ void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::Viewport void RendererViewport::viewport_set_use_taa(RID p_viewport, bool p_use_taa) { Viewport *viewport = viewport_owner.get_or_null(p_viewport); ERR_FAIL_COND(!viewport); + ERR_FAIL_COND_EDMSG(OS::get_singleton()->get_current_rendering_method() != "forward_plus", "TAA is only available when using the Forward+ renderer."); if (viewport->use_taa == p_use_taa) { return; diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 9b32cc3774..c24275de6e 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -85,7 +85,7 @@ public: bool viewport_render_direct_to_screen; bool disable_2d = false; - bool disable_environment = false; + RS::ViewportEnvironmentMode disable_environment = RS::VIEWPORT_ENVIRONMENT_INHERIT; bool disable_3d = false; bool measure_render_time = false; @@ -238,9 +238,11 @@ public: const RendererSceneRender::CameraData *viewport_get_prev_camera_data(RID p_viewport); void viewport_set_disable_2d(RID p_viewport, bool p_disable); - void viewport_set_disable_environment(RID p_viewport, bool p_disable); + void viewport_set_environment_mode(RID p_viewport, RS::ViewportEnvironmentMode p_mode); void viewport_set_disable_3d(RID p_viewport, bool p_disable); + bool viewport_is_environment_disabled(Viewport *viewport); + void viewport_attach_camera(RID p_viewport, RID p_camera); void viewport_set_scenario(RID p_viewport, RID p_scenario); void viewport_attach_canvas(RID p_viewport, RID p_canvas); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 9de21dcac6..447627b08e 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -530,7 +530,7 @@ public: TEXTURE_SLICE_2D_ARRAY, }; - virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D, uint32_t p_layers = 0) = 0; virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0; virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp index 5967835d03..3678b70254 100644 --- a/servers/rendering/rendering_device_binds.cpp +++ b/servers/rendering/rendering_device_binds.cpp @@ -31,6 +31,8 @@ #include "rendering_device_binds.h" Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) { + ERR_FAIL_NULL_V(RenderingDevice::get_singleton(), ERR_UNAVAILABLE); + Vector<String> lines = p_text.split("\n"); bool reading_versions = false; diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 4c4b3d13f9..6017eff55e 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -291,6 +291,10 @@ void RenderingServerDefault::set_boot_image(const Ref<Image> &p_image, const Col RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter); } +Color RenderingServerDefault::get_default_clear_color() { + return RSG::texture_storage->get_default_clear_color(); +} + void RenderingServerDefault::set_default_clear_color(const Color &p_color) { RSG::viewport->set_default_clear_color(p_color); } diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index f2fadd5e1f..4f52a63b2f 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -387,7 +387,7 @@ public: FUNC2(reflection_probe_set_ambient_energy, RID, float) FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode) FUNC2(reflection_probe_set_max_distance, RID, float) - FUNC2(reflection_probe_set_extents, RID, const Vector3 &) + FUNC2(reflection_probe_set_size, RID, const Vector3 &) FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &) FUNC2(reflection_probe_set_as_interior, RID, bool) FUNC2(reflection_probe_set_enable_box_projection, RID, bool) @@ -428,7 +428,7 @@ public: FUNCRIDSPLIT(decal) - FUNC2(decal_set_extents, RID, const Vector3 &) + FUNC2(decal_set_size, RID, const Vector3 &) FUNC3(decal_set_texture, RID, DecalTexture, RID) FUNC2(decal_set_emission_energy, RID, float) FUNC2(decal_set_albedo_mix, RID, float) @@ -540,7 +540,7 @@ public: FUNCRIDSPLIT(fog_volume) FUNC2(fog_volume_set_shape, RID, FogVolumeShape) - FUNC2(fog_volume_set_extents, RID, const Vector3 &) + FUNC2(fog_volume_set_size, RID, const Vector3 &) FUNC2(fog_volume_set_material, RID, RID) /* VISIBILITY_NOTIFIER */ @@ -608,7 +608,7 @@ public: FUNC1RC(RID, viewport_get_texture, RID) FUNC2(viewport_set_disable_2d, RID, bool) - FUNC2(viewport_set_disable_environment, RID, bool) + FUNC2(viewport_set_environment_mode, RID, ViewportEnvironmentMode) FUNC2(viewport_set_disable_3d, RID, bool) FUNC2(viewport_set_canvas_cull_mask, RID, uint32_t) @@ -854,7 +854,7 @@ public: FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float) FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &) FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) - FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) + FUNC5(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int) FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID) @@ -986,6 +986,7 @@ public: virtual double get_frame_setup_time_cpu() const override; virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override; + virtual Color get_default_clear_color() override; virtual void set_default_clear_color(const Color &p_color) override; virtual bool has_feature(Features p_feature) const override; diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 57215d9d63..2710724066 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -909,9 +909,6 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (p_default_actions.renames.has(vnode->name)) { code = p_default_actions.renames[vnode->name]; - if (vnode->name == "SCREEN_TEXTURE") { - r_gen_code.uses_screen_texture_mipmaps = true; - } } else { if (shader->uniforms.has(vnode->name)) { //its a uniform! @@ -919,29 +916,22 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene if (u.texture_order >= 0) { StringName name = vnode->name; if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) { - name = "SCREEN_TEXTURE"; + name = "color_buffer"; if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) { r_gen_code.uses_screen_texture_mipmaps = true; } + r_gen_code.uses_screen_texture = true; } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) { - name = "NORMAL_ROUGHNESS_TEXTURE"; + name = "normal_roughness_buffer"; + r_gen_code.uses_normal_roughness_texture = true; } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { - name = "DEPTH_TEXTURE"; + name = "depth_buffer"; + r_gen_code.uses_depth_texture = true; } else { name = _mkid(vnode->name); //texture, use as is } - if (p_default_actions.renames.has(name)) { - code = p_default_actions.renames[name]; - } else { - code = name; - } - - if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) { - *p_actions.usage_flag_pointers[name] = true; - used_flag_pointers.insert(name); - } - + code = name; } else { //a scalar or vector if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) { @@ -1183,6 +1173,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene code += "("; + // if color backbuffer, depth backbuffer or normal roughness texture is used, + // we will add logic to automatically switch between + // sampler2D and sampler2D array and vec2 UV and vec3 UV. + bool multiview_uv_needed = false; + for (int i = 1; i < onode->arguments.size(); i++) { if (i > 1) { code += ", "; @@ -1226,8 +1221,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) { - //need to map from texture to sampler in order to sample when using Vulkan GLSL + if (is_texture_func && i == 1) { + // If we're doing a texture lookup we need to check our texture argument StringName texture_uniform; bool correct_texture_uniform = false; @@ -1246,17 +1241,25 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene break; } - if (correct_texture_uniform) { - //TODO Needs to detect screen_texture hint as well - is_screen_texture = (texture_uniform == "SCREEN_TEXTURE"); - + if (correct_texture_uniform && !RS::get_singleton()->is_low_end()) { + // Need to map from texture to sampler in order to sample when using Vulkan GLSL. String sampler_name; + bool is_depth_texture = false; + bool is_normal_roughness_texture = false; if (actions.custom_samplers.has(texture_uniform)) { sampler_name = actions.custom_samplers[texture_uniform]; } else { if (shader->uniforms.has(texture_uniform)) { - sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat); + const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform]; + if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) { + is_screen_texture = true; + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + is_depth_texture = true; + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) { + is_normal_roughness_texture = true; + } + sampler_name = _get_sampler_name(u.filter, u.repeat); } else { bool found = false; @@ -1282,10 +1285,39 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } } - code += ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype()) + "(" + node_code + ", " + sampler_name + ")"; + String data_type_name = ""; + if (actions.check_multiview_samplers && (is_screen_texture || is_depth_texture || is_normal_roughness_texture)) { + data_type_name = "multiviewSampler"; + multiview_uv_needed = true; + } else { + data_type_name = ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype()); + } + + code += data_type_name + "(" + node_code + ", " + sampler_name + ")"; + } else if (actions.check_multiview_samplers && correct_texture_uniform && RS::get_singleton()->is_low_end()) { + // Texture function on low end hardware (i.e. OpenGL). + // We just need to know if the texture supports multiview. + + if (shader->uniforms.has(texture_uniform)) { + const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform]; + if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) { + multiview_uv_needed = true; + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) { + multiview_uv_needed = true; + } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) { + multiview_uv_needed = true; + } + } + + code += node_code; } else { code += node_code; } + } else if (multiview_uv_needed && i == 2) { + // UV coordinate after using color, depth or normal roughness texture. + node_code = "multiview_uv(" + node_code + ".xy)"; + + code += node_code; } else { code += node_code; } @@ -1498,6 +1530,9 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident r_gen_code.uses_vertex_time = false; r_gen_code.uses_global_textures = false; r_gen_code.uses_screen_texture_mipmaps = false; + r_gen_code.uses_screen_texture = false; + r_gen_code.uses_depth_texture = false; + r_gen_code.uses_normal_roughness_texture = false; used_name_defines.clear(); used_rmode_defines.clear(); diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h index eeb2916160..3bb29a545b 100644 --- a/servers/rendering/shader_compiler.h +++ b/servers/rendering/shader_compiler.h @@ -81,6 +81,9 @@ public: bool uses_fragment_time; bool uses_vertex_time; bool uses_screen_texture_mipmaps; + bool uses_screen_texture; + bool uses_depth_texture; + bool uses_normal_roughness_texture; }; struct DefaultIdentifierActions { @@ -98,6 +101,7 @@ public: String instance_uniform_index_variable; uint32_t base_varying_index = 0; bool apply_luminance_multiplier = false; + bool check_multiview_samplers = false; }; private: diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 59a2ff66f3..a727e83513 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -90,8 +90,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "IDENTIFIER", "TRUE", "FALSE", - "REAL_CONSTANT", + "FLOAT_CONSTANT", "INT_CONSTANT", + "UINT_CONSTANT", "TYPE_VOID", "TYPE_BOOL", "TYPE_BVEC2", @@ -126,6 +127,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "INTERPOLATION_FLAT", "INTERPOLATION_SMOOTH", "CONST", + "STRUCT", "PRECISION_LOW", "PRECISION_MID", "PRECISION_HIGH", @@ -169,6 +171,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "CF_DO", "CF_SWITCH", "CF_CASE", + "CF_DEFAULT", "CF_BREAK", "CF_CONTINUE", "CF_RETURN", @@ -185,19 +188,26 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "SEMICOLON", "PERIOD", "UNIFORM", + "UNIFORM_GROUP", "INSTANCE", "GLOBAL", "VARYING", - "IN", - "OUT", - "INOUT", + "ARG_IN", + "ARG_OUT", + "ARG_INOUT", "RENDER_MODE", - "SOURCE_COLOR", "HINT_DEFAULT_WHITE_TEXTURE", "HINT_DEFAULT_BLACK_TEXTURE", "HINT_DEFAULT_TRANSPARENT_TEXTURE", "HINT_NORMAL_TEXTURE", + "HINT_ROUGHNESS_NORMAL_TEXTURE", + "HINT_ROUGHNESS_R", + "HINT_ROUGHNESS_G", + "HINT_ROUGHNESS_B", + "HINT_ROUGHNESS_A", + "HINT_ROUGHNESS_GRAY", "HINT_ANISOTROPY_TEXTURE", + "HINT_SOURCE_COLOR", "HINT_RANGE", "HINT_INSTANCE_INDEX", "HINT_SCREEN_TEXTURE", @@ -612,7 +622,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { char_idx += 2; include_positions.resize(include_positions.size() - 1); // Pop back. - tk_line = include_positions[include_positions.size() - 1].line; // Restore line. + tk_line = include_positions[include_positions.size() - 1].line - 1; // Restore line. } else { return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)"); @@ -1215,7 +1225,7 @@ void ShaderLanguage::clear() { char_idx = 0; error_set = false; error_str = ""; - last_const = false; + is_const_decl = false; while (nodes) { Node *n = nodes; nodes = nodes->next; @@ -2827,6 +2837,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, + // dFdxCoarse + + { "dFdxCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + + // dFdxFine + + { "dFdxFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdxFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // dFdy { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, @@ -2834,6 +2858,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, + // dFdyCoarse + + { "dFdyCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + + // dFdyFine + + { "dFdyFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "dFdyFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // fwidth { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, @@ -2841,6 +2879,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false }, + // fwidthCoarse + + { "fwidthCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + + // fwidthFine + + { "fwidthFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + { "fwidthFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true }, + // Sub-functions. // array @@ -2849,10 +2901,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { // Modern functions. // fma - { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, - { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, - { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, - { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, false }, + { "fma", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, + { "fma", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "a", "b", "c" }, TAG_GLOBAL, true }, // Packing/Unpacking functions. @@ -3509,6 +3561,14 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Functio return false; } + if (is_const_decl && arg->type == Node::TYPE_VARIABLE) { + const VariableNode *var = static_cast<const VariableNode *>(arg); + if (!var->is_const) { + _set_error(RTR("Expected constant expression.")); + return false; + } + } + p_func->arguments.push_back(arg); tk = _get_token(); @@ -4478,14 +4538,14 @@ bool ShaderLanguage::_check_node_constness(const Node *p_node) const { case Node::TYPE_CONSTANT: break; case Node::TYPE_VARIABLE: { - const VariableNode *varn = static_cast<const VariableNode *>(p_node); - if (!varn->is_const) { + const VariableNode *var_node = static_cast<const VariableNode *>(p_node); + if (!var_node->is_const) { return false; } } break; case Node::TYPE_ARRAY: { - const ArrayNode *arrn = static_cast<const ArrayNode *>(p_node); - if (!arrn->is_const) { + const ArrayNode *arr_node = static_cast<const ArrayNode *>(p_node); + if (!arr_node->is_const) { return false; } } break; @@ -5132,6 +5192,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons expr = func; } else { //a function call + if (p_block == nullptr) { // Non-constructor function call in global space is forbidden. + if (is_const_decl) { + _set_error(RTR("Expected constant expression.")); + } + return nullptr; + } const StringName &name = identifier; @@ -5399,9 +5465,19 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } else { if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { + if (identifier == "SCREEN_TEXTURE" || identifier == "DEPTH_TEXTURE" || identifier == "NORMAL_ROUGHNESS_TEXTURE") { + String name = String(identifier); + String name_lower = name.to_lower(); + _set_error(vformat(RTR("%s has been removed in favor of using hint_%s with a uniform.\nTo continue with minimal code changes add 'uniform sampler2D %s : hint_%s, filter_linear_mipmap;' near the top of your shader."), name, name_lower, name, name_lower)); + return nullptr; + } _set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier))); return nullptr; } + if (is_const_decl && !is_const) { + _set_error(RTR("Expected constant expression.")); + return nullptr; + } if (ident_type == IDENTIFIER_VARYING) { TkPos prev_pos = _get_tkpos(); Token next_token = _get_token(); @@ -6477,7 +6553,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_function_info)) { - _set_error(RTR("Can't use increment/decrement operator in a constant expression.")); + _set_error(RTR("Invalid use of increment/decrement operator in a constant expression.")); return nullptr; } op->arguments.push_back(expression[i + 1].node); @@ -6919,6 +6995,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun } } #endif // DEBUG_ENABLED + is_const_decl = is_const; BlockNode::Variable var; var.type = type; @@ -7175,6 +7252,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun vdnode->declarations.push_back(decl); p_block->variables[name] = var; + is_const_decl = false; if (!fixed_array_size) { array_size = 0; @@ -8227,6 +8305,10 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier)); return ERR_PARSE_ERROR; } + if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + _set_error(RTR("Uniform instances are not supported in gl_compatibility shaders.")); + return ERR_PARSE_ERROR; + } if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) { tk = _get_token(); if (tk.type != TK_UNIFORM) { @@ -8339,7 +8421,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f _set_error(vformat(RTR("The '%s' data type is not supported for uniforms."), "struct")); return ERR_PARSE_ERROR; } else { - _set_error(vformat(RTR("The '%s' data type not allowed here."), "struct")); + _set_error(vformat(RTR("The '%s' data type is not allowed here."), "struct")); return ERR_PARSE_ERROR; } } @@ -8691,14 +8773,21 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f case TK_HINT_SCREEN_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE; --texture_uniforms; + --texture_binding; } break; case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE; --texture_uniforms; + --texture_binding; + if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") { + _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders.")); + return ERR_PARSE_ERROR; + } } break; case TK_HINT_DEPTH_TEXTURE: { new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE; --texture_uniforms; + --texture_binding; } break; case TK_FILTER_NEAREST: { new_filter = FILTER_NEAREST; @@ -9032,6 +9121,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f constant.precision = precision; constant.initializer = nullptr; constant.array_size = array_size; + is_const_decl = true; if (tk.type == TK_BRACKET_OPEN) { Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size); @@ -9291,6 +9381,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f unknown_size = false; } else if (tk.type == TK_SEMICOLON) { + is_const_decl = false; break; } else { _set_expected_error(",", ";"); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 32e497aa46..aea61e42c3 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -953,7 +953,7 @@ private: StringName shader_type_identifier; StringName current_function; - bool last_const = false; + bool is_const_decl = false; StringName last_name; bool is_shader_inc = false; diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp index 40c8acffe5..b45a7c0db3 100644 --- a/servers/rendering/shader_preprocessor.cpp +++ b/servers/rendering/shader_preprocessor.cpp @@ -78,19 +78,46 @@ char32_t ShaderPreprocessor::Tokenizer::peek() { return 0; } +int ShaderPreprocessor::Tokenizer::consume_line_continuations(int p_offset) { + int skips = 0; + + for (int i = index + p_offset; i < size; i++) { + char32_t c = code[i]; + if (c == '\\') { + if (i + 1 < size && code[i + 1] == '\n') { + // This line ends with "\" and "\n" continuation. + add_generated(Token('\n', line)); + line++; + skips++; + + i = i + 2; + index = i; + } else { + break; + } + } else if (!is_whitespace(c)) { + break; + } + } + return skips; +} + LocalVector<ShaderPreprocessor::Token> ShaderPreprocessor::Tokenizer::advance(char32_t p_what) { LocalVector<ShaderPreprocessor::Token> tokens; while (index < size) { char32_t c = code[index++]; - - tokens.push_back(ShaderPreprocessor::Token(c, line)); + if (c == '\\' && consume_line_continuations(-1) > 0) { + continue; + } if (c == '\n') { add_generated(ShaderPreprocessor::Token('\n', line)); line++; } + tokens.push_back(ShaderPreprocessor::Token(c, line)); + if (c == p_what || c == 0) { return tokens; } @@ -104,6 +131,11 @@ void ShaderPreprocessor::Tokenizer::skip_whitespace() { } } +bool ShaderPreprocessor::Tokenizer::consume_empty_line() { + // Read until newline and return true if the content was all whitespace/empty. + return tokens_to_string(advance('\n')).strip_edges().size() == 0; +} + String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_started) { if (r_is_cursor != nullptr) { *r_is_cursor = false; @@ -113,6 +145,10 @@ String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_s while (true) { char32_t c = peek(); + if (c == '\\' && consume_line_continuations(0) > 0) { + continue; + } + if (is_char_end(c) || c == '(' || c == ')' || c == ',' || c == ';') { break; } @@ -146,8 +182,10 @@ String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_s String ShaderPreprocessor::Tokenizer::peek_identifier() { const int original = index; + const int original_line = line; String id = get_identifier(); index = original; + line = original_line; return id; } @@ -330,8 +368,8 @@ String ShaderPreprocessor::vector_to_string(const LocalVector<char32_t> &p_v, in String ShaderPreprocessor::tokens_to_string(const LocalVector<Token> &p_tokens) { LocalVector<char32_t> result; - for (uint32_t i = 0; i < p_tokens.size(); i++) { - result.push_back(p_tokens[i].text); + for (const Token &token : p_tokens) { + result.push_back(token.text); } return vector_to_string(result); } @@ -485,7 +523,9 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { state->previous_region->to_line = line - 1; } - p_tokenizer->advance('\n'); + if (!p_tokenizer->consume_empty_line()) { + set_error(RTR("Invalid else."), p_tokenizer->get_line()); + } bool skip = false; for (int i = 0; i < state->current_branch->conditions.size(); i++) { @@ -508,17 +548,21 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) { } void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) { + const int line = p_tokenizer->get_line(); + state->condition_depth--; if (state->condition_depth < 0) { - set_error(RTR("Unmatched endif."), p_tokenizer->get_line()); + set_error(RTR("Unmatched endif."), line); return; } if (state->previous_region != nullptr) { - state->previous_region->to_line = p_tokenizer->get_line() - 1; + state->previous_region->to_line = line - 1; state->previous_region = state->previous_region->parent; } - p_tokenizer->advance('\n'); + if (!p_tokenizer->consume_empty_line()) { + set_error(RTR("Invalid endif."), line); + } state->current_branch = state->current_branch->parent; state->branches.pop_back(); @@ -574,12 +618,10 @@ void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) { return; } - p_tokenizer->skip_whitespace(); - if (!is_char_end(p_tokenizer->peek())) { + if (!p_tokenizer->consume_empty_line()) { set_error(RTR("Invalid ifdef."), line); return; } - p_tokenizer->advance('\n'); bool success = state->defines.has(label); start_branch_condition(p_tokenizer, success); @@ -598,12 +640,10 @@ void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) { return; } - p_tokenizer->skip_whitespace(); - if (!is_char_end(p_tokenizer->peek())) { + if (!p_tokenizer->consume_empty_line()) { set_error(RTR("Invalid ifndef."), line); return; } - p_tokenizer->advance('\n'); bool success = !state->defines.has(label); start_branch_condition(p_tokenizer, success); @@ -628,13 +668,17 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) { } } path = path.substr(0, path.length() - 1); - p_tokenizer->skip_whitespace(); - if (path.is_empty() || !is_char_end(p_tokenizer->peek())) { + if (path.is_empty() || !p_tokenizer->consume_empty_line()) { set_error(RTR("Invalid path."), line); return; } + path = path.simplify_path(); + if (path.is_relative_path()) { + path = state->current_filename.get_base_dir().path_join(path); + } + Ref<Resource> res = ResourceLoader::load(path); if (res.is_null()) { set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line); @@ -728,25 +772,24 @@ void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) { return; } - p_tokenizer->advance('\n'); + if (!p_tokenizer->consume_empty_line()) { + set_error(RTR("Invalid pragma directive."), line); + return; + } } void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) { const int line = p_tokenizer->get_line(); const String label = p_tokenizer->get_identifier(); - if (label.is_empty() || !state->defines.has(label)) { - set_error(RTR("Invalid name."), line); - return; - } - - p_tokenizer->skip_whitespace(); - if (!is_char_end(p_tokenizer->peek())) { + if (label.is_empty() || !p_tokenizer->consume_empty_line()) { set_error(RTR("Invalid undef."), line); return; } - memdelete(state->defines[label]); - state->defines.erase(label); + if (state->defines.has(label)) { + memdelete(state->defines[label]); + state->defines.erase(label); + } } void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent_region) { @@ -957,15 +1000,57 @@ bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_num String body = define->body; if (define->arguments.size() > 0) { // Complex macro with arguments. - int args_start = index + key.length(); - int args_end = p_line.find(")", args_start); - if (args_start == -1 || args_end == -1) { - set_error(RTR("Missing macro argument parenthesis."), p_line_number); - return false; + + int args_start = -1; + int args_end = -1; + int brackets_open = 0; + Vector<String> args; + for (int i = index_start - 1; i < p_line.length(); i++) { + bool add_argument = false; + bool reached_end = false; + char32_t c = p_line[i]; + + if (c == '(') { + brackets_open++; + if (brackets_open == 1) { + args_start = i + 1; + args_end = -1; + } + } else if (c == ')') { + brackets_open--; + if (brackets_open == 0) { + args_end = i; + add_argument = true; + reached_end = true; + } + } else if (c == ',') { + if (brackets_open == 1) { + args_end = i; + add_argument = true; + } + } + + if (add_argument) { + if (args_start == -1 || args_end == -1) { + set_error(RTR("Invalid macro argument list."), p_line_number); + return false; + } + + String arg = p_line.substr(args_start, args_end - args_start).strip_edges(); + if (arg.is_empty()) { + set_error(RTR("Invalid macro argument."), p_line_number); + return false; + } + args.append(arg); + + args_start = args_end + 1; + } + + if (reached_end) { + break; + } } - String values = result.substr(args_start + 1, args_end - (args_start + 1)); - Vector<String> args = values.split(","); if (args.size() != define->arguments.size()) { set_error(RTR("Invalid macro argument count."), p_line_number); return false; @@ -987,9 +1072,6 @@ bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_num result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length()); } else { result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length())); - // Manually reset index_start to where the body value of the define finishes. - // This ensures we don't skip another instance of this macro in the string. - index_start = index + body.length() + 1; } r_expanded = result; @@ -1081,21 +1163,17 @@ ShaderPreprocessor::Define *ShaderPreprocessor::create_define(const String &p_bo return define; } -void ShaderPreprocessor::clear() { - if (state_owner && state != nullptr) { +void ShaderPreprocessor::clear_state() { + if (state != nullptr) { for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) { memdelete(E->get()); } - - memdelete(state); + state->defines.clear(); } - state_owner = false; state = nullptr; } Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, String &r_result) { - clear(); - output.clear(); state = p_state; @@ -1242,6 +1320,9 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen } } } + + clear_state(); + return err; } @@ -1273,5 +1354,4 @@ ShaderPreprocessor::ShaderPreprocessor() { } ShaderPreprocessor::~ShaderPreprocessor() { - clear(); } diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h index f5902c64ca..f198af66f0 100644 --- a/servers/rendering/shader_preprocessor.h +++ b/servers/rendering/shader_preprocessor.h @@ -93,11 +93,13 @@ private: int get_line() const; int get_index() const; char32_t peek(); + int consume_line_continuations(int p_offset); void get_and_clear_generated(Vector<Token> *r_out); void backtrack(char32_t p_what); LocalVector<Token> advance(char32_t p_what); void skip_whitespace(); + bool consume_empty_line(); String get_identifier(bool *r_is_cursor = nullptr, bool p_started = false); String peek_identifier(); Token get_token(); @@ -167,7 +169,6 @@ private: private: LocalVector<char32_t> output; State *state = nullptr; - bool state_owner = false; private: static bool is_char_word(char32_t p_char); @@ -181,7 +182,7 @@ private: } void _set_unexpected_token_error(const String &p_what, int p_line) { - set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line); + set_error(vformat(RTR("Unexpected token: '%s'."), p_what), p_line); } void process_directive(Tokenizer *p_tokenizer); @@ -211,7 +212,7 @@ private: static Define *create_define(const String &p_body); - void clear(); + void clear_state(); Error preprocess(State *p_state, const String &p_code, String &r_result); diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 38dc806370..56d00fa1bb 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -106,6 +106,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["EYE_OFFSET"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); @@ -138,9 +139,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); @@ -154,6 +152,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EYE_OFFSET"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); @@ -267,7 +266,6 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].main_function = true; @@ -468,7 +466,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["WORLD_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["OBJECT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["UVW"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EXTENTS"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SIZE"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["SDF"] = constt(ShaderLanguage::TYPE_FLOAT); shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["DENSITY"] = ShaderLanguage::TYPE_FLOAT; diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h index 413f06bc5b..5bd4297179 100644 --- a/servers/rendering/storage/light_storage.h +++ b/servers/rendering/storage/light_storage.h @@ -84,6 +84,7 @@ public: virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0; virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0; virtual uint64_t light_get_version(RID p_light) const = 0; + virtual uint32_t light_get_cull_mask(RID p_light) const = 0; /* LIGHT INSTANCE API */ @@ -110,7 +111,7 @@ public: virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; + virtual void reflection_probe_set_size(RID p_probe, const Vector3 &p_size) = 0; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; @@ -121,7 +122,7 @@ public: virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0; virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0; + virtual Vector3 reflection_probe_get_size(RID p_probe) const = 0; virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0; virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0; virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h index 704c2e015c..76e46a696a 100644 --- a/servers/rendering/storage/mesh_storage.h +++ b/servers/rendering/storage/mesh_storage.h @@ -83,6 +83,7 @@ public: virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0; virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0; virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0; + virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) = 0; virtual void update_mesh_instances() = 0; /* MULTIMESH API */ diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp index 1320199833..6369139aa6 100644 --- a/servers/rendering/storage/render_scene_buffers.cpp +++ b/servers/rendering/storage/render_scene_buffers.cpp @@ -34,8 +34,8 @@ void RenderSceneBuffers::_bind_methods() { ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure); } -void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { - GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count); +void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { + GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_scaling_3d_mode, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count); }; void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) { diff --git a/servers/rendering/storage/render_scene_buffers.h b/servers/rendering/storage/render_scene_buffers.h index 83fc78ca1c..cf96a9f372 100644 --- a/servers/rendering/storage/render_scene_buffers.h +++ b/servers/rendering/storage/render_scene_buffers.h @@ -40,7 +40,7 @@ class RenderSceneBuffers : public RefCounted { protected: static void _bind_methods(); - GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t) + GDVIRTUAL11(_configure, RID, Size2i, Size2i, RS::ViewportScaling3DMode, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t) GDVIRTUAL1(_set_fsr_sharpness, float) GDVIRTUAL1(_set_texture_mipmap_bias, float) GDVIRTUAL1(_set_use_debanding, bool) @@ -49,7 +49,7 @@ public: RenderSceneBuffers(){}; virtual ~RenderSceneBuffers(){}; - virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count); + virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count); // for those settings that are unlikely to require buffers to be recreated, we'll add setters virtual void set_fsr_sharpness(float p_fsr_sharpness); diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 92149b0064..227d44aa27 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -107,7 +107,7 @@ public: virtual void decal_initialize(RID p_rid) = 0; virtual void decal_free(RID p_rid) = 0; - virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0; + virtual void decal_set_size(RID p_decal, const Vector3 &p_size) = 0; virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0; virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0; virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0; @@ -118,6 +118,7 @@ public: virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0; virtual AABB decal_get_aabb(RID p_decal) const = 0; + virtual uint32_t decal_get_cull_mask(RID p_decal) const = 0; virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0; @@ -127,6 +128,7 @@ public: virtual RID decal_instance_create(RID p_decal) = 0; virtual void decal_instance_free(RID p_decal_instance) = 0; virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) = 0; + virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) = 0; /* RENDER TARGET */ |