summaryrefslogtreecommitdiff
path: root/servers/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering')
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp20
-rw-r--r--servers/rendering/renderer_canvas_cull.h4
-rw-r--r--servers/rendering/renderer_canvas_render.cpp4
-rw-r--r--servers/rendering/renderer_canvas_render.h4
-rw-r--r--servers/rendering/renderer_compositor.cpp4
-rw-r--r--servers/rendering/renderer_compositor.h4
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp550
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h378
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp107
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h17
-rw-r--r--servers/rendering/renderer_rd/light_cluster_builder.cpp252
-rw-r--r--servers/rendering/renderer_rd/light_cluster_builder.h290
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp19
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp8
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward.cpp1671
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_forward.h413
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1150
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h202
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp265
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h103
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp12
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.h4
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp127
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h7
-rw-r--r--servers/rendering/renderer_rd/shaders/SCsub3
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_debug.glsl115
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_render.glsl168
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_store.glsl119
-rw-r--r--servers/rendering/renderer_rd/shaders/cube_to_dp.glsl45
-rw-r--r--servers/rendering/renderer_rd/shaders/gi.glsl75
-rw-r--r--servers/rendering/renderer_rd/shaders/giprobe.glsl11
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/resolve.glsl112
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward.glsl1676
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl110
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl107
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl160
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl184
-rw-r--r--servers/rendering/renderer_rd/shaders/ssao.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/volumetric_fog.glsl260
-rw-r--r--servers/rendering/renderer_scene.cpp4
-rw-r--r--servers/rendering/renderer_scene.h11
-rw-r--r--servers/rendering/renderer_scene_cull.cpp868
-rw-r--r--servers/rendering/renderer_scene_cull.h299
-rw-r--r--servers/rendering/renderer_scene_render.cpp4
-rw-r--r--servers/rendering/renderer_scene_render.h132
-rw-r--r--servers/rendering/renderer_storage.cpp27
-rw-r--r--servers/rendering/renderer_storage.h92
-rw-r--r--servers/rendering/renderer_thread_pool.cpp42
-rw-r--r--servers/rendering/renderer_thread_pool.h45
-rw-r--r--servers/rendering/renderer_viewport.cpp9
-rw-r--r--servers/rendering/renderer_viewport.h7
-rw-r--r--servers/rendering/rendering_device.cpp20
-rw-r--r--servers/rendering/rendering_device.h18
-rw-r--r--servers/rendering/rendering_device_binds.cpp6
-rw-r--r--servers/rendering/rendering_device_binds.h4
-rw-r--r--servers/rendering/rendering_server_default.cpp56
-rw-r--r--servers/rendering/rendering_server_default.h24
-rw-r--r--servers/rendering/rendering_server_globals.cpp4
-rw-r--r--servers/rendering/rendering_server_globals.h4
-rw-r--r--servers/rendering/rendering_server_wrap_mt.cpp4
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h18
-rw-r--r--servers/rendering/shader_language.cpp14
-rw-r--r--servers/rendering/shader_language.h4
-rw-r--r--servers/rendering/shader_types.cpp14
-rw-r--r--servers/rendering/shader_types.h4
72 files changed, 6790 insertions, 3766 deletions
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index ea6ed2b532..2d2847e6ca 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -524,7 +524,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!line);
if (p_width > 1.001) {
- Vector2 t = (p_from - p_to).tangent().normalized();
+ Vector2 t = (p_from - p_to).orthogonal().normalized();
line->points[0] = p_from + t * p_width;
line->points[1] = p_from - t * p_width;
line->points[2] = p_to - t * p_width;
@@ -600,7 +600,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
if (i == pc - 1) {
t = prev_t;
} else {
- t = (p_points[i + 1] - p_points[i]).normalized().tangent();
+ t = (p_points[i + 1] - p_points[i]).normalized().orthogonal();
if (i == 0) {
prev_t = t;
}
@@ -650,7 +650,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
if (i == pc - 1) {
t = prev_t;
} else {
- t = (p_points[i + 1] - p_points[i]).normalized().tangent();
+ t = (p_points[i + 1] - p_points[i]).normalized().orthogonal();
if (i == 0) {
prev_t = t;
}
@@ -874,7 +874,7 @@ void RendererCanvasCull::canvas_item_add_polygon(RID p_item, const Vector<Point2
ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount));
#endif
Vector<int> indices = Geometry2D::triangulate_polygon(p_points);
- ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed.");
+ ERR_FAIL_COND_MSG(indices.is_empty(), "Invalid polygon data, triangulation failed.");
Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();
ERR_FAIL_COND(!polygon);
@@ -889,10 +889,10 @@ void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector
int vertex_count = p_points.size();
ERR_FAIL_COND(vertex_count == 0);
- ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1);
- ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count);
- ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4);
- ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4);
+ ERR_FAIL_COND(!p_colors.is_empty() && p_colors.size() != vertex_count && p_colors.size() != 1);
+ ERR_FAIL_COND(!p_uvs.is_empty() && p_uvs.size() != vertex_count);
+ ERR_FAIL_COND(!p_bones.is_empty() && p_bones.size() != vertex_count * 4);
+ ERR_FAIL_COND(!p_weights.is_empty() && p_weights.size() != vertex_count * 4);
Vector<int> indices = p_indices;
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index ec2389bcb5..7496a413ee 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 9c7251763d..1945435586 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index ca95abcf65..f08986b021 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index e8c4a236fa..8861522d34 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index f328330efa..919ae2c6da 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
new file mode 100644
index 0000000000..8d9cff0f43
--- /dev/null
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -0,0 +1,550 @@
+/*************************************************************************/
+/* cluster_builder_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "cluster_builder_rd.h"
+#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/rendering_server_globals.h"
+
+ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
+ RD::VertexFormatID vertex_format;
+
+ {
+ Vector<RD::VertexAttribute> attributes;
+ {
+ RD::VertexAttribute va;
+ va.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ va.stride = sizeof(float) * 3;
+ attributes.push_back(va);
+ }
+ vertex_format = RD::get_singleton()->vertex_format_create(attributes);
+ }
+
+ {
+ Vector<String> versions;
+ versions.push_back("");
+ cluster_render.cluster_render_shader.initialize(versions);
+ cluster_render.shader_version = cluster_render.cluster_render_shader.version_create();
+ cluster_render.shader = cluster_render.cluster_render_shader.version_get_shader(cluster_render.shader_version, 0);
+ cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, RD::get_singleton()->framebuffer_format_create_empty(), vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState(), 0);
+ RD::PipelineMultisampleState ms;
+ ms.sample_count = RD::TEXTURE_SAMPLES_4;
+ cluster_render.shader_pipelines[ClusterRender::PIPELINE_MSAA] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, RD::get_singleton()->framebuffer_format_create_empty(), vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), ms, RD::PipelineDepthStencilState(), RD::PipelineColorBlendState(), 0);
+ }
+ {
+ Vector<String> versions;
+ versions.push_back("");
+ cluster_store.cluster_store_shader.initialize(versions);
+ cluster_store.shader_version = cluster_store.cluster_store_shader.version_create();
+ cluster_store.shader = cluster_store.cluster_store_shader.version_get_shader(cluster_store.shader_version, 0);
+ cluster_store.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_store.shader);
+ }
+ {
+ Vector<String> versions;
+ versions.push_back("");
+ cluster_debug.cluster_debug_shader.initialize(versions);
+ cluster_debug.shader_version = cluster_debug.cluster_debug_shader.version_create();
+ cluster_debug.shader = cluster_debug.cluster_debug_shader.version_get_shader(cluster_debug.shader_version, 0);
+ cluster_debug.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_debug.shader);
+ }
+
+ { // SPHERE
+ 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
+ };
+ static const uint32_t icosphere_triangle_count = 80;
+ static const uint32_t icosphere_triangle_indices[icosphere_triangle_count * 3] = {
+ 0, 13, 12, 1, 13, 15, 0, 12, 17, 0, 17, 19, 0, 19, 16, 1, 15, 22, 2, 14, 24, 3, 18, 26, 4, 20, 28, 5, 21, 30, 1, 22, 25, 2, 24, 27, 3, 26, 29, 4, 28, 31, 5, 30, 23, 6, 32, 37, 7, 33, 39, 8, 34, 40, 9, 35, 41, 10, 36, 38, 38, 41, 11, 38, 36, 41, 36, 9, 41, 41, 40, 11, 41, 35, 40, 35, 8, 40, 40, 39, 11, 40, 34, 39, 34, 7, 39, 39, 37, 11, 39, 33, 37, 33, 6, 37, 37, 38, 11, 37, 32, 38, 32, 10, 38, 23, 36, 10, 23, 30, 36, 30, 9, 36, 31, 35, 9, 31, 28, 35, 28, 8, 35, 29, 34, 8, 29, 26, 34, 26, 7, 34, 27, 33, 7, 27, 24, 33, 24, 6, 33, 25, 32, 6, 25, 22, 32, 22, 10, 32, 30, 31, 9, 30, 21, 31, 21, 4, 31, 28, 29, 8, 28, 20, 29, 20, 3, 29, 26, 27, 7, 26, 18, 27, 18, 2, 27, 24, 25, 6, 24, 14, 25, 14, 1, 25, 22, 23, 10, 22, 15, 23, 15, 5, 23, 16, 21, 5, 16, 19, 21, 19, 4, 21, 19, 20, 4, 19, 17, 20, 17, 3, 20, 17, 18, 3, 17, 12, 18, 12, 2, 18, 15, 16, 5, 15, 13, 16, 13, 0, 16, 12, 14, 2, 12, 13, 14, 13, 1, 14
+ };
+
+ Vector<uint8_t> vertex_data;
+ vertex_data.resize(sizeof(float) * icosphere_vertex_count * 3);
+ copymem(vertex_data.ptrw(), icosphere_vertices, vertex_data.size());
+
+ sphere_vertex_buffer = RD::get_singleton()->vertex_buffer_create(vertex_data.size(), vertex_data);
+
+ Vector<uint8_t> index_data;
+ index_data.resize(sizeof(uint32_t) * icosphere_triangle_count * 3);
+ copymem(index_data.ptrw(), icosphere_triangle_indices, index_data.size());
+
+ sphere_index_buffer = RD::get_singleton()->index_buffer_create(icosphere_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT32, index_data);
+
+ Vector<RID> buffers;
+ buffers.push_back(sphere_vertex_buffer);
+
+ sphere_vertex_array = RD::get_singleton()->vertex_array_create(icosphere_vertex_count, vertex_format, buffers);
+
+ sphere_index_array = RD::get_singleton()->index_array_create(sphere_index_buffer, 0, icosphere_triangle_count * 3);
+
+ float min_d = 1e20;
+ for (uint32_t i = 0; i < icosphere_triangle_count; i++) {
+ Vector3 vertices[3];
+ for (uint32_t j = 0; j < 3; j++) {
+ uint32_t index = icosphere_triangle_indices[i * 3 + j];
+ for (uint32_t k = 0; k < 3; k++) {
+ vertices[j][k] = icosphere_vertices[index * 3 + k];
+ }
+ }
+ Plane p(vertices[0], vertices[1], vertices[2]);
+ min_d = MIN(Math::abs(p.d), min_d);
+ }
+ sphere_overfit = 1.0 / min_d;
+ }
+
+ { // CONE
+ 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
+ };
+ static const uint32_t cone_triangle_count = 62;
+ static const uint32_t cone_triangle_indices[cone_triangle_count * 3] = {
+ 0, 23, 1, 1, 23, 2, 2, 23, 3, 3, 23, 4, 4, 23, 5, 5, 23, 6, 6, 23, 7, 7, 23, 8, 8, 23, 9, 9, 23, 10, 10, 23, 11, 11, 23, 12, 12, 23, 13, 13, 23, 14, 14, 23, 15, 15, 23, 16, 16, 23, 17, 17, 23, 18, 18, 23, 19, 19, 23, 20, 20, 23, 21, 21, 23, 22, 22, 23, 24, 24, 23, 25, 25, 23, 26, 26, 23, 27, 27, 23, 28, 28, 23, 29, 29, 23, 30, 30, 23, 31, 31, 23, 32, 32, 23, 0, 7, 15, 24, 32, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 3, 6, 7, 3, 7, 8, 9, 9, 10, 7, 10, 11, 7, 11, 12, 15, 12, 13, 15, 13, 14, 15, 15, 16, 17, 17, 18, 19, 19, 20, 24, 20, 21, 24, 21, 22, 24, 24, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 1, 3, 15, 17, 24, 17, 19, 24, 24, 26, 32, 26, 28, 32, 28, 30, 32, 32, 3, 7, 7, 11, 15, 32, 7, 24
+ };
+
+ Vector<uint8_t> vertex_data;
+ vertex_data.resize(sizeof(float) * cone_vertex_count * 3);
+ copymem(vertex_data.ptrw(), cone_vertices, vertex_data.size());
+
+ cone_vertex_buffer = RD::get_singleton()->vertex_buffer_create(vertex_data.size(), vertex_data);
+
+ Vector<uint8_t> index_data;
+ index_data.resize(sizeof(uint32_t) * cone_triangle_count * 3);
+ copymem(index_data.ptrw(), cone_triangle_indices, index_data.size());
+
+ cone_index_buffer = RD::get_singleton()->index_buffer_create(cone_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT32, index_data);
+
+ Vector<RID> buffers;
+ buffers.push_back(cone_vertex_buffer);
+
+ cone_vertex_array = RD::get_singleton()->vertex_array_create(cone_vertex_count, vertex_format, buffers);
+
+ cone_index_array = RD::get_singleton()->index_array_create(cone_index_buffer, 0, cone_triangle_count * 3);
+
+ float min_d = 1e20;
+ for (uint32_t i = 0; i < cone_triangle_count; i++) {
+ Vector3 vertices[3];
+ int32_t zero_index = -1;
+ for (uint32_t j = 0; j < 3; j++) {
+ uint32_t index = cone_triangle_indices[i * 3 + j];
+ for (uint32_t k = 0; k < 3; k++) {
+ vertices[j][k] = cone_vertices[index * 3 + k];
+ }
+ if (vertices[j] == Vector3()) {
+ zero_index = j;
+ }
+ }
+
+ if (zero_index != -1) {
+ Vector3 a = vertices[(zero_index + 1) % 3];
+ Vector3 b = vertices[(zero_index + 2) % 3];
+ Vector3 c = a + Vector3(0, 0, 1);
+ Plane p(a, b, c);
+ min_d = MIN(Math::abs(p.d), min_d);
+ }
+ }
+ cone_overfit = 1.0 / min_d;
+ }
+
+ { // BOX
+ 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
+ };
+ static const uint32_t box_triangle_count = 12;
+ static const uint32_t box_triangle_indices[box_triangle_count * 3] = {
+ 1, 2, 0, 3, 6, 2, 7, 4, 6, 5, 0, 4, 6, 0, 2, 3, 5, 7, 1, 3, 2, 3, 7, 6, 7, 5, 4, 5, 1, 0, 6, 4, 0, 3, 1, 5
+ };
+
+ Vector<uint8_t> vertex_data;
+ vertex_data.resize(sizeof(float) * box_vertex_count * 3);
+ copymem(vertex_data.ptrw(), box_vertices, vertex_data.size());
+
+ box_vertex_buffer = RD::get_singleton()->vertex_buffer_create(vertex_data.size(), vertex_data);
+
+ Vector<uint8_t> index_data;
+ index_data.resize(sizeof(uint32_t) * box_triangle_count * 3);
+ copymem(index_data.ptrw(), box_triangle_indices, index_data.size());
+
+ box_index_buffer = RD::get_singleton()->index_buffer_create(box_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT32, index_data);
+
+ Vector<RID> buffers;
+ buffers.push_back(box_vertex_buffer);
+
+ box_vertex_array = RD::get_singleton()->vertex_array_create(box_vertex_count, vertex_format, buffers);
+
+ box_index_array = RD::get_singleton()->index_array_create(box_index_buffer, 0, box_triangle_count * 3);
+ }
+}
+ClusterBuilderSharedDataRD::~ClusterBuilderSharedDataRD() {
+ RD::get_singleton()->free(sphere_vertex_buffer);
+ RD::get_singleton()->free(sphere_index_buffer);
+ RD::get_singleton()->free(cone_vertex_buffer);
+ RD::get_singleton()->free(cone_index_buffer);
+ RD::get_singleton()->free(box_vertex_buffer);
+ RD::get_singleton()->free(box_index_buffer);
+
+ cluster_render.cluster_render_shader.version_free(cluster_render.shader_version);
+ cluster_store.cluster_store_shader.version_free(cluster_store.shader_version);
+ cluster_debug.cluster_debug_shader.version_free(cluster_debug.shader_version);
+}
+
+/////////////////////////////
+
+void ClusterBuilderRD::_clear() {
+ if (cluster_buffer.is_null()) {
+ return; //nothing to clear
+ }
+ RD::get_singleton()->free(cluster_buffer);
+ RD::get_singleton()->free(cluster_render_buffer);
+ RD::get_singleton()->free(element_buffer);
+ cluster_buffer = RID();
+ cluster_render_buffer = RID();
+ element_buffer = RID();
+
+ memfree(render_elements);
+
+ render_elements = nullptr;
+ render_element_max = 0;
+ render_element_count = 0;
+
+ RD::get_singleton()->free(framebuffer);
+ framebuffer = RID();
+
+ cluster_render_uniform_set = RID();
+ cluster_store_uniform_set = RID();
+}
+
+void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer) {
+ ERR_FAIL_COND(p_max_elements == 0);
+ ERR_FAIL_COND(p_screen_size.x < 1);
+ ERR_FAIL_COND(p_screen_size.y < 1);
+
+ _clear();
+
+ screen_size = p_screen_size;
+
+ cluster_screen_size.width = (p_screen_size.width - 1) / cluster_size + 1;
+ 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
+ max_elements_by_type += 32 - (max_elements_by_type % 32);
+ }
+
+ cluster_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (max_elements_by_type / 32 + 32) * ELEMENT_TYPE_MAX * 4;
+
+ render_element_max = max_elements_by_type * ELEMENT_TYPE_MAX;
+
+ 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 = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size);
+ cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size);
+
+ render_elements = (RenderElementData *)memalloc(sizeof(RenderElementData *) * render_element_max);
+ render_element_count = 0;
+
+ element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max);
+
+ uint32_t div_value = 1 << divisor;
+ if (use_msaa) {
+ framebuffer = RD::get_singleton()->framebuffer_create_empty(p_screen_size / div_value, RD::TEXTURE_SAMPLES_4);
+ } else {
+ framebuffer = RD::get_singleton()->framebuffer_create_empty(p_screen_size / div_value);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(state_uniform);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(element_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ u.ids.push_back(cluster_render_buffer);
+ uniforms.push_back(u);
+ }
+
+ cluster_render_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shared->cluster_render.shader, 0);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(cluster_render_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.ids.push_back(cluster_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ u.ids.push_back(element_buffer);
+ uniforms.push_back(u);
+ }
+
+ cluster_store_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shared->cluster_store.shader, 0);
+ }
+
+ if (p_color_buffer.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.ids.push_back(cluster_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.ids.push_back(p_color_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 3;
+ u.ids.push_back(p_depth_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 4;
+ u.ids.push_back(p_depth_buffer_sampler);
+ uniforms.push_back(u);
+ }
+
+ debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shared->cluster_debug.shader, 0);
+ } else {
+ debug_uniform_set = RID();
+ }
+}
+
+void ClusterBuilderRD::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) {
+ view_xform = p_view_transform.affine_inverse();
+ projection = p_cam_projection;
+ z_near = projection.get_z_near();
+ z_far = projection.get_z_far();
+ orthogonal = p_cam_projection.is_orthogonal();
+ adjusted_projection = projection;
+ if (!orthogonal) {
+ adjusted_projection.adjust_perspective_znear(0.0001);
+ }
+
+ CameraMatrix correction;
+ correction.set_depth_correction(p_flip_y);
+ projection = correction * projection;
+ adjusted_projection = correction * adjusted_projection;
+
+ //reset counts
+ render_element_count = 0;
+ for (uint32_t i = 0; i < ELEMENT_TYPE_MAX; i++) {
+ cluster_count_by_type[i] = 0;
+ }
+}
+
+void ClusterBuilderRD::bake_cluster() {
+ RENDER_TIMESTAMP(">Bake Cluster");
+
+ //clear cluster buffer
+ RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, true);
+
+ if (render_element_count > 0) {
+ //clear render buffer
+ RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, true);
+
+ { //fill state uniform
+
+ StateUniform state;
+
+ RendererStorageRD::store_camera(adjusted_projection, state.projection);
+ state.inv_z_far = 1.0 / z_far;
+ state.screen_to_clusters_shift = get_shift_from_power_of_2(cluster_size);
+ state.screen_to_clusters_shift -= divisor; //screen is smaller, shift one less
+
+ state.cluster_screen_width = cluster_screen_size.x;
+ state.cluster_depth_offset = (render_element_max / 32);
+ state.cluster_data_size = state.cluster_depth_offset + render_element_max;
+
+ RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, true);
+ }
+
+ //update instances
+
+ RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, true);
+
+ RENDER_TIMESTAMP("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 = {};
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shared->cluster_render.shader_pipelines[use_msaa ? ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_MSAA : ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_NORMAL]);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, cluster_render_uniform_set, 0);
+
+ for (uint32_t i = 0; i < render_element_count;) {
+ push_constant.base_index = i;
+ switch (render_elements[i].type) {
+ case ELEMENT_TYPE_OMNI_LIGHT: {
+ 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);
+ } 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);
+ } break;
+ case ELEMENT_TYPE_DECAL:
+ case ELEMENT_TYPE_REFLECTION_PROBE: {
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->box_vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->box_index_array);
+ } break;
+ }
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant));
+
+ uint32_t instances = 1;
+#if 0
+ for (uint32_t j = i+1; j < element_count; j++) {
+ if (elements[i].type!=elements[j].type) {
+ break;
+ }
+ instances++;
+ }
+#endif
+ RD::get_singleton()->draw_list_draw(draw_list, true, instances);
+ i += instances;
+ }
+ RD::get_singleton()->draw_list_end();
+ }
+ //store elements
+ RENDER_TIMESTAMP("Pack Elements");
+
+ {
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shared->cluster_store.shader_pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cluster_store_uniform_set, 0);
+
+ ClusterBuilderSharedDataRD::ClusterStore::PushConstant push_constant;
+ push_constant.cluster_render_data_size = render_element_max / 32 + render_element_max;
+ push_constant.max_render_element_count_div_32 = render_element_max / 32;
+ push_constant.cluster_screen_size[0] = cluster_screen_size.x;
+ push_constant.cluster_screen_size[1] = cluster_screen_size.y;
+ push_constant.render_element_count_div_32 = render_element_count > 0 ? (render_element_count - 1) / 32 + 1 : 0;
+ push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32;
+ push_constant.pad1 = 0;
+ push_constant.pad2 = 0;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterStore::PushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, cluster_screen_size.x, cluster_screen_size.y, 1, 8, 8, 1);
+
+ RD::get_singleton()->compute_list_end();
+ }
+ }
+ RENDER_TIMESTAMP("<Bake Cluster");
+}
+
+void ClusterBuilderRD::debug(ElementType p_element) {
+ ERR_FAIL_COND(debug_uniform_set.is_null());
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shared->cluster_debug.shader_pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set, 0);
+
+ ClusterBuilderSharedDataRD::ClusterDebug::PushConstant push_constant;
+ push_constant.screen_size[0] = screen_size.x;
+ push_constant.screen_size[1] = screen_size.y;
+ push_constant.cluster_screen_size[0] = cluster_screen_size.x;
+ 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.z_far = z_far;
+ push_constant.z_near = z_near;
+ push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterDebug::PushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, screen_size.x, screen_size.y, 1, 8, 8, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+RID ClusterBuilderRD::get_cluster_buffer() const {
+ return cluster_buffer;
+}
+
+uint32_t ClusterBuilderRD::get_cluster_size() const {
+ return cluster_size;
+}
+
+uint32_t ClusterBuilderRD::get_max_cluster_elements() const {
+ return max_elements_by_type;
+}
+
+void ClusterBuilderRD::set_shared(ClusterBuilderSharedDataRD *p_shared) {
+ shared = p_shared;
+}
+
+ClusterBuilderRD::ClusterBuilderRD() {
+ state_uniform = RD::get_singleton()->uniform_buffer_create(sizeof(StateUniform));
+}
+
+ClusterBuilderRD::~ClusterBuilderRD() {
+ _clear();
+ RD::get_singleton()->free(state_uniform);
+}
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
new file mode 100644
index 0000000000..dc1707b534
--- /dev/null
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -0,0 +1,378 @@
+/*************************************************************************/
+/* cluster_builder_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 CLUSTER_BUILDER_RD_H
+#define CLUSTER_BUILDER_RD_H
+
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/shaders/cluster_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/cluster_render.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/cluster_store.glsl.gen.h"
+
+class ClusterBuilderSharedDataRD {
+ friend class ClusterBuilderRD;
+
+ RID sphere_vertex_buffer;
+ 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
+
+ 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
+
+ RID box_vertex_buffer;
+ RID box_vertex_array;
+ RID box_index_buffer;
+ RID box_index_array;
+
+ enum Divisor {
+ DIVISOR_1,
+ DIVISOR_2,
+ DIVISOR_4,
+ };
+
+ struct ClusterRender {
+ struct PushConstant {
+ uint32_t base_index;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
+ };
+
+ ClusterRenderShaderRD cluster_render_shader;
+ RID shader_version;
+ RID shader;
+ enum PipelineVersion {
+ PIPELINE_NORMAL,
+ PIPELINE_MSAA,
+ PIPELINE_MAX
+ };
+
+ RID shader_pipelines[PIPELINE_MAX];
+ } cluster_render;
+
+ 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 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 pad1;
+ uint32_t pad2;
+ };
+
+ ClusterStoreShaderRD cluster_store_shader;
+ RID shader_version;
+ RID shader;
+ RID shader_pipeline;
+ } cluster_store;
+
+ struct ClusterDebug {
+ struct PushConstant {
+ uint32_t screen_size[2];
+ uint32_t cluster_screen_size[2];
+
+ uint32_t cluster_shift;
+ uint32_t cluster_type;
+ float z_near;
+ float z_far;
+
+ uint32_t orthogonal;
+ uint32_t max_cluster_element_count_div_32;
+ uint32_t pad1;
+ uint32_t pad2;
+ };
+
+ ClusterDebugShaderRD cluster_debug_shader;
+ RID shader_version;
+ RID shader;
+ RID shader_pipeline;
+ } cluster_debug;
+
+public:
+ ClusterBuilderSharedDataRD();
+ ~ClusterBuilderSharedDataRD();
+};
+
+class ClusterBuilderRD {
+public:
+ enum LightType {
+ LIGHT_TYPE_OMNI,
+ LIGHT_TYPE_SPOT
+ };
+
+ enum BoxType {
+ BOX_TYPE_REFLECTION_PROBE,
+ BOX_TYPE_DECAL,
+ };
+
+ enum ElementType {
+ ELEMENT_TYPE_OMNI_LIGHT,
+ ELEMENT_TYPE_SPOT_LIGHT,
+ ELEMENT_TYPE_DECAL,
+ ELEMENT_TYPE_REFLECTION_PROBE,
+ ELEMENT_TYPE_MAX,
+
+ };
+
+private:
+ ClusterBuilderSharedDataRD *shared = nullptr;
+
+ struct RenderElementData {
+ 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 scale[3];
+ uint32_t pad;
+ };
+
+ uint32_t cluster_count_by_type[ELEMENT_TYPE_MAX] = {};
+ uint32_t max_elements_by_type = 0;
+
+ RenderElementData *render_elements = nullptr;
+ uint32_t render_element_count = 0;
+ uint32_t render_element_max = 0;
+
+ Transform view_xform;
+ CameraMatrix adjusted_projection;
+ CameraMatrix projection;
+ float z_far = 0;
+ float z_near = 0;
+ bool orthogonal = false;
+
+ enum Divisor {
+ DIVISOR_1,
+ DIVISOR_2,
+ DIVISOR_4,
+ };
+
+ uint32_t cluster_size = 32;
+ bool use_msaa = true;
+ Divisor divisor = DIVISOR_4;
+
+ Size2i screen_size;
+ 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
+ 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
+
+ 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 cluster_depth_offset;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
+ };
+
+ RID state_uniform;
+
+ RID debug_uniform_set;
+
+public:
+ void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer);
+
+ void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y);
+
+ _FORCE_INLINE_ void add_light(LightType p_type, const Transform &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
+ }
+ if (p_type == LIGHT_TYPE_SPOT && cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT] == max_elements_by_type) {
+ return; //max number elements reached
+ }
+
+ RenderElementData &e = render_elements[render_element_count];
+
+ Transform xform = view_xform * p_transform;
+
+ float radius = xform.basis.get_uniform_scale();
+ if (radius > 0.98 || radius < 1.02) {
+ xform.basis.orthonormalize();
+ }
+
+ radius *= p_radius;
+
+ if (p_type == LIGHT_TYPE_OMNI) {
+ radius *= shared->sphere_overfit; // overfit icosphere
+
+ //omni
+ float depth = -xform.origin.z;
+ if (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)
+ e.touches_near = xform.origin.length_squared() < radius2 * radius2;
+ }
+
+ e.touches_far = (depth + radius) > z_far;
+ e.scale[0] = radius;
+ e.scale[1] = radius;
+ e.scale[2] = radius;
+ e.type = ELEMENT_TYPE_OMNI_LIGHT;
+ e.original_index = cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT];
+
+ RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+
+ cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
+
+ } else {
+ //spot
+ radius *= shared->cone_overfit; // overfit icosphere
+
+ real_t len = Math::tan(Math::deg2rad(p_spot_aperture)) * radius;
+ //approximate, probably better to use a cone support function
+ float max_d = -1e20;
+ float min_d = 1e20;
+#define CONE_MINMAX(m_x, m_y) \
+ { \
+ float d = -xform.xform(Vector3(len * m_x, len * m_y, -radius)).z; \
+ min_d = MIN(d, min_d); \
+ max_d = MAX(d, max_d); \
+ }
+
+ CONE_MINMAX(1, 1);
+ CONE_MINMAX(-1, 1);
+ CONE_MINMAX(-1, -1);
+ CONE_MINMAX(1, -1);
+
+ if (orthogonal) {
+ e.touches_near = min_d < z_near;
+ } else {
+ //contains camera inside light
+ Plane base_plane(xform.origin, -xform.basis.get_axis(Vector3::AXIS_Z));
+ float dist = base_plane.distance_to(Vector3());
+ if (dist >= 0 && dist < radius) {
+ //inside, check angle
+ float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_axis(Vector3::AXIS_Z))));
+ e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit
+ } else {
+ e.touches_near = false;
+ }
+ }
+
+ 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;
+
+ e.type = ELEMENT_TYPE_SPOT_LIGHT;
+ e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index
+
+ RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+
+ cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]++;
+ }
+
+ render_element_count++;
+ }
+
+ _FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform &p_transform, const Vector3 &p_half_extents) {
+ if (p_box_type == BOX_TYPE_DECAL && cluster_count_by_type[ELEMENT_TYPE_DECAL] == max_elements_by_type) {
+ 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
+ }
+
+ RenderElementData &e = render_elements[render_element_count];
+ Transform xform = view_xform * p_transform;
+
+ //extract scale and scale the matrix by it, makes things simpler
+ Vector3 scale = p_half_extents;
+ for (uint32_t i = 0; i < 3; i++) {
+ float s = xform.basis.elements[i].length();
+ scale[i] *= s;
+ xform.basis.elements[i] /= s;
+ };
+
+ float box_depth = Math::abs(xform.basis.xform_inv(Vector3(0, 0, -1)).dot(scale));
+ float depth = -xform.origin.z;
+
+ if (orthogonal) {
+ e.touches_near = depth - box_depth < z_near;
+ } else {
+ //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;
+ }
+
+ e.touches_far = depth + box_depth > z_far;
+
+ e.scale[0] = scale.x;
+ e.scale[1] = scale.y;
+ e.scale[2] = scale.z;
+
+ e.type = (p_box_type == BOX_TYPE_DECAL) ? ELEMENT_TYPE_DECAL : ELEMENT_TYPE_REFLECTION_PROBE;
+ e.original_index = cluster_count_by_type[e.type];
+
+ RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+
+ cluster_count_by_type[e.type]++;
+ render_element_count++;
+ }
+
+ void bake_cluster();
+ void debug(ElementType p_element);
+
+ RID get_cluster_buffer() const;
+ uint32_t get_cluster_size() const;
+ uint32_t get_max_cluster_elements() const;
+
+ void set_shared(ClusterBuilderSharedDataRD *p_shared);
+
+ ClusterBuilderRD();
+ ~ClusterBuilderRD();
+};
+
+#endif // CLUSTER_BUILDER_H
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index b33255b54b..5a6a4d2a55 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -702,27 +702,24 @@ void EffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const S
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) {
+void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip) {
CopyToDPPushConstant push_constant;
- push_constant.screen_size[0] = p_rect.size.x;
- push_constant.screen_size[1] = p_rect.size.y;
- push_constant.dest_offset[0] = p_rect.position.x;
- push_constant.dest_offset[1] = p_rect.position.y;
- push_constant.bias = p_bias;
+ push_constant.screen_rect[0] = p_rect.position.x;
+ push_constant.screen_rect[1] = p_rect.position.y;
+ push_constant.screen_rect[2] = p_rect.size.width;
+ push_constant.screen_rect[3] = p_rect.size.height;
push_constant.z_far = p_z_far;
push_constant.z_near = p_z_near;
push_constant.z_flip = p_dp_flip;
- int32_t x_groups = (p_rect.size.width - 1) / 8 + 1;
- int32_t y_groups = (p_rect.size.height - 1) / 8 + 1;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cube_to_dp.pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(CopyToDPPushConstant));
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
- RD::get_singleton()->compute_list_end();
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
}
void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) {
@@ -992,47 +989,48 @@ void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>
ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.screen_size.x;
- ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.screen_size.y;
+ ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
ssao.gather_push_constant.pass = i;
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2);
RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
- int x_groups = ((p_settings.screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
- int y_groups = ((p_settings.screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
RD::get_singleton()->compute_list_dispatch(p_compute_list, x_groups, y_groups, 1);
}
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
}
-void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) {
+void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
+ RD::get_singleton()->draw_command_begin_label("SSAO");
/* FIRST PASS */
// Downsample and deinterleave the depth buffer.
{
+ RD::get_singleton()->draw_command_begin_label("Downsample Depth");
if (p_invalidate_uniform_sets) {
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 0;
- u.ids.push_back(depth_mipmaps[1]);
+ u.ids.push_back(p_depth_mipmaps[1]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 1;
- u.ids.push_back(depth_mipmaps[2]);
+ u.ids.push_back(p_depth_mipmaps[2]);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 2;
- u.ids.push_back(depth_mipmaps[3]);
+ u.ids.push_back(p_depth_mipmaps[3]);
uniforms.push_back(u);
}
ssao.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2);
@@ -1051,8 +1049,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
ssao.downsample_push_constant.z_near = p_projection.get_z_near();
ssao.downsample_push_constant.z_far = p_projection.get_z_far();
}
- ssao.downsample_push_constant.pixel_size[0] = 1.0 / p_settings.screen_size.x;
- ssao.downsample_push_constant.pixel_size[1] = 1.0 / p_settings.screen_size.y;
+ ssao.downsample_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssao.downsample_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
ssao.downsample_push_constant.radius_sq = p_settings.radius * p_settings.radius;
int downsample_pipeline = SSAO_DOWNSAMPLE;
@@ -1068,24 +1066,26 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[downsample_pipeline]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[0]), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[0]), 1);
if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.downsample_uniform_set, 2);
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant));
- int x_groups = (MAX(1, p_settings.screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
- int y_groups = (MAX(1, p_settings.screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ int x_groups = (MAX(1, p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ int y_groups = (MAX(1, p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Downsample SSAO
}
/* SECOND PASS */
// Sample SSAO
{
- ssao.gather_push_constant.screen_size[0] = p_settings.screen_size.x;
- ssao.gather_push_constant.screen_size[1] = p_settings.screen_size.y;
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
@@ -1122,7 +1122,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
- ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_size.x) * (p_settings.quarter_size.y) * 255);
+ ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
ssao.gather_push_constant.detail_intensity = p_settings.detail;
@@ -1184,6 +1184,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
}
if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
ssao.importance_map_push_constant.intensity = p_settings.intensity;
@@ -1192,8 +1193,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
gather_ssao(compute_list, p_ao_pong_slices, p_settings, true);
//generate importance map
- int x_groups = (p_settings.quarter_size.x - 1) / 8 + 1;
- int y_groups = (p_settings.quarter_size.y - 1) / 8 + 1;
+ int x_groups = (p_settings.quarter_screen_size.x - 1) / 8 + 1;
+ int y_groups = (p_settings.quarter_screen_size.y - 1) / 8 + 1;
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0);
@@ -1218,17 +1219,20 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_add_barrier(compute_list);
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
} else {
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
}
gather_ssao(compute_list, p_ao_slices, p_settings, false);
+ RD::get_singleton()->draw_command_end_label(); // Gather SSAO
}
// /* THIRD PASS */
// // Blur
//
{
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
@@ -1268,8 +1272,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
}
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
- int x_groups = ((p_settings.screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
- int y_groups = ((p_settings.screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
+ int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
}
@@ -1278,15 +1282,17 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
}
+ RD::get_singleton()->draw_command_end_label(); // Blur
}
/* FOURTH PASS */
// Interleave buffers
// back to full size
{
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.screen_size.x;
- ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.screen_size.y;
+ ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
int interleave_pipeline = SSAO_INTERLEAVE_HALF;
@@ -1307,13 +1313,14 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
- int x_groups = (p_settings.screen_size.x - 1) / 8 + 1;
- int y_groups = (p_settings.screen_size.y - 1) / 8 + 1;
+ int x_groups = (p_settings.full_screen_size.x - 1) / 8 + 1;
+ int y_groups = (p_settings.full_screen_size.y - 1) / 8 + 1;
RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
}
-
+ RD::get_singleton()->draw_command_end_label(); //SSAO
RD::get_singleton()->compute_list_end();
int zero[1] = { 0 };
@@ -1678,8 +1685,12 @@ EffectsRD::EffectsRD() {
cube_to_dp.shader.initialize(copy_modes);
cube_to_dp.shader_version = cube_to_dp.shader.version_create();
-
- cube_to_dp.pipeline = RD::get_singleton()->compute_pipeline_create(cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0));
+ RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
+ RD::PipelineDepthStencilState dss;
+ dss.enable_depth_test = true;
+ dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS;
+ dss.enable_depth_write = true;
+ cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
}
{
@@ -1796,6 +1807,7 @@ EffectsRD::EffectsRD() {
ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
int zero[1] = { 0 };
RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, false);
+ RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
Vector<RD::Uniform> uniforms;
{
@@ -1806,6 +1818,7 @@ EffectsRD::EffectsRD() {
uniforms.push_back(u);
}
ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
}
{
Vector<String> ssao_modes;
@@ -1834,7 +1847,7 @@ EffectsRD::EffectsRD() {
ssao.interleave_shader_version = ssao.interleave_shader.version_create();
for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
-
+ RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
pipeline++;
}
}
@@ -2039,12 +2052,14 @@ EffectsRD::EffectsRD() {
sampler.max_lod = 0;
default_sampler = RD::get_singleton()->sampler_create(sampler);
+ RD::get_singleton()->set_resource_name(default_sampler, "Default Linear Sampler");
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.mip_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.max_lod = 1e20;
default_mipmap_sampler = RD::get_singleton()->sampler_create(sampler);
+ RD::get_singleton()->set_resource_name(default_mipmap_sampler, "Default MipMap Sampler");
{ //create index array for copy shaders
Vector<uint8_t> pv;
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 8731466dea..00309b4d0f 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -234,18 +234,17 @@ class EffectsRD {
} luminance_reduce;
struct CopyToDPPushConstant {
- int32_t screen_size[2];
- int32_t dest_offset[2];
- float bias;
float z_far;
float z_near;
uint32_t z_flip;
+ uint32_t pad;
+ float screen_rect[4];
};
struct CoptToDP {
CubeToDpShaderRD shader;
RID shader_version;
- RID pipeline;
+ PipelineCacheRD pipeline;
} cube_to_dp;
struct BokehPushConstant {
@@ -687,7 +686,7 @@ public:
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
- void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
+ void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip);
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 bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
@@ -745,9 +744,9 @@ public:
float fadeout_from = 50.0;
float fadeout_to = 300.0;
- Size2i screen_size = Size2i();
+ Size2i full_screen_size = Size2i();
Size2i half_screen_size = Size2i();
- Size2i quarter_size = Size2i();
+ Size2i quarter_screen_size = Size2i();
};
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
diff --git a/servers/rendering/renderer_rd/light_cluster_builder.cpp b/servers/rendering/renderer_rd/light_cluster_builder.cpp
deleted file mode 100644
index b76b41ba26..0000000000
--- a/servers/rendering/renderer_rd/light_cluster_builder.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*************************************************************************/
-/* light_cluster_builder.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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 "light_cluster_builder.h"
-
-void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection) {
- view_xform = p_view_transform;
- projection = p_cam_projection;
- z_near = -projection.get_z_near();
- z_far = -projection.get_z_far();
-
- //reset counts
- light_count = 0;
- refprobe_count = 0;
- decal_count = 0;
- item_count = 0;
- sort_id_count = 0;
-}
-
-void LightClusterBuilder::bake_cluster() {
- float slice_depth = (z_near - z_far) / depth;
-
- uint8_t *cluster_dataw = cluster_data.ptrw();
- Cell *cluster_data_ptr = (Cell *)cluster_dataw;
- //clear the cluster
- zeromem(cluster_data_ptr, (width * height * depth * sizeof(Cell)));
-
- /* Step 1, create cell positions and count them */
-
- for (uint32_t i = 0; i < item_count; i++) {
- const Item &item = items[i];
-
- int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth);
- int to_slice = Math::floor((z_near - item.aabb.position.z) / slice_depth);
-
- if (from_slice >= (int)depth || to_slice < 0) {
- continue; //sorry no go
- }
-
- from_slice = MAX(0, from_slice);
- to_slice = MIN((int)depth - 1, to_slice);
-
- for (int j = from_slice; j <= to_slice; j++) {
- Vector3 min = item.aabb.position;
- Vector3 max = item.aabb.position + item.aabb.size;
-
- float limit_near = MIN((z_near - slice_depth * j), max.z);
- float limit_far = MAX((z_near - slice_depth * (j + 1)), min.z);
-
- max.z = limit_near;
- min.z = limit_near;
-
- Vector3 proj_min = projection.xform(min);
- Vector3 proj_max = projection.xform(max);
-
- int near_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
- int near_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
- int near_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
- int near_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
-
- max.z = limit_far;
- min.z = limit_far;
-
- proj_min = projection.xform(min);
- proj_max = projection.xform(max);
-
- int far_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
- int far_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
- int far_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
- int far_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
-
- //print_line(itos(j) + " near - " + Vector2i(near_from_x, near_from_y) + " -> " + Vector2i(near_to_x, near_to_y));
- //print_line(itos(j) + " far - " + Vector2i(far_from_x, far_from_y) + " -> " + Vector2i(far_to_x, far_to_y));
-
- int from_x = MIN(near_from_x, far_from_x);
- int from_y = MIN(near_from_y, far_from_y);
- int to_x = MAX(near_to_x, far_to_x);
- int to_y = MAX(near_to_y, far_to_y);
-
- if (from_x >= (int)width || to_x < 0 || from_y >= (int)height || to_y < 0) {
- continue;
- }
-
- int sx = MAX(0, from_x);
- int sy = MAX(0, from_y);
- int dx = MIN((int)width - 1, to_x);
- int dy = MIN((int)height - 1, to_y);
-
- //print_line(itos(j) + " - " + Vector2i(sx, sy) + " -> " + Vector2i(dx, dy));
-
- for (int x = sx; x <= dx; x++) {
- for (int y = sy; y <= dy; y++) {
- uint32_t offset = j * (width * height) + y * width + x;
-
- if (unlikely(sort_id_count == sort_id_max)) {
- sort_id_max = nearest_power_of_2_templated(sort_id_max + 1);
- sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max);
- if (ids.size()) {
- ids.resize(sort_id_max);
- RD::get_singleton()->free(items_buffer);
- items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max);
- }
- }
-
- sort_ids[sort_id_count].cell_index = offset;
- sort_ids[sort_id_count].item_index = item.index;
- sort_ids[sort_id_count].item_type = item.type;
-
- sort_id_count++;
-
- //for now, only count
- cluster_data_ptr[offset].item_pointers[item.type]++;
- //print_line("at offset " + itos(offset) + " value: " + itos(cluster_data_ptr[offset].item_pointers[item.type]));
- }
- }
- }
- }
-
- /* Step 2, Assign pointers (and reset counters) */
-
- uint32_t offset = 0;
- for (uint32_t i = 0; i < (width * height * depth); i++) {
- for (int j = 0; j < ITEM_TYPE_MAX; j++) {
- uint32_t count = cluster_data_ptr[i].item_pointers[j]; //save count
- cluster_data_ptr[i].item_pointers[j] = offset; //replace count by pointer
- offset += count; //increase offset by count;
- }
- }
-
- //print_line("offset: " + itos(offset));
- /* Step 3, Place item lists */
-
- uint32_t *ids_ptr = ids.ptrw();
-
- for (uint32_t i = 0; i < sort_id_count; i++) {
- const SortID &id = sort_ids[i];
- Cell &cell = cluster_data_ptr[id.cell_index];
- uint32_t pointer = cell.item_pointers[id.item_type] & POINTER_MASK;
- uint32_t counter = cell.item_pointers[id.item_type] >> COUNTER_SHIFT;
- ids_ptr[pointer + counter] = id.item_index;
-
- cell.item_pointers[id.item_type] = pointer | ((counter + 1) << COUNTER_SHIFT);
- }
-
- RD::get_singleton()->texture_update(cluster_texture, 0, cluster_data, true);
- RD::get_singleton()->buffer_update(items_buffer, 0, offset * sizeof(uint32_t), ids_ptr, true);
-}
-
-void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
- if (width == p_width && height == p_height && depth == p_depth) {
- return;
- }
- if (cluster_texture.is_valid()) {
- RD::get_singleton()->free(cluster_texture);
- }
-
- width = p_width;
- height = p_height;
- depth = p_depth;
-
- cluster_data.resize(width * height * depth * sizeof(Cell));
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
- tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.width = width;
- tf.height = height;
- tf.depth = depth;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
-
- cluster_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-}
-
-RID LightClusterBuilder::get_cluster_texture() const {
- return cluster_texture;
-}
-
-RID LightClusterBuilder::get_cluster_indices_buffer() const {
- return items_buffer;
-}
-
-LightClusterBuilder::LightClusterBuilder() {
- //initialize accumulators to something
- lights = (LightData *)memalloc(sizeof(LightData) * 1024);
- light_max = 1024;
-
- refprobes = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
- refprobe_max = 1024;
-
- decals = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
- decal_max = 1024;
-
- items = (Item *)memalloc(sizeof(Item) * 1024);
- item_max = 1024;
-
- sort_ids = (SortID *)memalloc(sizeof(SortID) * 1024);
- ids.resize(2014);
- items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024);
- item_max = 1024;
-}
-
-LightClusterBuilder::~LightClusterBuilder() {
- if (cluster_data.size()) {
- RD::get_singleton()->free(cluster_texture);
- }
-
- if (lights) {
- memfree(lights);
- }
- if (refprobes) {
- memfree(refprobes);
- }
- if (decals) {
- memfree(decals);
- }
- if (items) {
- memfree(items);
- }
- if (sort_ids) {
- memfree(sort_ids);
- RD::get_singleton()->free(items_buffer);
- }
-}
diff --git a/servers/rendering/renderer_rd/light_cluster_builder.h b/servers/rendering/renderer_rd/light_cluster_builder.h
deleted file mode 100644
index 0767a96817..0000000000
--- a/servers/rendering/renderer_rd/light_cluster_builder.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/*************************************************************************/
-/* light_cluster_builder.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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 LIGHT_CLUSTER_BUILDER_H
-#define LIGHT_CLUSTER_BUILDER_H
-
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-
-class LightClusterBuilder {
-public:
- enum LightType {
- LIGHT_TYPE_OMNI,
- LIGHT_TYPE_SPOT
- };
-
- enum ItemType {
- ITEM_TYPE_OMNI_LIGHT,
- ITEM_TYPE_SPOT_LIGHT,
- ITEM_TYPE_REFLECTION_PROBE,
- ITEM_TYPE_DECAL,
- ITEM_TYPE_MAX //should always be 4
- };
-
- enum {
- COUNTER_SHIFT = 20, //one million total ids
- POINTER_MASK = (1 << COUNTER_SHIFT) - 1,
- COUNTER_MASK = 0xfff // 4096 items per cell
- };
-
-private:
- struct LightData {
- float position[3];
- uint32_t type;
- float radius;
- float spot_aperture;
- uint32_t pad[2];
- };
-
- uint32_t light_count = 0;
- uint32_t light_max = 0;
- LightData *lights = nullptr;
-
- struct OrientedBoxData {
- float position[3];
- uint32_t pad;
- float x_axis[3];
- uint32_t pad2;
- float y_axis[3];
- uint32_t pad3;
- float z_axis[3];
- uint32_t pad4;
- };
-
- uint32_t refprobe_count = 0;
- uint32_t refprobe_max = 0;
- OrientedBoxData *refprobes = nullptr;
-
- uint32_t decal_count = 0;
- uint32_t decal_max = 0;
- OrientedBoxData *decals = nullptr;
-
- struct Item {
- AABB aabb;
- ItemType type;
- uint32_t index;
- };
-
- Item *items = nullptr;
- uint32_t item_count = 0;
- uint32_t item_max = 0;
-
- uint32_t width = 0;
- uint32_t height = 0;
- uint32_t depth = 0;
-
- struct Cell {
- uint32_t item_pointers[ITEM_TYPE_MAX];
- };
-
- Vector<uint8_t> cluster_data;
- RID cluster_texture;
-
- struct SortID {
- uint32_t cell_index;
- uint32_t item_index;
- ItemType item_type;
- };
-
- SortID *sort_ids = nullptr;
- Vector<uint32_t> ids;
- uint32_t sort_id_count = 0;
- uint32_t sort_id_max = 0;
- RID items_buffer;
-
- Transform view_xform;
- CameraMatrix projection;
- float z_far = 0;
- float z_near = 0;
-
- _FORCE_INLINE_ void _add_item(const AABB &p_aabb, ItemType p_type, uint32_t p_index) {
- if (unlikely(item_count == item_max)) {
- item_max = nearest_power_of_2_templated(item_max + 1);
- items = (Item *)memrealloc(items, sizeof(Item) * item_max);
- }
-
- Item &item = items[item_count];
- item.aabb = p_aabb;
- item.index = p_index;
- item.type = p_type;
- item_count++;
- }
-
-public:
- void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection);
-
- _FORCE_INLINE_ void add_light(LightType p_type, const Transform &p_transform, float p_radius, float p_spot_aperture) {
- if (unlikely(light_count == light_max)) {
- light_max = nearest_power_of_2_templated(light_max + 1);
- lights = (LightData *)memrealloc(lights, sizeof(LightData) * light_max);
- }
-
- LightData &ld = lights[light_count];
- ld.type = p_type;
- ld.position[0] = p_transform.origin.x;
- ld.position[1] = p_transform.origin.y;
- ld.position[2] = p_transform.origin.z;
- ld.radius = p_radius;
- ld.spot_aperture = p_spot_aperture;
-
- Transform xform = view_xform * p_transform;
-
- ld.radius *= xform.basis.get_uniform_scale();
-
- AABB aabb;
-
- switch (p_type) {
- case LIGHT_TYPE_OMNI: {
- aabb.position = xform.origin;
- aabb.size = Vector3(ld.radius, ld.radius, ld.radius);
- aabb.position -= aabb.size;
- aabb.size *= 2.0;
-
- _add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
- } break;
- case LIGHT_TYPE_SPOT: {
- float r = ld.radius;
- real_t len = Math::tan(Math::deg2rad(ld.spot_aperture)) * r;
-
- aabb.position = xform.origin;
- aabb.expand_to(xform.xform(Vector3(len, len, -r)));
- aabb.expand_to(xform.xform(Vector3(-len, len, -r)));
- aabb.expand_to(xform.xform(Vector3(-len, -len, -r)));
- aabb.expand_to(xform.xform(Vector3(len, -len, -r)));
- _add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
- } break;
- }
-
- light_count++;
- }
-
- _FORCE_INLINE_ void add_reflection_probe(const Transform &p_transform, const Vector3 &p_half_extents) {
- if (unlikely(refprobe_count == refprobe_max)) {
- refprobe_max = nearest_power_of_2_templated(refprobe_max + 1);
- refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max);
- }
-
- Transform xform = view_xform * p_transform;
-
- OrientedBoxData &rp = refprobes[refprobe_count];
- Vector3 origin = xform.origin;
- rp.position[0] = origin.x;
- rp.position[1] = origin.y;
- rp.position[2] = origin.z;
-
- Vector3 x_axis = xform.basis.get_axis(0) * p_half_extents.x;
- rp.x_axis[0] = x_axis.x;
- rp.x_axis[1] = x_axis.y;
- rp.x_axis[2] = x_axis.z;
-
- Vector3 y_axis = xform.basis.get_axis(1) * p_half_extents.y;
- rp.y_axis[0] = y_axis.x;
- rp.y_axis[1] = y_axis.y;
- rp.y_axis[2] = y_axis.z;
-
- Vector3 z_axis = xform.basis.get_axis(2) * p_half_extents.z;
- rp.z_axis[0] = z_axis.x;
- rp.z_axis[1] = z_axis.y;
- rp.z_axis[2] = z_axis.z;
-
- AABB aabb;
-
- aabb.position = origin + x_axis + y_axis + z_axis;
- aabb.expand_to(origin + x_axis + y_axis - z_axis);
- aabb.expand_to(origin + x_axis - y_axis + z_axis);
- aabb.expand_to(origin + x_axis - y_axis - z_axis);
- aabb.expand_to(origin - x_axis + y_axis + z_axis);
- aabb.expand_to(origin - x_axis + y_axis - z_axis);
- aabb.expand_to(origin - x_axis - y_axis + z_axis);
- aabb.expand_to(origin - x_axis - y_axis - z_axis);
-
- _add_item(aabb, ITEM_TYPE_REFLECTION_PROBE, refprobe_count);
-
- refprobe_count++;
- }
-
- _FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector3 &p_half_extents) {
- if (unlikely(decal_count == decal_max)) {
- decal_max = nearest_power_of_2_templated(decal_max + 1);
- decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max);
- }
-
- Transform xform = view_xform * p_transform;
-
- OrientedBoxData &dc = decals[decal_count];
-
- Vector3 origin = xform.origin;
- dc.position[0] = origin.x;
- dc.position[1] = origin.y;
- dc.position[2] = origin.z;
-
- Vector3 x_axis = xform.basis.get_axis(0) * p_half_extents.x;
- dc.x_axis[0] = x_axis.x;
- dc.x_axis[1] = x_axis.y;
- dc.x_axis[2] = x_axis.z;
-
- Vector3 y_axis = xform.basis.get_axis(1) * p_half_extents.y;
- dc.y_axis[0] = y_axis.x;
- dc.y_axis[1] = y_axis.y;
- dc.y_axis[2] = y_axis.z;
-
- Vector3 z_axis = xform.basis.get_axis(2) * p_half_extents.z;
- dc.z_axis[0] = z_axis.x;
- dc.z_axis[1] = z_axis.y;
- dc.z_axis[2] = z_axis.z;
-
- AABB aabb;
-
- aabb.position = origin + x_axis + y_axis + z_axis;
- aabb.expand_to(origin + x_axis + y_axis - z_axis);
- aabb.expand_to(origin + x_axis - y_axis + z_axis);
- aabb.expand_to(origin + x_axis - y_axis - z_axis);
- aabb.expand_to(origin - x_axis + y_axis + z_axis);
- aabb.expand_to(origin - x_axis + y_axis - z_axis);
- aabb.expand_to(origin - x_axis - y_axis + z_axis);
- aabb.expand_to(origin - x_axis - y_axis - z_axis);
-
- _add_item(aabb, ITEM_TYPE_DECAL, decal_count);
-
- decal_count++;
- }
-
- void bake_cluster();
-
- void setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth);
-
- RID get_cluster_texture() const;
- RID get_cluster_indices_buffer() const;
-
- LightClusterBuilder();
- ~LightClusterBuilder();
-};
-
-#endif // LIGHT_CLUSTER_BUILDER_H
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index 8319e3eed1..b2b919c40e 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 2f91c3c3b5..b1c8f21ecc 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 591018346a..792fcb0b59 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1689,7 +1689,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
to_light_xform[2] = from_pos;
to_light_xform[1] = light_dir;
- to_light_xform[0] = -light_dir.tangent();
+ to_light_xform[0] = -light_dir.orthogonal();
to_light_xform.invert();
@@ -2239,6 +2239,11 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
return Variant();
}
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const {
+ RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+ return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
+}
+
RendererCanvasRenderRD::ShaderData::ShaderData() {
valid = false;
uses_screen_texture = false;
@@ -2488,8 +2493,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.renames["COLOR"] = "color";
actions.renames["NORMAL"] = "normal";
- actions.renames["NORMALMAP"] = "normal_map";
- actions.renames["NORMALMAP_DEPTH"] = "normal_depth";
+ actions.renames["NORMAL_MAP"] = "normal_map";
+ actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["TEXTURE"] = "color_texture";
actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size";
actions.renames["NORMAL_TEXTURE"] = "normal_texture";
@@ -2501,7 +2506,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["POINT_COORD"] = "gl_PointCoord";
- actions.renames["LIGHT_POSITION"] = "light_pos";
+ actions.renames["LIGHT_POSITION"] = "light_position";
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT_ENERGY"] = "light_energy";
actions.renames["LIGHT"] = "light";
@@ -2517,7 +2522,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
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";
- actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
+ actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 203d7a4890..cb947d7180 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -188,6 +188,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
ShaderData();
virtual ~ShaderData();
};
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 4ae7e68219..be2552bd32 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -154,12 +154,9 @@ void RendererCompositorRD::initialize() {
}
}
-ThreadWorkPool RendererCompositorRD::thread_work_pool;
uint64_t RendererCompositorRD::frame = 1;
void RendererCompositorRD::finalize() {
- thread_work_pool.finish();
-
memdelete(scene);
memdelete(canvas);
memdelete(storage);
@@ -174,7 +171,6 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
singleton = this;
- thread_work_pool.init();
time = 0;
storage = memnew(RendererStorageRD);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 877f47d702..cb85fc79e0 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -90,8 +90,6 @@ public:
virtual bool is_low_end() const { return false; }
- static ThreadWorkPool thread_work_pool;
-
static RendererCompositorRD *singleton;
RendererCompositorRD();
~RendererCompositorRD() {}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
index 983fbc9b64..eebf8debcd 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -112,7 +112,7 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
- actions.usage_flag_pointers["NORMALMAP"] = &uses_normal;
+ actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
@@ -394,6 +394,12 @@ Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const Stri
return Variant();
}
+RS::ShaderNativeSourceCode RendererSceneRenderForward::ShaderData::get_native_source_code() const {
+ RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton;
+
+ return scene_singleton->shader.scene_shader.version_get_native_source_code(version);
+}
+
RendererSceneRenderForward::ShaderData::ShaderData() {
valid = false;
uses_screen_texture = false;
@@ -577,19 +583,6 @@ void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() {
}
}
-void RendererSceneRenderForward::RenderBufferDataForward::ensure_gi() {
- if (!reflection_buffer.is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = width;
- tf.height = height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-}
-
void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() {
if (!giprobe_buffer.is_valid()) {
RD::TextureFormat tf;
@@ -627,16 +620,6 @@ void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() {
}
void RendererSceneRenderForward::RenderBufferDataForward::clear() {
- if (ambient_buffer != RID() && ambient_buffer != color) {
- RD::get_singleton()->free(ambient_buffer);
- ambient_buffer = RID();
- }
-
- if (reflection_buffer != RID() && reflection_buffer != specular) {
- RD::get_singleton()->free(reflection_buffer);
- reflection_buffer = RID();
- }
-
if (giprobe_buffer != RID()) {
RD::get_singleton()->free(giprobe_buffer);
giprobe_buffer = RID();
@@ -806,252 +789,89 @@ bool RendererSceneRenderForward::free(RID p_rid) {
return false;
}
-void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi, bool p_has_opaque_gi) {
- uint32_t lightmap_captures_used = 0;
-
- for (int i = 0; i < p_element_count; i++) {
- const RenderList::Element *e = p_elements[i];
- InstanceData &id = scene_state.instances[i];
- bool store_transform = true;
- id.flags = 0;
- id.mask = e->instance->layer_mask;
- id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0;
-
- if (e->instance->base_type == RS::INSTANCE_MULTIMESH) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- uint32_t stride;
- if (storage->multimesh_get_transform_format(e->instance->base) == RS::MULTIMESH_TRANSFORM_2D) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
- stride = 2;
- } else {
- stride = 3;
- }
- if (storage->multimesh_uses_colors(e->instance->base)) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
- stride += 1;
- }
- if (storage->multimesh_uses_custom_data(e->instance->base)) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
- stride += 1;
- }
-
- id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
- } else if (e->instance->base_type == RS::INSTANCE_PARTICLES) {
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- uint32_t stride;
- if (false) { // 2D particles
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
- stride = 2;
- } else {
- stride = 3;
- }
-
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
- stride += 1;
-
- id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
- stride += 1;
-
- id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
-
- if (!storage->particles_is_using_local_coords(e->instance->base)) {
- store_transform = false;
- }
-
- } else if (e->instance->base_type == RS::INSTANCE_MESH) {
- if (e->instance->skeleton.is_valid()) {
- id.flags |= INSTANCE_DATA_FLAG_SKELETON;
- }
- }
-
- if (store_transform) {
- RendererStorageRD::store_transform(e->instance->transform, id.transform);
- RendererStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform);
- } else {
- RendererStorageRD::store_transform(Transform(), id.transform);
- RendererStorageRD::store_transform(Transform(), id.normal_transform);
- }
-
- if (p_for_depth) {
- id.gi_offset = 0xFFFFFFFF;
- continue;
- }
-
- if (e->instance->lightmap) {
- int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base);
- if (lightmap_index >= 0) {
- id.gi_offset = lightmap_index;
- id.gi_offset |= e->instance->lightmap_slice_index << 12;
- id.gi_offset |= e->instance->lightmap_cull_index << 20;
- id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x;
- id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y;
- id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width;
- id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height;
- id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
- if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) {
- id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
- }
- } else {
- id.gi_offset = 0xFFFFFFFF;
- }
- } else if (!e->instance->lightmap_sh.empty()) {
- if (lightmap_captures_used < scene_state.max_lightmap_captures) {
- const Color *src_capture = e->instance->lightmap_sh.ptr();
- LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
- for (int j = 0; j < 9; j++) {
- lcd.sh[j * 4 + 0] = src_capture[j].r;
- lcd.sh[j * 4 + 1] = src_capture[j].g;
- lcd.sh[j * 4 + 2] = src_capture[j].b;
- lcd.sh[j * 4 + 3] = src_capture[j].a;
- }
- id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE;
- id.gi_offset = lightmap_captures_used;
- lightmap_captures_used++;
- }
-
- } else {
- if (p_has_opaque_gi) {
- id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
- }
-
- if (!low_end && !e->instance->gi_probe_instances.empty()) {
- uint32_t written = 0;
- for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) {
- RID probe = e->instance->gi_probe_instances[j];
-
- uint32_t index = gi_probe_instance_get_render_index(probe);
-
- if (written == 0) {
- id.gi_offset = index;
- id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE;
- written = 1;
- } else {
- id.gi_offset = index << 16;
- written = 2;
- break;
- }
- }
- if (written == 0) {
- id.gi_offset = 0xFFFFFFFF;
- } else if (written == 1) {
- id.gi_offset |= 0xFFFF0000;
- }
- } else {
- if (p_has_sdfgi && (e->instance->baked_light || e->instance->dynamic_gi)) {
- id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
- }
- id.gi_offset = 0xFFFFFFFF;
- }
- }
- }
-
- RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true);
- if (lightmap_captures_used) {
- RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true);
- }
-}
-
/// RENDERING ///
-void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+template <RendererSceneRenderForward::PassMode p_pass_mode>
+void RendererSceneRenderForward::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
//global scope bindings
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_pass_uniform_set, RENDER_PASS_UNIFORM_SET);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_params->render_pass_uniform_set, RENDER_PASS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET);
- MaterialData *prev_material = nullptr;
+ RID prev_material_uniform_set;
RID prev_vertex_array_rd;
RID prev_index_array_rd;
RID prev_pipeline_rd;
RID prev_xforms_uniform_set;
- PushConstant push_constant;
- zeromem(&push_constant, sizeof(PushConstant));
- push_constant.bake_uv2_offset[0] = p_uv_offset.x;
- push_constant.bake_uv2_offset[1] = p_uv_offset.y;
+ bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
+
+ float old_offset[2] = { 0, 0 };
- for (int i = 0; i < p_element_count; i++) {
- const RenderList::Element *e = p_elements[i];
+ for (uint32_t i = p_from_element; i < p_to_element; i++) {
+ const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
- MaterialData *material = e->material;
- ShaderData *shader = material->shader_data;
- RID xforms_uniform_set;
+ RID material_uniform_set;
+ ShaderData *shader;
+ void *mesh_surface;
+
+ if (shadow_pass || p_params->pass_mode == PASS_MODE_DEPTH) { //regular depth pass can use these too
+ material_uniform_set = surf->material_uniform_set_shadow;
+ shader = surf->shader_shadow;
+ mesh_surface = surf->surface_shadow;
+
+ } else {
+ material_uniform_set = surf->material_uniform_set;
+ shader = surf->shader;
+ mesh_surface = surf->surface;
+ }
+
+ if (!mesh_surface) {
+ continue;
+ }
+
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ old_offset[0] = surf->owner->push_constant.lightmap_uv_scale[0];
+ old_offset[1] = surf->owner->push_constant.lightmap_uv_scale[1];
+ surf->owner->push_constant.lightmap_uv_scale[0] = p_params->uv_offset.x;
+ surf->owner->push_constant.lightmap_uv_scale[1] = p_params->uv_offset.y;
+ }
//find cull variant
ShaderData::CullVariant cull_variant;
- if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) {
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;
} else {
- bool mirror = e->instance->mirror;
- if (p_reverse_cull) {
+ bool mirror = surf->owner->mirror;
+ if (p_params->reverse_cull) {
mirror = !mirror;
}
cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL;
}
- //find primitive and vertex format
- RS::PrimitiveType primitive;
- void *mesh_surface = nullptr;
-
- switch (e->instance->base_type) {
- case RS::INSTANCE_MESH: {
- mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index);
-
- primitive = storage->mesh_surface_get_primitive(mesh_surface);
- if (e->instance->skeleton.is_valid()) {
- xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET);
- }
- } break;
- case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(e->instance->base);
- ERR_CONTINUE(!mesh.is_valid()); //should be a bug
-
- mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index);
-
- primitive = storage->mesh_surface_get_primitive(mesh_surface);
-
- xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
-
- } break;
- case RS::INSTANCE_IMMEDIATE: {
- ERR_CONTINUE(true); //should be a bug
- } break;
- case RS::INSTANCE_PARTICLES: {
- RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16);
- ERR_CONTINUE(!mesh.is_valid()); //should be a bug
-
- mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index & 0xFFFF);
-
- primitive = storage->mesh_surface_get_primitive(mesh_surface);
-
- xforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
-
- } break;
- default: {
- ERR_CONTINUE(true); //should be a bug
- }
- }
+ RS::PrimitiveType primitive = surf->primitive;
+ RID xforms_uniform_set = surf->owner->transforms_uniform_set;
ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
- switch (p_pass_mode) {
+ switch (p_params->pass_mode) {
case PASS_MODE_COLOR:
case PASS_MODE_COLOR_TRANSPARENT: {
- if (e->uses_lightmap) {
+ if (surf->sort.uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS;
- } else if (e->uses_forward_gi) {
+ } else if (surf->sort.uses_forward_gi) {
shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI;
} else {
shader_version = SHADER_VERSION_COLOR_PASS;
}
} break;
case PASS_MODE_COLOR_SPECULAR: {
- if (e->uses_lightmap) {
+ if (surf->sort.uses_lightmap) {
shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;
} else {
shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR;
@@ -1086,40 +906,37 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
RID vertex_array_rd;
RID index_array_rd;
- if (mesh_surface) {
- if (e->instance->mesh_instance.is_valid()) { //skeleton and blend shape
- storage->mesh_instance_surface_get_vertex_arrays_and_format(e->instance->mesh_instance, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
- } else {
- storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
- }
-
- if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) {
- Vector3 support_min = e->instance->transformed_aabb.get_support(-p_lod_plane.normal);
- Vector3 support_max = e->instance->transformed_aabb.get_support(p_lod_plane.normal);
-
- float distance_min = p_lod_plane.distance_to(support_min);
- float distance_max = p_lod_plane.distance_to(support_max);
+ //skeleton and blend shape
+ if (surf->owner->mesh_instance.is_valid()) {
+ storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ } else {
+ storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ }
- float distance = 0.0;
+ if (p_params->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) {
+ //lod
+ Vector3 support_min = surf->owner->transformed_aabb.get_support(-p_params->lod_plane.normal);
+ Vector3 support_max = surf->owner->transformed_aabb.get_support(p_params->lod_plane.normal);
- if (distance_min * distance_max < 0.0) {
- //crossing plane
- distance = 0.0;
- } else if (distance_min >= 0.0) {
- distance = distance_min;
- } else if (distance_max <= 0.0) {
- distance = -distance_max;
- }
+ float distance_min = p_params->lod_plane.distance_to(support_min);
+ float distance_max = p_params->lod_plane.distance_to(support_max);
- Vector3 model_scale_vec = e->instance->transform.basis.get_scale_abs();
+ float distance = 0.0;
- float model_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ if (distance_min * distance_max < 0.0) {
+ //crossing plane
+ distance = 0.0;
+ } else if (distance_min >= 0.0) {
+ distance = distance_min;
+ } else if (distance_max <= 0.0) {
+ distance = -distance_max;
+ }
- index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, model_scale * e->instance->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold);
+ index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, surf->owner->lod_model_scale * surf->owner->lod_bias, distance * p_params->lod_distance_multiplier, p_params->screen_lod_threshold);
- } else {
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);
- }
+ } else {
+ //no lod
+ index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);
}
if (prev_vertex_array_rd != vertex_array_rd) {
@@ -1134,7 +951,7 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
prev_index_array_rd = index_array_rd;
}
- RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_force_wireframe);
+ RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);
if (pipeline_rd != prev_pipeline_rd) {
// checking with prev shader does not make so much sense, as
@@ -1148,40 +965,90 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw
prev_xforms_uniform_set = xforms_uniform_set;
}
- if (material != prev_material) {
+ if (material_uniform_set != prev_material_uniform_set) {
//update uniform set
- if (material->uniform_set.is_valid()) {
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET);
+ if (material_uniform_set.is_valid()) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);
}
- prev_material = material;
+ prev_material_uniform_set = material_uniform_set;
}
- push_constant.index = i;
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &surf->owner->push_constant, sizeof(GeometryInstanceForward::PushConstant));
- switch (e->instance->base_type) {
- case RS::INSTANCE_MESH: {
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid());
- } break;
- case RS::INSTANCE_MULTIMESH: {
- uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base);
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
- } break;
- case RS::INSTANCE_IMMEDIATE: {
- } break;
- case RS::INSTANCE_PARTICLES: {
- uint32_t instances = storage->particles_get_amount(e->instance->base);
- RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances);
- } break;
- default: {
- ERR_CONTINUE(true); //should be a bug
- }
+ RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), surf->owner->instance_count);
+
+ if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ surf->owner->push_constant.lightmap_uv_scale[0] = old_offset[0];
+ surf->owner->push_constant.lightmap_uv_scale[1] = old_offset[1];
}
}
}
-void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
+void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+ //use template for faster performance (pass mode comparisons are inlined)
+
+ switch (p_params->pass_mode) {
+ case PASS_MODE_COLOR: {
+ _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_COLOR_SPECULAR: {
+ _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_COLOR_TRANSPARENT: {
+ _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_SHADOW: {
+ _render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_SHADOW_DP: {
+ _render_list_template<PASS_MODE_SHADOW_DP>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH: {
+ _render_list_template<PASS_MODE_DEPTH>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
+ _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: {
+ _render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_DEPTH_MATERIAL: {
+ _render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ case PASS_MODE_SDF: {
+ _render_list_template<PASS_MODE_SDF>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ } break;
+ }
+}
+
+void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
+ uint32_t render_total = p_params->element_count;
+ uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t render_from = p_thread * render_total / total_threads;
+ uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
+ _render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
+}
+
+void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) {
+ RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer);
+ p_params->framebuffer_format = fb_format;
+
+ if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
+ //multi threaded
+ thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
+ RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForward::_render_list_thread_function, p_params);
+ RD::get_singleton()->draw_list_end();
+ } else {
+ //single threaded
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
+ _render_list(draw_list, fb_format, p_params, 0, p_params->element_count);
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
+void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {
//CameraMatrix projection = p_cam_projection;
//projection.flip_y(); // Vulkan and modern APIs use Y-Down
CameraMatrix correction;
@@ -1209,8 +1076,18 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren
scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
- scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x;
- scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y;
+ Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
+ scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
+ scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
+
+ scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_cluster_size);
+ scene_state.ubo.max_cluster_element_count_div_32 = p_max_cluster_elements / 32;
+ {
+ uint32_t cluster_screen_width = (p_screen_size.width - 1) / p_cluster_size + 1;
+ uint32_t cluster_screen_height = (p_screen_size.height - 1) / p_cluster_size + 1;
+ scene_state.ubo.cluster_type_size = cluster_screen_width * cluster_screen_height * (scene_state.ubo.max_cluster_element_count_div_32 + 32);
+ scene_state.ubo.cluster_width = cluster_screen_width;
+ }
if (p_shadow_atlas.is_valid()) {
Vector2 sas = shadow_atlas_get_size(p_shadow_atlas);
@@ -1413,128 +1290,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren
RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);
}
-void RendererSceneRenderForward::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
- RID m_src;
-
- m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material;
-
- if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) {
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) {
- m_src = overdraw_material;
- } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) {
- m_src = default_material;
- }
- }
-
- MaterialData *material = nullptr;
-
- if (m_src.is_valid()) {
- material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
- m_src = default_material;
- }
-
- ERR_FAIL_COND(!material);
-
- _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index, p_using_sdfgi);
-
- while (material->next_pass.is_valid()) {
- material = (MaterialData *)storage->material_get_data(material->next_pass, RendererStorageRD::SHADER_TYPE_3D);
- if (!material || !material->shader_data->valid) {
- break;
- }
- _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index, p_using_sdfgi);
- }
-}
-
-void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) {
- 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 || has_read_screen_alpha);
- bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
- bool has_alpha = has_base_alpha || has_blend_alpha;
-
- if (p_material->shader_data->uses_sss) {
- scene_state.used_sss = true;
- }
-
- if (p_material->shader_data->uses_screen_texture) {
- scene_state.used_screen_texture = true;
- }
-
- if (p_material->shader_data->uses_depth_texture) {
- scene_state.used_depth_texture = true;
- }
-
- if (p_material->shader_data->uses_normal_texture) {
- scene_state.used_normal_texture = true;
- }
-
- if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) {
- if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
- //conditions in which no depth pass should be processed
- return;
- }
-
- if ((p_pass_mode != PASS_MODE_DEPTH_MATERIAL && p_pass_mode != PASS_MODE_SDF) && !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_pre_pass) {
- //shader does not use discard and does not write a vertex position, use generic material
- if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) {
- p_material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
- } else if ((p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) {
- p_material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
- }
- }
-
- has_alpha = false;
- }
-
- has_alpha = has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED;
-
- RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element();
-
- if (!e) {
- return;
- }
-
- e->instance = p_instance;
- e->material = p_material;
- e->surface_index = p_surface;
- e->sort_key = 0;
-
- if (e->material->last_pass != render_pass) {
- if (!RD::get_singleton()->uniform_set_is_valid(e->material->uniform_set)) {
- //uniform set no longer valid, probably a texture changed
- storage->material_force_update_textures(p_material_rid, RendererStorageRD::SHADER_TYPE_3D);
- }
- e->material->last_pass = render_pass;
- e->material->index = scene_state.current_material_index++;
- if (e->material->shader_data->last_pass != render_pass) {
- e->material->shader_data->last_pass = scene_state.current_material_index++;
- e->material->shader_data->index = scene_state.current_shader_index++;
- }
- }
- e->geometry_index = p_geometry_index;
- e->material_index = e->material->index;
- e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH;
- e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.empty();
- e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instances.size() || p_using_sdfgi);
- e->shader_index = e->shader_index;
- e->depth_layer = e->instance->depth_layer;
- e->priority = p_material->priority;
-
- if (p_material->shader_data->uses_time) {
- RenderingServerDefault::redraw_request();
- }
-}
-
-void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi) {
- scene_state.current_shader_index = 0;
- scene_state.current_material_index = 0;
+void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
scene_state.used_normal_texture = false;
@@ -1543,125 +1299,185 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase
Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));
near_plane.d += p_cam_projection.get_z_near();
float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near();
+ uint32_t lightmap_captures_used = 0;
- uint32_t geometry_index = 0;
+ _update_dirty_geometry_instances();
+ render_list.clear();
//fill list
for (int i = 0; i < (int)p_instances.size(); i++) {
- InstanceBase *inst = p_instances[i];
-
- inst->depth = near_plane.distance_to(inst->transform.origin);
- inst->depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
+ GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]);
- //add geometry for drawing
- switch (inst->base_type) {
- case RS::INSTANCE_MESH: {
- const RID *materials = nullptr;
- uint32_t surface_count;
+ Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal);
+ inst->depth = near_plane.distance_to(support_min);
+ uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15);
- materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count);
- if (!materials) {
- continue; //nothing to do
- }
+ uint32_t flags = inst->base_flags; //fill flags if appropriate
- const RID *inst_materials = inst->materials.ptr();
+ bool uses_lightmap = false;
+ bool uses_gi = false;
- for (uint32_t j = 0; j < surface_count; j++) {
- RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j];
+ if (p_pass_mode == PASS_MODE_COLOR) {
+ //setup GI
- uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index);
- _add_geometry(inst, j, material, p_pass_mode, surface_index, p_using_sdfgi);
+ if (inst->lightmap_instance.is_valid()) {
+ int32_t lightmap_cull_index = -1;
+ for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) {
+ if (scene_state.lightmap_ids[j] == inst->lightmap_instance) {
+ lightmap_cull_index = j;
+ break;
+ }
}
-
- //mesh->last_pass=frame;
-
- } break;
-
- case RS::INSTANCE_MULTIMESH: {
- if (storage->multimesh_get_instances_to_draw(inst->base) == 0) {
- //not visible, 0 instances
- continue;
+ if (lightmap_cull_index >= 0) {
+ inst->push_constant.gi_offset &= 0xFFFF;
+ inst->push_constant.gi_offset |= lightmap_cull_index;
+ flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP;
+ if (scene_state.lightmap_has_sh[lightmap_cull_index]) {
+ flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP;
+ }
+ uses_lightmap = true;
+ } else {
+ inst->push_constant.gi_offset = 0xFFFFFFFF;
}
- RID mesh = storage->multimesh_get_mesh(inst->base);
- if (!mesh.is_valid()) {
- continue;
+ } else if (inst->lightmap_sh) {
+ if (lightmap_captures_used < scene_state.max_lightmap_captures) {
+ const Color *src_capture = inst->lightmap_sh->sh;
+ LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used];
+ for (int j = 0; j < 9; j++) {
+ lcd.sh[j * 4 + 0] = src_capture[j].r;
+ lcd.sh[j * 4 + 1] = src_capture[j].g;
+ lcd.sh[j * 4 + 2] = src_capture[j].b;
+ lcd.sh[j * 4 + 3] = src_capture[j].a;
+ }
+ flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE;
+ inst->push_constant.gi_offset = lightmap_captures_used;
+ lightmap_captures_used++;
+ uses_lightmap = true;
}
- const RID *materials = nullptr;
- uint32_t surface_count;
-
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
- if (!materials) {
- continue; //nothing to do
+ } else if (!low_end) {
+ if (p_using_opaque_gi) {
+ flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;
}
- for (uint32_t j = 0; j < surface_count; j++) {
- uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index);
- _add_geometry(inst, j, materials[j], p_pass_mode, surface_index, p_using_sdfgi);
- }
+ if (inst->gi_probes[0].is_valid()) {
+ uint32_t probe0_index = 0xFFFF;
+ uint32_t probe1_index = 0xFFFF;
- } break;
-#if 0
- case RS::INSTANCE_IMMEDIATE: {
- RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
- ERR_CONTINUE(!immediate);
+ for (uint32_t j = 0; j < scene_state.giprobes_used; j++) {
+ if (scene_state.giprobe_ids[j] == inst->gi_probes[0]) {
+ probe0_index = j;
+ } else if (scene_state.giprobe_ids[j] == inst->gi_probes[1]) {
+ probe1_index = j;
+ }
+ }
- _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
+ if (probe0_index == 0xFFFF && probe1_index != 0xFFFF) {
+ //0 must always exist if a probe exists
+ SWAP(probe0_index, probe1_index);
+ }
- } break;
-#endif
- case RS::INSTANCE_PARTICLES: {
- int draw_passes = storage->particles_get_draw_passes(inst->base);
+ inst->push_constant.gi_offset = probe0_index | (probe1_index << 16);
+ flags |= INSTANCE_DATA_FLAG_USE_GIPROBE;
+ uses_gi = true;
+ } else {
+ if (p_using_sdfgi && inst->can_sdfgi) {
+ flags |= INSTANCE_DATA_FLAG_USE_SDFGI;
+ uses_gi = true;
+ }
+ inst->push_constant.gi_offset = 0xFFFFFFFF;
+ }
+ }
+ }
+ inst->push_constant.flags = flags;
- for (int j = 0; j < draw_passes; j++) {
- RID mesh = storage->particles_get_draw_pass_mesh(inst->base, j);
- if (!mesh.is_valid())
- continue;
+ GeometryInstanceSurfaceDataCache *surf = inst->surface_caches;
- const RID *materials = nullptr;
- uint32_t surface_count;
+ while (surf) {
+ surf->sort.uses_forward_gi = 0;
+ surf->sort.uses_lightmap = 0;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
- if (!materials) {
- continue; //nothing to do
+ if (p_pass_mode == PASS_MODE_COLOR) {
+ if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ render_list.add_element(surf);
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) {
+ render_list.add_alpha_element(surf);
+ if (uses_gi) {
+ surf->sort.uses_forward_gi = 1;
}
+ }
- for (uint32_t k = 0; k < surface_count; k++) {
- uint32_t surface_index = storage->mesh_surface_get_particles_render_pass_index(mesh, j, render_pass, &geometry_index);
- _add_geometry(inst, (j << 16) | k, materials[j], p_pass_mode, surface_index, p_using_sdfgi);
- }
+ if (uses_lightmap) {
+ surf->sort.uses_lightmap = 1;
}
- } break;
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
+ scene_state.used_sss = true;
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) {
+ scene_state.used_screen_texture = true;
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) {
+ scene_state.used_normal_texture = true;
+ }
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
+ scene_state.used_depth_texture = true;
+ }
- default: {
+ } else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
+ if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
+ render_list.add_element(surf);
+ }
+ } else {
+ if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ render_list.add_element(surf);
+ }
}
+
+ surf->sort.depth_layer = depth_layer;
+
+ surf = surf->next;
}
}
+
+ if (lightmap_captures_used) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true);
+ }
}
-void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform) {
- uint32_t lightmaps_used = 0;
+void RendererSceneRenderForward::_setup_giprobes(const PagedArray<RID> &p_giprobes) {
+ scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES));
+ for (uint32_t i = 0; i < scene_state.giprobes_used; i++) {
+ scene_state.giprobe_ids[i] = p_giprobes[i];
+ }
+}
+
+void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) {
+ scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
break;
}
- InstanceBase *lm = p_lightmaps[i];
- Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis;
+ RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]);
+
+ Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
- lm->lightmap_cull_index = i;
- lightmaps_used++;
+ scene_state.lightmap_ids[i] = p_lightmaps[i];
+ scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+
+ scene_state.lightmaps_used++;
}
- if (lightmaps_used > 0) {
- RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true);
+ if (scene_state.lightmaps_used > 0) {
+ RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, true);
}
}
-void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {
RenderBufferDataForward *render_buffer = nullptr;
if (p_render_buffer.is_valid()) {
render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);
@@ -1694,7 +1510,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
scene_state.ubo.viewport_size[1] = vp_he.y;
scene_state.ubo.directional_light_count = p_directional_light_count;
- Size2 screen_pixel_size;
Size2i screen_size;
RID opaque_framebuffer;
RID opaque_specular_framebuffer;
@@ -1709,8 +1524,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
bool using_giprobe = false;
if (render_buffer) {
- screen_pixel_size.width = 1.0 / render_buffer->width;
- screen_pixel_size.height = 1.0 / render_buffer->height;
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
@@ -1718,7 +1531,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
if (!low_end && p_gi_probes.size() > 0) {
using_giprobe = true;
- render_buffer->ensure_gi();
}
if (!p_environment.is_valid() && using_giprobe) {
@@ -1728,7 +1540,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
if (environment_is_sdfgi_enabled(p_environment)) {
depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also giprobe
using_sdfgi = true;
- render_buffer->ensure_gi();
} else {
depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1767,8 +1578,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
alpha_framebuffer = opaque_framebuffer;
} else if (p_reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe);
- screen_pixel_size.width = 1.0 / resolution;
- screen_pixel_size.height = 1.0 / resolution;
screen_size.x = resolution;
screen_size.y = resolution;
@@ -1784,12 +1593,12 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
_setup_lightmaps(p_lightmaps, p_cam_transform);
- _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
+ _setup_giprobes(p_gi_probes);
+ _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
- render_list.clear();
- _fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi);
+ _fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe);
bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
@@ -1849,6 +1658,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
// setup sky if used for ambient, reflections, or background
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
+ RD::get_singleton()->draw_command_begin_label("Setup Sky");
CameraMatrix projection = p_cam_projection;
if (p_reflection_probe.is_valid()) {
CameraMatrix correction;
@@ -1866,20 +1676,16 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
// do not try to draw sky if invalid
draw_sky = false;
}
+ RD::get_singleton()->draw_command_end_label();
}
} else {
clear_color = p_default_bg_color;
}
- RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes);
-
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, false, false, using_sdfgi || using_giprobe);
-
bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
-
bool depth_pre_pass = !low_end && depth_framebuffer.is_valid();
bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment);
@@ -1887,13 +1693,16 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
if (depth_pre_pass) { //depth pre pass
RENDER_TIMESTAMP("Render Depth Pre-Pass");
- bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
+ bool finish_depth = using_ssao || using_sdfgi || using_giprobe;
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ RD::get_singleton()->draw_command_begin_label("Render Depth Pre-Pass");
+ _render_list_with_threads(&render_list_params, depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);
+ RD::get_singleton()->draw_command_end_label();
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass");
+ RD::get_singleton()->draw_command_insert_label("Resolve Depth Pre-Pass");
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) {
static int texture_samples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 };
storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_giprobe ? render_buffer->giprobe_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_giprobe ? render_buffer->giprobe_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]);
@@ -1910,13 +1719,15 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
if (using_sdfgi || using_giprobe) {
- _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probes);
+ _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probes);
}
- _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
+ _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid());
RENDER_TIMESTAMP("Render Opaque Pass");
+ RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_cluster_buffer, p_gi_probes, p_lightmaps, 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;
@@ -1936,13 +1747,13 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
-
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
+ _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ RD::get_singleton()->draw_command_end_label();
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
- draw_list = RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
RD::get_singleton()->draw_list_end();
}
}
@@ -1956,9 +1767,11 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_command_begin_label("Debug GIProbes");
for (int i = 0; i < (int)p_gi_probes.size(); i++) {
_debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0);
}
+ RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
@@ -1971,7 +1784,9 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
_debug_sdfgi_probes(p_render_buffer, draw_list, opaque_framebuffer, cm);
+ RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
@@ -1984,8 +1799,9 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
correction.set_depth_correction(true);
projection = correction * p_cam_projection;
}
-
+ RD::get_singleton()->draw_command_begin_label("Draw Sky");
_draw_sky(can_continue_color, can_continue_depth, opaque_framebuffer, p_environment, projection, p_cam_transform);
+ RD::get_singleton()->draw_command_end_label();
}
if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2002,12 +1818,16 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
if (using_separate_specular) {
if (using_sss) {
RENDER_TIMESTAMP("Sub Surface Scattering");
+ RD::get_singleton()->draw_command_begin_label("Process Sub Surface Scattering");
_process_sss(p_render_buffer, p_cam_projection);
+ RD::get_singleton()->draw_command_end_label();
}
if (using_ssr) {
RENDER_TIMESTAMP("Screen Space Reflection");
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Reflections");
_process_ssr(p_render_buffer, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_environment, p_cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
@@ -2017,16 +1837,15 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
RENDER_TIMESTAMP("Render Transparent Pass");
- _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
+ _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);
render_list.sort_by_reverse_depth_and_priority(true);
- _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, using_sdfgi);
-
{
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
+ RenderListParameters render_list_params(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_command_end_label();
}
if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
@@ -2034,7 +1853,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf
}
}
-void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end) {
RENDER_TIMESTAMP("Setup Rendering Shadow");
_update_render_base_uniform_set();
@@ -2043,35 +1862,36 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr
scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
- _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake);
+ _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), !p_flip_y, Color(), 0, p_zfar, false, p_use_pancake);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
p_screen_lod_threshold = 0.0;
}
- render_list.clear();
-
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
_fill_render_list(p_instances, pass_mode, p_projection, p_transform);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Shadow");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
//regular forward for now
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
- RD::get_singleton()->draw_list_end();
+ bool flip_cull = p_use_dp_flip;
+ if (p_flip_y) {
+ flip_cull = !flip_cull;
+ }
+ RD::get_singleton()->draw_command_begin_label("Render Shadow");
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, flip_cull, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
+ _render_list_with_threads(&render_list_params, p_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : RD::INITIAL_ACTION_CONTINUE, p_end ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, Vector<Color>(), 1.0, 0, p_rect);
+ RD::get_singleton()->draw_command_end_label();
}
}
-void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup Render Collider Heightfield");
_update_render_base_uniform_set();
@@ -2080,31 +1900,28 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,
scene_state.ubo.dual_paraboloid_side = 0;
- _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false);
-
- render_list.clear();
+ _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false);
PassMode pass_mode = PASS_MODE_SHADOW;
_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
- RENDER_TIMESTAMP("Render Collider Heightield");
+ RENDER_TIMESTAMP("Render Collider Heightfield");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
//regular forward for now
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_fb), render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set);
- RD::get_singleton()->draw_list_end();
+ RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set);
+ _render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_command_end_label();
}
}
-void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering Material");
_update_render_base_uniform_set();
@@ -2112,24 +1929,21 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
render_pass++;
scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.material_uv2_mode = true;
+ scene_state.ubo.material_uv2_mode = false;
- _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
-
- render_list.clear();
+ _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0);
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform);
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -2138,12 +1952,12 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo
clear.push_back(Color(0, 0, 0, 0));
clear.push_back(Color(0, 0, 0, 0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set);
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
_update_render_base_uniform_set();
@@ -2153,22 +1967,19 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
- _setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
-
- render_list.clear();
+ _setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0);
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
- RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>());
+ RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());
RENDER_TIMESTAMP("Render Material");
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
-
{
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear;
clear.push_back(Color(0, 0, 0, 0));
@@ -2196,15 +2007,17 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p
Vector2 ofs = uv_offsets[i];
ofs.x /= p_region.size.width;
ofs.y /= p_region.size.height;
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true, ofs); //first wireframe, for pseudo conservative
+ render_list_params.uv_offset = ofs;
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //first wireframe, for pseudo conservative
}
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); //second regular triangles
+ render_list_params.uv_offset = Vector2();
+ _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //second regular triangles
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
RENDER_TIMESTAMP("Render SDFGI");
_update_render_base_uniform_set();
@@ -2213,12 +2026,10 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
ERR_FAIL_COND(!render_buffer);
render_pass++;
- render_list.clear();
PassMode pass_mode = PASS_MODE_SDF;
_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());
render_list.sort_by_key(false);
- _fill_instances(render_list.elements, render_list.element_count, true);
RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
@@ -2271,7 +2082,7 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
RendererStorageRD::store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds);
- _setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0);
+ _setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0);
Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size);
if (!E) {
@@ -2279,9 +2090,8 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
- _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(E->get()), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); //second regular triangles
- RD::get_singleton()->draw_list_end();
+ RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false);
+ _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
}
@@ -2338,19 +2148,19 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
u.ids.push_back(scene_state.uniform_buffer);
uniforms.push_back(u);
}
+
{
RD::Uniform u;
u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(scene_state.instance_buffer);
+ u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
-
{
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_positional_light_buffer());
+ u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
}
@@ -2370,28 +2180,21 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 11;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids = storage->lightmap_array_get_textures();
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 12;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(scene_state.lightmap_capture_buffer);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 13;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -2399,7 +2202,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 14;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -2407,7 +2210,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 15;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -2415,35 +2218,8 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
{
RD::Uniform u;
- u.binding = 16;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.ids.push_back(get_cluster_builder_texture());
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 17;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_cluster_builder_indices_buffer());
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.binding = 18;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- if (directional_shadow_get_texture().is_valid()) {
- u.ids.push_back(directional_shadow_get_texture());
- } else {
- u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
- }
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 19;
+ u.binding = 13;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2451,7 +2227,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
if (!low_end) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 20;
+ u.binding = 14;
u.ids.push_back(sdfgi_get_ubo());
uniforms.push_back(u);
}
@@ -2460,7 +2236,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {
}
}
-RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes) {
+RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas) {
if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {
RD::get_singleton()->free(render_pass_uniform_set);
}
@@ -2515,11 +2291,40 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
u.ids.push_back(texture);
uniforms.push_back(u);
}
-
{
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
+ u.ids.push_back(directional_shadow_get_texture());
+ } else {
+ u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE));
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.resize(scene_state.max_lightmaps);
+ RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
+ if (i < p_lightmaps.size()) {
+ RID base = lightmap_instance_get_lightmap(p_lightmaps[i]);
+ RID texture = storage->lightmap_get_texture(base);
+ RID rd_texture = storage->texture_get_rd_texture(texture);
+ u.ids.write[i] = rd_texture;
+ } else {
+ u.ids.write[i] = default_tex;
+ }
+ }
+
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 5;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_GI_PROBES; i++) {
@@ -2539,7 +2344,16 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 4;
+ u.binding = 6;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : default_vec4_xform_buffer;
+ u.ids.push_back(cb);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
u.ids.push_back(texture);
@@ -2547,17 +2361,18 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID();
RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
u.ids.push_back(texture);
uniforms.push_back(u);
}
+
if (!low_end) {
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);
u.ids.push_back(texture);
@@ -2566,7 +2381,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID();
RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
@@ -2576,24 +2391,26 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = rb && rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID ambient_buffer = p_render_buffers.is_valid() ? render_buffers_get_gi_ambient_texture(p_render_buffers) : RID();
+ RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
u.ids.push_back(texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = rb && rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID reflection_buffer = p_render_buffers.is_valid() ? render_buffers_get_gi_reflection_texture(p_render_buffers) : RID();
+ RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);
u.ids.push_back(texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID t;
if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
@@ -2606,7 +2423,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 14;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {
u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers));
@@ -2617,14 +2434,14 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff
}
{
RD::Uniform u;
- u.binding = 12;
+ u.binding = 15;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 13;
+ u.binding = 16;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID vfog = RID();
if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) {
@@ -2682,10 +2499,34 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
}
{
- // No GIProbes
+ // No directional shadow atlas.
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);
+ u.ids.push_back(texture);
+ uniforms.push_back(u);
+ }
+
+ {
+ // No Lightmaps
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.ids.resize(scene_state.max_lightmaps);
+ RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
+ u.ids.write[i] = default_tex;
+ }
+
+ uniforms.push_back(u);
+ }
+
+ {
+ // No GIProbes
+ RD::Uniform u;
+ u.binding = 5;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_GI_PROBES);
RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_GI_PROBES; i++) {
@@ -2694,33 +2535,43 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed
uniforms.push_back(u);
}
+
+ {
+ RD::Uniform u;
+ u.binding = 6;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ RID cb = default_vec4_xform_buffer;
+ u.ids.push_back(cb);
+ uniforms.push_back(u);
+ }
+
// actual sdfgi stuff
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 4;
+ u.binding = 7;
u.ids.push_back(p_albedo_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 5;
+ u.binding = 8;
u.ids.push_back(p_emission_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 6;
+ u.binding = 9;
u.ids.push_back(p_emission_aniso_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 7;
+ u.binding = 10;
u.ids.push_back(p_geom_facing_texture);
uniforms.push_back(u);
}
@@ -2744,23 +2595,547 @@ RID RendererSceneRenderForward::_render_buffers_get_normal_texture(RID p_render_
return rb->normal_roughness_buffer;
}
-RID RendererSceneRenderForward::_render_buffers_get_ambient_texture(RID p_render_buffers) {
- RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);
+RendererSceneRenderForward *RendererSceneRenderForward::singleton = nullptr;
- return rb->ambient_buffer;
+void RendererSceneRenderForward::set_time(double p_time, double p_step) {
+ time = p_time;
+ RendererSceneRenderRD::set_time(p_time, p_step);
}
-RID RendererSceneRenderForward::_render_buffers_get_reflection_texture(RID p_render_buffers) {
- RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);
+void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ if (ginstance->dirty_list_element.in_list()) {
+ return;
+ }
+
+ //clear surface caches
+ GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
- return rb->reflection_buffer;
+ while (surf) {
+ GeometryInstanceSurfaceDataCache *next = surf->next;
+ geometry_instance_surface_alloc.free(surf);
+ surf = next;
+ }
+
+ ginstance->surface_caches = nullptr;
+
+ geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
}
-RendererSceneRenderForward *RendererSceneRenderForward::singleton = nullptr;
+void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ 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 || has_read_screen_alpha);
+ bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
+ bool has_alpha = has_base_alpha || has_blend_alpha;
-void RendererSceneRenderForward::set_time(double p_time, double p_step) {
- time = p_time;
- RendererSceneRenderRD::set_time(p_time, p_step);
+ uint32_t flags = 0;
+
+ if (p_material->shader_data->uses_sss) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING;
+ }
+
+ if (p_material->shader_data->uses_screen_texture) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
+ }
+
+ if (p_material->shader_data->uses_depth_texture) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
+ }
+
+ if (p_material->shader_data->uses_normal_texture) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE;
+ }
+
+ if (ginstance->data->cast_double_sided_shaodows) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS;
+ }
+
+ if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) {
+ //material is only meant for alpha pass
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA;
+ if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED)) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH;
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW;
+ }
+ } else {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE;
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH;
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW;
+ }
+
+ MaterialData *material_shadow = nullptr;
+ void *surface_shadow = nullptr;
+ if (!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_pre_pass) {
+ flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
+ material_shadow = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+
+ RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+
+ if (shadow_mesh.is_valid()) {
+ surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ }
+
+ } else {
+ material_shadow = p_material;
+ }
+
+ GeometryInstanceSurfaceDataCache *sdcache = geometry_instance_surface_alloc.alloc();
+
+ sdcache->flags = flags;
+
+ sdcache->shader = p_material->shader_data;
+ sdcache->material_uniform_set = p_material->uniform_set;
+ sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface);
+ sdcache->surface_index = p_surface;
+
+ if (ginstance->data->dirty_dependencies) {
+ storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ }
+
+ //shadow
+ sdcache->shader_shadow = material_shadow->shader_data;
+ sdcache->material_uniform_set_shadow = material_shadow->uniform_set;
+
+ sdcache->surface_shadow = surface_shadow ? surface_shadow : sdcache->surface;
+
+ sdcache->owner = ginstance;
+
+ sdcache->next = ginstance->surface_caches;
+ ginstance->surface_caches = sdcache;
+
+ //sortkey
+
+ sdcache->sort.sort_key1 = 0;
+ sdcache->sort.sort_key2 = 0;
+
+ sdcache->sort.surface_type = ginstance->data->base_type;
+ sdcache->sort.material_id = p_material_id;
+ sdcache->sort.shader_id = p_shader_id;
+ sdcache->sort.geometry_id = p_mesh.get_local_index();
+ sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
+ sdcache->sort.priority = p_material->priority;
+}
+
+void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
+ RID m_src;
+
+ m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material;
+
+ MaterialData *material = nullptr;
+
+ if (m_src.is_valid()) {
+ material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (material) {
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
+ }
+ } else {
+ material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
+ m_src = default_material;
+ }
+
+ ERR_FAIL_COND(!material);
+
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh);
+
+ while (material->next_pass.is_valid()) {
+ RID next_pass = material->next_pass;
+ material = (MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D);
+ if (!material || !material->shader_data->valid) {
+ break;
+ }
+ if (ginstance->data->dirty_dependencies) {
+ storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker);
+ }
+ _geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh);
+ }
+}
+
+void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+
+ if (ginstance->data->dirty_dependencies) {
+ ginstance->data->dependency_tracker.update_begin();
+ }
+
+ //add geometry for drawing
+ switch (ginstance->data->base_type) {
+ case RS::INSTANCE_MESH: {
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+ RID mesh = ginstance->data->base;
+
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ //if no materials, no surfaces.
+ const RID *inst_materials = ginstance->data->surface_materials.ptr();
+ uint32_t surf_mat_count = ginstance->data->surface_materials.size();
+
+ for (uint32_t j = 0; j < surface_count; j++) {
+ RID material = (j < surf_mat_count && inst_materials[j].is_valid()) ? inst_materials[j] : materials[j];
+ _geometry_instance_add_surface(ginstance, j, material, mesh);
+ }
+ }
+
+ ginstance->instance_count = 1;
+
+ } break;
+
+ case RS::INSTANCE_MULTIMESH: {
+ RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ if (mesh.is_valid()) {
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ for (uint32_t j = 0; j < surface_count; j++) {
+ _geometry_instance_add_surface(ginstance, j, materials[j], mesh);
+ }
+ }
+
+ ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ }
+
+ } break;
+#if 0
+ case RS::INSTANCE_IMMEDIATE: {
+ RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base);
+ ERR_CONTINUE(!immediate);
+
+ _add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass);
+
+ } break;
+#endif
+ case RS::INSTANCE_PARTICLES: {
+ int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+
+ for (int j = 0; j < draw_passes; j++) {
+ RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+ if (!mesh.is_valid())
+ continue;
+
+ const RID *materials = nullptr;
+ uint32_t surface_count;
+
+ materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ if (materials) {
+ for (uint32_t k = 0; k < surface_count; k++) {
+ _geometry_instance_add_surface(ginstance, k, materials[k], mesh);
+ }
+ }
+ }
+
+ ginstance->instance_count = storage->particles_get_amount(ginstance->data->base);
+
+ } break;
+
+ default: {
+ }
+ }
+
+ //Fill push constant
+
+ ginstance->push_constant.instance_uniforms_ofs = ginstance->data->shader_parameters_offset >= 0 ? ginstance->data->shader_parameters_offset : 0;
+ ginstance->push_constant.layer_mask = ginstance->data->layer_mask;
+ ginstance->push_constant.flags = 0;
+ ginstance->push_constant.gi_offset = 0xFFFFFFFF; //disabled
+
+ bool store_transform = true;
+
+ if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+ uint32_t stride;
+ if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
+ stride = 2;
+ } else {
+ stride = 3;
+ }
+ if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
+ stride += 1;
+ }
+ if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
+ stride += 1;
+ }
+
+ ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
+ ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
+
+ } else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
+ uint32_t stride;
+ if (false) { // 2D particles
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
+ stride = 2;
+ } else {
+ stride = 3;
+ }
+
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
+ stride += 1;
+
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
+ stride += 1;
+
+ ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT);
+
+ if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+ store_transform = false;
+ }
+ ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET);
+
+ } else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
+ if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_SKELETON;
+ ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (ginstance->data->dirty_dependencies) {
+ storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ }
+ }
+ }
+
+ if (store_transform) {
+ RendererStorageRD::store_transform(ginstance->data->transform, ginstance->push_constant.transform);
+ } else {
+ RendererStorageRD::store_transform(Transform(), ginstance->push_constant.transform);
+ }
+
+ ginstance->can_sdfgi = false;
+
+ if (lightmap_instance_is_valid(ginstance->lightmap_instance)) {
+ ginstance->push_constant.gi_offset = ginstance->data->lightmap_slice_index << 16;
+ ginstance->push_constant.lightmap_uv_scale[0] = ginstance->data->lightmap_uv_scale.position.x;
+ ginstance->push_constant.lightmap_uv_scale[1] = ginstance->data->lightmap_uv_scale.position.y;
+ ginstance->push_constant.lightmap_uv_scale[2] = ginstance->data->lightmap_uv_scale.size.width;
+ ginstance->push_constant.lightmap_uv_scale[3] = ginstance->data->lightmap_uv_scale.size.height;
+ } else if (!low_end) {
+ if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) {
+ ginstance->can_sdfgi = true;
+ }
+ }
+
+ if (ginstance->data->dirty_dependencies) {
+ ginstance->data->dependency_tracker.update_end();
+ ginstance->data->dirty_dependencies = false;
+ }
+
+ ginstance->dirty_list_element.remove_from_list();
+}
+
+void RendererSceneRenderForward::_update_dirty_geometry_instances() {
+ while (geometry_instance_dirty_list.first()) {
+ _geometry_instance_update(geometry_instance_dirty_list.first()->self());
+ }
+}
+
+void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+ switch (p_notification) {
+ case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
+ case RendererStorage::DEPENDENCY_CHANGED_MESH:
+ case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
+ case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ } break;
+ case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_tracker->userdata);
+ if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
+ ginstance->instance_count = static_cast<RendererSceneRenderForward *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ }
+ } break;
+ default: {
+ //rest of notifications of no interest
+ } break;
+ }
+}
+void RendererSceneRenderForward::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
+ static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+}
+
+RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) {
+ RS::InstanceType type = storage->get_base_type(p_base);
+ ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
+
+ GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc();
+ ginstance->data = memnew(GeometryInstanceForward::Data);
+
+ 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;
+
+ _geometry_instance_mark_dirty(ginstance);
+
+ return ginstance;
+}
+void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->skeleton = p_skeleton;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->material_override = p_override;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->surface_materials = p_materials;
+ _geometry_instance_mark_dirty(ginstance);
+ ginstance->data->dirty_dependencies = true;
+}
+void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->mesh_instance = p_mesh_instance;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ RendererStorageRD::store_transform(p_transform, ginstance->push_constant.transform);
+ ginstance->data->transform = p_transform;
+ ginstance->mirror = p_transform.basis.determinant() < 0;
+ ginstance->data->aabb = p_aabb;
+ ginstance->transformed_aabb = p_transformed_aabb;
+
+ Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
+ // handle non uniform scale here
+
+ float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+ ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
+
+ ginstance->lod_model_scale = max_scale;
+}
+void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->lod_bias = p_lod_bias;
+}
+void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->use_baked_light = p_enable;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->use_dynamic_gi = p_enable;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->lightmap_instance = p_lightmap_instance;
+ ginstance->data->lightmap_uv_scale = p_lightmap_uv_scale;
+ ginstance->data->lightmap_slice_index = p_lightmap_slice_index;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ if (p_sh9) {
+ if (ginstance->lightmap_sh == nullptr) {
+ ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ }
+
+ copymem(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ } else {
+ if (ginstance->lightmap_sh != nullptr) {
+ geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
+ ginstance->lightmap_sh = nullptr;
+ }
+ }
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->shader_parameters_offset = p_offset;
+ _geometry_instance_mark_dirty(ginstance);
+}
+void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+
+ ginstance->data->cast_double_sided_shaodows = p_enable;
+ _geometry_instance_mark_dirty(ginstance);
+}
+
+void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ ginstance->data->layer_mask = p_layer_mask;
+ ginstance->push_constant.layer_mask = p_layer_mask;
+}
+
+void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ if (ginstance->lightmap_sh != nullptr) {
+ geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
+ }
+ GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ while (surf) {
+ GeometryInstanceSurfaceDataCache *next = surf->next;
+ geometry_instance_surface_alloc.free(surf);
+ surf = next;
+ }
+ memdelete(ginstance->data);
+ geometry_instance_alloc.free(ginstance);
+}
+
+uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() {
+ return (1 << RS::INSTANCE_GI_PROBE);
+}
+void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
+}
+void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+}
+void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+}
+
+Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+ ERR_FAIL_COND_V(!ginstance, Transform());
+ return ginstance->data->transform;
+}
+AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance);
+ ERR_FAIL_COND_V(!ginstance, AABB());
+ return ginstance->data->aabb;
+}
+
+void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) {
+ GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
+ if (p_gi_probe_instance_count > 0) {
+ ginstance->gi_probes[0] = p_gi_probe_instances[0];
+ } else {
+ ginstance->gi_probes[0] = RID();
+ }
+
+ if (p_gi_probe_instance_count > 1) {
+ ginstance->gi_probes[1] = p_gi_probe_instances[1];
+ } else {
+ ginstance->gi_probes[1] = RID();
+ }
}
RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :
@@ -2786,11 +3161,10 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
{
//lightmaps
- scene_state.max_lightmaps = storage->lightmap_array_get_size();
+ scene_state.max_lightmaps = low_end ? 2 : MAX_LIGHTMAPS;
defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n";
defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n";
- scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps);
scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps);
}
{
@@ -2867,8 +3241,8 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
- actions.renames["NORMALMAP"] = "normalmap";
- actions.renames["NORMALMAP_DEPTH"] = "normaldepth";
+ actions.renames["NORMAL_MAP"] = "normal_map";
+ actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions.renames["ALBEDO"] = "albedo";
actions.renames["ALPHA"] = "alpha";
actions.renames["METALLIC"] = "metallic";
@@ -2935,8 +3309,8 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n";
actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n";
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n";
- actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n";
- actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP";
+ actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
+ actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
@@ -3003,7 +3377,7 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
actions.global_buffer_array_variable = "global_variables.data";
- actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
+ actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
shader.compiler.initialize(actions);
}
@@ -3013,12 +3387,6 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
render_list.init();
render_pass = 0;
- {
- scene_state.max_instances = render_list.max_elements;
- scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances);
- scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances);
- }
-
scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
{
@@ -3066,6 +3434,8 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor
sampler.compare_op = RD::COMPARE_OP_LESS;
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
+
+ render_list_thread_threshold = GLOBAL_GET("rendering/forward_renderer/threaded_render_minimum_instances");
}
RendererSceneRenderForward::~RendererSceneRenderForward() {
@@ -3093,11 +3463,8 @@ RendererSceneRenderForward::~RendererSceneRenderForward() {
{
RD::get_singleton()->free(scene_state.uniform_buffer);
- RD::get_singleton()->free(scene_state.instance_buffer);
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
- memdelete_arr(scene_state.instances);
- memdelete_arr(scene_state.lightmaps);
memdelete_arr(scene_state.lightmap_captures);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward.h
index eca83893c3..0b57c7f76c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,6 +31,7 @@
#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H
#define RENDERING_SERVER_SCENE_RENDER_FORWARD_H
+#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
@@ -46,7 +47,9 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
enum {
SDFGI_MAX_CASCADES = 8,
- MAX_GI_PROBES = 8
+ MAX_GI_PROBES = 8,
+ MAX_LIGHTMAPS = 8,
+ MAX_GI_PROBES_PER_INSTANCE = 2,
};
/* Scene Shader */
@@ -166,6 +169,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
ShaderData();
virtual ~ShaderData();
};
@@ -197,14 +202,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
- /* Push Constant */
-
- struct PushConstant {
- uint32_t index;
- uint32_t pad;
- float bake_uv2_offset[2];
- };
-
/* Framebuffer */
struct RenderBufferDataForward : public RenderBufferData {
@@ -216,9 +213,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RID normal_roughness_buffer;
RID giprobe_buffer;
- RID ambient_buffer;
- RID reflection_buffer;
-
RS::ViewportMSAA msaa;
RD::TextureSamples texture_samples;
@@ -239,7 +233,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RID render_sdfgi_uniform_set;
void ensure_specular();
- void ensure_gi();
void ensure_giprobe();
void clear();
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
@@ -261,12 +254,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
void _render_buffers_clear_uniform_set(RenderBufferDataForward *rb);
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
- virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers);
- virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers);
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
- RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes);
+ RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas = false);
struct LightmapData {
float normal_xform[12];
@@ -292,16 +283,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
INSTANCE_DATA_FLAG_SKELETON = 1 << 19,
};
- struct InstanceData {
- float transform[16];
- float normal_transform[16];
- uint32_t flags;
- uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer
- uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
- uint32_t mask;
- float lightmap_uv_scale[4];
- };
-
struct SceneState {
struct UBO {
float projection_matrix[16];
@@ -313,6 +294,11 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
float viewport_size[2];
float screen_pixel_size[2];
+ uint32_t cluster_shift;
+ uint32_t cluster_width;
+ uint32_t cluster_type_size;
+ uint32_t max_cluster_element_count_div_32;
+
float directional_penumbra_shadow_kernel[128]; //32 vec4s
float directional_soft_shadow_kernel[128];
float penumbra_shadow_kernel[128];
@@ -385,7 +371,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
RID uniform_buffer;
- LightmapData *lightmaps;
+ LightmapData lightmaps[MAX_LIGHTMAPS];
+ RID lightmap_ids[MAX_LIGHTMAPS];
+ bool lightmap_has_sh[MAX_LIGHTMAPS];
+ uint32_t lightmaps_used = 0;
uint32_t max_lightmaps;
RID lightmap_buffer;
@@ -393,47 +382,231 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
- RID instance_buffer;
- InstanceData *instances;
- uint32_t max_instances;
+ RID giprobe_ids[MAX_GI_PROBES];
+ uint32_t giprobes_used = 0;
bool used_screen_texture = false;
bool used_normal_texture = false;
bool used_depth_texture = false;
bool used_sss = false;
- uint32_t current_shader_index = 0;
- uint32_t current_material_index = 0;
} scene_state;
- /* Render List */
+ static RendererSceneRenderForward *singleton;
+ uint64_t render_pass;
+ double time;
+ RID default_shader;
+ RID default_material;
+ RID overdraw_material_shader;
+ RID overdraw_material;
+ RID wireframe_material_shader;
+ RID wireframe_material;
+ RID default_shader_rd;
+ RID default_shader_sdfgi_rd;
- struct RenderList {
- int max_elements;
+ RID default_vec4_xform_buffer;
+ RID default_vec4_xform_uniform_set;
- struct Element {
- RendererSceneRender::InstanceBase *instance;
- MaterialData *material;
- union {
- struct {
- //from least significant to most significant in sort, TODO: should be endian swapped on big endian
- uint64_t geometry_index : 20;
- uint64_t material_index : 15;
- uint64_t shader_index : 12;
- uint64_t uses_instancing : 1;
- uint64_t uses_forward_gi : 1;
- uint64_t uses_lightmap : 1;
- uint64_t depth_layer : 4;
- uint64_t priority : 8;
- };
-
- uint64_t sort_key;
+ enum PassMode {
+ PASS_MODE_COLOR,
+ PASS_MODE_COLOR_SPECULAR,
+ PASS_MODE_COLOR_TRANSPARENT,
+ PASS_MODE_SHADOW,
+ PASS_MODE_SHADOW_DP,
+ PASS_MODE_DEPTH,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
+ PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
+ PASS_MODE_DEPTH_MATERIAL,
+ PASS_MODE_SDF,
+ };
+
+ void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
+ void _setup_giprobes(const PagedArray<RID> &p_giprobes);
+ void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
+
+ struct GeometryInstanceSurfaceDataCache;
+
+ struct RenderListParameters {
+ GeometryInstanceSurfaceDataCache **elements = nullptr;
+ int element_count = 0;
+ bool reverse_cull = false;
+ PassMode pass_mode = PASS_MODE_COLOR;
+ bool no_gi = false;
+ RID render_pass_uniform_set;
+ bool force_wireframe = false;
+ Vector2 uv_offset;
+ Plane lod_plane;
+ float lod_distance_multiplier = 0.0;
+ float screen_lod_threshold = 0.0;
+ RD::FramebufferFormatID framebuffer_format = 0;
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) {
+ elements = p_elements;
+ element_count = p_element_count;
+ reverse_cull = p_reverse_cull;
+ pass_mode = p_pass_mode;
+ no_gi = p_no_gi;
+ render_pass_uniform_set = p_render_pass_uniform_set;
+ force_wireframe = p_force_wireframe;
+ uv_offset = p_uv_offset;
+ lod_plane = p_lod_plane;
+ lod_distance_multiplier = p_lod_distance_multiplier;
+ screen_lod_threshold = p_screen_lod_threshold;
+ }
+ };
+
+ template <PassMode p_pass_mode>
+ _FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
+
+ void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
+
+ LocalVector<RD::DrawListID> thread_draw_lists;
+ void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params);
+ void _render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
+
+ uint32_t render_list_thread_threshold = 500;
+
+ void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false);
+
+ Map<Size2i, RID> sdfgi_framebuffer_size_cache;
+
+ struct GeometryInstanceData;
+ struct GeometryInstanceForward;
+
+ struct GeometryInstanceLightmapSH {
+ Color sh[9];
+ };
+
+ // Cached data for drawing surfaces
+ struct GeometryInstanceSurfaceDataCache {
+ enum {
+ FLAG_PASS_DEPTH = 1,
+ FLAG_PASS_OPAQUE = 2,
+ FLAG_PASS_ALPHA = 4,
+ FLAG_PASS_SHADOW = 8,
+ FLAG_USES_SHARED_SHADOW_MATERIAL = 128,
+ FLAG_USES_SUBSURFACE_SCATTERING = 2048,
+ FLAG_USES_SCREEN_TEXTURE = 4096,
+ FLAG_USES_DEPTH_TEXTURE = 8192,
+ FLAG_USES_NORMAL_TEXTURE = 16384,
+ FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
+ };
+
+ union {
+ struct {
+ uint32_t geometry_id;
+ uint32_t material_id;
+ uint32_t shader_id;
+ uint32_t surface_type : 4;
+ uint32_t uses_forward_gi : 1; //set during addition
+ uint32_t uses_lightmap : 1; //set during addition
+ uint32_t depth_layer : 4; //set during addition
+ uint32_t priority : 8;
};
- uint32_t surface_index;
+ struct {
+ uint64_t sort_key1;
+ uint64_t sort_key2;
+ };
+ } sort;
+
+ RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
+ uint32_t flags = 0;
+ uint32_t surface_index = 0;
+
+ void *surface = nullptr;
+ RID material_uniform_set;
+ ShaderData *shader = nullptr;
+
+ void *surface_shadow = nullptr;
+ RID material_uniform_set_shadow;
+ ShaderData *shader_shadow = nullptr;
+
+ GeometryInstanceSurfaceDataCache *next = nullptr;
+ GeometryInstanceForward *owner = nullptr;
+ };
+
+ struct GeometryInstanceForward : public GeometryInstance {
+ //used during rendering
+ bool mirror = false;
+ bool non_uniform_scale = false;
+ float lod_bias = 0.0;
+ float lod_model_scale = 1.0;
+ AABB transformed_aabb; //needed for LOD
+ float depth = 0;
+ struct PushConstant {
+ float transform[16];
+ uint32_t flags;
+ uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index)
+ uint32_t layer_mask;
+ float lightmap_uv_scale[4];
+ } push_constant;
+ RID transforms_uniform_set;
+ uint32_t instance_count = 0;
+ RID mesh_instance;
+ bool can_sdfgi = false;
+ //used during setup
+ uint32_t base_flags = 0;
+ RID gi_probes[MAX_GI_PROBES_PER_INSTANCE];
+ RID lightmap_instance;
+ GeometryInstanceLightmapSH *lightmap_sh = nullptr;
+ GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
+ SelfList<GeometryInstanceForward> dirty_list_element;
+
+ struct Data {
+ //data used less often goes into regular heap
+ RID base;
+ RS::InstanceType base_type;
+
+ RID skeleton;
+
+ uint32_t layer_mask = 1;
+
+ Vector<RID> surface_materials;
+ RID material_override;
+ Transform transform;
+ AABB aabb;
+ int32_t shader_parameters_offset = -1;
+
+ bool use_dynamic_gi = false;
+ bool use_baked_light = false;
+ bool cast_double_sided_shaodows = false;
+ bool mirror = false;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index = 0;
+ bool dirty_dependencies = false;
+
+ RendererStorage::DependencyTracker dependency_tracker;
};
- Element *base_elements;
- Element **elements;
+ Data *data = nullptr;
+
+ GeometryInstanceForward() :
+ dirty_list_element(this) {}
+ };
+
+ static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+
+ SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list;
+
+ PagedAllocator<GeometryInstanceForward> geometry_instance_alloc;
+ PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
+ PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
+
+ void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
+ void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
+ void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _update_dirty_geometry_instances();
+
+ bool low_end = false;
+
+ /* Render List */
+
+ struct RenderList {
+ int max_elements;
+
+ GeometryInstanceSurfaceDataCache **elements = nullptr;
int element_count;
int alpha_element_count;
@@ -446,13 +619,13 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
//should eventually be replaced by radix
struct SortByKey {
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->sort_key < B->sort_key;
+ _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
+ return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2);
}
};
void sort_by_key(bool p_alpha) {
- SortArray<Element *, SortByKey> sorter;
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
@@ -461,14 +634,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
struct SortByDepth {
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- return A->instance->depth < B->instance->depth;
+ _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
+ return (A->owner->depth < B->owner->depth);
}
};
void sort_by_depth(bool p_alpha) { //used for shadows
- SortArray<Element *, SortByDepth> sorter;
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
@@ -477,20 +650,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
struct SortByReverseDepthAndPriority {
- _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
- uint32_t layer_A = uint32_t(A->priority);
- uint32_t layer_B = uint32_t(B->priority);
- if (layer_A == layer_B) {
- return A->instance->depth > B->instance->depth;
- } else {
- return layer_A < layer_B;
- }
+ _FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
+ return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority);
}
};
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
- SortArray<Element *, SortByReverseDepthAndPriority> sorter;
+ SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
if (p_alpha) {
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
} else {
@@ -498,32 +665,27 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
}
}
- _FORCE_INLINE_ Element *add_element() {
+ _FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) {
if (element_count + alpha_element_count >= max_elements) {
- return nullptr;
+ return;
}
- elements[element_count] = &base_elements[element_count];
- return elements[element_count++];
+ elements[element_count] = p_element;
+ element_count++;
}
- _FORCE_INLINE_ Element *add_alpha_element() {
+ _FORCE_INLINE_ void add_alpha_element(GeometryInstanceSurfaceDataCache *p_element) {
if (element_count + alpha_element_count >= max_elements) {
- return nullptr;
+ return;
}
int idx = max_elements - alpha_element_count - 1;
- elements[idx] = &base_elements[idx];
+ elements[idx] = p_element;
alpha_element_count++;
- return elements[idx];
}
void init() {
element_count = 0;
alpha_element_count = 0;
- elements = memnew_arr(Element *, max_elements);
- base_elements = memnew_arr(Element, max_elements);
- for (int i = 0; i < max_elements; i++) {
- elements[i] = &base_elements[i]; // assign elements
- }
+ elements = memnew_arr(GeometryInstanceSurfaceDataCache *, max_elements);
}
RenderList() {
@@ -532,63 +694,46 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
~RenderList() {
memdelete_arr(elements);
- memdelete_arr(base_elements);
}
};
RenderList render_list;
- static RendererSceneRenderForward *singleton;
- uint64_t render_pass;
- double time;
- RID default_shader;
- RID default_material;
- RID overdraw_material_shader;
- RID overdraw_material;
- RID wireframe_material_shader;
- RID wireframe_material;
- RID default_shader_rd;
- RID default_shader_sdfgi_rd;
-
- RID default_vec4_xform_buffer;
- RID default_vec4_xform_uniform_set;
-
- enum PassMode {
- PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
- PASS_MODE_SHADOW,
- PASS_MODE_SHADOW_DP,
- PASS_MODE_DEPTH,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
- PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
- PASS_MODE_DEPTH_MATERIAL,
- PASS_MODE_SDF,
- };
-
- void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false);
- void _setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform);
-
- void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false);
- void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
- _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
- _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false);
-
- void _fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false);
-
- Map<Size2i, RID> sdfgi_framebuffer_size_cache;
-
- bool low_end = false;
-
protected:
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
- virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0);
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances);
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold);
+ virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
+ virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
public:
+ virtual GeometryInstance *geometry_instance_create(RID p_base);
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
+
+ virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance);
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
+
+ virtual uint32_t geometry_instance_get_pair_mask();
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
+ virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
+
virtual void set_time(double p_time, double p_step);
virtual bool free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index e9bc67b053..2f35a6db23 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -183,13 +183,11 @@ void RendererSceneRenderRD::_create_reflection_importance_sample(ReflectionData
void RendererSceneRenderRD::_update_reflection_mipmaps(ReflectionData &rd, int p_start, int p_end) {
for (int i = p_start; i < p_end; i++) {
- for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) {
- for (int k = 0; k < 6; k++) {
- RID view = rd.layers[i].mipmaps[j].views[k];
- RID texture = rd.layers[i].mipmaps[j + 1].views[k];
- Size2i size = rd.layers[i].mipmaps[j + 1].size;
- storage->get_effects()->make_mipmap(view, texture, size);
- }
+ for (int j = 0; j < rd.layers[i].views.size() - 1; j++) {
+ RID view = rd.layers[i].views[j];
+ RID texture = rd.layers[i].views[j + 1];
+ Size2i size = rd.layers[i].mipmaps[j + 1].size;
+ storage->get_effects()->cubemap_downsample(view, texture, size);
}
}
}
@@ -1278,14 +1276,26 @@ void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_envi
push_constant.multibounce = rb->sdfgi->uses_multibounce;
push_constant.y_mult = rb->sdfgi->y_mult;
- push_constant.process_offset = 0;
- push_constant.process_increment = 1;
-
for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
SDFGI::Cascade &cascade = rb->sdfgi->cascades[i];
push_constant.light_count = cascade_light_count[i];
push_constant.cascade = i;
+ if (rb->sdfgi->cascades[i].all_dynamic_lights_dirty || sdfgi_frames_to_update_light == RS::ENV_SDFGI_UPDATE_LIGHT_IN_1_FRAME) {
+ push_constant.process_offset = 0;
+ push_constant.process_increment = 1;
+ } else {
+ static uint32_t frames_to_update_table[RS::ENV_SDFGI_UPDATE_LIGHT_MAX] = {
+ 1, 2, 4, 8, 16
+ };
+
+ uint32_t frames_to_update = frames_to_update_table[sdfgi_frames_to_update_light];
+
+ push_constant.process_offset = RSG::rasterizer->get_frame_number() % frames_to_update;
+ push_constant.process_increment = frames_to_update;
+ }
+ rb->sdfgi->cascades[i].all_dynamic_lights_dirty = false;
+
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0);
@@ -1303,7 +1313,7 @@ void RendererSceneRenderRD::sdfgi_update_probes(RID p_render_buffers, RID p_envi
push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
push_constant.history_index = rb->sdfgi->render_pass % rb->sdfgi->history_size;
push_constant.history_size = rb->sdfgi->history_size;
- static const uint32_t ray_count[RS::ENV_SDFGI_RAY_COUNT_MAX] = { 8, 16, 32, 64, 96, 128 };
+ static const uint32_t ray_count[RS::ENV_SDFGI_RAY_COUNT_MAX] = { 4, 8, 16, 32, 64, 96, 128 };
push_constant.ray_count = ray_count[sdfgi_ray_count];
push_constant.ray_bias = rb->sdfgi->probe_bias;
push_constant.image_size[0] = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count;
@@ -1494,13 +1504,35 @@ void RendererSceneRenderRD::_setup_giprobes(RID p_render_buffers, const Transfor
}
}
-void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes) {
+void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes) {
RENDER_TIMESTAMP("Render GI");
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(rb == nullptr);
Environment *env = environment_owner.getornull(p_environment);
+ if (rb->ambient_buffer.is_null() || rb->using_half_size_gi != gi.half_resolution) {
+ if (rb->ambient_buffer.is_valid()) {
+ RD::get_singleton()->free(rb->ambient_buffer);
+ RD::get_singleton()->free(rb->reflection_buffer);
+ }
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = rb->width;
+ tf.height = rb->height;
+ if (gi.half_resolution) {
+ tf.width >>= 1;
+ tf.height >>= 1;
+ }
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ rb->using_half_size_gi = gi.half_resolution;
+
+ _render_buffers_uniform_set_changed(p_render_buffers);
+ }
+
GI::PushConstant push_constant;
push_constant.screen_size[0] = rb->width;
@@ -1514,7 +1546,9 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
push_constant.max_giprobes = MIN((uint64_t)RenderBuffers::MAX_GIPROBES, p_gi_probes.size());
push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH;
- push_constant.use_sdfgi = rb->sdfgi != nullptr;
+
+ bool use_sdfgi = rb->sdfgi != nullptr;
+ bool use_giprobes = push_constant.max_giprobes > 0;
if (env) {
push_constant.ao_color[0] = env->ao_color.r;
@@ -1693,7 +1727,7 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.ids.push_back(p_ambient_buffer);
+ u.ids.push_back(rb->ambient_buffer);
uniforms.push_back(u);
}
@@ -1701,7 +1735,7 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
- u.ids.push_back(p_reflection_buffer);
+ u.ids.push_back(rb->reflection_buffer);
uniforms.push_back(u);
}
@@ -1765,11 +1799,23 @@ void RendererSceneRenderRD::_process_gi(RID p_render_buffers, RID p_normal_rough
rb->gi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi.shader.version_get_shader(gi.shader_version, 0), 0);
}
+ GI::Mode mode;
+
+ if (rb->using_half_size_gi) {
+ mode = (use_sdfgi && use_giprobes) ? GI::MODE_HALF_RES_COMBINED : (use_sdfgi ? GI::MODE_HALF_RES_SDFGI : GI::MODE_HALF_RES_GIPROBE);
+ } else {
+ mode = (use_sdfgi && use_giprobes) ? GI::MODE_COMBINED : (use_sdfgi ? GI::MODE_SDFGI : GI::MODE_GIPROBE);
+ }
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi.pipelines[0]);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi.pipelines[mode]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GI::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1, 8, 8, 1);
+
+ if (rb->using_half_size_gi) {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width >> 1, rb->height >> 1, 1, 8, 8, 1);
+ } else {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1, 8, 8, 1);
+ }
RD::get_singleton()->compute_list_end();
}
@@ -2674,6 +2720,12 @@ Variant RendererSceneRenderRD::SkyShaderData::get_default_parameter(const String
return Variant();
}
+RS::ShaderNativeSourceCode RendererSceneRenderRD::SkyShaderData::get_native_source_code() const {
+ RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+ return scene_singleton->sky_shader.shader.version_get_native_source_code(version);
+}
+
RendererSceneRenderRD::SkyShaderData::SkyShaderData() {
valid = false;
}
@@ -3098,6 +3150,9 @@ void RendererSceneRenderRD::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGI
void RendererSceneRenderRD::environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) {
sdfgi_frames_to_converge = p_frames;
}
+void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) {
+ sdfgi_frames_to_update_light = p_update;
+}
void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
Environment *env = environment_owner.getornull(p_env);
@@ -3227,6 +3282,10 @@ RID RendererSceneRenderRD::reflection_atlas_create() {
ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count");
ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size");
+ ra.cluster_builder = memnew(ClusterBuilderRD);
+ ra.cluster_builder->set_shared(&cluster_builder_shared);
+ ra.cluster_builder->setup(Size2i(ra.size, ra.size), max_cluster_elements, RID(), RID(), RID());
+
return reflection_atlas_owner.make_rid(ra);
}
@@ -3238,6 +3297,8 @@ void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_ref
return; //no changes
}
+ ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID());
+
ra->size = p_reflection_size;
ra->count = p_reflection_count;
@@ -3247,7 +3308,6 @@ void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_ref
ra->reflection = RID();
RD::get_singleton()->free(ra->depth_buffer);
ra->depth_buffer = RID();
-
for (int i = 0; i < ra->reflections.size(); i++) {
_clear_reflection_data(ra->reflections.write[i].data);
if (ra->reflections[i].owner.is_null()) {
@@ -3504,13 +3564,28 @@ RID RendererSceneRenderRD::shadow_atlas_create() {
return shadow_atlas_owner.make_rid(ShadowAtlas());
}
-void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
+void RendererSceneRenderRD::_update_shadow_atlas(ShadowAtlas *shadow_atlas) {
+ if (shadow_atlas->size > 0 && shadow_atlas->depth.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = shadow_atlas->use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT;
+ tf.width = shadow_atlas->size;
+ tf.height = shadow_atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Vector<RID> fb_tex;
+ fb_tex.push_back(shadow_atlas->depth);
+ shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+}
+
+void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas);
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(p_size < 0);
p_size = next_power_of_2(p_size);
- if (p_size == shadow_atlas->size) {
+ if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
return;
}
@@ -3537,16 +3612,7 @@ void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size) {
shadow_atlas->shadow_owners.clear();
shadow_atlas->size = p_size;
-
- if (shadow_atlas->size) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = shadow_atlas->size;
- tf.height = shadow_atlas->size;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
+ shadow_atlas->use_16_bits = p_size;
}
void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
@@ -3801,10 +3867,24 @@ bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_i
return false;
}
-void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size) {
+void RendererSceneRenderRD::_update_directional_shadow_atlas() {
+ if (directional_shadow.depth.is_null() && directional_shadow.size > 0) {
+ RD::TextureFormat tf;
+ tf.format = directional_shadow.use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT;
+ tf.width = directional_shadow.size;
+ tf.height = directional_shadow.size;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Vector<RID> fb_tex;
+ fb_tex.push_back(directional_shadow.depth);
+ directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+}
+void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
p_size = nearest_power_of_2_templated(p_size);
- if (directional_shadow.size == p_size) {
+ if (directional_shadow.size == p_size && directional_shadow.use_16_bits == p_16_bits) {
return;
}
@@ -3814,19 +3894,8 @@ void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size) {
RD::get_singleton()->free(directional_shadow.depth);
_clear_shadow_shrink_stages(directional_shadow.shrink_stages);
directional_shadow.depth = RID();
+ _base_uniforms_changed();
}
-
- if (p_size > 0) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = p_size;
- tf.height = p_size;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- _base_uniforms_changed();
}
void RendererSceneRenderRD::set_directional_shadow_count(int p_count) {
@@ -3996,29 +4065,6 @@ RendererSceneRenderRD::ShadowCubemap *RendererSceneRenderRD::_get_shadow_cubemap
return &shadow_cubemaps[p_size];
}
-RendererSceneRenderRD::ShadowMap *RendererSceneRenderRD::_get_shadow_map(const Size2i &p_size) {
- if (!shadow_maps.has(p_size)) {
- ShadowMap sm;
- {
- RD::TextureFormat tf;
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
- tf.width = p_size.width;
- tf.height = p_size.height;
- tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- sm.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- Vector<RID> fbtex;
- fbtex.push_back(sm.depth);
- sm.fb = RD::get_singleton()->framebuffer_create(fbtex);
-
- shadow_maps[p_size] = sm;
- }
-
- return &shadow_maps[p_size];
-}
-
//////////////////////////
RID RendererSceneRenderRD::decal_instance_create(RID p_decal) {
@@ -4035,6 +4081,19 @@ void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Tran
/////////////////////////////////
+RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) {
+ LightmapInstance li;
+ li.lightmap = p_lightmap;
+ return lightmap_instance_owner.make_rid(li);
+}
+void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) {
+ LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap);
+ ERR_FAIL_COND(!li);
+ li->transform = p_transform;
+}
+
+/////////////////////////////////
+
RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {
GIProbeInstance gi_probe;
gi_probe.probe = p_base;
@@ -4061,7 +4120,7 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {
return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);
}
-void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<InstanceBase *> &p_dynamic_objects) {
+void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gi_probe);
@@ -4397,7 +4456,10 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
}
}
- dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT], 0);
+ dmap.uniform_set = RD::get_singleton()->uniform_set_create(
+ uniforms,
+ giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : (write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT)],
+ 0);
}
gi_probe->dynamic_maps.push_back(dmap);
@@ -4578,13 +4640,10 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins
//this could probably be better parallelized in compute..
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- InstanceBase *instance = p_dynamic_objects[i];
- //not used, so clear
- instance->depth_layer = 0;
- instance->depth = 0;
+ GeometryInstance *instance = p_dynamic_objects[i];
//transform aabb to giprobe
- AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb);
+ AABB aabb = (to_probe_xform * geometry_instance_get_transform(instance)).xform(geometry_instance_get_aabb(instance));
//this needs to wrap to grid resolution to avoid jitter
//also extend margin a bit just in case
@@ -4834,7 +4893,16 @@ void RendererSceneRenderRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw
}
giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0);
- RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, giprobe_debug_shader_version_pipelines[p_emission ? GI_PROBE_DEBUG_EMISSION : p_lighting ? (gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT) : GI_PROBE_DEBUG_COLOR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+
+ int giprobe_debug_pipeline = GI_PROBE_DEBUG_COLOR;
+ if (p_emission) {
+ giprobe_debug_pipeline = GI_PROBE_DEBUG_EMISSION;
+ } else if (p_lighting) {
+ giprobe_debug_pipeline = gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT;
+ }
+ RD::get_singleton()->draw_list_bind_render_pipeline(
+ p_draw_list,
+ giprobe_debug_shader_version_pipelines[giprobe_debug_pipeline].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0);
RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant));
RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36);
@@ -5125,6 +5193,13 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
RD::get_singleton()->free(rb->ssr.normal_scaled);
rb->ssr.normal_scaled = RID();
}
+
+ if (rb->ambient_buffer.is_valid()) {
+ RD::get_singleton()->free(rb->ambient_buffer);
+ RD::get_singleton()->free(rb->reflection_buffer);
+ rb->ambient_buffer = RID();
+ rb->reflection_buffer = RID();
+ }
}
void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
@@ -5257,9 +5332,11 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.array_layers = 4;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ssao.depth, "SSAO Depth");
for (uint32_t i = 0; i < tf.mipmaps; i++) {
RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i, RD::TEXTURE_SLICE_2D_ARRAY);
rb->ssao.depth_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(rb->ssao.depth_slices[i], "SSAO Depth Mip " + itos(i) + " ");
}
}
@@ -5272,9 +5349,11 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.array_layers = 4;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ssao.ao_deinterleaved, "SSAO De-interleaved Array");
for (uint32_t i = 0; i < 4; i++) {
RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.ao_deinterleaved, i, 0);
rb->ssao.ao_deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(rb->ssao.ao_deinterleaved_slices[i], "SSAO De-interleaved Array Layer " + itos(i) + " ");
}
}
@@ -5287,9 +5366,11 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.array_layers = 4;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ssao.ao_pong, "SSAO De-interleaved Array Pong");
for (uint32_t i = 0; i < 4; i++) {
RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.ao_pong, i, 0);
rb->ssao.ao_pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(rb->ssao.ao_deinterleaved_slices[i], "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
}
}
@@ -5300,7 +5381,9 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.height = half_height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ssao.importance_map[0], "SSAO Importance Map");
rb->ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ssao.importance_map[1], "SSAO Importance Map Pong");
}
{
RD::TextureFormat tf;
@@ -5309,6 +5392,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
tf.height = rb->height;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final");
_render_buffers_uniform_set_changed(p_render_buffers);
}
ssao_using_half_size = ssao_half_size;
@@ -5329,9 +5413,9 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
settings.blur_passes = ssao_blur_passes;
settings.fadeout_from = ssao_fadeout_from;
settings.fadeout_to = ssao_fadeout_to;
- settings.screen_size = Size2i(rb->width, rb->height);
+ settings.full_screen_size = Size2i(rb->width, rb->height);
settings.half_screen_size = Size2i(buffer_width, buffer_height);
- settings.quarter_size = Size2i(half_width, half_height);
+ settings.quarter_screen_size = Size2i(half_width, half_height);
storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid);
}
@@ -5524,10 +5608,10 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && _render_buffers_get_ambient_texture(p_render_buffers).is_valid()) {
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) {
Size2 rtsize = storage->render_target_get_size(rb->render_target);
- RID ambient_texture = _render_buffers_get_ambient_texture(p_render_buffers);
- RID reflection_texture = _render_buffers_get_reflection_texture(p_render_buffers);
+ RID ambient_texture = rb->ambient_buffer;
+ RID reflection_texture = rb->reflection_buffer;
effects->copy_to_fb_rect(ambient_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
}
}
@@ -5719,6 +5803,17 @@ RID RendererSceneRenderRD::render_buffers_get_default_gi_probe_buffer() {
return default_giprobe_buffer;
}
+RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND_V(!rb, RID());
+ return rb->ambient_buffer;
+}
+RID RendererSceneRenderRD::render_buffers_get_gi_reflection_texture(RID p_render_buffers) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ ERR_FAIL_COND_V(!rb, RID());
+ return rb->reflection_buffer;
+}
+
uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const {
const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND_V(!rb, 0);
@@ -5856,6 +5951,11 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->msaa = p_msaa;
rb->screen_space_aa = p_screen_space_aa;
rb->use_debanding = p_use_debanding;
+ if (rb->cluster_builder == nullptr) {
+ rb->cluster_builder = memnew(ClusterBuilderRD);
+ }
+ rb->cluster_builder->set_shared(&cluster_builder_shared);
+
_free_render_buffer_data(rb);
{
@@ -5896,6 +5996,12 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa);
_render_buffers_uniform_set_changed(p_render_buffers);
+
+ rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
+}
+
+void RendererSceneRenderRD::gi_set_use_half_resolution(bool p_enable) {
+ gi.half_resolution = p_enable;
}
void RendererSceneRenderRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
@@ -6006,17 +6112,34 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
}
void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment) {
+ cluster.reflection_count = 0;
+
for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
- RID rpi = p_reflections[i];
+ if (cluster.reflection_count == cluster.max_reflections) {
+ break;
+ }
- if (i >= cluster.max_reflections) {
- reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflections[i]);
+ if (!rpi) {
continue;
}
- reflection_probe_instance_set_render_index(rpi, i);
+ cluster.reflection_sort[cluster.reflection_count].instance = rpi;
+ cluster.reflection_sort[cluster.reflection_count].depth = -p_camera_inverse_transform.xform(rpi->transform.origin).z;
+ cluster.reflection_count++;
+ }
+
+ if (cluster.reflection_count > 0) {
+ SortArray<Cluster::InstanceSort<ReflectionProbeInstance>> sort_array;
+ sort_array.sort(cluster.reflection_sort, cluster.reflection_count);
+ }
+
+ for (uint32_t i = 0; i < cluster.reflection_count; i++) {
+ ReflectionProbeInstance *rpi = cluster.reflection_sort[i].instance;
- RID base_probe = reflection_probe_instance_get_probe(rpi);
+ rpi->render_index = i;
+
+ RID base_probe = rpi->probe;
Cluster::ReflectionData &reflection_ubo = cluster.reflections[i];
@@ -6025,7 +6148,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
reflection_ubo.box_extents[0] = extents.x;
reflection_ubo.box_extents[1] = extents.y;
reflection_ubo.box_extents[2] = extents.z;
- reflection_ubo.index = reflection_probe_instance_get_atlas_index(rpi);
+ reflection_ubo.index = rpi->atlas_index;
Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
@@ -6034,46 +6157,50 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
reflection_ubo.box_offset[2] = origin_offset.z;
reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
- float intensity = storage->reflection_probe_get_intensity(base_probe);
- bool interior = storage->reflection_probe_is_interior(base_probe);
- bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
+ reflection_ubo.intensity = storage->reflection_probe_get_intensity(base_probe);
+ reflection_ubo.ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
- reflection_ubo.params[0] = intensity;
- reflection_ubo.params[1] = 0;
- reflection_ubo.params[2] = interior ? 1.0 : 0.0;
- reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
+ reflection_ubo.exterior = !storage->reflection_probe_is_interior(base_probe);
+ reflection_ubo.box_project = storage->reflection_probe_is_box_projection(base_probe);
Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear();
float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
- uint32_t ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
- reflection_ubo.ambient_mode = ambient_mode;
- Transform transform = reflection_probe_instance_get_transform(rpi);
+ Transform transform = rpi->transform;
Transform proj = (p_camera_inverse_transform * transform).inverse();
RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix);
- cluster.builder.add_reflection_probe(transform, extents);
+ current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents);
- reflection_probe_instance_set_render_pass(rpi, RSG::rasterizer->get_frame_number());
+ rpi->last_pass = RSG::rasterizer->get_frame_number();
}
- if (p_reflections.size()) {
- RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, MIN(cluster.max_reflections, (unsigned int)p_reflections.size()) * sizeof(ReflectionData), cluster.reflections, true);
+ if (cluster.reflection_count) {
+ RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, cluster.reflection_count * sizeof(ReflectionData), cluster.reflections, true);
}
}
-void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
- uint32_t light_count = 0;
+void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
+ Transform inverse_transform = p_camera_transform.affine_inverse();
+
r_directional_light_count = 0;
r_positional_light_count = 0;
sky_scene_state.ubo.directional_light_count = 0;
+ Plane camera_plane(p_camera_transform.origin, -p_camera_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
+
+ cluster.omni_light_count = 0;
+ cluster.spot_light_count = 0;
+
for (int i = 0; i < (int)p_lights.size(); i++) {
- RID li = p_lights[i];
- RID base = light_instance_get_base_light(li);
+ LightInstance *li = light_instance_owner.getornull(p_lights[i]);
+ if (!li) {
+ continue;
+ }
+ RID base = li->light;
ERR_CONTINUE(base.is_null());
@@ -6083,7 +6210,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
// Copy to SkyDirectionalLightData
if (r_directional_light_count < sky_scene_state.max_directional_lights) {
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[r_directional_light_count];
- Transform light_transform = light_instance_get_base_transform(li);
+ Transform light_transform = li->transform;
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
sky_light_data.direction[0] = world_direction.x;
@@ -6119,9 +6246,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
Cluster::DirectionalLightData &light_data = cluster.directional_lights[r_directional_light_count];
- Transform light_transform = light_instance_get_base_transform(li);
+ Transform light_transform = li->transform;
- Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
+ Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
light_data.direction[0] = direction.x;
light_data.direction[1] = direction.y;
@@ -6200,28 +6327,28 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
light_data.blend_splits = storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
- Rect2 atlas_rect = light_instance_get_directional_shadow_atlas_rect(li, j);
- CameraMatrix matrix = light_instance_get_shadow_camera(li, j);
- float split = light_instance_get_directional_shadow_split(li, MIN(limit, j));
+ Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
+ CameraMatrix matrix = li->shadow_transform[j].camera;
+ float split = li->shadow_transform[MIN(limit, j)].split;
CameraMatrix bias;
bias.set_light_bias();
CameraMatrix rectm;
rectm.set_light_atlas_rect(atlas_rect);
- Transform modelview = (p_camera_inverse_transform * light_instance_get_shadow_transform(li, j)).inverse();
+ Transform modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
- float bias_scale = light_instance_get_shadow_bias_scale(li, j);
+ float bias_scale = li->shadow_transform[j].bias_scale;
light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_scale;
- light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * light_instance_get_directional_shadow_texel_size(li, j);
+ light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
- light_data.shadow_z_range[j] = light_instance_get_shadow_range(li, j);
- light_data.shadow_range_begin[j] = light_instance_get_shadow_range_begin(li, j);
+ light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
+ light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin;
RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
- Vector2 uv_scale = light_instance_get_shadow_uv_scale(li, j);
+ Vector2 uv_scale = li->shadow_transform[j].uv_scale;
uv_scale *= atlas_rect.size; //adapt to atlas size
switch (j) {
case 0: {
@@ -6258,166 +6385,198 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
r_directional_light_count++;
} break;
- case RS::LIGHT_SPOT:
case RS::LIGHT_OMNI: {
- if (light_count >= cluster.max_lights) {
+ if (cluster.omni_light_count >= cluster.max_lights) {
continue;
}
- Transform light_transform = light_instance_get_base_transform(li);
+ cluster.omni_light_sort[cluster.omni_light_count].instance = li;
+ cluster.omni_light_sort[cluster.omni_light_count].depth = camera_plane.distance_to(li->transform.origin);
+ cluster.omni_light_count++;
+ } break;
+ case RS::LIGHT_SPOT: {
+ if (cluster.spot_light_count >= cluster.max_lights) {
+ continue;
+ }
- Cluster::LightData &light_data = cluster.lights[light_count];
- cluster.lights_instances[light_count] = li;
+ cluster.spot_light_sort[cluster.spot_light_count].instance = li;
+ cluster.spot_light_sort[cluster.spot_light_count].depth = camera_plane.distance_to(li->transform.origin);
+ cluster.spot_light_count++;
+ } break;
+ }
- float sign = storage->light_is_negative(base) ? -1 : 1;
- Color linear_col = storage->light_get_color(base).to_linear();
+ li->last_pass = RSG::rasterizer->get_frame_number();
+ }
- light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION));
- light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI);
+ if (cluster.omni_light_count) {
+ SortArray<Cluster::InstanceSort<LightInstance>> sorter;
+ sorter.sort(cluster.omni_light_sort, cluster.omni_light_count);
+ }
- light_data.color_specular[0] = MIN(uint32_t(linear_col.r * 255), 255);
- light_data.color_specular[1] = MIN(uint32_t(linear_col.g * 255), 255);
- light_data.color_specular[2] = MIN(uint32_t(linear_col.b * 255), 255);
- light_data.color_specular[3] = MIN(uint32_t(storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 255), 255);
+ if (cluster.spot_light_count) {
+ SortArray<Cluster::InstanceSort<LightInstance>> sorter;
+ sorter.sort(cluster.spot_light_sort, cluster.spot_light_count);
+ }
- float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
- light_data.inv_radius = 1.0 / radius;
+ ShadowAtlas *shadow_atlas = nullptr;
- Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin);
+ if (p_shadow_atlas.is_valid() && p_using_shadows) {
+ shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
+ }
- light_data.position[0] = pos.x;
- light_data.position[1] = pos.y;
- light_data.position[2] = pos.z;
+ for (uint32_t i = 0; i < (cluster.omni_light_count + cluster.spot_light_count); i++) {
+ uint32_t index = (i < cluster.omni_light_count) ? i : i - (cluster.omni_light_count);
+ Cluster::LightData &light_data = (i < cluster.omni_light_count) ? cluster.omni_lights[index] : cluster.spot_lights[index];
+ RS::LightType type = (i < cluster.omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
+ LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance;
+ RID base = li->light;
- Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
+ cluster.lights_instances[i] = li->self;
- light_data.direction[0] = direction.x;
- light_data.direction[1] = direction.y;
- light_data.direction[2] = direction.z;
+ Transform light_transform = li->transform;
- float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float sign = storage->light_is_negative(base) ? -1 : 1;
+ Color linear_col = storage->light_get_color(base).to_linear();
- light_data.size = size;
+ light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
- light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION));
- float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
- light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle)));
+ float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
- light_data.mask = storage->light_get_cull_mask(base);
+ light_data.color[0] = linear_col.r * energy;
+ light_data.color[1] = linear_col.g * energy;
+ light_data.color[2] = linear_col.b * energy;
+ light_data.specular_amount = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
- light_data.atlas_rect[0] = 0;
- light_data.atlas_rect[1] = 0;
- light_data.atlas_rect[2] = 0;
- light_data.atlas_rect[3] = 0;
+ float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
+ light_data.inv_radius = 1.0 / radius;
- RID projector = storage->light_get_projector(base);
+ Vector3 pos = inverse_transform.xform(light_transform.origin);
- if (projector.is_valid()) {
- Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
+ light_data.position[0] = pos.x;
+ light_data.position[1] = pos.y;
+ light_data.position[2] = pos.z;
- if (type == RS::LIGHT_SPOT) {
- light_data.projector_rect[0] = rect.position.x;
- light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
- light_data.projector_rect[2] = rect.size.width;
- light_data.projector_rect[3] = -rect.size.height;
- } else {
- light_data.projector_rect[0] = rect.position.x;
- light_data.projector_rect[1] = rect.position.y;
- light_data.projector_rect[2] = rect.size.width;
- light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
- }
- } else {
- light_data.projector_rect[0] = 0;
- light_data.projector_rect[1] = 0;
- light_data.projector_rect[2] = 0;
- light_data.projector_rect[3] = 0;
- }
+ Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
- if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
- // fill in the shadow information
+ light_data.direction[0] = direction.x;
+ light_data.direction[1] = direction.y;
+ light_data.direction[2] = direction.z;
- Color shadow_color = storage->light_get_shadow_color(base);
+ float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
- light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
- light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
- light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
- light_data.shadow_color_enabled[3] = 255;
+ light_data.size = size;
- if (type == RS::LIGHT_SPOT) {
- light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
- float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0;
- shadow_texel_size *= light_instance_get_shadow_texel_size(li, p_shadow_atlas);
+ light_data.cone_attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ light_data.cone_angle = Math::cos(Math::deg2rad(spot_angle));
- light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size;
+ light_data.mask = storage->light_get_cull_mask(base);
- } else { //omni
- light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0;
- float shadow_texel_size = light_instance_get_shadow_texel_size(li, p_shadow_atlas);
- light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space
- }
+ light_data.atlas_rect[0] = 0;
+ light_data.atlas_rect[1] = 0;
+ light_data.atlas_rect[2] = 0;
+ light_data.atlas_rect[3] = 0;
- light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
+ RID projector = storage->light_get_projector(base);
- Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas);
+ if (projector.is_valid()) {
+ Rect2 rect = storage->decal_atlas_get_texture_rect(projector);
- light_data.atlas_rect[0] = rect.position.x;
- light_data.atlas_rect[1] = rect.position.y;
- light_data.atlas_rect[2] = rect.size.width;
- light_data.atlas_rect[3] = rect.size.height;
+ if (type == RS::LIGHT_SPOT) {
+ light_data.projector_rect[0] = rect.position.x;
+ light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
+ light_data.projector_rect[2] = rect.size.width;
+ light_data.projector_rect[3] = -rect.size.height;
+ } else {
+ light_data.projector_rect[0] = rect.position.x;
+ light_data.projector_rect[1] = rect.position.y;
+ light_data.projector_rect[2] = rect.size.width;
+ light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
+ }
+ } else {
+ light_data.projector_rect[0] = 0;
+ light_data.projector_rect[1] = 0;
+ light_data.projector_rect[2] = 0;
+ light_data.projector_rect[3] = 0;
+ }
- light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
- light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+ if (shadow_atlas && shadow_atlas->shadow_owners.has(li->self)) {
+ // fill in the shadow information
- if (type == RS::LIGHT_OMNI) {
- light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
- Transform proj = (p_camera_inverse_transform * light_transform).inverse();
+ light_data.shadow_enabled = true;
- RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
+ if (type == RS::LIGHT_SPOT) {
+ light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
+ float shadow_texel_size = Math::tan(Math::deg2rad(spot_angle)) * radius * 2.0;
+ shadow_texel_size *= light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
- if (size > 0.0) {
- light_data.soft_shadow_size = size;
- } else {
- light_data.soft_shadow_size = 0.0;
- light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
- }
+ light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size;
- } else if (type == RS::LIGHT_SPOT) {
- Transform modelview = (p_camera_inverse_transform * light_transform).inverse();
- CameraMatrix bias;
- bias.set_light_bias();
+ } else { //omni
+ light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0;
+ float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
+ light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 2.0; // applied in -1 .. 1 space
+ }
- CameraMatrix shadow_mtx = bias * light_instance_get_shadow_camera(li, 0) * modelview;
- RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
+ light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
- if (size > 0.0) {
- CameraMatrix cm = light_instance_get_shadow_camera(li, 0);
- float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
- light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
- } else {
- light_data.soft_shadow_size = 0.0;
- light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
- }
- }
+ Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas);
+
+ light_data.atlas_rect[0] = rect.position.x;
+ light_data.atlas_rect[1] = rect.position.y;
+ light_data.atlas_rect[2] = rect.size.width;
+ light_data.atlas_rect[3] = rect.size.height;
+
+ light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+
+ if (type == RS::LIGHT_OMNI) {
+ light_data.atlas_rect[3] *= 0.5; //one paraboloid on top of another
+ Transform proj = (inverse_transform * light_transform).inverse();
+
+ RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
+
+ if (size > 0.0) {
+ light_data.soft_shadow_size = size;
} else {
- light_data.shadow_color_enabled[3] = 0;
+ light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
}
- light_instance_set_index(li, light_count);
+ } else if (type == RS::LIGHT_SPOT) {
+ Transform modelview = (inverse_transform * light_transform).inverse();
+ CameraMatrix bias;
+ bias.set_light_bias();
- cluster.builder.add_light(type == RS::LIGHT_SPOT ? LightClusterBuilder::LIGHT_TYPE_SPOT : LightClusterBuilder::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
+ CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
+ RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
- light_count++;
- r_positional_light_count++;
- } break;
+ if (size > 0.0) {
+ CameraMatrix cm = li->shadow_transform[0].camera;
+ float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
+ light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
+ } else {
+ light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
+ }
+ }
+ } else {
+ light_data.shadow_enabled = false;
}
- light_instance_set_render_pass(li, RSG::rasterizer->get_frame_number());
+ li->light_index = index;
+
+ current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
+
+ r_positional_light_count++;
+ }
- //update UBO for forward rendering, blit to texture for clustered
+ if (cluster.omni_light_count) {
+ RD::get_singleton()->buffer_update(cluster.omni_light_buffer, 0, sizeof(Cluster::LightData) * cluster.omni_light_count, cluster.omni_lights, true);
}
- if (light_count) {
- RD::get_singleton()->buffer_update(cluster.light_buffer, 0, sizeof(Cluster::LightData) * light_count, cluster.lights, true);
+ if (cluster.spot_light_count) {
+ RD::get_singleton()->buffer_update(cluster.spot_light_buffer, 0, sizeof(Cluster::LightData) * cluster.spot_light_count, cluster.spot_lights, true);
}
if (r_directional_light_count) {
@@ -6430,18 +6589,26 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
- uint32_t decal_count = MIN((uint32_t)p_decals.size(), cluster.max_decals);
- int idx = 0;
+ uint32_t decal_count = p_decals.size();
+
+ cluster.decal_count = 0;
+
for (uint32_t i = 0; i < decal_count; i++) {
- RID di = p_decals[i];
- RID decal = decal_instance_get_base(di);
+ if (cluster.decal_count == cluster.max_decals) {
+ break;
+ }
- Transform xform = decal_instance_get_transform(di);
+ DecalInstance *di = decal_instance_owner.getornull(p_decals[i]);
+ if (!di) {
+ continue;
+ }
+ RID decal = di->decal;
- float fade = 1.0;
+ Transform xform = di->transform;
+
+ real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
if (storage->decal_is_distance_fade_enabled(decal)) {
- real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
float fade_begin = storage->decal_get_distance_fade_begin(decal);
float fade_length = storage->decal_get_distance_fade_length(decal);
@@ -6449,18 +6616,43 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
if (distance > fade_begin + fade_length) {
continue; // do not use this decal, its invisible
}
+ }
+ }
+ cluster.decal_sort[cluster.decal_count].instance = di;
+ cluster.decal_sort[cluster.decal_count].depth = distance;
+ cluster.decal_count++;
+ }
+
+ if (cluster.decal_count > 0) {
+ SortArray<Cluster::InstanceSort<DecalInstance>> sort_array;
+ sort_array.sort(cluster.decal_sort, cluster.decal_count);
+ }
+
+ for (uint32_t i = 0; i < cluster.decal_count; i++) {
+ DecalInstance *di = cluster.decal_sort[i].instance;
+ RID decal = di->decal;
+
+ Transform xform = di->transform;
+ float fade = 1.0;
+
+ if (storage->decal_is_distance_fade_enabled(decal)) {
+ real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ float fade_begin = storage->decal_get_distance_fade_begin(decal);
+ float fade_length = storage->decal_get_distance_fade_length(decal);
+
+ if (distance > fade_begin) {
fade = 1.0 - (distance - fade_begin) / fade_length;
}
}
- Cluster::DecalData &dd = cluster.decals[idx];
+ Cluster::DecalData &dd = cluster.decals[i];
Vector3 decal_extents = storage->decal_get_extents(decal);
Transform scale_xform;
scale_xform.basis.scale(Vector3(decal_extents.x, decal_extents.y, decal_extents.z));
- Transform to_decal_xform = (p_camera_inverse_xform * decal_instance_get_transform(di) * scale_xform * uv_xform).affine_inverse();
+ Transform to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
RendererStorageRD::store_transform(to_decal_xform, dd.xform);
Vector3 normal = xform.basis.get_axis(Vector3::AXIS_Y).normalized();
@@ -6545,13 +6737,11 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.upper_fade = storage->decal_get_upper_fade(decal);
dd.lower_fade = storage->decal_get_lower_fade(decal);
- cluster.builder.add_decal(xform, decal_extents);
-
- idx++;
+ current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
}
- if (idx > 0) {
- RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * idx, cluster.decals, true);
+ if (cluster.decal_count > 0) {
+ RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * cluster.decal_count, cluster.decals, true);
}
}
@@ -6681,7 +6871,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
//update directional shadow
if (p_use_directional_shadows) {
- if (directional_shadow.shrink_stages.empty()) {
+ if (directional_shadow.shrink_stages.is_empty()) {
if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
//invalidate uniform set, we will need a new one
RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
@@ -6716,7 +6906,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
bool force_shrink_shadows = false;
- if (shadow_atlas->shrink_stages.empty()) {
+ if (shadow_atlas->shrink_stages.is_empty()) {
if (rb->volumetric_fog->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->uniform_set)) {
//invalidate uniform set, we will need a new one
RD::get_singleton()->free(rb->volumetric_fog->uniform_set);
@@ -6734,8 +6924,10 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
cluster.lights_shadow_rect_cache_count = 0;
- for (int i = 0; i < p_positional_light_count; i++) {
- if (cluster.lights[i].shadow_color_enabled[3] > 127) {
+ for (uint32_t i = 0; i < cluster.omni_light_count + cluster.spot_light_count; i++) {
+ Cluster::LightData &ld = i < cluster.omni_light_count ? cluster.omni_lights[i] : cluster.spot_lights[i - cluster.omni_light_count];
+
+ if (ld.shadow_enabled != 0) {
RID li = cluster.lights_instances[i];
ERR_CONTINUE(!shadow_atlas->shadow_owners.has(li));
@@ -6773,7 +6965,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
cluster.lights_shadow_rect_cache_count++;
- if (cluster.lights_shadow_rect_cache_count == cluster.max_lights) {
+ if (cluster.lights_shadow_rect_cache_count == cluster.max_lights * 2) {
break; //light limit reached
}
}
@@ -6870,23 +7062,22 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 3;
- u.ids.push_back(get_positional_light_buffer());
+ u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
-
{
RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 4;
- u.ids.push_back(get_directional_light_buffer());
+ u.ids.push_back(get_spot_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.binding = 5;
- u.ids.push_back(get_cluster_builder_texture());
+ u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
}
@@ -6894,7 +7085,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 6;
- u.ids.push_back(get_cluster_builder_indices_buffer());
+ u.ids.push_back(rb->cluster_builder->get_cluster_buffer());
uniforms.push_back(u);
}
@@ -6954,6 +7145,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 14;
+ u.ids.push_back(volumetric_fog.params_ubo);
+ uniforms.push_back(u);
+ }
rb->volumetric_fog->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);
@@ -6999,7 +7197,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
rb->volumetric_fog->length = env->volumetric_fog_length;
rb->volumetric_fog->spread = env->volumetric_fog_detail_spread;
- VolumetricFogShader::PushConstant push_constant;
+ VolumetricFogShader::ParamsUBO params;
Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
@@ -7015,51 +7213,71 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
fog_near_size = Vector2();
}
- push_constant.fog_frustum_size_begin[0] = fog_near_size.x;
- push_constant.fog_frustum_size_begin[1] = fog_near_size.y;
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
- push_constant.fog_frustum_size_end[0] = fog_far_size.x;
- push_constant.fog_frustum_size_end[1] = fog_far_size.y;
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
- push_constant.z_near = z_near;
- push_constant.z_far = z_far;
+ params.z_near = z_near;
+ params.z_far = z_far;
- push_constant.fog_frustum_end = fog_end;
+ params.fog_frustum_end = fog_end;
- push_constant.fog_volume_size[0] = rb->volumetric_fog->width;
- push_constant.fog_volume_size[1] = rb->volumetric_fog->height;
- push_constant.fog_volume_size[2] = rb->volumetric_fog->depth;
+ params.fog_volume_size[0] = rb->volumetric_fog->width;
+ params.fog_volume_size[1] = rb->volumetric_fog->height;
+ params.fog_volume_size[2] = rb->volumetric_fog->depth;
- push_constant.directional_light_count = p_directional_light_count;
+ params.directional_light_count = p_directional_light_count;
Color light = env->volumetric_fog_light.to_linear();
- push_constant.light_energy[0] = light.r * env->volumetric_fog_light_energy;
- push_constant.light_energy[1] = light.g * env->volumetric_fog_light_energy;
- push_constant.light_energy[2] = light.b * env->volumetric_fog_light_energy;
- push_constant.base_density = env->volumetric_fog_density;
+ params.light_energy[0] = light.r * env->volumetric_fog_light_energy;
+ params.light_energy[1] = light.g * env->volumetric_fog_light_energy;
+ params.light_energy[2] = light.b * env->volumetric_fog_light_energy;
+ params.base_density = env->volumetric_fog_density;
+
+ params.detail_spread = env->volumetric_fog_detail_spread;
+ params.gi_inject = env->volumetric_fog_gi_inject;
+
+ params.cam_rotation[0] = p_cam_transform.basis[0][0];
+ params.cam_rotation[1] = p_cam_transform.basis[1][0];
+ params.cam_rotation[2] = p_cam_transform.basis[2][0];
+ params.cam_rotation[3] = 0;
+ params.cam_rotation[4] = p_cam_transform.basis[0][1];
+ params.cam_rotation[5] = p_cam_transform.basis[1][1];
+ params.cam_rotation[6] = p_cam_transform.basis[2][1];
+ params.cam_rotation[7] = 0;
+ params.cam_rotation[8] = p_cam_transform.basis[0][2];
+ params.cam_rotation[9] = p_cam_transform.basis[1][2];
+ params.cam_rotation[10] = p_cam_transform.basis[2][2];
+ params.cam_rotation[11] = 0;
+ params.filter_axis = 0;
+ params.max_gi_probes = env->volumetric_fog_gi_inject > 0.001 ? p_gi_probe_count : 0;
- push_constant.detail_spread = env->volumetric_fog_detail_spread;
- push_constant.gi_inject = env->volumetric_fog_gi_inject;
+ {
+ uint32_t cluster_size = rb->cluster_builder->get_cluster_size();
+ params.cluster_shift = get_shift_from_power_of_2(cluster_size);
- push_constant.cam_rotation[0] = p_cam_transform.basis[0][0];
- push_constant.cam_rotation[1] = p_cam_transform.basis[1][0];
- push_constant.cam_rotation[2] = p_cam_transform.basis[2][0];
- push_constant.cam_rotation[3] = 0;
- push_constant.cam_rotation[4] = p_cam_transform.basis[0][1];
- push_constant.cam_rotation[5] = p_cam_transform.basis[1][1];
- push_constant.cam_rotation[6] = p_cam_transform.basis[2][1];
- push_constant.cam_rotation[7] = 0;
- push_constant.cam_rotation[8] = p_cam_transform.basis[0][2];
- push_constant.cam_rotation[9] = p_cam_transform.basis[1][2];
- push_constant.cam_rotation[10] = p_cam_transform.basis[2][2];
- push_constant.cam_rotation[11] = 0;
- push_constant.filter_axis = 0;
- push_constant.max_gi_probes = env->volumetric_fog_gi_inject > 0.001 ? p_gi_probe_count : 0;
+ uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1;
+ uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1;
+ params.cluster_type_size = cluster_screen_width * cluster_screen_height * (32 + 32);
+ params.cluster_width = cluster_screen_width;
+ params.max_cluster_element_count_div_32 = max_cluster_elements / 32;
+
+ params.screen_size[0] = rb->width;
+ params.screen_size[1] = rb->height;
+ }
/* Vector2 dssize = directional_shadow_get_size();
push_constant.directional_shadow_pixel_size[0] = 1.0 / dssize.x;
push_constant.directional_shadow_pixel_size[1] = 1.0 / dssize.y;
*/
+
+ RENDER_TIMESTAMP(">Volumetric Fog");
+
+ RENDER_TIMESTAMP("Render Fog");
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, true);
+
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
bool use_filter = volumetric_fog_filter_active;
@@ -7067,41 +7285,51 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[using_sdfgi ? VOLUMETRIC_FOG_SHADER_DENSITY_WITH_SDFGI : VOLUMETRIC_FOG_SHADER_DENSITY]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
+
if (using_sdfgi) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
}
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::PushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth, 4, 4, 4);
RD::get_singleton()->compute_list_add_barrier(compute_list);
if (use_filter) {
+ RENDER_TIMESTAMP("Filter Fog");
+
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::PushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth, 8, 8, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->compute_list_end();
+ //need restart for buffer update
- push_constant.filter_axis = 1;
+ params.filter_axis = 1;
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, true);
+ compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FILTER]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set2, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::PushConstant));
+ if (using_sdfgi) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
+ }
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth, 8, 8, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
}
+ RENDER_TIMESTAMP("Integrate Fog");
+
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.pipelines[VOLUMETRIC_FOG_SHADER_FOG]);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::PushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1, 8, 8, 1);
RD::get_singleton()->compute_list_end();
+
+ RENDER_TIMESTAMP("<Volumetric Fog");
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {
Color clear_color;
if (p_render_buffers.is_valid()) {
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
@@ -7131,7 +7359,24 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
gi_probes = &empty;
}
- cluster.builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster
+ if (render_buffers_owner.owns(p_render_buffers)) {
+ RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
+ current_cluster_builder = rb->cluster_builder;
+ } else if (reflection_probe_instance_owner.owns(p_reflection_probe)) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe);
+ ReflectionAtlas *ra = reflection_atlas_owner.getornull(rpi->atlas);
+ if (!ra) {
+ ERR_PRINT("reflection probe has no reflection atlas! Bug?");
+ current_cluster_builder = nullptr;
+ } else {
+ current_cluster_builder = ra->cluster_builder;
+ }
+ } else {
+ ERR_PRINT("No cluster builder, bug"); //should never happen, will crash
+ current_cluster_builder = nullptr;
+ }
+
+ current_cluster_builder->begin(p_cam_transform, p_cam_projection, !p_reflection_probe.is_valid());
bool using_shadows = true;
@@ -7146,12 +7391,15 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
- _setup_lights(*lights, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
+ _setup_lights(*lights, p_cam_transform, p_shadow_atlas, using_shadows, directional_light_count, positional_light_count);
_setup_decals(p_decals, p_cam_transform.affine_inverse());
- cluster.builder.bake_cluster(); //bake to cluster
+
+ current_cluster_builder->bake_cluster();
uint32_t gi_probe_count = 0;
- _setup_giprobes(p_render_buffers, p_cam_transform, *gi_probes, gi_probe_count);
+ if (p_render_buffers.is_valid()) {
+ _setup_giprobes(p_render_buffers, p_cam_transform, *gi_probes, gi_probe_count);
+ }
if (p_render_buffers.is_valid()) {
bool directional_shadows = false;
@@ -7164,9 +7412,30 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
_update_volumetric_fog(p_render_buffers, p_environment, p_cam_projection, p_cam_transform, p_shadow_atlas, directional_light_count, directional_shadows, positional_light_count, gi_probe_count);
}
- _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, directional_light_count, *gi_probes, p_lightmaps, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
+ _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, directional_light_count, *gi_probes, p_lightmaps, p_environment, current_cluster_builder->get_cluster_buffer(), current_cluster_builder->get_cluster_size(), current_cluster_builder->get_max_cluster_elements(), p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
if (p_render_buffers.is_valid()) {
+ if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
+ ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX;
+ switch (debug_draw) {
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT;
+ break;
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_SPOT_LIGHT;
+ break;
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_DECAL;
+ break;
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_REFLECTION_PROBE;
+ break;
+ default: {
+ }
+ }
+ current_cluster_builder->debug(elem_type);
+ }
+
RENDER_TIMESTAMP("Tonemap");
_render_buffers_post_process_and_tonemap(p_render_buffers, p_environment, p_camera_effects, p_cam_projection);
@@ -7177,31 +7446,36 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
}
}
-void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
+void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {
LightInstance *light_instance = light_instance_owner.getornull(p_light);
ERR_FAIL_COND(!light_instance);
Rect2i atlas_rect;
- RID atlas_texture;
+ uint32_t atlas_size;
+ RID atlas_fb;
bool using_dual_paraboloid = false;
bool using_dual_paraboloid_flip = false;
- float znear = 0;
- float zfar = 0;
RID render_fb;
RID render_texture;
- float bias = 0;
- float normal_bias = 0;
+ float zfar;
bool use_pancake = false;
- bool use_linear_depth = false;
bool render_cubemap = false;
bool finalize_cubemap = false;
+ bool flip_y = false;
+
CameraMatrix light_projection;
Transform light_transform;
+ bool clear_region = true;
+ bool begin_texture = true;
+ bool end_texture = true;
+
if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
+ _update_directional_shadow_atlas();
+
//set pssm stuff
if (light_instance->last_scene_shadow_pass != scene_pass) {
light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
@@ -7218,6 +7492,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
atlas_rect.size.width = light_instance->directional_rect.size.x;
atlas_rect.size.height = light_instance->directional_rect.size.y;
+ int pass_count = 1;
if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
atlas_rect.size.width /= 2;
atlas_rect.size.height /= 2;
@@ -7230,7 +7505,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
atlas_rect.position.x += atlas_rect.size.width;
atlas_rect.position.y += atlas_rect.size.height;
}
-
+ pass_count = 4;
} else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
atlas_rect.size.height /= 2;
@@ -7238,6 +7513,7 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
} else {
atlas_rect.position.y += atlas_rect.size.height;
}
+ pass_count = 2;
}
light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect;
@@ -7245,15 +7521,15 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
- float bias_mult = light_instance->shadow_transform[p_pass].bias_scale;
zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
- bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult;
- normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult;
- ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
- render_fb = shadow_map->fb;
- render_texture = shadow_map->depth;
- atlas_texture = directional_shadow.depth;
+ render_fb = directional_shadow.fb;
+ render_texture = RID();
+ flip_y = true;
+
+ clear_region = false;
+ begin_texture = (directional_shadow.current_light == 1) && (p_pass == 0); //light is 1-index because it was incremented above
+ end_texture = (directional_shadow.current_light == directional_shadow.light_count) && (p_pass == pass_count - 1);
} else {
//set from shadow atlas
@@ -7262,6 +7538,8 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
ERR_FAIL_COND(!shadow_atlas);
ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
+ _update_shadow_atlas(shadow_atlas);
+
uint32_t key = shadow_atlas->shadow_owners[p_light];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
@@ -7280,11 +7558,8 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
atlas_rect.size.width = shadow_size;
atlas_rect.size.height = shadow_size;
- atlas_texture = shadow_atlas->depth;
zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
- bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS);
- normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS);
if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
@@ -7297,6 +7572,10 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
light_transform = light_instance->shadow_transform[0].transform;
render_cubemap = true;
finalize_cubemap = p_pass == 5;
+ atlas_fb = shadow_atlas->fb;
+
+ atlas_size = shadow_atlas->size;
+ clear_region = false;
} else {
light_projection = light_instance->shadow_transform[0].camera;
@@ -7307,22 +7586,17 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
using_dual_paraboloid = true;
using_dual_paraboloid_flip = p_pass == 1;
-
- ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
- render_fb = shadow_map->fb;
- render_texture = shadow_map->depth;
+ render_fb = shadow_atlas->fb;
+ flip_y = true;
}
} else if (storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
- ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size);
- render_fb = shadow_map->fb;
- render_texture = shadow_map->depth;
+ render_fb = shadow_atlas->fb;
- znear = light_instance->shadow_transform[0].camera.get_z_near();
- use_linear_depth = true;
+ flip_y = true;
}
}
@@ -7331,33 +7605,27 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p
_render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
if (finalize_cubemap) {
//reblit
- atlas_rect.size.height /= 2;
- storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_texture, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, false);
- atlas_rect.position.y += atlas_rect.size.height;
- storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_texture, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), 0.0, true);
+ Rect2 atlas_rect_norm = atlas_rect;
+ atlas_rect_norm.position.x /= float(atlas_size);
+ atlas_rect_norm.position.y /= float(atlas_size);
+ atlas_rect_norm.size.x /= float(atlas_size);
+ atlas_rect_norm.size.y /= float(atlas_size);
+ atlas_rect_norm.size.height /= 2;
+ storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, light_projection.get_z_near(), light_projection.get_z_far(), false);
+ atlas_rect_norm.position.y += atlas_rect_norm.size.height;
+ storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, light_projection.get_z_near(), light_projection.get_z_far(), true);
}
} else {
//render shadow
-
- _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold);
-
- //copy to atlas
- if (use_linear_depth) {
- storage->get_effects()->copy_depth_to_rect_and_linearize(render_texture, atlas_texture, atlas_rect, true, znear, zfar);
- } else {
- storage->get_effects()->copy_depth_to_rect(render_texture, atlas_texture, atlas_rect, true);
- }
-
- //does not work from depth to color
- //RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true);
+ _render_shadow(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, atlas_rect, flip_y, clear_region, begin_texture, end_texture);
}
}
-void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);
}
-void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) {
//print_line("rendering region " + itos(p_region));
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
ERR_FAIL_COND(!rb);
@@ -7405,6 +7673,9 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, con
push_constant.scroll[1] = 0;
push_constant.scroll[2] = 0;
}
+
+ rb->sdfgi->cascades[cascade].all_dynamic_lights_dirty = true;
+
push_constant.grid_size = rb->sdfgi->cascade_size;
push_constant.cascade = cascade;
@@ -7480,6 +7751,23 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, con
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant));
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ if (rb->sdfgi->uses_multibounce) {
+ //multibounce requires this to be stored so direct light can read from it
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_STORE]);
+
+ //convert to octahedral to store
+ ipush_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
+ ipush_constant.image_size[1] *= SDFGI::LIGHTPROBE_OCT_SIZE;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].integrate_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1, 8, 8, 1);
+ }
}
//ok finally barrier
@@ -7694,7 +7982,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, con
}
}
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
CameraMatrix cm;
@@ -7718,25 +8006,8 @@ void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uin
_sdfgi_update_cascades(p_render_buffers); //need cascades updated for this
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_STATIC]);
-
- SDGIShader::DirectLightPushConstant dl_push_constant;
-
- dl_push_constant.grid_size[0] = rb->sdfgi->cascade_size;
- dl_push_constant.grid_size[1] = rb->sdfgi->cascade_size;
- dl_push_constant.grid_size[2] = rb->sdfgi->cascade_size;
- dl_push_constant.max_cascades = rb->sdfgi->cascades.size();
- dl_push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
- dl_push_constant.multibounce = false; // this is static light, do not multibounce yet
- dl_push_constant.y_mult = rb->sdfgi->y_mult;
-
- //all must be processed
- dl_push_constant.process_offset = 0;
- dl_push_constant.process_increment = 1;
-
SDGIShader::Light lights[SDFGI::MAX_STATIC_LIGHTS];
+ uint32_t light_count[SDFGI::MAX_STATIC_LIGHTS];
for (uint32_t i = 0; i < p_cascade_count; i++) {
ERR_CONTINUE(p_cascade_indices[i] >= rb->sdfgi->cascades.size());
@@ -7801,9 +8072,36 @@ void RendererSceneRenderRD::render_sdfgi_static_lights(RID p_render_buffers, uin
if (idx > 0) {
RD::get_singleton()->buffer_update(cc.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights, true);
}
- dl_push_constant.light_count = idx;
+
+ light_count[i] = idx;
}
+ }
+
+ /* Static Lights */
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_STATIC]);
+
+ SDGIShader::DirectLightPushConstant dl_push_constant;
+
+ dl_push_constant.grid_size[0] = rb->sdfgi->cascade_size;
+ dl_push_constant.grid_size[1] = rb->sdfgi->cascade_size;
+ dl_push_constant.grid_size[2] = rb->sdfgi->cascade_size;
+ dl_push_constant.max_cascades = rb->sdfgi->cascades.size();
+ dl_push_constant.probe_axis_size = rb->sdfgi->probe_axis_count;
+ dl_push_constant.multibounce = false; // this is static light, do not multibounce yet
+ dl_push_constant.y_mult = rb->sdfgi->y_mult;
+
+ //all must be processed
+ dl_push_constant.process_offset = 0;
+ dl_push_constant.process_increment = 1;
+
+ for (uint32_t i = 0; i < p_cascade_count; i++) {
+ ERR_CONTINUE(p_cascade_indices[i] >= rb->sdfgi->cascades.size());
+
+ SDFGI::Cascade &cc = rb->sdfgi->cascades[p_cascade_indices[i]];
+
+ dl_push_constant.light_count = light_count[i];
dl_push_constant.cascade = p_cascade_indices[i];
if (dl_push_constant.light_count > 0) {
@@ -7827,6 +8125,9 @@ bool RendererSceneRenderRD::free(RID p_rid) {
if (rb->volumetric_fog) {
_volumetric_fog_erase(rb);
}
+ if (rb->cluster_builder) {
+ memdelete(rb->cluster_builder);
+ }
render_buffers_owner.free(p_rid);
} else if (environment_owner.owns(p_rid)) {
//not much to delete, just free it
@@ -7836,6 +8137,10 @@ bool RendererSceneRenderRD::free(RID p_rid) {
camera_effects_owner.free(p_rid);
} else if (reflection_atlas_owner.owns(p_rid)) {
reflection_atlas_set_size(p_rid, 0, 0);
+ ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_rid);
+ if (ra->cluster_builder) {
+ memdelete(ra->cluster_builder);
+ }
reflection_atlas_owner.free(p_rid);
} else if (reflection_probe_instance_owner.owns(p_rid)) {
//not much to delete, just free it
@@ -7844,6 +8149,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
reflection_probe_instance_owner.free(p_rid);
} else if (decal_instance_owner.owns(p_rid)) {
decal_instance_owner.free(p_rid);
+ } else if (lightmap_instance_owner.owns(p_rid)) {
+ lightmap_instance_owner.free(p_rid);
} else if (gi_probe_instance_owner.owns(p_rid)) {
GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);
if (gi_probe->texture.is_valid()) {
@@ -7979,23 +8286,28 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
//RID sampled_light;
- InstanceBase ins;
+ GeometryInstance *gi = geometry_instance_create(p_base);
- ins.base_type = RSG::storage->get_base_type(p_base);
- ins.base = p_base;
- ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base));
- for (int i = 0; i < ins.materials.size(); i++) {
- if (i < p_material_overrides.size()) {
- ins.materials.write[i] = p_material_overrides[i];
+ uint32_t sc = RSG::storage->mesh_get_surface_count(p_base);
+ Vector<RID> materials;
+ materials.resize(sc);
+
+ for (uint32_t i = 0; i < sc; i++) {
+ if (i < (uint32_t)p_material_overrides.size()) {
+ materials.write[i] = p_material_overrides[i];
}
}
+ geometry_instance_set_surface_materials(gi, materials);
+
if (cull_argument.size() == 0) {
cull_argument.push_back(nullptr);
}
- cull_argument[0] = &ins;
+ cull_argument[0] = gi;
_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
+ geometry_instance_free(gi);
+
TypedArray<Image> ret;
{
@@ -8047,20 +8359,17 @@ void RendererSceneRenderRD::sdfgi_set_debug_probe_select(const Vector3 &p_positi
RendererSceneRenderRD *RendererSceneRenderRD::singleton = nullptr;
-RID RendererSceneRenderRD::get_cluster_builder_texture() {
- return cluster.builder.get_cluster_texture();
-}
-
-RID RendererSceneRenderRD::get_cluster_builder_indices_buffer() {
- return cluster.builder.get_cluster_indices_buffer();
-}
-
RID RendererSceneRenderRD::get_reflection_probe_buffer() {
return cluster.reflection_buffer;
}
-RID RendererSceneRenderRD::get_positional_light_buffer() {
- return cluster.light_buffer;
+RID RendererSceneRenderRD::get_omni_light_buffer() {
+ return cluster.omni_light_buffer;
}
+
+RID RendererSceneRenderRD::get_spot_light_buffer() {
+ return cluster.spot_light_buffer;
+}
+
RID RendererSceneRenderRD::get_directional_light_buffer() {
return cluster.directional_light_buffer;
}
@@ -8076,13 +8385,21 @@ bool RendererSceneRenderRD::is_low_end() const {
}
RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
+ max_cluster_elements = GLOBAL_GET("rendering/cluster_builder/max_clustered_elements");
+
storage = p_storage;
singleton = this;
roughness_layers = GLOBAL_GET("rendering/quality/reflections/roughness_layers");
sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples");
sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");
- // sky_use_cubemap_array = false;
+
+ sdfgi_ray_count = RS::EnvironmentSDFGIRayCount(CLAMP(int32_t(GLOBAL_GET("rendering/sdfgi/probe_ray_count")), 0, int32_t(RS::ENV_SDFGI_RAY_COUNT_MAX - 1)));
+ sdfgi_frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(CLAMP(int32_t(GLOBAL_GET("rendering/sdfgi/frames_to_converge")), 0, int32_t(RS::ENV_SDFGI_CONVERGE_MAX - 1)));
+ sdfgi_frames_to_update_light = RS::EnvironmentSDFGIFramesToUpdateLight(CLAMP(int32_t(GLOBAL_GET("rendering/sdfgi/frames_to_update_lights")), 0, int32_t(RS::ENV_SDFGI_UPDATE_LIGHT_MAX - 1)));
+
+ directional_shadow.size = GLOBAL_GET("rendering/quality/directional_shadow/size");
+ directional_shadow.use_16_bits = GLOBAL_GET("rendering/quality/directional_shadow/16_bits");
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
@@ -8410,11 +8727,18 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1);
}
}
+ //GK
{
//calculate tables
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
Vector<String> gi_modes;
- gi_modes.push_back("");
+ gi_modes.push_back("\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define USE_SDFGI\n");
+ gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_GIPROBES\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n");
+ gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_GIPROBES\n");
+
gi.shader.initialize(gi_modes, defines);
gi.shader_version = gi.shader.version_create();
for (int i = 0; i < GI::MODE_MAX; i++) {
@@ -8458,31 +8782,29 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES);
}
- //cluster setup
- uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE);
-
{ //reflections
- uint32_t reflection_buffer_size;
- if (uniform_max_size < 65536) {
- //Yes, you guessed right, ARM again
- reflection_buffer_size = uniform_max_size;
- } else {
- reflection_buffer_size = 65536;
- }
- cluster.max_reflections = reflection_buffer_size / sizeof(Cluster::ReflectionData);
+ cluster.max_reflections = max_cluster_elements;
cluster.reflections = memnew_arr(Cluster::ReflectionData, cluster.max_reflections);
- cluster.reflection_buffer = RD::get_singleton()->storage_buffer_create(reflection_buffer_size);
+ cluster.reflection_sort = memnew_arr(Cluster::InstanceSort<ReflectionProbeInstance>, cluster.max_decals);
+ cluster.reflection_buffer = RD::get_singleton()->storage_buffer_create(sizeof(Cluster::ReflectionData) * cluster.max_reflections);
}
{ //lights
- cluster.max_lights = MIN(1024 * 1024, uniform_max_size) / sizeof(Cluster::LightData); //1mb of lights
+ cluster.max_lights = max_cluster_elements;
+
uint32_t light_buffer_size = cluster.max_lights * sizeof(Cluster::LightData);
- cluster.lights = memnew_arr(Cluster::LightData, cluster.max_lights);
- cluster.light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+ cluster.omni_lights = memnew_arr(Cluster::LightData, cluster.max_lights);
+ cluster.omni_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+ cluster.omni_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights);
+ cluster.spot_lights = memnew_arr(Cluster::LightData, cluster.max_lights);
+ cluster.spot_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+ cluster.spot_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights);
//defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(cluster.max_lights) + "\n";
- cluster.lights_instances = memnew_arr(RID, cluster.max_lights);
- cluster.lights_shadow_rect_cache = memnew_arr(Rect2i, cluster.max_lights);
+
+ //used for volumetric fog shrinking
+ cluster.lights_instances = memnew_arr(RID, cluster.max_lights * 2);
+ cluster.lights_shadow_rect_cache = memnew_arr(Rect2i, cluster.max_lights * 2);
cluster.max_directional_lights = MAX_DIRECTIONAL_LIGHTS;
uint32_t directional_light_buffer_size = cluster.max_directional_lights * sizeof(Cluster::DirectionalLightData);
@@ -8491,14 +8813,13 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
}
{ //decals
- cluster.max_decals = MIN(1024 * 1024, uniform_max_size) / sizeof(Cluster::DecalData); //1mb of decals
+ cluster.max_decals = max_cluster_elements;
uint32_t decal_buffer_size = cluster.max_decals * sizeof(Cluster::DecalData);
cluster.decals = memnew_arr(Cluster::DecalData, cluster.max_decals);
+ cluster.decal_sort = memnew_arr(Cluster::InstanceSort<DecalInstance>, cluster.max_decals);
cluster.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
}
- cluster.builder.setup(16, 8, 24);
-
if (!low_end) {
String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
Vector<String> volumetric_fog_modes;
@@ -8511,6 +8832,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
for (int i = 0; i < VOLUMETRIC_FOG_SHADER_MAX; i++) {
volumetric_fog.pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, i));
}
+ volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
}
{
@@ -8547,12 +8869,11 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
environment_set_volumetric_fog_positional_shadow_shrink_size(GLOBAL_GET("rendering/volumetric_fog/positional_shadow_shrink"));
cull_argument.set_page_pool(&cull_argument_pool);
+
+ gi.half_resolution = GLOBAL_GET("rendering/quality/gi/use_half_resolution");
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
- for (Map<Vector2i, ShadowMap>::Element *E = shadow_maps.front(); E; E = E->next()) {
- RD::get_singleton()->free(E->get().depth);
- }
for (Map<int, ShadowCubemap>::Element *E = shadow_cubemaps.front(); E; E = E->next()) {
RD::get_singleton()->free(E->get().cubemap);
}
@@ -8576,6 +8897,7 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader);
volumetric_fog.shader.version_free(volumetric_fog.shader_version);
+ RD::get_singleton()->free(volumetric_fog.params_ubo);
memdelete_arr(gi_probe_lights);
}
@@ -8597,15 +8919,21 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
{
RD::get_singleton()->free(cluster.directional_light_buffer);
- RD::get_singleton()->free(cluster.light_buffer);
+ RD::get_singleton()->free(cluster.omni_light_buffer);
+ RD::get_singleton()->free(cluster.spot_light_buffer);
RD::get_singleton()->free(cluster.reflection_buffer);
RD::get_singleton()->free(cluster.decal_buffer);
memdelete_arr(cluster.directional_lights);
- memdelete_arr(cluster.lights);
+ memdelete_arr(cluster.omni_lights);
+ memdelete_arr(cluster.spot_lights);
+ memdelete_arr(cluster.omni_light_sort);
+ memdelete_arr(cluster.spot_light_sort);
memdelete_arr(cluster.lights_shadow_rect_cache);
memdelete_arr(cluster.lights_instances);
memdelete_arr(cluster.reflections);
+ memdelete_arr(cluster.reflection_sort);
memdelete_arr(cluster.decals);
+ memdelete_arr(cluster.decal_sort);
}
RD::get_singleton()->free(shadow_sampler);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index e4dc98571e..af8cdb9b71 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,7 +34,7 @@
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_rd/light_cluster_builder.h"
+#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/giprobe.glsl.gen.h"
@@ -104,17 +104,17 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
+ void _setup_lights(const PagedArray<RID> &p_lights, const Transform &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform);
void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);
void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used);
- virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
- virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0;
- virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) = 0;
+ virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0;
+ virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) = 0;
+ virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
@@ -124,8 +124,6 @@ protected:
virtual void _base_uniforms_changed() = 0;
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0;
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
- virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers) = 0;
- virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers) = 0;
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
@@ -134,11 +132,11 @@ protected:
void _setup_sky(RID p_environment, RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform, const Size2i p_screen_size);
void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform);
- void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
+ void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);
// needed for a single argument calls (material and uv2)
- PagedArrayPool<InstanceBase *> cull_argument_pool;
- PagedArray<InstanceBase *> cull_argument; //need this to exist
+ PagedArrayPool<GeometryInstance *> cull_argument_pool;
+ PagedArray<GeometryInstance *> cull_argument; //need this to exist
private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
double time_step = 0;
@@ -233,6 +231,7 @@ private:
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
SkyShaderData();
virtual ~SkyShaderData();
};
@@ -340,6 +339,8 @@ private:
};
Vector<Reflection> reflections;
+
+ ClusterBuilderRD *cluster_builder = nullptr;
};
mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner;
@@ -374,6 +375,15 @@ private:
mutable RID_Owner<DecalInstance> decal_instance_owner;
+ /* LIGHTMAP INSTANCE */
+
+ struct LightmapInstance {
+ RID lightmap;
+ Transform transform;
+ };
+
+ mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
+
/* GIPROBE INSTANCE */
struct GIProbeLight {
@@ -562,6 +572,7 @@ private:
uint32_t smallest_subdiv = 0;
int size = 0;
+ bool use_16_bits = false;
RID depth;
RID fb; //for copying
@@ -573,6 +584,8 @@ private:
RID_Owner<ShadowAtlas> shadow_atlas_owner;
+ void _update_shadow_atlas(ShadowAtlas *shadow_atlas);
+
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
RS::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set
@@ -593,9 +606,11 @@ private:
struct DirectionalShadow {
RID depth;
+ RID fb; //when renderign direct
int light_count = 0;
int size = 0;
+ bool use_16_bits = false;
int current_light = 0;
Vector<ShadowShrinkStage> shrink_stages;
@@ -605,6 +620,8 @@ private:
void _allocate_shadow_shrink_stages(RID p_base, int p_base_size, Vector<ShadowShrinkStage> &shrink_stages, uint32_t p_target_size);
void _clear_shadow_shrink_stages(Vector<ShadowShrinkStage> &shrink_stages);
+ void _update_directional_shadow_atlas();
+
/* SHADOW CUBEMAPS */
struct ShadowCubemap {
@@ -615,14 +632,6 @@ private:
Map<int, ShadowCubemap> shadow_cubemaps;
ShadowCubemap *_get_shadow_cubemap(int p_size);
- struct ShadowMap {
- RID depth;
- RID fb;
- };
-
- Map<Vector2i, ShadowMap> shadow_maps;
- ShadowMap *_get_shadow_map(const Size2i &p_size);
-
void _create_shadow_cubemaps();
/* LIGHT INSTANCE */
@@ -823,6 +832,9 @@ private:
/* RENDER BUFFERS */
+ ClusterBuilderSharedDataRD cluster_builder_shared;
+ ClusterBuilderRD *current_cluster_builder = nullptr;
+
struct SDFGI;
struct VolumetricFog;
@@ -848,6 +860,8 @@ private:
SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
+ ClusterBuilderRD *cluster_builder = nullptr;
+
//built-in textures used for ping pong image processing and blurring
struct Blur {
RID texture;
@@ -887,6 +901,16 @@ private:
RID giprobe_textures[MAX_GIPROBES];
RID giprobe_buffer;
+
+ RID ambient_buffer;
+ RID reflection_buffer;
+ bool using_half_size_gi = false;
+
+ struct GI {
+ RID full_buffer;
+ RID full_dispatch;
+ RID full_mask;
+ } gi;
};
RID default_giprobe_buffer;
@@ -948,6 +972,8 @@ private:
RID scroll_occlusion_uniform_set;
RID integrate_uniform_set;
RID lights_buffer;
+
+ bool all_dynamic_lights_dirty = true;
};
//used for rendering (voxelization)
@@ -1009,6 +1035,8 @@ private:
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
RS::EnvironmentSDFGIFramesToConverge sdfgi_frames_to_converge = RS::ENV_SDFGI_CONVERGE_IN_10_FRAMES;
+ RS::EnvironmentSDFGIFramesToUpdateLight sdfgi_frames_to_update_light = RS::ENV_SDFGI_UPDATE_LIGHT_IN_4_FRAMES;
+
float sdfgi_solid_cell_ratio = 0.25;
Vector3 sdfgi_debug_probe_pos;
Vector3 sdfgi_debug_probe_dir;
@@ -1246,23 +1274,28 @@ private:
float z_far;
float proj_info[4];
-
+ float ao_color[3];
uint32_t max_giprobes;
+
uint32_t high_quality_vct;
- uint32_t use_sdfgi;
uint32_t orthogonal;
-
- float ao_color[3];
- uint32_t pad;
+ uint32_t pad[2];
float cam_rotation[12];
};
RID sdfgi_ubo;
- enum {
- MODE_MAX = 1
+ enum Mode {
+ MODE_GIPROBE,
+ MODE_SDFGI,
+ MODE_COMBINED,
+ MODE_HALF_RES_GIPROBE,
+ MODE_HALF_RES_SDFGI,
+ MODE_HALF_RES_COMBINED,
+ MODE_MAX
};
+ bool half_resolution = false;
GiShaderRD shader;
RID shader_version;
RID pipelines[MODE_MAX];
@@ -1287,14 +1320,23 @@ private:
struct Cluster {
/* Scene State UBO */
- struct ReflectionData { //should always be 128 bytes
+ enum {
+ REFLECTION_AMBIENT_DISABLED = 0,
+ REFLECTION_AMBIENT_ENVIRONMENT = 1,
+ REFLECTION_AMBIENT_COLOR = 2,
+ };
+
+ struct ReflectionData {
float box_extents[3];
float index;
float box_offset[3];
uint32_t mask;
- float params[4]; // intensity, 0, interior , boxproject
float ambient[3]; // ambient color,
+ float intensity;
+ bool exterior;
+ bool box_project;
uint32_t ambient_mode;
+ uint32_t pad;
float local_matrix[16]; // up to here for spot and omni, rest is for directional
};
@@ -1303,10 +1345,15 @@ private:
float inv_radius;
float direction[3];
float size;
- uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
- uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
- uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
- uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
+
+ float color[3];
+ float attenuation;
+
+ float cone_attenuation;
+ float cone_angle;
+ float specular_amount;
+ uint32_t shadow_enabled;
+
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
float shadow_matrix[16];
float shadow_bias;
@@ -1370,18 +1417,39 @@ private:
float normal_fade;
};
+ template <class T>
+ struct InstanceSort {
+ float depth;
+ T *instance;
+ bool operator<(const InstanceSort &p_sort) const {
+ return depth < p_sort.depth;
+ }
+ };
+
ReflectionData *reflections;
+ InstanceSort<ReflectionProbeInstance> *reflection_sort;
uint32_t max_reflections;
RID reflection_buffer;
uint32_t max_reflection_probes_per_instance;
+ uint32_t reflection_count = 0;
DecalData *decals;
+ InstanceSort<DecalInstance> *decal_sort;
uint32_t max_decals;
RID decal_buffer;
+ uint32_t decal_count;
+
+ LightData *omni_lights;
+ LightData *spot_lights;
- LightData *lights;
+ InstanceSort<LightInstance> *omni_light_sort;
+ InstanceSort<LightInstance> *spot_light_sort;
uint32_t max_lights;
- RID light_buffer;
+ RID omni_light_buffer;
+ RID spot_light_buffer;
+ uint32_t omni_light_count = 0;
+ uint32_t spot_light_count = 0;
+
RID *lights_instances;
Rect2i *lights_shadow_rect_cache;
uint32_t lights_shadow_rect_cache_count = 0;
@@ -1390,8 +1458,6 @@ private:
uint32_t max_directional_lights;
RID directional_light_buffer;
- LightClusterBuilder builder;
-
} cluster;
struct VolumetricFog {
@@ -1421,7 +1487,7 @@ private:
};
struct VolumetricFogShader {
- struct PushConstant {
+ struct ParamsUBO {
float fog_frustum_size_begin[2];
float fog_frustum_size_end[2];
@@ -1439,13 +1505,21 @@ private:
float detail_spread;
float gi_inject;
uint32_t max_gi_probes;
- uint32_t pad;
+ uint32_t cluster_type_size;
+
+ float screen_size[2];
+ uint32_t cluster_shift;
+ uint32_t cluster_width;
+
+ uint32_t cluster_pad[3];
+ uint32_t max_cluster_element_count_div_32;
float cam_rotation[12];
};
VolumetricFogShaderRD shader;
+ RID params_ubo;
RID shader_version;
RID pipelines[VOLUMETRIC_FOG_SHADER_MAX];
@@ -1470,13 +1544,17 @@ private:
float weight;
};
+ uint32_t max_cluster_elements = 512;
bool low_end = false;
public:
+ virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
+ virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
+
/* SHADOW ATLAS API */
RID shadow_atlas_create();
- void shadow_atlas_set_size(RID p_atlas, int p_size);
+ void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision);
bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version);
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
@@ -1497,7 +1575,7 @@ public:
return Size2(atlas->size, atlas->size);
}
- void directional_shadow_atlas_set_size(int p_size);
+ void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false);
int get_directional_light_shadow_size(RID p_light_intance);
void set_directional_shadow_count(int p_count);
@@ -1592,6 +1670,7 @@ public:
virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count);
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames);
+ virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update);
void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
@@ -1822,10 +1901,25 @@ public:
return decal->transform;
}
+ virtual RID lightmap_instance_create(RID p_lightmap);
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform);
+ _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
+ return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr;
+ }
+
+ _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
+ LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+ return li->lightmap;
+ }
+ _FORCE_INLINE_ Transform lightmap_instance_get_transform(RID p_lightmap_instance) {
+ LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance);
+ return li->transform;
+ }
+
RID gi_probe_instance_create(RID p_base);
void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);
bool gi_probe_needs_update(RID p_probe) const;
- void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects);
+ void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);
void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; }
@@ -1875,11 +1969,14 @@ public:
*/
RID render_buffers_create();
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding);
+ void gi_set_use_half_resolution(bool p_enable);
RID render_buffers_get_ao_texture(RID p_render_buffers);
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
RID render_buffers_get_gi_probe_buffer(RID p_render_buffers);
RID render_buffers_get_default_gi_probe_buffer();
+ RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
+ RID render_buffers_get_gi_reflection_texture(RID p_render_buffers);
uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const;
bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const;
@@ -1900,16 +1997,16 @@ public:
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
- void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
+ void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
- void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
+ void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0);
- void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
+ void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
- void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances);
+ void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances);
void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
- void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances);
+ void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances);
virtual void set_scene_pass(uint64_t p_pass) {
scene_pass = p_pass;
@@ -1960,10 +2057,9 @@ public:
virtual void set_time(double p_time, double p_step);
- RID get_cluster_builder_texture();
- RID get_cluster_builder_indices_buffer();
RID get_reflection_probe_buffer();
- RID get_positional_light_buffer();
+ RID get_omni_light_buffer();
+ RID get_spot_light_buffer();
RID get_directional_light_buffer();
RID get_decal_buffer();
int get_max_directional_lights() const;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 61b390b956..96dd5a6669 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -537,7 +537,7 @@ Ref<Image> RendererStorageRD::_validate_texture_format(const Ref<Image> &p_image
RID RendererStorageRD::texture_2d_create(const Ref<Image> &p_image) {
ERR_FAIL_COND_V(p_image.is_null(), RID());
- ERR_FAIL_COND_V(p_image->empty(), RID());
+ ERR_FAIL_COND_V(p_image->is_empty(), RID());
TextureToRDFormat ret_format;
Ref<Image> image = _validate_texture_format(p_image, ret_format);
@@ -620,7 +620,7 @@ RID RendererStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_lay
Image::Format valid_format = Image::FORMAT_MAX;
for (int i = 0; i < p_layers.size(); i++) {
- ERR_FAIL_COND_V(p_layers[i]->empty(), RID());
+ ERR_FAIL_COND_V(p_layers[i]->is_empty(), RID());
if (i == 0) {
valid_width = p_layers[i]->get_width();
@@ -855,7 +855,7 @@ RID RendererStorageRD::texture_proxy_create(RID p_base) {
}
void RendererStorageRD::_texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate) {
- ERR_FAIL_COND(p_image.is_null() || p_image->empty());
+ ERR_FAIL_COND(p_image.is_null() || p_image->is_empty());
Texture *tex = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!tex);
@@ -1039,7 +1039,7 @@ Ref<Image> RendererStorageRD::texture_2d_get(RID p_texture) const {
Ref<Image> image;
image.instance();
image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->empty(), Ref<Image>());
+ ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
image->convert(tex->format);
}
@@ -1062,7 +1062,7 @@ Ref<Image> RendererStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) c
Ref<Image> image;
image.instance();
image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->empty(), Ref<Image>());
+ ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
image->convert(tex->format);
}
@@ -1090,7 +1090,7 @@ Vector<Ref<Image>> RendererStorageRD::texture_3d_get(RID p_texture) const {
Ref<Image> img;
img.instance();
img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
- ERR_FAIL_COND_V(img->empty(), Vector<Ref<Image>>());
+ ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
if (tex->format != tex->validated_format) {
img->convert(tex->format);
}
@@ -1234,7 +1234,7 @@ void RendererStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::Can
ct->diffuse = p_texture;
} break;
case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
- ct->normalmap = p_texture;
+ ct->normal_map = p_texture;
} break;
case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
ct->specular = p_texture;
@@ -1316,7 +1316,7 @@ bool RendererStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::Canvas
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- t = texture_owner.getornull(ct->normalmap);
+ t = texture_owner.getornull(ct->normal_map);
if (!t) {
u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
ct->use_normal_cache = false;
@@ -1438,7 +1438,7 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {
for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
}
@@ -1499,6 +1499,15 @@ void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_typ
shader_data_request_func[p_shader_type] = p_function;
}
+RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const {
+ Shader *shader = shader_owner.getornull(p_shader);
+ ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
+ if (shader->data) {
+ return shader->data->get_native_source_code();
+ }
+ return RS::ShaderNativeSourceCode();
+}
+
/* COMMON MATERIAL API */
RID RendererStorageRD::material_create() {
@@ -1547,7 +1556,8 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
}
if (p_shader.is_null()) {
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
+ material->shader_id = 0;
return;
}
@@ -1555,6 +1565,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
ERR_FAIL_COND(!shader);
material->shader = shader;
material->shader_type = shader->type;
+ material->shader_id = p_shader.get_local_index();
shader->owners.insert(material);
if (shader->type == SHADER_TYPE_MAX) {
@@ -1568,7 +1579,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
//updating happens later
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
@@ -1613,7 +1624,7 @@ void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_materi
material->data->set_next_pass(p_next_material);
}
- material->instance_dependency.instance_notify_changed(false, true);
+ material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
}
void RendererStorageRD::material_set_render_priority(RID p_material, int priority) {
@@ -1663,10 +1674,10 @@ void RendererStorageRD::material_get_instance_shader_parameters(RID p_material,
}
}
-void RendererStorageRD::material_update_dependency(RID p_material, InstanceBaseDependency *p_instance) {
+void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
Material *material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
- p_instance->update_dependency(&material->instance_dependency);
+ p_instance->update_dependency(&material->dependency);
if (material->next_pass.is_valid()) {
material_update_dependency(material->next_pass, p_instance);
}
@@ -2216,7 +2227,7 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
RendererStorageRD *singleton = (RendererStorageRD *)RendererStorage::base_singleton;
#ifdef TOOLS_ENABLED
Texture *roughness_detect_texture = nullptr;
- RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGNHESS_R;
+ RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
Texture *normal_detect_texture = nullptr;
#endif
@@ -2596,7 +2607,13 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
}
- mesh->instance_dependency.instance_notify_changed(true, true);
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
+
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
+ }
mesh->material_cache.clear();
}
@@ -2638,7 +2655,7 @@ void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material;
- mesh->instance_dependency.instance_notify_changed(false, true);
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
mesh->material_cache.clear();
}
@@ -2813,6 +2830,25 @@ AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
return aabb;
}
+void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ Mesh *shadow_mesh = mesh_owner.getornull(mesh->shadow_mesh);
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.erase(mesh);
+ }
+ mesh->shadow_mesh = p_shadow_mesh;
+
+ shadow_mesh = mesh_owner.getornull(mesh->shadow_mesh);
+
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.insert(mesh);
+ }
+
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
+}
+
void RendererStorageRD::mesh_clear(RID p_mesh) {
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -2858,8 +2894,14 @@ void RendererStorageRD::mesh_clear(RID p_mesh) {
MeshInstance *mi = E->get();
_mesh_instance_clear(mi);
}
- mesh->instance_dependency.instance_notify_changed(true, true);
mesh->has_bone_weights = false;
+ mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
+
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
+ }
}
bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
@@ -3298,6 +3340,8 @@ void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS:
if (multimesh->instances) {
multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
}
+
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH);
}
int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
@@ -3331,7 +3375,7 @@ void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
}
}
- multimesh->instance_dependency.instance_notify_changed(true, true);
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
}
#define MULTIMESH_DIRTY_REGION_SIZE 512
@@ -3690,7 +3734,7 @@ void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float
const float *data = p_buffer.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->instance_dependency.instance_notify_changed(true, false);
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
}
@@ -3731,6 +3775,8 @@ void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_v
}
multimesh->visible_instances = p_visible;
+
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
}
int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
@@ -3788,7 +3834,7 @@ void RendererStorageRD::_update_dirty_multimeshes() {
//aabb is dirty..
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
- multimesh->instance_dependency.instance_notify_changed(true, false);
+ multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
}
@@ -3926,7 +3972,7 @@ void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->custom_aabb = p_aabb;
- particles->instance_dependency.instance_notify_changed(true, false);
+ particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) {
@@ -4155,24 +4201,18 @@ RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass)
return particles->draw_passes[p_pass];
}
-void RendererStorageRD::particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance) {
- RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance);
-
+void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(instance->base_type != RS::INSTANCE_PARTICLES_COLLISION);
-
- particles->collisions.insert(instance);
+ particles->collisions.insert(p_particles_collision_instance);
}
-void RendererStorageRD::particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance) {
- RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance);
-
+void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
- particles->collisions.erase(instance);
+ particles->collisions.erase(p_particles_collision_instance);
}
void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
@@ -4272,9 +4312,15 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
to_particles = p_particles->emission_transform.affine_inverse();
}
uint32_t collision_3d_textures_used = 0;
- for (const Set<RendererSceneRender::InstanceBase *>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
- ParticlesCollision *pc = particles_collision_owner.getornull(E->get()->base);
- Transform to_collider = E->get()->transform;
+ for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get());
+ if (!pci || !pci->active) {
+ continue;
+ }
+ ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision);
+ ERR_CONTINUE(!pc);
+
+ Transform to_collider = pci->transform;
if (p_particles->use_local_coords) {
to_collider = to_particles * to_collider;
}
@@ -4687,7 +4733,7 @@ void RendererStorageRD::update_particles() {
RD::get_singleton()->compute_list_end();
}
- particles->instance_dependency.instance_notify_changed(true, false); //make sure shadows are updated
+ particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
}
@@ -4817,6 +4863,10 @@ Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const Stri
return Variant();
}
+RS::ShaderNativeSourceCode RendererStorageRD::ParticlesShaderData::get_native_source_code() const {
+ return base_singleton->particles_shader.shader.version_get_native_source_code(version);
+}
+
RendererStorageRD::ParticlesShaderData::ParticlesShaderData() {
valid = false;
}
@@ -4986,7 +5036,7 @@ void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_c
particles_collision->heightfield_texture = RID();
}
particles_collision->type = p_type;
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
@@ -5000,7 +5050,7 @@ void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_co
ERR_FAIL_COND(!particles_collision);
particles_collision->radius = p_radius;
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
@@ -5008,7 +5058,7 @@ void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_coll
ERR_FAIL_COND(!particles_collision);
particles_collision->extents = p_extents;
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) {
@@ -5042,7 +5092,7 @@ void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_co
void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
- particles_collision->instance_dependency.instance_notify_changed(true, false);
+ particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
@@ -5096,6 +5146,22 @@ bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_colli
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
+RID RendererStorageRD::particles_collision_instance_create(RID p_collision) {
+ ParticlesCollisionInstance pci;
+ pci.collision = p_collision;
+ return particles_collision_instance_owner.make_rid(pci);
+}
+void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->transform = p_transform;
+}
+void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->active = p_active;
+}
+
/* SKELETON API */
RID RendererStorageRD::skeleton_create() {
@@ -5149,6 +5215,8 @@ void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d
skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
}
}
+
+ skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA);
}
int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
@@ -5269,7 +5337,8 @@ void RendererStorageRD::_update_dirty_skeletons() {
skeleton_dirty_list = skeleton->dirty_list;
- skeleton->instance_dependency.instance_notify_changed(true, false);
+ skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES);
+
skeleton->version++;
skeleton->dirty = false;
@@ -5290,17 +5359,20 @@ RID RendererStorageRD::light_create(RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
+ light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;
light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+ light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
- light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+ light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
- light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0;
+ light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
return light_owner.make_rid(light);
}
@@ -5328,7 +5400,7 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
} break;
default: {
}
@@ -5343,7 +5415,7 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
light->shadow = p_enabled;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) {
@@ -5385,7 +5457,7 @@ void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->cull_mask = p_mask;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
@@ -5395,7 +5467,7 @@ void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_ena
light->reverse_cull = p_enabled;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
@@ -5405,7 +5477,7 @@ void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bak
light->bake_mode = p_bake_mode;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
@@ -5415,7 +5487,7 @@ void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_casc
light->max_sdfgi_cascade = p_cascade;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
@@ -5425,7 +5497,7 @@ void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniSha
light->omni_shadow_mode = p_mode;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) {
@@ -5441,7 +5513,7 @@ void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::Light
light->directional_shadow_mode = p_mode;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
@@ -5450,7 +5522,7 @@ void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_e
light->directional_blend_splits = p_enable;
light->version++;
- light->instance_dependency.instance_notify_changed(true, false);
+ light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
}
bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const {
@@ -5549,7 +5621,7 @@ void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::Reflec
ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
@@ -5586,7 +5658,7 @@ void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_d
reflection_probe->max_distance = p_distance;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
@@ -5597,7 +5669,7 @@ void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3
return;
}
reflection_probe->extents = p_extents;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
@@ -5605,7 +5677,7 @@ void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Ve
ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
@@ -5613,7 +5685,7 @@ void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_ena
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
@@ -5628,7 +5700,7 @@ void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
@@ -5636,7 +5708,7 @@ void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_l
ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
@@ -5653,7 +5725,7 @@ void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_
reflection_probe->lod_threshold = p_ratio;
- reflection_probe->instance_dependency.instance_notify_changed(true, false);
+ reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
@@ -5771,7 +5843,7 @@ void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents)
Decal *decal = decal_owner.getornull(p_decal);
ERR_FAIL_COND(!decal);
decal->extents = p_extents;
- decal->instance_dependency.instance_notify_changed(true, false);
+ decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
@@ -5795,7 +5867,7 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type,
texture_add_to_decal_atlas(decal->textures[p_type]);
}
- decal->instance_dependency.instance_notify_changed(false, true);
+ decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL);
}
void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) {
@@ -5820,7 +5892,7 @@ void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
Decal *decal = decal_owner.getornull(p_decal);
ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers;
- decal->instance_dependency.instance_notify_changed(true, false);
+ decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
@@ -5977,7 +6049,7 @@ void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_
gi_probe->version++;
gi_probe->data_version++;
- gi_probe->instance_dependency.instance_notify_changed(true, false);
+ gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const {
@@ -7055,45 +7127,45 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta
rt->backbuffer_uniform_set = p_uniform_set;
}
-void RendererStorageRD::base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) {
+void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (mesh_owner.owns(p_base)) {
Mesh *mesh = mesh_owner.getornull(p_base);
- p_instance->update_dependency(&mesh->instance_dependency);
+ p_instance->update_dependency(&mesh->dependency);
} else if (multimesh_owner.owns(p_base)) {
MultiMesh *multimesh = multimesh_owner.getornull(p_base);
- p_instance->update_dependency(&multimesh->instance_dependency);
+ p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
}
} else if (reflection_probe_owner.owns(p_base)) {
ReflectionProbe *rp = reflection_probe_owner.getornull(p_base);
- p_instance->update_dependency(&rp->instance_dependency);
+ p_instance->update_dependency(&rp->dependency);
} else if (decal_owner.owns(p_base)) {
Decal *decal = decal_owner.getornull(p_base);
- p_instance->update_dependency(&decal->instance_dependency);
+ p_instance->update_dependency(&decal->dependency);
} else if (gi_probe_owner.owns(p_base)) {
GIProbe *gip = gi_probe_owner.getornull(p_base);
- p_instance->update_dependency(&gip->instance_dependency);
+ p_instance->update_dependency(&gip->dependency);
} else if (lightmap_owner.owns(p_base)) {
Lightmap *lm = lightmap_owner.getornull(p_base);
- p_instance->update_dependency(&lm->instance_dependency);
+ p_instance->update_dependency(&lm->dependency);
} else if (light_owner.owns(p_base)) {
Light *l = light_owner.getornull(p_base);
- p_instance->update_dependency(&l->instance_dependency);
+ p_instance->update_dependency(&l->dependency);
} else if (particles_owner.owns(p_base)) {
Particles *p = particles_owner.getornull(p_base);
- p_instance->update_dependency(&p->instance_dependency);
+ p_instance->update_dependency(&p->dependency);
} else if (particles_collision_owner.owns(p_base)) {
ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
- p_instance->update_dependency(&pc->instance_dependency);
+ p_instance->update_dependency(&pc->dependency);
}
}
-void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance) {
+void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND(!skeleton);
- p_instance->update_dependency(&skeleton->instance_dependency);
+ p_instance->update_dependency(&skeleton->dependency);
}
RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
@@ -7299,6 +7371,7 @@ void RendererStorageRD::_update_decal_atlas() {
tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1, true);
{
//create the framebuffer
@@ -8114,21 +8187,31 @@ bool RendererStorageRD::free(RID p_rid) {
_update_queued_materials();
}
material_set_shader(p_rid, RID()); //clean up shader
- material->instance_dependency.instance_notify_deleted(p_rid);
+ material->dependency.deleted_notify(p_rid);
+
material_owner.free(p_rid);
} else if (mesh_owner.owns(p_rid)) {
mesh_clear(p_rid);
+ mesh_set_shadow_mesh(p_rid, RID());
Mesh *mesh = mesh_owner.getornull(p_rid);
- mesh->instance_dependency.instance_notify_deleted(p_rid);
+ mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances");
}
+ if (mesh->shadow_owners.size()) {
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
+ }
+ }
mesh_owner.free(p_rid);
} else if (mesh_instance_owner.owns(p_rid)) {
MeshInstance *mi = mesh_instance_owner.getornull(p_rid);
_mesh_instance_clear(mi);
mi->mesh->instances.erase(mi->I);
mi->I = nullptr;
+
mesh_instance_owner.free(p_rid);
memdelete(mi);
@@ -8136,17 +8219,17 @@ bool RendererStorageRD::free(RID p_rid) {
_update_dirty_multimeshes();
multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
MultiMesh *multimesh = multimesh_owner.getornull(p_rid);
- multimesh->instance_dependency.instance_notify_deleted(p_rid);
+ multimesh->dependency.deleted_notify(p_rid);
multimesh_owner.free(p_rid);
} else if (skeleton_owner.owns(p_rid)) {
_update_dirty_skeletons();
skeleton_allocate(p_rid, 0);
Skeleton *skeleton = skeleton_owner.getornull(p_rid);
- skeleton->instance_dependency.instance_notify_deleted(p_rid);
+ skeleton->dependency.deleted_notify(p_rid);
skeleton_owner.free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) {
ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid);
- reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
+ reflection_probe->dependency.deleted_notify(p_rid);
reflection_probe_owner.free(p_rid);
} else if (decal_owner.owns(p_rid)) {
Decal *decal = decal_owner.getornull(p_rid);
@@ -8155,30 +8238,30 @@ bool RendererStorageRD::free(RID p_rid) {
texture_remove_from_decal_atlas(decal->textures[i]);
}
}
- decal->instance_dependency.instance_notify_deleted(p_rid);
+ decal->dependency.deleted_notify(p_rid);
decal_owner.free(p_rid);
} else if (gi_probe_owner.owns(p_rid)) {
gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
- gi_probe->instance_dependency.instance_notify_deleted(p_rid);
+ gi_probe->dependency.deleted_notify(p_rid);
gi_probe_owner.free(p_rid);
} else if (lightmap_owner.owns(p_rid)) {
lightmap_set_textures(p_rid, RID(), false);
Lightmap *lightmap = lightmap_owner.getornull(p_rid);
- lightmap->instance_dependency.instance_notify_deleted(p_rid);
+ lightmap->dependency.deleted_notify(p_rid);
lightmap_owner.free(p_rid);
} else if (light_owner.owns(p_rid)) {
light_set_projector(p_rid, RID()); //clear projector
// delete the texture
Light *light = light_owner.getornull(p_rid);
- light->instance_dependency.instance_notify_deleted(p_rid);
+ light->dependency.deleted_notify(p_rid);
light_owner.free(p_rid);
} else if (particles_owner.owns(p_rid)) {
Particles *particles = particles_owner.getornull(p_rid);
_particles_free_data(particles);
- particles->instance_dependency.instance_notify_deleted(p_rid);
+ particles->dependency.deleted_notify(p_rid);
particles_owner.free(p_rid);
} else if (particles_collision_owner.owns(p_rid)) {
ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid);
@@ -8186,8 +8269,10 @@ bool RendererStorageRD::free(RID p_rid) {
if (particles_collision->heightfield_texture.is_valid()) {
RD::get_singleton()->free(particles_collision->heightfield_texture);
}
- particles_collision->instance_dependency.instance_notify_deleted(p_rid);
+ particles_collision->dependency.deleted_notify(p_rid);
particles_collision_owner.free(p_rid);
+ } else if (particles_collision_instance_owner.owns(p_rid)) {
+ particles_collision_instance_owner.free(p_rid);
} else if (render_target_owner.owns(p_rid)) {
RenderTarget *rt = render_target_owner.getornull(p_rid);
@@ -8736,7 +8821,7 @@ RendererStorageRD::RendererStorageRD() {
actions.renames["RESTART_VELOCITY"] = "restart_velocity";
actions.renames["RESTART_COLOR"] = "restart_color";
actions.renames["RESTART_CUSTOM"] = "restart_custom";
- actions.renames["emit_particle"] = "emit_particle";
+ actions.renames["emit_subparticle"] = "emit_subparticle";
actions.renames["COLLIDED"] = "collided";
actions.renames["COLLISION_NORMAL"] = "collision_normal";
actions.renames["COLLISION_DEPTH"] = "collision_depth";
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index e4199ffd12..aa7195232a 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -95,6 +95,21 @@ public:
p_array[11] = 0;
}
+ static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.elements[0][0];
+ p_array[1] = p_mtx.basis.elements[0][1];
+ p_array[2] = p_mtx.basis.elements[0][2];
+ p_array[3] = p_mtx.origin.x;
+ p_array[4] = p_mtx.basis.elements[1][0];
+ p_array[5] = p_mtx.basis.elements[1][1];
+ p_array[6] = p_mtx.basis.elements[1][2];
+ p_array[7] = p_mtx.origin.y;
+ p_array[8] = p_mtx.basis.elements[2][0];
+ p_array[9] = p_mtx.basis.elements[2][1];
+ p_array[10] = p_mtx.basis.elements[2][2];
+ p_array[11] = p_mtx.origin.z;
+ }
+
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
@@ -127,6 +142,8 @@ public:
virtual bool is_animated() const = 0;
virtual bool casts_shadows() const = 0;
virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
+
virtual ~ShaderData() {}
};
@@ -187,7 +204,7 @@ private:
struct CanvasTexture {
RID diffuse;
- RID normalmap;
+ RID normal_map;
RID specular;
Color specular_color = Color(1, 1, 1, 1);
float shininess = 1.0;
@@ -360,6 +377,7 @@ private:
Shader *shader;
//shortcut to shader data and type
ShaderType shader_type;
+ uint32_t shader_id = 0;
bool update_requested;
bool uniform_dirty;
bool texture_dirty;
@@ -367,7 +385,7 @@ private:
Map<StringName, Variant> params;
int32_t priority;
RID next_pass;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
@@ -460,7 +478,10 @@ private:
List<MeshInstance *> instances;
- RendererStorage::InstanceDependency instance_dependency;
+ RID shadow_mesh;
+ Set<Mesh *> shadow_owners;
+
+ Dependency dependency;
};
mutable RID_Owner<Mesh> mesh_owner;
@@ -563,7 +584,7 @@ private:
bool dirty = false;
MultiMesh *dirty_list = nullptr;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<MultiMesh> multimesh_owner;
@@ -734,7 +755,7 @@ private:
ParticleEmissionBuffer *emission_buffer = nullptr;
RID emission_storage_buffer;
- Set<RendererSceneRender::InstanceBase *> collisions;
+ Set<RID> collisions;
Particles() :
inactive(true),
@@ -761,7 +782,7 @@ private:
clear(true) {
}
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
ParticlesFrameParams frame_params;
};
@@ -839,6 +860,8 @@ private:
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
ParticlesShaderData();
virtual ~ParticlesShaderData();
};
@@ -889,11 +912,19 @@ private:
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<ParticlesCollision> particles_collision_owner;
+ struct ParticlesCollisionInstance {
+ RID collision;
+ Transform transform;
+ bool active = false;
+ };
+
+ mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
/* Skeleton */
struct Skeleton {
@@ -911,7 +942,7 @@ private:
uint64_t version = 1;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Skeleton> skeleton_owner;
@@ -943,7 +974,7 @@ private:
bool directional_sky_only = false;
uint64_t version = 0;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Light> light_owner;
@@ -966,7 +997,7 @@ private:
uint32_t cull_mask = (1 << 20) - 1;
float lod_threshold = 0.01;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<ReflectionProbe> reflection_probe_owner;
@@ -987,7 +1018,7 @@ private:
float distance_fade_length = 1;
float normal_fade = 0.0;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
mutable RID_Owner<Decal> decal_owner;
@@ -1025,7 +1056,7 @@ private:
uint32_t version = 1;
uint32_t data_version = 1;
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
GiprobeSdfShaderRD giprobe_sdf_shader;
@@ -1054,7 +1085,7 @@ private:
int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
};
- RendererStorage::InstanceDependency instance_dependency;
+ Dependency dependency;
};
bool using_lightmap_array; //high end uses this
@@ -1330,6 +1361,8 @@ public:
Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const;
+
/* COMMON MATERIAL API */
RID material_create();
@@ -1347,11 +1380,16 @@ public:
void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters);
- void material_update_dependency(RID p_material, InstanceBaseDependency *p_instance);
+ void material_update_dependency(RID p_material, DependencyTracker *p_instance);
void material_force_update_textures(RID p_material, ShaderType p_shader_type);
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
+ _FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) {
+ Material *material = material_owner.getornull(p_material);
+ return material->shader_id;
+ }
+
_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {
Material *material = material_owner.getornull(p_material);
if (!material || material->shader_type != p_shader_type) {
@@ -1388,6 +1426,7 @@ public:
virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID());
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh);
virtual void mesh_clear(RID p_mesh);
@@ -1408,7 +1447,7 @@ public:
if (r_surface_count == 0) {
return nullptr;
}
- if (mesh->material_cache.empty()) {
+ if (mesh->material_cache.is_empty()) {
mesh->material_cache.resize(mesh->surface_count);
for (uint32_t i = 0; i < r_surface_count; i++) {
mesh->material_cache.write[i] = mesh->surfaces[i]->material;
@@ -1426,6 +1465,13 @@ public:
return mesh->surfaces[p_surface_index];
}
+ _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
+ Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ return mesh->shadow_mesh;
+ }
+
_FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
return surface->primitive;
@@ -1664,6 +1710,10 @@ public:
void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
+ _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
+ return skeleton_owner.getornull(p_skeleton) != nullptr;
+ }
+
_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
ERR_FAIL_COND_V(!skeleton, RID());
@@ -1827,8 +1877,8 @@ public:
Color reflection_probe_get_ambient_color(RID p_probe) const;
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
- void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance);
- void skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance);
+ void base_update_dependency(RID p_base, DependencyTracker *p_instance);
+ void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
/* DECAL API */
@@ -1977,7 +2027,11 @@ public:
_FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
return lightmap_probe_capture_update_speed;
}
-
+ _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
+ ERR_FAIL_COND_V(!lm, RID());
+ return lm->light_texture;
+ }
_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
const Lightmap *lm = lightmap_owner.getornull(p_lightmap);
@@ -2078,8 +2132,8 @@ public:
return particles->particles_transforms_buffer_uniform_set;
}
- virtual void particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance);
- virtual void particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance);
+ virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance);
+ virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);
/* PARTICLES COLLISION */
@@ -2099,6 +2153,11 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
+ //used from 2D and 3D
+ virtual RID particles_collision_instance_create(RID p_collision);
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform);
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
+
/* GLOBAL VARIABLES API */
virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value);
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index ae392b7586..e77141b26c 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -1340,8 +1340,8 @@ ShaderCompilerRD::ShaderCompilerRD() {
actions[RS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord";
actions[RS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing";
- actions[RS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap";
- actions[RS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth";
+ actions[RS::SHADER_SPATIAL].renames["NORMAL_MAP"] = "normal_map";
+ actions[RS::SHADER_SPATIAL].renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
actions[RS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo";
actions[RS::SHADER_SPATIAL].renames["ALPHA"] = "alpha";
actions[RS::SHADER_SPATIAL].renames["METALLIC"] = "metallic";
@@ -1387,8 +1387,8 @@ ShaderCompilerRD::ShaderCompilerRD() {
actions[RS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n";
actions[RS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n";
actions[RS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n";
- actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n";
- actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP";
+ actions[RS::SHADER_SPATIAL].usage_defines["NORMAL_MAP"] = "#define ENABLE_NORMAL_MAP\n";
+ actions[RS::SHADER_SPATIAL].usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
actions[RS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n";
actions[RS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
actions[RS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n";
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.h b/servers/rendering/renderer_rd/shader_compiler_rd.h
index 694f8fff91..d127d8e01c 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.h
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 41126218ae..2ae22a8a38 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -351,6 +351,127 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
}
}
+RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_version) {
+ Version *version = version_owner.getornull(p_version);
+ RS::ShaderNativeSourceCode source_code;
+ ERR_FAIL_COND_V(!version, source_code);
+
+ source_code.versions.resize(variant_defines.size());
+
+ for (int i = 0; i < source_code.versions.size(); i++) {
+ if (!is_compute) {
+ //vertex stage
+
+ StringBuilder builder;
+
+ builder.append(vertex_codev.get_data()); // version info (if exists)
+ builder.append("\n"); //make sure defines begin at newline
+ builder.append(general_defines.get_data());
+ builder.append(variant_defines[i].get_data());
+
+ for (int j = 0; j < version->custom_defines.size(); j++) {
+ builder.append(version->custom_defines[j].get_data());
+ }
+
+ builder.append(vertex_code0.get_data()); //first part of vertex
+
+ builder.append(version->uniforms.get_data()); //uniforms (same for vertex and fragment)
+
+ builder.append(vertex_code1.get_data()); //second part of vertex
+
+ builder.append(version->vertex_globals.get_data()); // vertex globals
+
+ builder.append(vertex_code2.get_data()); //third part of vertex
+
+ builder.append(version->vertex_code.get_data()); // code
+
+ builder.append(vertex_code3.get_data()); //fourth of vertex
+
+ RS::ShaderNativeSourceCode::Version::Stage stage;
+ stage.name = "vertex";
+ stage.code = builder.as_string();
+
+ source_code.versions.write[i].stages.push_back(stage);
+ }
+
+ if (!is_compute) {
+ //fragment stage
+
+ StringBuilder builder;
+
+ builder.append(fragment_codev.get_data()); // version info (if exists)
+ builder.append("\n"); //make sure defines begin at newline
+
+ builder.append(general_defines.get_data());
+ builder.append(variant_defines[i].get_data());
+ for (int j = 0; j < version->custom_defines.size(); j++) {
+ builder.append(version->custom_defines[j].get_data());
+ }
+
+ builder.append(fragment_code0.get_data()); //first part of fragment
+
+ builder.append(version->uniforms.get_data()); //uniforms (same for fragment and fragment)
+
+ builder.append(fragment_code1.get_data()); //first part of fragment
+
+ builder.append(version->fragment_globals.get_data()); // fragment globals
+
+ builder.append(fragment_code2.get_data()); //third part of fragment
+
+ builder.append(version->fragment_light.get_data()); // fragment light
+
+ builder.append(fragment_code3.get_data()); //fourth part of fragment
+
+ builder.append(version->fragment_code.get_data()); // fragment code
+
+ builder.append(fragment_code4.get_data()); //fourth part of fragment
+
+ RS::ShaderNativeSourceCode::Version::Stage stage;
+ stage.name = "fragment";
+ stage.code = builder.as_string();
+
+ source_code.versions.write[i].stages.push_back(stage);
+ }
+
+ if (is_compute) {
+ //compute stage
+
+ StringBuilder builder;
+
+ builder.append(compute_codev.get_data()); // version info (if exists)
+ builder.append("\n"); //make sure defines begin at newline
+ builder.append(general_defines.get_data());
+ builder.append(variant_defines[i].get_data());
+
+ for (int j = 0; j < version->custom_defines.size(); j++) {
+ builder.append(version->custom_defines[j].get_data());
+ }
+
+ builder.append(compute_code0.get_data()); //first part of compute
+
+ builder.append(version->uniforms.get_data()); //uniforms (same for compute and fragment)
+
+ builder.append(compute_code1.get_data()); //second part of compute
+
+ builder.append(version->compute_globals.get_data()); // compute globals
+
+ builder.append(compute_code2.get_data()); //third part of compute
+
+ builder.append(version->compute_code.get_data()); // code
+
+ builder.append(compute_code3.get_data()); //fourth of compute
+
+ RS::ShaderNativeSourceCode::Version::Stage stage;
+ stage.name = "compute";
+ stage.code = builder.as_string();
+
+ source_code.versions.write[i].stages.push_back(stage);
+ }
+ }
+
+ return source_code;
+}
+
void ShaderRD::_compile_version(Version *p_version) {
_clear_version(p_version);
@@ -360,7 +481,7 @@ void ShaderRD::_compile_version(Version *p_version) {
p_version->variants = memnew_arr(RID, variant_defines.size());
#if 1
- RendererCompositorRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
+ RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
#else
for (int i = 0; i < variant_defines.size(); i++) {
_compile_variant(i, p_version);
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index 05e07d3cf3..a3474c6f93 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,6 +36,7 @@
#include "core/templates/map.h"
#include "core/templates/rid_owner.h"
#include "core/variant/variant.h"
+#include "servers/rendering_server.h"
#include <stdio.h>
/**
@@ -133,6 +134,8 @@ public:
void set_variant_enabled(int p_variant, bool p_enabled);
bool is_variant_enabled(int p_variant) const;
+ RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version);
+
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
virtual ~ShaderRD();
};
diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub
index deaa9668df..1b0197c1c1 100644
--- a/servers/rendering/renderer_rd/shaders/SCsub
+++ b/servers/rendering/renderer_rd/shaders/SCsub
@@ -44,3 +44,6 @@ if "RD_GLSL" in env["BUILDERS"]:
env.RD_GLSL("particles_copy.glsl")
env.RD_GLSL("sort.glsl")
env.RD_GLSL("skeleton.glsl")
+ env.RD_GLSL("cluster_render.glsl")
+ env.RD_GLSL("cluster_store.glsl")
+ env.RD_GLSL("cluster_debug.glsl")
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index 7808e7ed52..3b39edc70e 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -396,7 +396,7 @@ vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv
vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color);
#ifdef LIGHT_SHADER_CODE_USED
- shadow_color *= shadow_modulate;
+ shadow_color.rgb *= shadow_modulate;
#endif
shadow_color.a *= light_color.a; //respect light alpha
@@ -497,9 +497,9 @@ void main() {
vec2 shadow_vertex = vertex;
{
- float normal_depth = 1.0;
+ float normal_map_depth = 1.0;
-#if defined(NORMALMAP_USED)
+#if defined(NORMAL_MAP_USED)
vec3 normal_map = vec3(0.0, 0.0, 1.0);
normal_used = true;
#endif
@@ -510,8 +510,8 @@ FRAGMENT_SHADER_CODE
/* clang-format on */
-#if defined(NORMALMAP_USED)
- normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth);
+#if defined(NORMAL_MAP_USED)
+ normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_map_depth);
#endif
}
@@ -546,7 +546,7 @@ FRAGMENT_SHADER_CODE
#ifdef LIGHT_SHADER_CODE_USED
vec4 shadow_modulate = vec4(1.0);
- light_color = light_compute(light_vertex, direction, normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, true);
+ light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, true);
#else
if (normal_used) {
@@ -563,7 +563,7 @@ FRAGMENT_SHADER_CODE
light_color = light_shadow_compute(light_base, light_color, shadow_uv
#ifdef LIGHT_SHADER_CODE_USED
,
- shadow_modulate
+ shadow_modulate.rgb
#endif
);
}
@@ -605,7 +605,7 @@ FRAGMENT_SHADER_CODE
vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
light_color.rgb *= light_base_color.rgb;
- light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, false);
+ light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, false);
#else
light_color.rgb *= light_base_color.rgb * light_base_color.a;
@@ -659,7 +659,7 @@ FRAGMENT_SHADER_CODE
light_color = light_shadow_compute(light_base, light_color, shadow_uv
#ifdef LIGHT_SHADER_CODE_USED
,
- shadow_modulate
+ shadow_modulate.rgb
#endif
);
}
diff --git a/servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl b/servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl
index e723468dd8..3a4bf4da07 100644
--- a/servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl
@@ -6,12 +6,18 @@
struct LightData { //this structure needs to be as packed as possible
vec3 position;
float inv_radius;
+
vec3 direction;
float size;
- uint attenuation_energy; //attenuation
- uint color_specular; //rgb color, a specular (8 bit unorm)
- uint cone_attenuation_angle; // attenuation and angle, (16bit float)
- uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
+
+ vec3 color;
+ float attenuation;
+
+ float cone_attenuation;
+ float cone_angle;
+ float specular_amount;
+ bool shadow_enabled;
+
vec4 atlas_rect; // rect in the shadow atlas
mat4 shadow_matrix;
float shadow_bias;
@@ -34,9 +40,13 @@ struct ReflectionData {
float index;
vec3 box_offset;
uint mask;
- vec4 params; // intensity, 0, interior , boxproject
vec3 ambient; // ambient color
+ float intensity;
+ bool exterior;
+ bool box_project;
uint ambient_mode;
+ uint pad;
+ //0-8 is intensity,8-9 is ambient, mode
mat4 local_matrix; // up to here for spot and omni, rest is for directional
// notes: for ambientblend, use distance to edge to blend between already existing global environment
};
diff --git a/servers/rendering/renderer_rd/shaders/cluster_debug.glsl b/servers/rendering/renderer_rd/shaders/cluster_debug.glsl
new file mode 100644
index 0000000000..70a875192c
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cluster_debug.glsl
@@ -0,0 +1,115 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+const vec3 usage_gradient[33] = vec3[]( // 1 (none) + 32
+ vec3(0.14, 0.17, 0.23),
+ vec3(0.24, 0.44, 0.83),
+ vec3(0.23, 0.57, 0.84),
+ vec3(0.22, 0.71, 0.84),
+ vec3(0.22, 0.85, 0.83),
+ vec3(0.21, 0.85, 0.72),
+ vec3(0.21, 0.85, 0.57),
+ vec3(0.20, 0.85, 0.42),
+ vec3(0.20, 0.85, 0.27),
+ vec3(0.27, 0.86, 0.19),
+ vec3(0.51, 0.85, 0.19),
+ vec3(0.57, 0.86, 0.19),
+ vec3(0.62, 0.85, 0.19),
+ vec3(0.67, 0.86, 0.20),
+ vec3(0.73, 0.85, 0.20),
+ vec3(0.78, 0.85, 0.20),
+ vec3(0.83, 0.85, 0.20),
+ vec3(0.85, 0.82, 0.20),
+ vec3(0.85, 0.76, 0.20),
+ vec3(0.85, 0.81, 0.20),
+ vec3(0.85, 0.65, 0.20),
+ vec3(0.84, 0.60, 0.21),
+ vec3(0.84, 0.56, 0.21),
+ vec3(0.84, 0.51, 0.21),
+ vec3(0.84, 0.46, 0.21),
+ vec3(0.84, 0.41, 0.21),
+ vec3(0.84, 0.36, 0.21),
+ vec3(0.84, 0.31, 0.21),
+ vec3(0.84, 0.27, 0.21),
+ vec3(0.83, 0.22, 0.22),
+ vec3(0.83, 0.22, 0.27),
+ vec3(0.83, 0.22, 0.32),
+ vec3(1.00, 0.63, 0.70));
+layout(push_constant, binding = 0, std430) uniform Params {
+ uvec2 screen_size;
+ uvec2 cluster_screen_size;
+
+ uint cluster_shift;
+ uint cluster_type;
+ float z_near;
+ float z_far;
+
+ bool orthogonal;
+ uint max_cluster_element_count_div_32;
+ uint pad1;
+ uint pad2;
+}
+params;
+
+layout(set = 0, binding = 1, std430) buffer restrict readonly ClusterData {
+ uint data[];
+}
+cluster_data;
+
+layout(rgba16f, set = 0, binding = 2) uniform restrict writeonly image2D screen_buffer;
+layout(set = 0, binding = 3) uniform texture2D depth_buffer;
+layout(set = 0, binding = 4) uniform sampler depth_buffer_sampler;
+
+void main() {
+ uvec2 screen_pos = gl_GlobalInvocationID.xy;
+ if (any(greaterThanEqual(screen_pos, params.screen_size))) {
+ return;
+ }
+
+ uvec2 cluster_pos = screen_pos >> params.cluster_shift;
+
+ uint offset = cluster_pos.y * params.cluster_screen_size.x + cluster_pos.x;
+ offset += params.cluster_screen_size.x * params.cluster_screen_size.y * params.cluster_type;
+ offset *= (params.max_cluster_element_count_div_32 + 32);
+
+ //depth buffers generally can't be accessed via image API
+ float depth = texelFetch(sampler2D(depth_buffer, depth_buffer_sampler), ivec2(screen_pos), 0).r * 2.0 - 1.0;
+
+ if (params.orthogonal) {
+ depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ } else {
+ depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
+ }
+ depth /= params.z_far;
+
+ uint slice = uint(clamp(floor(depth * 32.0), 0.0, 31.0));
+ uint slice_minmax = cluster_data.data[offset + params.max_cluster_element_count_div_32 + slice];
+ uint item_min = slice_minmax & 0xFFFF;
+ uint item_max = slice_minmax >> 16;
+
+ uint item_count = 0;
+ for (uint i = 0; i < params.max_cluster_element_count_div_32; i++) {
+ uint slice_bits = cluster_data.data[offset + i];
+ while (slice_bits != 0) {
+ uint bit = findLSB(slice_bits);
+ uint item = i * 32 + bit;
+ if ((item >= item_min && item < item_max)) {
+ item_count++;
+ }
+ slice_bits &= ~(1 << bit);
+ }
+ }
+
+ item_count = min(item_count, 32);
+
+ vec3 color = usage_gradient[item_count];
+
+ color = mix(color * 1.2, color * 0.3, float(slice) / 31.0);
+
+ imageStore(screen_buffer, ivec2(screen_pos), vec4(color, 1.0));
+}
diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
new file mode 100644
index 0000000000..8723ea78e4
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
@@ -0,0 +1,168 @@
+#[vertex]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) in vec3 vertex_attrib;
+
+layout(location = 0) out float depth_interp;
+layout(location = 1) out flat uint element_index;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+ uint base_index;
+ uint pad0;
+ uint pad1;
+ uint pad2;
+}
+params;
+
+layout(set = 0, binding = 1, std140) uniform State {
+ mat4 projection;
+
+ float inv_z_far;
+ uint screen_to_clusters_shift; // shift to obtain coordinates in block indices
+ uint cluster_screen_width; //
+ uint cluster_data_size; // how much data for a single cluster takes
+
+ uint cluster_depth_offset;
+ uint pad0;
+ uint pad1;
+ uint pad2;
+}
+state;
+
+struct RenderElement {
+ uint type; //0-4
+ bool touches_near;
+ bool touches_far;
+ uint original_index;
+ mat3x4 transform_inv;
+ vec3 scale;
+ uint pad;
+};
+
+layout(set = 0, binding = 2, std430) buffer restrict readonly RenderElements {
+ RenderElement data[];
+}
+render_elements;
+
+void main() {
+ element_index = params.base_index + gl_InstanceIndex;
+
+ vec3 vertex = vertex_attrib;
+ vertex *= render_elements.data[element_index].scale;
+
+ vertex = vec4(vertex, 1.0) * render_elements.data[element_index].transform_inv;
+ depth_interp = -vertex.z;
+
+ gl_Position = state.projection * vec4(vertex, 1.0);
+}
+
+#[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+#if defined(GL_KHR_shader_subgroup_ballot) && defined(GL_KHR_shader_subgroup_arithmetic) && defined(GL_KHR_shader_subgroup_vote)
+
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_KHR_shader_subgroup_arithmetic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+
+#define USE_SUBGROUPS
+#endif
+
+layout(location = 0) in float depth_interp;
+layout(location = 1) in flat uint element_index;
+
+layout(set = 0, binding = 1, std140) uniform State {
+ mat4 projection;
+ float inv_z_far;
+ uint screen_to_clusters_shift; // shift to obtain coordinates in block indices
+ uint cluster_screen_width; //
+ uint cluster_data_size; // how much data for a single cluster takes
+ uint cluster_depth_offset;
+ uint pad0;
+ uint pad1;
+ uint pad2;
+}
+state;
+
+//cluster data is layout linearly, each cell contains the follow information:
+// - list of bits for every element to mark as used, so (max_elem_count/32)*4 uints
+// - a uint for each element to mark the depth bits used when rendering (0-31)
+
+layout(set = 0, binding = 3, std430) buffer restrict ClusterRender {
+ uint data[];
+}
+cluster_render;
+
+void main() {
+ //convert from screen to cluster
+ uvec2 cluster = uvec2(gl_FragCoord.xy) >> state.screen_to_clusters_shift;
+
+ //get linear cluster offset from screen poss
+ uint cluster_offset = cluster.x + state.cluster_screen_width * cluster.y;
+ //multiply by data size to position at the beginning of the element list for this cluster
+ cluster_offset *= state.cluster_data_size;
+
+ //find the current element in the list and plot the bit to mark it as used
+ uint usage_write_offset = cluster_offset + (element_index >> 5);
+ uint usage_write_bit = 1 << (element_index & 0x1F);
+
+#ifdef USE_SUBGROUPS
+
+ uint cluster_thread_group_index;
+
+ if (!gl_HelperInvocation) {
+ //http://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf
+
+ uvec4 mask;
+
+ while (true) {
+ // find the cluster offset of the first active thread
+ // threads that did break; go inactive and no longer count
+ uint first = subgroupBroadcastFirst(cluster_offset);
+ // update the mask for thread that match this cluster
+ mask = subgroupBallot(first == cluster_offset);
+ if (first == cluster_offset) {
+ // This thread belongs to the group of threads that match this offset,
+ // so exit the loop.
+ break;
+ }
+ }
+
+ cluster_thread_group_index = subgroupBallotExclusiveBitCount(mask);
+
+ if (cluster_thread_group_index == 0) {
+ atomicOr(cluster_render.data[usage_write_offset], usage_write_bit);
+ }
+ }
+#else
+ if (!gl_HelperInvocation) {
+ atomicOr(cluster_render.data[usage_write_offset], usage_write_bit);
+ }
+#endif
+ //find the current element in the depth usage list and mark the current depth as used
+ float unit_depth = depth_interp * state.inv_z_far;
+
+ uint z_bit = clamp(uint(floor(unit_depth * 32.0)), 0, 31);
+
+ uint z_write_offset = cluster_offset + state.cluster_depth_offset + element_index;
+ uint z_write_bit = 1 << z_bit;
+
+#ifdef USE_SUBGROUPS
+ if (!gl_HelperInvocation) {
+ z_write_bit = subgroupOr(z_write_bit); //merge all Zs
+ if (cluster_thread_group_index == 0) {
+ atomicOr(cluster_render.data[z_write_offset], z_write_bit);
+ }
+ }
+#else
+ if (!gl_HelperInvocation) {
+ atomicOr(cluster_render.data[z_write_offset], z_write_bit);
+ }
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/cluster_store.glsl b/servers/rendering/renderer_rd/shaders/cluster_store.glsl
new file mode 100644
index 0000000000..5be0893c4f
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/cluster_store.glsl
@@ -0,0 +1,119 @@
+#[compute]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
+layout(push_constant, binding = 0, std430) uniform Params {
+ uint cluster_render_data_size; // how much data for a single cluster takes
+ uint max_render_element_count_div_32; //divided by 32
+ uvec2 cluster_screen_size;
+ uint render_element_count_div_32; //divided by 32
+
+ uint max_cluster_element_count_div_32; //divided by 32
+ uint pad1;
+ uint pad2;
+}
+params;
+
+layout(set = 0, binding = 1, std430) buffer restrict readonly ClusterRender {
+ uint data[];
+}
+cluster_render;
+
+layout(set = 0, binding = 2, std430) buffer restrict ClusterStore {
+ uint data[];
+}
+cluster_store;
+
+struct RenderElement {
+ uint type; //0-4
+ bool touches_near;
+ bool touches_far;
+ uint original_index;
+ mat3x4 transform_inv;
+ vec3 scale;
+ uint pad;
+};
+
+layout(set = 0, binding = 3, std430) buffer restrict readonly RenderElements {
+ RenderElement data[];
+}
+render_elements;
+
+void main() {
+ uvec2 pos = gl_GlobalInvocationID.xy;
+ if (any(greaterThanEqual(pos, params.cluster_screen_size))) {
+ return;
+ }
+
+ //counter for each type of render_element
+
+ //base offset for this cluster
+ uint base_offset = (pos.x + params.cluster_screen_size.x * pos.y);
+ uint src_offset = base_offset * params.cluster_render_data_size;
+
+ uint render_element_offset = 0;
+
+ //check all render_elements and see which one was written to
+ while (render_element_offset < params.render_element_count_div_32) {
+ uint bits = cluster_render.data[src_offset + render_element_offset];
+ while (bits != 0) {
+ //if bits exist, check the render_element
+ uint index_bit = findLSB(bits);
+ uint index = render_element_offset * 32 + index_bit;
+ uint type = render_elements.data[index].type;
+
+ uint z_range_offset = src_offset + params.max_render_element_count_div_32 + index;
+ uint z_range = cluster_render.data[z_range_offset];
+
+ //if object was written, z was written, but check just in case
+ if (z_range != 0) { //should always be > 0
+
+ uint from_z = findLSB(z_range);
+ uint to_z = findMSB(z_range) + 1;
+
+ if (render_elements.data[index].touches_near) {
+ from_z = 0;
+ }
+
+ if (render_elements.data[index].touches_far) {
+ to_z = 32;
+ }
+
+ // find cluster offset in the buffer used for indexing in the renderer
+ uint dst_offset = (base_offset + type * (params.cluster_screen_size.x * params.cluster_screen_size.y)) * (params.max_cluster_element_count_div_32 + 32);
+
+ uint orig_index = render_elements.data[index].original_index;
+ //store this index in the Z slices by setting the relevant bit
+ for (uint i = from_z; i < to_z; i++) {
+ uint slice_ofs = dst_offset + params.max_cluster_element_count_div_32 + i;
+
+ uint minmax = cluster_store.data[slice_ofs];
+
+ if (minmax == 0) {
+ minmax = 0xFFFF; //min 0, max 0xFFFF
+ }
+
+ uint elem_min = min(orig_index, minmax & 0xFFFF);
+ uint elem_max = max(orig_index + 1, minmax >> 16); //always store plus one, so zero means range is empty when not written to
+
+ minmax = elem_min | (elem_max << 16);
+ cluster_store.data[slice_ofs] = minmax;
+ }
+
+ uint store_word = orig_index >> 5;
+ uint store_bit = orig_index & 0x1F;
+
+ //store the actual render_element index at the end, so the rendering code can reference it
+ cluster_store.data[dst_offset + store_word] |= 1 << store_bit;
+ }
+
+ bits &= ~(1 << index_bit); //clear the bit to continue iterating
+ }
+
+ render_element_offset++;
+ }
+}
diff --git a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl
index 54d67db6c6..c3ac0bee57 100644
--- a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl
+++ b/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl
@@ -1,33 +1,48 @@
-#[compute]
+#[vertex]
#version 450
VERSION_DEFINES
-layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+layout(push_constant, binding = 1, std430) uniform Params {
+ float z_far;
+ float z_near;
+ bool z_flip;
+ uint pad;
+ vec4 screen_rect;
+}
+params;
+
+layout(location = 0) out vec2 uv_interp;
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+ vec2 screen_pos = uv_interp * params.screen_rect.zw + params.screen_rect.xy;
+ gl_Position = vec4(screen_pos * 2.0 - 1.0, 0.0, 1.0);
+}
+
+#[fragment]
+
+#version 450
+
+VERSION_DEFINES
+
+layout(location = 0) in vec2 uv_interp;
layout(set = 0, binding = 0) uniform samplerCube source_cube;
layout(push_constant, binding = 1, std430) uniform Params {
- ivec2 screen_size;
- ivec2 offset;
- float bias;
float z_far;
float z_near;
bool z_flip;
+ uint pad;
+ vec4 screen_rect;
}
params;
-layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D depth_buffer;
-
void main() {
- ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
- return;
- }
-
- vec2 pixel_size = 1.0 / vec2(params.screen_size);
- vec2 uv = (vec2(pos) + 0.5) * pixel_size;
+ vec2 uv = uv_interp;
vec3 normal = vec3(uv * 2.0 - 1.0, 0.0);
@@ -65,5 +80,5 @@ void main() {
float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
depth = (linear_depth * depth_fix) / params.z_far;
- imageStore(depth_buffer, pos + params.offset, vec4(depth));
+ gl_FragDepth = depth;
}
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/gi.glsl
index 8011dadc72..35522103df 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/gi.glsl
@@ -97,13 +97,12 @@ layout(push_constant, binding = 0, std430) uniform Params {
vec4 proj_info;
+ vec3 ao_color;
uint max_giprobes;
+
bool high_quality_vct;
- bool use_sdfgi;
bool orthogonal;
-
- vec3 ao_color;
- uint pad;
+ uint pad[2];
mat3x4 cam_rotation;
}
@@ -331,7 +330,7 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
}
ambient_light.rgb = diffuse;
-#if 1
+
if (roughness < 0.2) {
vec3 pos_to_uvw = 1.0 / sdfgi.grid_size;
vec4 light_accum = vec4(0.0);
@@ -363,7 +362,6 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
//ray_pos += ray_dir * (bias / sdfgi.cascades[cascade].to_cell); //bias to avoid self occlusion
ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell;
}
-
float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade
while (length(ray_pos) < max_distance) {
for (uint i = 0; i < sdfgi.max_cascades; i++) {
@@ -434,8 +432,6 @@ void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, o
}
}
-#endif
-
reflection_light.rgb = specular;
ambient_light.rgb *= sdfgi.energy;
@@ -597,35 +593,24 @@ vec4 fetch_normal_and_roughness(ivec2 pos) {
return normal_roughness;
}
-void main() {
- // Pixel being shaded
- ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing
- return;
- }
-
- vec3 vertex = reconstruct_position(pos);
- vertex.y = -vertex.y;
-
+void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 reflection_light) {
vec4 normal_roughness = fetch_normal_and_roughness(pos);
- vec3 normal = normal_roughness.xyz;
- vec4 ambient_light = vec4(0.0), reflection_light = vec4(0.0);
+ vec3 normal = normal_roughness.xyz;
if (normal.length() > 0.5) {
//valid normal, can do GI
float roughness = normal_roughness.w;
-
vertex = mat3(params.cam_rotation) * vertex;
normal = normalize(mat3(params.cam_rotation) * normal);
-
vec3 reflection = normalize(reflect(normalize(vertex), normal));
- if (params.use_sdfgi) {
- sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light);
- }
+#ifdef USE_SDFGI
+ sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light);
+#endif
- if (params.max_giprobes > 0) {
+#ifdef USE_GIPROBES
+ {
uvec2 giprobe_tex = texelFetch(usampler2D(giprobe_buffer, linear_sampler), pos, 0).rg;
roughness *= roughness;
//find arbitrary tangent and bitangent, then build a matrix
@@ -648,16 +633,40 @@ void main() {
spec_accum /= blend_accum;
}
- if (params.use_sdfgi) {
- reflection_light = blend_color(spec_accum, reflection_light);
- ambient_light = blend_color(amb_accum, ambient_light);
- } else {
- reflection_light = spec_accum;
- ambient_light = amb_accum;
- }
+#ifdef USE_SDFGI
+ reflection_light = blend_color(spec_accum, reflection_light);
+ ambient_light = blend_color(amb_accum, ambient_light);
+#else
+ reflection_light = spec_accum;
+ ambient_light = amb_accum;
+#endif
}
+#endif
+ }
+}
+
+void main() {
+ ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
+
+#ifdef MODE_HALF_RES
+ pos <<= 1;
+#endif
+ if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing
+ return;
}
+ vec4 ambient_light = vec4(0.0);
+ vec4 reflection_light = vec4(0.0);
+
+ vec3 vertex = reconstruct_position(pos);
+ vertex.y = -vertex.y;
+
+ process_gi(pos, vertex, ambient_light, reflection_light);
+
+#ifdef MODE_HALF_RES
+ pos >>= 1;
+#endif
+
imageStore(ambient_buffer, pos, ambient_light);
imageStore(reflection_buffer, pos, reflection_light);
}
diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl
index ea4237a45e..4f4753d147 100644
--- a/servers/rendering/renderer_rd/shaders/giprobe.glsl
+++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl
@@ -208,6 +208,15 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
return occlusion; //max(0.0,distance);
}
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
@@ -220,7 +229,7 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3
return false;
}
- attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
+ attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation);
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
vec3 rel = normalize(pos - light_pos);
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 926c7ef9fc..cb6d8dc7f6 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -173,7 +173,7 @@ uint hash(uint x) {
return x;
}
-bool emit_particle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom, uint p_flags) {
+bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom, uint p_flags) {
if (!params.can_emit) {
return false;
}
diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/resolve.glsl
index 9429a66dc9..e83c4ca93b 100644
--- a/servers/rendering/renderer_rd/shaders/resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/resolve.glsl
@@ -58,6 +58,116 @@ void main() {
#else
+#if 1
+
+ vec4 group1;
+ vec4 group2;
+ vec4 group3;
+ vec4 group4;
+ int best_index = 0;
+
+ //2X
+ group1.x = texelFetch(source_depth, pos, 0).r;
+ group1.y = texelFetch(source_depth, pos, 1).r;
+
+ //4X
+ if (params.sample_count >= 4) {
+ group1.z = texelFetch(source_depth, pos, 2).r;
+ group1.w = texelFetch(source_depth, pos, 3).r;
+ }
+ //8X
+ if (params.sample_count >= 8) {
+ group2.x = texelFetch(source_depth, pos, 4).r;
+ group2.y = texelFetch(source_depth, pos, 5).r;
+ group2.z = texelFetch(source_depth, pos, 6).r;
+ group2.w = texelFetch(source_depth, pos, 7).r;
+ }
+ //16X
+ if (params.sample_count >= 16) {
+ group3.x = texelFetch(source_depth, pos, 8).r;
+ group3.y = texelFetch(source_depth, pos, 9).r;
+ group3.z = texelFetch(source_depth, pos, 10).r;
+ group3.w = texelFetch(source_depth, pos, 11).r;
+
+ group4.x = texelFetch(source_depth, pos, 12).r;
+ group4.y = texelFetch(source_depth, pos, 13).r;
+ group4.z = texelFetch(source_depth, pos, 14).r;
+ group4.w = texelFetch(source_depth, pos, 15).r;
+ }
+
+ if (params.sample_count == 2) {
+ best_index = (pos.x & 1) ^ ((pos.y >> 1) & 1); //not much can be done here
+ } else if (params.sample_count == 4) {
+ vec4 freq = vec4(equal(group1, vec4(group1.x)));
+ freq += vec4(equal(group1, vec4(group1.y)));
+ freq += vec4(equal(group1, vec4(group1.z)));
+ freq += vec4(equal(group1, vec4(group1.w)));
+
+ float min_f = freq.x;
+ best_index = 0;
+ if (freq.y < min_f) {
+ best_index = 1;
+ min_f = freq.y;
+ }
+ if (freq.z < min_f) {
+ best_index = 2;
+ min_f = freq.z;
+ }
+ if (freq.w < min_f) {
+ best_index = 3;
+ }
+ } else if (params.sample_count == 8) {
+ vec4 freq0 = vec4(equal(group1, vec4(group1.x)));
+ vec4 freq1 = vec4(equal(group2, vec4(group1.x)));
+ freq0 += vec4(equal(group1, vec4(group1.y)));
+ freq1 += vec4(equal(group2, vec4(group1.y)));
+ freq0 += vec4(equal(group1, vec4(group1.z)));
+ freq1 += vec4(equal(group2, vec4(group1.z)));
+ freq0 += vec4(equal(group1, vec4(group1.w)));
+ freq1 += vec4(equal(group2, vec4(group1.w)));
+ freq0 += vec4(equal(group1, vec4(group2.x)));
+ freq1 += vec4(equal(group2, vec4(group2.x)));
+ freq0 += vec4(equal(group1, vec4(group2.y)));
+ freq1 += vec4(equal(group2, vec4(group2.y)));
+ freq0 += vec4(equal(group1, vec4(group2.z)));
+ freq1 += vec4(equal(group2, vec4(group2.z)));
+ freq0 += vec4(equal(group1, vec4(group2.w)));
+ freq1 += vec4(equal(group2, vec4(group2.w)));
+
+ float min_f0 = freq0.x;
+ int best_index0 = 0;
+ if (freq0.y < min_f0) {
+ best_index0 = 1;
+ min_f0 = freq0.y;
+ }
+ if (freq0.z < min_f0) {
+ best_index0 = 2;
+ min_f0 = freq0.z;
+ }
+ if (freq0.w < min_f0) {
+ best_index0 = 3;
+ min_f0 = freq0.w;
+ }
+
+ float min_f1 = freq1.x;
+ int best_index1 = 4;
+ if (freq1.y < min_f1) {
+ best_index1 = 5;
+ min_f1 = freq1.y;
+ }
+ if (freq1.z < min_f1) {
+ best_index1 = 6;
+ min_f1 = freq1.z;
+ }
+ if (freq1.w < min_f1) {
+ best_index1 = 7;
+ min_f1 = freq1.w;
+ }
+
+ best_index = mix(best_index0, best_index1, min_f0 < min_f1);
+ }
+
+#else
float depths[16];
int depth_indices[16];
int depth_amount[16];
@@ -91,7 +201,7 @@ void main() {
depth_least = depth_amount[j];
}
}
-
+#endif
best_depth = texelFetch(source_depth, pos, best_index).r;
best_normal_roughness = texelFetch(source_normal_roughness, pos, best_index);
#ifdef GIPROBE_RESOLVE
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward.glsl b/servers/rendering/renderer_rd/shaders/scene_forward.glsl
index a7fe86b029..ea203c8abe 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward.glsl
@@ -16,7 +16,7 @@ layout(location = 0) in vec3 vertex_attrib;
layout(location = 1) in vec3 normal_attrib;
#endif
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
layout(location = 2) in vec4 tangent_attrib;
#endif
@@ -76,7 +76,7 @@ layout(location = 3) out vec2 uv_interp;
layout(location = 4) out vec2 uv2_interp;
#endif
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
layout(location = 5) out vec3 tangent_interp;
layout(location = 6) out vec3 binormal_interp;
#endif
@@ -97,8 +97,6 @@ VERTEX_SHADER_GLOBALS
invariant gl_Position;
-layout(location = 7) flat out uint instance_index;
-
#ifdef MODE_DUAL_PARABOLOID
layout(location = 8) out float dp_clip;
@@ -106,22 +104,27 @@ layout(location = 8) out float dp_clip;
#endif
void main() {
- instance_index = draw_call.instance_index;
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
- mat4 world_matrix = instances.data[instance_index].transform;
- mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform);
+ mat4 world_matrix = draw_call.transform;
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) {
+ mat3 world_normal_matrix;
+ if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
+ world_normal_matrix = inverse(mat3(world_matrix));
+ } else {
+ world_normal_matrix = mat3(world_matrix);
+ }
+
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH)) {
//multimesh, instances are for it
- uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
+ uint offset = (draw_call.flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;
offset *= gl_InstanceIndex;
mat4 matrix;
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
offset += 2;
} else {
@@ -129,14 +132,14 @@ void main() {
offset += 3;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {
#ifdef COLOR_USED
color_interp *= transforms.data[offset];
#endif
offset += 1;
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {
instance_custom = transforms.data[offset];
}
@@ -144,10 +147,6 @@ void main() {
matrix = transpose(matrix);
world_matrix = world_matrix * matrix;
world_normal_matrix = world_normal_matrix * mat3(matrix);
-
- } else {
- //not a multimesh, instances are for multiple draw calls
- instance_index += gl_InstanceIndex;
}
vec3 vertex = vertex_attrib;
@@ -155,14 +154,14 @@ void main() {
vec3 normal = normal_attrib * 2.0 - 1.0;
#endif
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
float binormalf = tangent_attrib.a * 2.0 - 1.0;
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
#if 0
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) {
+ if (bool(draw_call.flags & INSTANCE_FLAGS_SKELETON)) {
//multimesh, instances are for it
uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3;
@@ -179,7 +178,7 @@ void main() {
vertex = (vec4(vertex, 1.0) * m).xyz;
normal = (vec4(normal, 0.0) * m).xyz;
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
tangent = (vec4(tangent, 0.0) * m).xyz;
binormal = (vec4(binormal, 0.0) * m).xyz;
@@ -208,7 +207,7 @@ void main() {
normal = world_normal_matrix * normal;
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
tangent = world_normal_matrix * tangent;
binormal = world_normal_matrix * binormal;
@@ -239,7 +238,7 @@ VERTEX_SHADER_CODE
#endif
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
binormal = modelview_normal * binormal;
tangent = modelview_normal * tangent;
@@ -251,7 +250,7 @@ VERTEX_SHADER_CODE
vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz;
normal = mat3(scene_data.inverse_normal_matrix) * normal;
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal;
tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent;
@@ -263,7 +262,7 @@ VERTEX_SHADER_CODE
normal_interp = normal;
#endif
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
tangent_interp = tangent;
binormal_interp = binormal;
#endif
@@ -305,7 +304,7 @@ VERTEX_SHADER_CODE
#endif
#ifdef MODE_RENDER_MATERIAL
if (scene_data.material_uv2_mode) {
- gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0;
+ gl_Position.xy = (uv2_attrib.xy + draw_call.lightmap_uv_scale.xy) * 2.0 - 1.0;
gl_Position.z = 0.00001;
gl_Position.w = 1.0;
}
@@ -340,13 +339,11 @@ layout(location = 3) in vec2 uv_interp;
layout(location = 4) in vec2 uv2_interp;
#endif
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
layout(location = 5) in vec3 tangent_interp;
layout(location = 6) in vec3 binormal_interp;
#endif
-layout(location = 7) flat in uint instance_index;
-
#ifdef MODE_DUAL_PARABOLOID
layout(location = 8) in float dp_clip;
@@ -355,8 +352,7 @@ layout(location = 8) in float dp_clip;
//defines to keep compatibility with vertex
-#define world_matrix instances.data[instance_index].transform
-#define world_normal_matrix instances.data[instance_index].normal_transform
+#define world_matrix draw_call.transform
#define projection_matrix scene_data.projection_matrix
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
@@ -545,7 +541,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
return mix(vec3(dielectric), albedo, vec3(metallic));
}
-void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 shadow_attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity,
+void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
#ifdef LIGHT_BACKLIGHT_USED
vec3 backlight,
#endif
@@ -557,7 +553,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- float rim, float rim_tint,
+ float rim, float rim_tint, vec3 rim_color,
#endif
#ifdef LIGHT_CLEARCOAT_USED
float clearcoat, float clearcoat_gloss,
@@ -565,6 +561,9 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#ifdef LIGHT_ANISOTROPY_USED
vec3 B, vec3 T, float anisotropy,
#endif
+#ifdef USE_SOFT_SHADOWS
+ float A,
+#endif
#ifdef USE_SHADOW_TO_OPACITY
inout float alpha,
#endif
@@ -574,7 +573,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
// light is written by the light shader
vec3 normal = N;
- vec3 albedo = diffuse_color;
vec3 light = L;
vec3 view = V;
@@ -585,7 +583,12 @@ LIGHT_SHADER_CODE
/* clang-format on */
#else
+
+#ifdef USE_SOFT_SHADOWS
float NdotL = min(A + dot(N, L), 1.0);
+#else
+ float NdotL = dot(N, L);
+#endif
float cNdotL = max(NdotL, 0.0); // clamped NdotL
float NdotV = dot(N, V);
float cNdotV = max(NdotV, 0.0);
@@ -595,14 +598,25 @@ LIGHT_SHADER_CODE
#endif
#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
+#ifdef USE_SOFT_SHADOWS
float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
+#else
+ float cNdotH = clamp(dot(N, H), 0.0, 1.0);
+#endif
#endif
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
+#ifdef USE_SOFT_SHADOWS
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
+#else
+ float cLdotH = clamp(dot(L, H), 0.0, 1.0);
+#endif
#endif
+ float metallic = unpackUnorm4x8(orms).z;
if (metallic < 1.0) {
+ float roughness = unpackUnorm4x8(orms).y;
+
#if defined(DIFFUSE_OREN_NAYAR)
vec3 diffuse_brdf_NL;
#else
@@ -612,23 +626,6 @@ LIGHT_SHADER_CODE
#if defined(DIFFUSE_LAMBERT_WRAP)
// energy conserving lambert wrap shader
diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
-
-#elif defined(DIFFUSE_OREN_NAYAR)
-
- {
- // see http://mimosa-pudica.net/improved-oren-nayar.html
- float LdotV = dot(L, V);
-
- float s = LdotV - NdotL * NdotV;
- float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
-
- float sigma2 = roughness * roughness; // TODO: this needs checking
- vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13));
- float B = 0.45 * sigma2 / (sigma2 + 0.09);
-
- diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI);
- }
-
#elif defined(DIFFUSE_TOON)
diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL);
@@ -656,15 +653,15 @@ LIGHT_SHADER_CODE
diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
#endif
- diffuse_light += light_color * diffuse_color * shadow_attenuation * diffuse_brdf_NL * attenuation;
+ diffuse_light += light_color * diffuse_brdf_NL * attenuation;
#if defined(LIGHT_BACKLIGHT_USED)
- diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
+ diffuse_light += light_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * backlight * attenuation;
#endif
#if defined(LIGHT_RIM_USED)
float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0));
- diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color;
+ diffuse_light += rim_light * rim * mix(vec3(1.0), rim_color, rim_tint) * light_color;
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
@@ -682,7 +679,7 @@ LIGHT_SHADER_CODE
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
- diffuse_light += profile * transmittance_color.a * diffuse_color * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI) * attenuation;
+ diffuse_light += profile * transmittance_color.a * light_color * clamp(transmittance_boost - NdotL, 0.0, 1.0) * (1.0 / M_PI);
}
#else
@@ -692,7 +689,7 @@ LIGHT_SHADER_CODE
fade = pow(max(0.0, 1.0 - fade), transmittance_curve);
fade *= clamp(transmittance_boost - NdotL, 0.0, 1.0);
- diffuse_light += diffuse_color * transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade * attenuation;
+ diffuse_light += transmittance_color.rgb * light_color * (1.0 / M_PI) * transmittance_color.a * fade;
}
#endif //SSS_MODE_SKIN
@@ -700,6 +697,7 @@ LIGHT_SHADER_CODE
#endif //LIGHT_TRANSMITTANCE_USED
}
+ float roughness = unpackUnorm4x8(orms).y;
if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely
// D
@@ -712,7 +710,7 @@ LIGHT_SHADER_CODE
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = blinn;
- specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
+ specular_light += light_color * intensity * attenuation * specular_amount;
#elif defined(SPECULAR_PHONG)
@@ -723,7 +721,7 @@ LIGHT_SHADER_CODE
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75);
- specular_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation;
+ specular_light += light_color * intensity * attenuation * specular_amount;
#elif defined(SPECULAR_TOON)
@@ -732,7 +730,7 @@ LIGHT_SHADER_CODE
float mid = 1.0 - roughness;
mid *= mid;
float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid;
- diffuse_light += light_color * shadow_attenuation * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection
+ diffuse_light += light_color * intensity * attenuation * specular_amount; // write to diffuse_light, as in toon shading you generally want no reflection
#elif defined(SPECULAR_DISABLED)
// none..
@@ -757,13 +755,12 @@ LIGHT_SHADER_CODE
float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx);
#endif
// F
- vec3 f0 = F0(metallic, specular, diffuse_color);
float cLdotH5 = SchlickFresnel(cLdotH);
vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
vec3 specular_brdf_NL = cNdotL * D * F * G;
- specular_light += specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
+ specular_light += specular_brdf_NL * light_color * attenuation * specular_amount;
#endif
#if defined(LIGHT_CLEARCOAT_USED)
@@ -777,12 +774,12 @@ LIGHT_SHADER_CODE
float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL;
- specular_light += clearcoat_specular_brdf_NL * light_color * shadow_attenuation * specular_blob_intensity * attenuation;
+ specular_light += clearcoat_specular_brdf_NL * light_color * attenuation * specular_amount;
#endif
}
#ifdef USE_SHADOW_TO_OPACITY
- alpha = min(alpha, clamp(1.0 - length(shadow_attenuation * attenuation), 0.0, 1.0));
+ alpha = min(alpha, clamp(1.0 - attenuation), 0.0, 1.0));
#endif
#endif //defined(USE_LIGHT_SHADER_CODE)
@@ -895,69 +892,39 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
#endif //USE_NO_SHADOWS
-void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
-#ifdef LIGHT_BACKLIGHT_USED
- vec3 backlight,
-#endif
-#ifdef LIGHT_TRANSMITTANCE_USED
- vec4 transmittance_color,
- float transmittance_depth,
- float transmittance_curve,
- float transmittance_boost,
-#endif
-#ifdef LIGHT_RIM_USED
- float rim, float rim_tint,
-#endif
-#ifdef LIGHT_CLEARCOAT_USED
- float clearcoat, float clearcoat_gloss,
-#endif
-#ifdef LIGHT_ANISOTROPY_USED
- vec3 binormal, vec3 tangent, float anisotropy,
-#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
- inout vec3 diffuse_light, inout vec3 specular_light) {
- vec3 light_rel_vec = lights.data[idx].position - vertex;
- float light_length = length(light_rel_vec);
- float normalized_distance = light_length * lights.data[idx].inv_radius;
- vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
- float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x);
- float light_attenuation = omni_attenuation;
- vec3 shadow_attenuation = vec3(1.0);
- vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
- color_specular.rgb *= attenuation_energy.y;
- float size_A = 0.0;
-
- if (lights.data[idx].size > 0.0) {
- float t = lights.data[idx].size / max(0.001, light_length);
- size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
- }
-
-#ifdef LIGHT_TRANSMITTANCE_USED
- float transmittance_z = transmittance_depth; //no transmittance by default
-#endif
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef USE_NO_SHADOWS
- vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
- if (shadow_color_enabled.w > 0.5) {
+ if (omni_lights.data[idx].shadow_enabled) {
// there is a shadowmap
+ vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+
vec4 v = vec4(vertex, 1.0);
- vec4 splane = (lights.data[idx].shadow_matrix * v);
+ vec4 splane = (omni_lights.data[idx].shadow_matrix * v);
float shadow_len = length(splane.xyz); //need to remember shadow len from here
{
- vec3 nofs = normal_interp * lights.data[idx].shadow_normal_bias / lights.data[idx].inv_radius;
+ vec3 nofs = normal_interp * omni_lights.data[idx].shadow_normal_bias / omni_lights.data[idx].inv_radius;
nofs *= (1.0 - max(0.0, dot(normalize(light_rel_vec), normalize(normal_interp))));
v.xyz += nofs;
- splane = (lights.data[idx].shadow_matrix * v);
+ splane = (omni_lights.data[idx].shadow_matrix * v);
}
float shadow;
- if (lights.data[idx].soft_shadow_size > 0.0) {
+#ifdef USE_SOFT_SHADOWS
+ if (omni_lights.data[idx].soft_shadow_size > 0.0) {
//soft shadow
//find blocker
@@ -977,10 +944,10 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
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));
- float z_norm = shadow_len * lights.data[idx].inv_radius;
+ float z_norm = shadow_len * omni_lights.data[idx].inv_radius;
- tangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
- bitangent *= lights.data[idx].soft_shadow_size * lights.data[idx].soft_shadow_scale;
+ tangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
+ bitangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale;
for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
@@ -988,7 +955,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
pos = normalize(pos);
- vec4 uv_rect = lights.data[idx].atlas_rect;
+ vec4 uv_rect = omni_lights.data[idx].atlas_rect;
if (pos.z >= 0.0) {
pos.z += 1.0;
@@ -1016,7 +983,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
tangent *= penumbra;
bitangent *= penumbra;
- z_norm -= lights.data[idx].inv_radius * lights.data[idx].shadow_bias;
+ z_norm -= omni_lights.data[idx].inv_radius * omni_lights.data[idx].shadow_bias;
shadow = 0.0;
for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
@@ -1024,7 +991,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
pos = normalize(pos);
- vec4 uv_rect = lights.data[idx].atlas_rect;
+ vec4 uv_rect = omni_lights.data[idx].atlas_rect;
if (pos.z >= 0.0) {
pos.z += 1.0;
@@ -1047,8 +1014,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
shadow = 1.0;
}
} else {
+#endif
splane.xyz = normalize(splane.xyz);
- vec4 clamp_rect = lights.data[idx].atlas_rect;
+ vec4 clamp_rect = omni_lights.data[idx].atlas_rect;
if (splane.z >= 0.0) {
splane.z += 1.0;
@@ -1062,101 +1030,149 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
splane.xy /= splane.z;
splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = (shadow_len - lights.data[idx].shadow_bias) * lights.data[idx].inv_radius;
+ splane.z = (shadow_len - omni_lights.data[idx].shadow_bias) * omni_lights.data[idx].inv_radius;
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
splane.w = 1.0; //needed? i think it should be 1 already
- shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
+ shadow = sample_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
+#ifdef USE_SOFT_SHADOWS
}
+#endif
+
+ return shadow;
+ }
+#endif
+ return 1.0;
+}
+
+void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+#ifdef LIGHT_BACKLIGHT_USED
+ vec3 backlight,
+#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 clamp_rect = lights.data[idx].atlas_rect;
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint, vec3 rim_color,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha,
+#endif
+ inout vec3 diffuse_light, inout vec3 specular_light) {
+ vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+ float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
+ float light_attenuation = omni_attenuation;
+ vec3 color = omni_lights.data[idx].color;
- //redo shadowmapping, but shrink the model a bit to avoid arctifacts
- splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
+#ifdef USE_SOFT_SHADOWS
+ float size_A = 0.0;
- shadow_len = length(splane.xyz);
- splane = normalize(splane.xyz);
+ if (omni_lights.data[idx].size > 0.0) {
+ float t = omni_lights.data[idx].size / max(0.001, light_length);
+ size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ }
+#endif
- if (splane.z >= 0.0) {
- splane.z += 1.0;
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth; //no transmittance by default
+ transmittance_color.a *= light_attenuation;
+ {
+ vec4 clamp_rect = omni_lights.data[idx].atlas_rect;
- } else {
- splane.z = 1.0 - splane.z;
- }
+ //redo shadowmapping, but shrink the model a bit to avoid arctifacts
+ vec4 splane = (omni_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * omni_lights.data[idx].transmittance_bias, 1.0));
- splane.xy /= splane.z;
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len * lights.data[idx].inv_radius;
- splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
- splane.w = 1.0; //needed? i think it should be 1 already
+ shadow_len = length(splane.xyz);
+ splane = normalize(splane.xyz);
+
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
- float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
- transmittance_z = (splane.z - shadow_z) / lights.data[idx].inv_radius;
+ } else {
+ splane.z = 1.0 - splane.z;
}
-#endif
- vec3 no_shadow = vec3(1.0);
+ splane.xy /= splane.z;
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * omni_lights.data[idx].inv_radius;
+ splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ splane.w = 1.0; //needed? i think it should be 1 already
- if (lights.data[idx].projector_rect != vec4(0.0)) {
- vec3 local_v = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
- local_v = normalize(local_v);
+ float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+ transmittance_z = (splane.z - shadow_z) / omni_lights.data[idx].inv_radius;
+ }
+#endif
- vec4 atlas_rect = lights.data[idx].projector_rect;
+#if 0
- if (local_v.z >= 0.0) {
- local_v.z += 1.0;
- atlas_rect.y += atlas_rect.w;
+ if (omni_lights.data[idx].projector_rect != vec4(0.0)) {
+ vec3 local_v = (omni_lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
+ local_v = normalize(local_v);
- } else {
- local_v.z = 1.0 - local_v.z;
- }
+ vec4 atlas_rect = omni_lights.data[idx].projector_rect;
- local_v.xy /= local_v.z;
- local_v.xy = local_v.xy * 0.5 + 0.5;
- vec2 proj_uv = local_v.xy * atlas_rect.zw;
+ if (local_v.z >= 0.0) {
+ local_v.z += 1.0;
+ atlas_rect.y += atlas_rect.w;
- vec2 proj_uv_ddx;
- vec2 proj_uv_ddy;
- {
- vec3 local_v_ddx = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz;
- local_v_ddx = normalize(local_v_ddx);
+ } else {
+ local_v.z = 1.0 - local_v.z;
+ }
- if (local_v_ddx.z >= 0.0) {
- local_v_ddx.z += 1.0;
- } else {
- local_v_ddx.z = 1.0 - local_v_ddx.z;
- }
+ local_v.xy /= local_v.z;
+ local_v.xy = local_v.xy * 0.5 + 0.5;
+ vec2 proj_uv = local_v.xy * atlas_rect.zw;
- local_v_ddx.xy /= local_v_ddx.z;
- local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
+ vec2 proj_uv_ddx;
+ vec2 proj_uv_ddy;
+ {
+ vec3 local_v_ddx = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0)).xyz;
+ local_v_ddx = normalize(local_v_ddx);
- proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
+ if (local_v_ddx.z >= 0.0) {
+ local_v_ddx.z += 1.0;
+ } else {
+ local_v_ddx.z = 1.0 - local_v_ddx.z;
+ }
- vec3 local_v_ddy = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
- local_v_ddy = normalize(local_v_ddy);
+ local_v_ddx.xy /= local_v_ddx.z;
+ local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
- if (local_v_ddy.z >= 0.0) {
- local_v_ddy.z += 1.0;
- } else {
- local_v_ddy.z = 1.0 - local_v_ddy.z;
- }
+ proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
- local_v_ddy.xy /= local_v_ddy.z;
- local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5;
+ vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
+ local_v_ddy = normalize(local_v_ddy);
- proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv;
+ if (local_v_ddy.z >= 0.0) {
+ local_v_ddy.z += 1.0;
+ } else {
+ local_v_ddy.z = 1.0 - local_v_ddy.z;
}
- vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
- no_shadow = mix(no_shadow, proj.rgb, proj.a);
+ local_v_ddy.xy /= local_v_ddy.z;
+ local_v_ddy.xy = local_v_ddy.xy * 0.5 + 0.5;
+
+ proj_uv_ddy = local_v_ddy.xy * atlas_rect.zw - proj_uv;
}
- shadow_attenuation = mix(shadow_color_enabled.rgb, no_shadow, shadow);
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ no_shadow = mix(no_shadow, proj.rgb, proj.a);
}
-#endif //USE_NO_SHADOWS
+#endif
+
+ light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1168,7 +1184,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * omni_attenuation, rim_tint,
+ rim * omni_attenuation, rim_tint, rim_color,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1176,6 +1192,9 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
+#ifdef USE_SOFT_SHADOWS
+ size_A,
+#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
@@ -1183,89 +1202,39 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
specular_light);
}
-void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,
-#ifdef LIGHT_BACKLIGHT_USED
- vec3 backlight,
-#endif
-#ifdef LIGHT_TRANSMITTANCE_USED
- vec4 transmittance_color,
- float transmittance_depth,
- float transmittance_curve,
- float transmittance_boost,
-#endif
-#ifdef LIGHT_RIM_USED
- float rim, float rim_tint,
-#endif
-#ifdef LIGHT_CLEARCOAT_USED
- float clearcoat, float clearcoat_gloss,
-#endif
-#ifdef LIGHT_ANISOTROPY_USED
- vec3 binormal, vec3 tangent, float anisotropy,
-#endif
-#ifdef USE_SHADOW_TO_OPACITY
- inout float alpha,
-#endif
- inout vec3 diffuse_light,
- inout vec3 specular_light) {
- vec3 light_rel_vec = lights.data[idx].position - vertex;
- float light_length = length(light_rel_vec);
- float normalized_distance = light_length * lights.data[idx].inv_radius;
- vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy);
- float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x);
- vec3 spot_dir = lights.data[idx].direction;
- vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
- spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
- float light_attenuation = spot_attenuation;
- vec3 shadow_attenuation = vec3(1.0);
- vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular);
- color_specular.rgb *= attenuation_energy.y;
-
- float size_A = 0.0;
-
- if (lights.data[idx].size > 0.0) {
- float t = lights.data[idx].size / max(0.001, light_length);
- size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
- }
-/*
- if (lights.data[idx].atlas_rect!=vec4(0.0)) {
- //use projector texture
- }
- */
-#ifdef LIGHT_TRANSMITTANCE_USED
- float transmittance_z = transmittance_depth;
-#endif
-
+float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef USE_NO_SHADOWS
- vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled);
- if (shadow_color_enabled.w > 0.5) {
+ if (spot_lights.data[idx].shadow_enabled) {
+ vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
+ float light_length = length(light_rel_vec);
+ vec3 spot_dir = spot_lights.data[idx].direction;
//there is a shadowmap
vec4 v = vec4(vertex, 1.0);
- v.xyz -= spot_dir * lights.data[idx].shadow_bias;
+ v.xyz -= spot_dir * spot_lights.data[idx].shadow_bias;
- float z_norm = dot(spot_dir, -light_rel_vec) * lights.data[idx].inv_radius;
+ float z_norm = dot(spot_dir, -light_rel_vec) * spot_lights.data[idx].inv_radius;
float depth_bias_scale = 1.0 / (max(0.0001, z_norm)); //the closer to the light origin, the more you have to offset to reach 1px in the map
- vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * lights.data[idx].shadow_normal_bias * depth_bias_scale;
+ vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(spot_dir, -normalize(normal_interp)))) * spot_lights.data[idx].shadow_normal_bias * depth_bias_scale;
normal_bias -= spot_dir * dot(spot_dir, normal_bias); //only XY, no Z
v.xyz += normal_bias;
//adjust with bias
- z_norm = dot(spot_dir, v.xyz - lights.data[idx].position) * lights.data[idx].inv_radius;
+ z_norm = dot(spot_dir, v.xyz - spot_lights.data[idx].position) * spot_lights.data[idx].inv_radius;
float shadow;
- vec4 splane = (lights.data[idx].shadow_matrix * v);
+ vec4 splane = (spot_lights.data[idx].shadow_matrix * v);
splane /= splane.w;
- if (lights.data[idx].soft_shadow_size > 0.0) {
+#ifdef USE_SOFT_SHADOWS
+ if (spot_lights.data[idx].soft_shadow_size > 0.0) {
//soft shadow
//find blocker
- vec2 shadow_uv = splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy;
+ vec2 shadow_uv = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy;
float blocker_count = 0.0;
float blocker_average = 0.0;
@@ -1278,11 +1247,11 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- float uv_size = lights.data[idx].soft_shadow_size * z_norm * lights.data[idx].soft_shadow_scale;
- vec2 clamp_max = lights.data[idx].atlas_rect.xy + lights.data[idx].atlas_rect.zw;
+ float uv_size = spot_lights.data[idx].soft_shadow_size * z_norm * spot_lights.data[idx].soft_shadow_scale;
+ vec2 clamp_max = spot_lights.data[idx].atlas_rect.xy + spot_lights.data[idx].atlas_rect.zw;
for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
- suv = clamp(suv, lights.data[idx].atlas_rect.xy, clamp_max);
+ suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < z_norm) {
blocker_average += d;
@@ -1299,7 +1268,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
shadow = 0.0;
for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
- suv = clamp(suv, lights.data[idx].atlas_rect.xy, clamp_max);
+ suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
}
@@ -1311,54 +1280,93 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
}
} else {
+#endif
//hard shadow
- vec4 shadow_uv = vec4(splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy, z_norm, 1.0);
+ vec4 shadow_uv = vec4(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z, 1.0);
- shadow = sample_pcf_shadow(shadow_atlas, lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
+ shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
+#ifdef USE_SOFT_SHADOWS
}
+#endif
- vec3 no_shadow = vec3(1.0);
+ return shadow;
+ }
- if (lights.data[idx].projector_rect != vec4(0.0)) {
- splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
- splane /= splane.w;
+#endif //USE_NO_SHADOWS
- vec2 proj_uv = splane.xy * lights.data[idx].projector_rect.zw;
+ return 1.0;
+}
- //ensure we have proper mipmaps
- vec4 splane_ddx = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
- splane_ddx /= splane_ddx.w;
- vec2 proj_uv_ddx = splane_ddx.xy * lights.data[idx].projector_rect.zw - proj_uv;
+void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
+#ifdef LIGHT_BACKLIGHT_USED
+ vec3 backlight,
+#endif
+#ifdef LIGHT_TRANSMITTANCE_USED
+ vec4 transmittance_color,
+ float transmittance_depth,
+ float transmittance_curve,
+ float transmittance_boost,
+#endif
+#ifdef LIGHT_RIM_USED
+ float rim, float rim_tint, vec3 rim_color,
+#endif
+#ifdef LIGHT_CLEARCOAT_USED
+ float clearcoat, float clearcoat_gloss,
+#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ vec3 binormal, vec3 tangent, float anisotropy,
+#endif
+#ifdef USE_SHADOW_TO_OPACITY
+ inout float alpha,
+#endif
+ inout vec3 diffuse_light,
+ inout vec3 specular_light) {
+ vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
+ 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));
+ 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;
+ float specular_amount = spot_lights.data[idx].specular_amount;
- vec4 splane_ddy = (lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
- splane_ddy /= splane_ddy.w;
- vec2 proj_uv_ddy = splane_ddy.xy * lights.data[idx].projector_rect.zw - proj_uv;
+#ifdef USE_SOFT_SHADOWS
+ float size_A = 0.0;
- vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
- no_shadow = mix(no_shadow, proj.rgb, proj.a);
- }
+ if (spot_lights.data[idx].size > 0.0) {
+ float t = spot_lights.data[idx].size / max(0.001, light_length);
+ size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
+ }
+#endif
- shadow_attenuation = mix(shadow_color_enabled.rgb, no_shadow, shadow);
+ /*
+ if (spot_lights.data[idx].atlas_rect!=vec4(0.0)) {
+ //use projector texture
+ }
+ */
#ifdef LIGHT_TRANSMITTANCE_USED
- {
- splane = (lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * lights.data[idx].transmittance_bias, 1.0));
- splane /= splane.w;
- splane.xy = splane.xy * lights.data[idx].atlas_rect.zw + lights.data[idx].atlas_rect.xy;
-
- float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
- //reconstruct depth
- shadow_z /= lights.data[idx].inv_radius;
- //distance to light plane
- float z = dot(spot_dir, -light_rel_vec);
- transmittance_z = z - shadow_z;
- }
-#endif //LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth;
+ transmittance_color.a *= light_attenuation;
+ {
+ splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex - normalize(normal_interp) * spot_lights.data[idx].transmittance_bias, 1.0));
+ splane /= splane.w;
+ splane.xy = splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy;
+
+ float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r;
+ //reconstruct depth
+ shadow_z /= spot_lights.data[idx].inv_radius;
+ //distance to light plane
+ float z = dot(spot_dir, -light_rel_vec);
+ transmittance_z = z - shadow_z;
}
+#endif //LIGHT_TRANSMITTANCE_USED
-#endif //USE_NO_SHADOWS
+ light_attenuation *= shadow;
- light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color_specular.rgb, light_attenuation, shadow_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity,
+ light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
#ifdef LIGHT_BACKLIGHT_USED
backlight,
#endif
@@ -1370,7 +1378,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim * spot_attenuation, rim_tint,
+ rim * spot_attenuation, rim_tint, rim_color,
#endif
#ifdef LIGHT_CLEARCOAT_USED
clearcoat, clearcoat_gloss,
@@ -1378,6 +1386,9 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
#ifdef LIGHT_ANISOTROPY_USED
binormal, tangent, anisotropy,
#endif
+#ifdef USE_SOFT_SHADOW
+ size_A,
+#endif
#ifdef USE_SHADOW_TO_OPACITY
alpha,
#endif
@@ -1401,11 +1412,11 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
blend *= blend;
blend = max(0.0, 1.0 - blend);
- if (reflections.data[ref_index].params.x > 0.0) { // compute reflection
+ if (reflections.data[ref_index].intensity > 0.0) { // compute reflection
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
- if (reflections.data[ref_index].params.w > 0.5) { //box project
+ if (reflections.data[ref_index].box_project) { //box project
vec3 nrdir = normalize(local_ref_vec);
vec3 rbmax = (box_extents - local_pos) / nrdir;
@@ -1422,11 +1433,11 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb;
- if (reflections.data[ref_index].params.z < 0.5) {
+ if (reflections.data[ref_index].exterior) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);
}
- reflection.rgb *= reflections.data[ref_index].params.x;
+ reflection.rgb *= reflections.data[ref_index].intensity; //intensity
reflection.a = blend;
reflection.rgb *= reflection.a;
@@ -1445,7 +1456,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
ambient_out.a = blend;
- if (reflections.data[ref_index].params.z < 0.5) { //interior
+ if (reflections.data[ref_index].exterior) {
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
}
@@ -1456,7 +1467,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
vec4 ambient_out;
ambient_out.a = blend;
ambient_out.rgb = reflections.data[ref_index].ambient;
- if (reflections.data[ref_index].params.z < 0.5) {
+ if (reflections.data[ref_index].exterior) {
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
}
ambient_out.rgb *= ambient_out.a;
@@ -1774,7 +1785,43 @@ vec4 fog_process(vec3 vertex) {
return vec4(fog_color, fog_amount);
}
+void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
+ uint item_min_max = cluster_buffer.data[p_offset];
+ item_min = item_min_max & 0xFFFF;
+ item_max = item_min_max >> 16;
+ ;
+
+ item_from = item_min >> 5;
+ item_to = (item_max == 0) ? 0 : ((item_max - 1) >> 5) + 1; //side effect of how it is stored, as item_max 0 means no elements
+}
+
+uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
+ int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
+ int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
+ return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
+}
+
+float blur_shadow(float shadow) {
+ return shadow;
+#if 0
+ //disabling for now, will investigate later
+ float interp_shadow = shadow;
+ if (gl_HelperInvocation) {
+ interp_shadow = -4.0; // technically anything below -4 will do but just to make sure
+ }
+
+ uvec2 fc2 = uvec2(gl_FragCoord.xy);
+ interp_shadow -= dFdx(interp_shadow) * (float(fc2.x & 1) - 0.5);
+ interp_shadow -= dFdy(interp_shadow) * (float(fc2.y & 1) - 0.5);
+
+ if (interp_shadow >= 0.0) {
+ shadow = interp_shadow;
+ }
+ return shadow;
#endif
+}
+
+#endif //!MODE_RENDER DEPTH
void main() {
#ifdef MODE_DUAL_PARABOLOID
@@ -1802,9 +1849,7 @@ void main() {
float clearcoat_gloss = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
-#if defined(CUSTOM_FOG_USED)
- vec4 custom_fog = vec4(0.0);
-#endif
+ vec4 fog = vec4(0.0);
#if defined(CUSTOM_RADIANCE_USED)
vec4 custom_radiance = vec4(0.0);
#endif
@@ -1812,14 +1857,12 @@ void main() {
vec4 custom_irradiance = vec4(0.0);
#endif
-#if defined(AO_USED)
float ao = 1.0;
float ao_light_affect = 0.0;
-#endif
float alpha = 1.0;
-#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED)
+#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
vec3 binormal = normalize(binormal_interp);
vec3 tangent = normalize(tangent_interp);
#else
@@ -1850,12 +1893,12 @@ void main() {
vec4 color = color_interp;
#endif
-#if defined(NORMALMAP_USED)
+#if defined(NORMAL_MAP_USED)
- vec3 normalmap = vec3(0.5);
+ vec3 normal_map = vec3(0.5);
#endif
- float normaldepth = 1.0;
+ float normal_map_depth = 1.0;
vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center
@@ -1926,12 +1969,12 @@ FRAGMENT_SHADER_CODE
#endif // !USE_SHADOW_TO_OPACITY
-#ifdef NORMALMAP_USED
+#ifdef NORMAL_MAP_USED
- normalmap.xy = normalmap.xy * 2.0 - 1.0;
- normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
+ normal_map.xy = normal_map.xy * 2.0 - 1.0;
+ normal_map.z = sqrt(max(0.0, 1.0 - dot(normal_map.xy, normal_map.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
- normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth));
+ normal = normalize(mix(normal, tangent * normal_map.x + binormal * normal_map.y + normal * normal_map.z, normal_map_depth));
#endif
@@ -1953,77 +1996,147 @@ FRAGMENT_SHADER_CODE
discard;
}
#endif
+
+ /////////////////////// FOG //////////////////////
+#ifndef MODE_RENDER_DEPTH
+
+#ifndef CUSTOM_FOG_USED
+ // fog must be processed as early as possible and then packed.
+ // to maximize VGPR usage
+ // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
+
+ if (scene_data.fog_enabled) {
+ fog = fog_process(vertex);
+ }
+
+#ifndef LOW_END_MODE
+ if (scene_data.volumetric_fog_enabled) {
+ vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z);
+ if (scene_data.fog_enabled) {
+ //must use the full blending equation here to blend fogs
+ vec4 res;
+ float sa = 1.0 - volumetric_fog.a;
+ res.a = fog.a * sa + volumetric_fog.a;
+ if (res.a == 0.0) {
+ res.rgb = vec3(0.0);
+ } else {
+ res.rgb = (fog.rgb * fog.a * sa + volumetric_fog.rgb * volumetric_fog.a) / res.a;
+ }
+ fog = res;
+ } else {
+ fog = volumetric_fog;
+ }
+ }
+#endif //!LOW_END_MODE
+#endif //!CUSTOM_FOG_USED
+
+ uint fog_rg = packHalf2x16(fog.rg);
+ uint fog_ba = packHalf2x16(fog.ba);
+
+#endif //!MODE_RENDER_DEPTH
+
/////////////////////// DECALS ////////////////////////////////
#ifndef MODE_RENDER_DEPTH
- uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)));
+ uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> scene_data.cluster_shift;
+ uint cluster_offset = (scene_data.cluster_width * cluster_pos.y + cluster_pos.x) * (scene_data.max_cluster_element_count_div_32 + 32);
+
+ uint cluster_z = uint(clamp((-vertex.z / scene_data.z_far) * 32.0, 0.0, 31.0));
+
//used for interpolating anything cluster related
vec3 vertex_ddx = dFdx(vertex);
vec3 vertex_ddy = dFdy(vertex);
{ // process decals
- uint decal_count = cluster_cell.w >> CLUSTER_COUNTER_SHIFT;
- uint decal_pointer = cluster_cell.w & CLUSTER_POINTER_MASK;
+ uint cluster_decal_offset = cluster_offset + scene_data.cluster_type_size * 2;
- //do outside for performance and avoiding arctifacts
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
- for (uint i = 0; i < decal_count; i++) {
- uint decal_index = cluster_data.indices[decal_pointer + i];
- if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
+ cluster_get_item_range(cluster_decal_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
- if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
- continue; //out of decal
- }
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
- //we need ddx/ddy for mipmaps, so simulate them
- vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
- vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_decal_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
- float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+ uint decal_index = 32 * i + bit;
- if (decals.data[decal_index].normal_fade > 0.0) {
- fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
- }
+ if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
- if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
- //has albedo
- vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
- decal_albedo *= decals.data[decal_index].modulate;
- decal_albedo.a *= fade;
- albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
-
- if (decals.data[decal_index].normal_rect != vec4(0.0)) {
- vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
- decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
- decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
- //convert to view space, use xzy because y is up
- decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
-
- normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+ vec3 uv_local = (decals.data[decal_index].xform * vec4(vertex, 1.0)).xyz;
+ if (any(lessThan(uv_local, vec3(0.0, -1.0, 0.0))) || any(greaterThan(uv_local, vec3(1.0)))) {
+ continue; //out of decal
}
- if (decals.data[decal_index].orm_rect != vec4(0.0)) {
- vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
-#if defined(AO_USED)
- ao = mix(ao, decal_orm.r, decal_albedo.a);
-#endif
- roughness = mix(roughness, decal_orm.g, decal_albedo.a);
- metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+ //we need ddx/ddy for mipmaps, so simulate them
+ vec2 ddx = (decals.data[decal_index].xform * vec4(vertex_ddx, 0.0)).xz;
+ vec2 ddy = (decals.data[decal_index].xform * vec4(vertex_ddy, 0.0)).xz;
+
+ float fade = pow(1.0 - (uv_local.y > 0.0 ? uv_local.y : -uv_local.y), uv_local.y > 0.0 ? decals.data[decal_index].upper_fade : decals.data[decal_index].lower_fade);
+
+ if (decals.data[decal_index].normal_fade > 0.0) {
+ fade *= smoothstep(decals.data[decal_index].normal_fade, 1.0, dot(normal_interp, decals.data[decal_index].normal) * 0.5 + 0.5);
+ }
+
+ if (decals.data[decal_index].albedo_rect != vec4(0.0)) {
+ //has albedo
+ vec4 decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, ddx * decals.data[decal_index].albedo_rect.zw, ddy * decals.data[decal_index].albedo_rect.zw);
+ decal_albedo *= decals.data[decal_index].modulate;
+ decal_albedo.a *= fade;
+ albedo = mix(albedo, decal_albedo.rgb, decal_albedo.a * decals.data[decal_index].albedo_mix);
+
+ if (decals.data[decal_index].normal_rect != vec4(0.0)) {
+ vec3 decal_normal = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, ddx * decals.data[decal_index].normal_rect.zw, ddy * decals.data[decal_index].normal_rect.zw).xyz;
+ decal_normal.xy = decal_normal.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); //users prefer flipped y normal maps in most authoring software
+ decal_normal.z = sqrt(max(0.0, 1.0 - dot(decal_normal.xy, decal_normal.xy)));
+ //convert to view space, use xzy because y is up
+ decal_normal = (decals.data[decal_index].normal_xform * decal_normal.xzy).xyz;
+
+ normal = normalize(mix(normal, decal_normal, decal_albedo.a));
+ }
+
+ if (decals.data[decal_index].orm_rect != vec4(0.0)) {
+ vec3 decal_orm = textureGrad(sampler2D(decal_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, ddx * decals.data[decal_index].orm_rect.zw, ddy * decals.data[decal_index].orm_rect.zw).xyz;
+ ao = mix(ao, decal_orm.r, decal_albedo.a);
+ roughness = mix(roughness, decal_orm.g, decal_albedo.a);
+ metallic = mix(metallic, decal_orm.b, decal_albedo.a);
+ }
}
- }
- if (decals.data[decal_index].emission_rect != vec4(0.0)) {
- //emission is additive, so its independent from albedo
- emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ if (decals.data[decal_index].emission_rect != vec4(0.0)) {
+ //emission is additive, so its independent from albedo
+ emission += textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ }
}
}
}
+ //pack albedo until needed again, saves 2 VGPRs in the meantime
+
#endif //not render depth
/////////////////////// LIGHTING //////////////////////////////
@@ -2091,19 +2204,14 @@ FRAGMENT_SHADER_CODE
//radiance
- float specular_blob_intensity = 1.0;
-
-#if defined(SPECULAR_TOON)
- specular_blob_intensity *= specular * 2.0;
-#endif
-
+/// GI ///
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
#ifdef USE_LIGHTMAP
//lightmap
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
- uint index = instances.data[instance_index].gi_offset;
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture
+ uint index = draw_call.gi_offset;
vec3 wnormal = mat3(scene_data.camera_matrix) * normal;
const float c1 = 0.429043;
@@ -2122,12 +2230,12 @@ FRAGMENT_SHADER_CODE
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
- } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
- bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
- uint ofs = instances.data[instance_index].gi_offset & 0xFFF;
+ } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
+ bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
+ uint ofs = draw_call.gi_offset & 0xFFFF;
vec3 uvw;
- uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy;
- uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF);
+ uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
+ uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data
@@ -2136,7 +2244,7 @@ FRAGMENT_SHADER_CODE
vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
- uint idx = instances.data[instance_index].gi_offset >> 20;
+ uint idx = draw_call.gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
ambient_light += lm_light_l0 * 0.282095f;
@@ -2156,7 +2264,7 @@ FRAGMENT_SHADER_CODE
}
#elif defined(USE_FORWARD_GI)
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
//make vertex orientation the world one, but still align to camera
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
@@ -2228,9 +2336,9 @@ FRAGMENT_SHADER_CODE
}
}
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
+ uint index1 = draw_call.gi_offset & 0xFFFF;
vec3 ref_vec = normalize(reflect(normalize(vertex), 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);
@@ -2242,7 +2350,7 @@ FRAGMENT_SHADER_CODE
vec4 spec_accum = vec4(0.0);
gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
- uint index2 = instances.data[instance_index].gi_offset >> 16;
+ uint index2 = draw_call.gi_offset >> 16;
if (index2 != 0xFFFF) {
gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
@@ -2261,19 +2369,19 @@ FRAGMENT_SHADER_CODE
}
#elif !defined(LOW_END_MODE)
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
- ivec2 coord;
+ vec2 coord;
if (scene_data.gi_upscale_for_msaa) {
- ivec2 base_coord = ivec2(gl_FragCoord.xy);
- ivec2 closest_coord = base_coord;
- float closest_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0).xyz * 2.0 - 1.0);
+ vec2 base_coord = screen_uv;
+ vec2 closest_coord = base_coord;
+ float closest_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0.0).xyz * 2.0 - 1.0);
for (int i = 0; i < 4; i++) {
- const ivec2 neighbours[4] = ivec2[](ivec2(-1, 0), ivec2(1, 0), ivec2(0, -1), ivec2(0, 1));
- ivec2 neighbour_coord = base_coord + neighbours[i];
- float neighbour_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0).xyz * 2.0 - 1.0);
+ 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;
+ float neighbour_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0.0).xyz * 2.0 - 1.0);
if (neighbour_ang > closest_ang) {
closest_ang = neighbour_ang;
closest_coord = neighbour_coord;
@@ -2283,28 +2391,69 @@ FRAGMENT_SHADER_CODE
coord = closest_coord;
} else {
- coord = ivec2(gl_FragCoord.xy);
+ coord = screen_uv;
}
- vec4 buffer_ambient = texelFetch(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0);
- vec4 buffer_reflection = texelFetch(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0);
+ vec4 buffer_ambient = textureLod(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0);
+ vec4 buffer_reflection = textureLod(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0);
ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a);
specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a);
}
#endif
+#ifndef LOW_END_MODE
+ if (scene_data.ssao_enabled) {
+ float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
+ ao = min(ao, ssao);
+ ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect);
+ }
+#endif //LOW_END_MODE
+
{ // process reflections
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
- uint reflection_probe_count = cluster_cell.z >> CLUSTER_COUNTER_SHIFT;
- uint reflection_probe_pointer = cluster_cell.z & CLUSTER_POINTER_MASK;
+ uint cluster_reflection_offset = cluster_offset + scene_data.cluster_type_size * 3;
+
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_reflection_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- for (uint i = 0; i < reflection_probe_count; i++) {
- uint ref_index = cluster_data.indices[reflection_probe_pointer + i];
- reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_reflection_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+ uint reflection_index = 32 * i + bit;
+
+ if (!bool(reflections.data[reflection_index].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
+
+ reflection_process(reflection_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+ }
}
if (reflection_accum.a > 0.0) {
@@ -2318,6 +2467,16 @@ FRAGMENT_SHADER_CODE
#endif
}
+ //finalize ambient light here
+ ambient_light *= albedo.rgb;
+ ambient_light *= ao;
+
+ // convert ao to direct light ao
+ ao = mix(1.0, ao, ao_light_affect);
+
+ //this saves some VGPRs
+ vec3 f0 = F0(metallic, specular, albedo);
+
{
#if defined(DIFFUSE_TOON)
//simplify for toon, as
@@ -2335,24 +2494,39 @@ FRAGMENT_SHADER_CODE
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- vec3 f0 = F0(metallic, specular, albedo);
specular_light *= env.x * f0 + env.y;
#endif
}
+#endif //GI !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+
+#if !defined(MODE_RENDER_DEPTH)
+ //this saves some VGPRs
+ uint orms = packUnorm4x8(vec4(ao, roughness, metallic, specular));
+#endif
+
+// LIGHTING
+#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+
{ //directional light
- for (uint i = 0; i < scene_data.directional_light_count; i++) {
- if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
+ // Do shadow and lighting in two passes to reduce register pressure
+ uint shadow0 = 0;
+ uint shadow1 = 0;
+
+ for (uint i = 0; i < 8; i++) {
+ if (i >= scene_data.directional_light_count) {
+ break;
}
- vec3 shadow_attenuation = vec3(1.0);
+ if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
-#ifdef LIGHT_TRANSMITTANCE_USED
- float transmittance_z = transmittance_depth;
-#endif
+ float shadow = 1.0;
+#ifdef USE_SOFT_SHADOWS
+ //version with soft shadows, more expensive
if (directional_lights.data[i].shadow_enabled) {
float depth_z = -vertex.z;
@@ -2366,8 +2540,6 @@ FRAGMENT_SHADER_CODE
normal_bias -= light_dir * dot(light_dir, normal_bias); \
m_var.xyz += normal_bias;
- float shadow = 0.0;
-
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
@@ -2388,19 +2560,6 @@ FRAGMENT_SHADER_CODE
shadow_color = directional_lights.data[i].shadow_color1.rgb;
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.x;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.x;
-
- transmittance_z = z - shadow_z;
- }
-#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
@@ -2420,19 +2579,6 @@ FRAGMENT_SHADER_CODE
}
shadow_color = directional_lights.data[i].shadow_color2.rgb;
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.y;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.y;
-
- transmittance_z = z - shadow_z;
- }
-#endif
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
@@ -2452,19 +2598,6 @@ FRAGMENT_SHADER_CODE
}
shadow_color = directional_lights.data[i].shadow_color3.rgb;
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.z;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.z;
-
- transmittance_z = z - shadow_z;
- }
-#endif
} else {
vec4 v = vec4(vertex, 1.0);
@@ -2485,20 +2618,6 @@ FRAGMENT_SHADER_CODE
}
shadow_color = directional_lights.data[i].shadow_color4.rgb;
-
-#ifdef LIGHT_TRANSMITTANCE_USED
- {
- vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
- vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
- trans_coord /= trans_coord.w;
-
- float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
- shadow_z *= directional_lights.data[i].shadow_z_range.w;
- float z = trans_coord.z * directional_lights.data[i].shadow_z_range.w;
-
- transmittance_z = z - shadow_z;
- }
-#endif
}
if (directional_lights.data[i].blend_splits) {
@@ -2572,130 +2691,407 @@ FRAGMENT_SHADER_CODE
shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
- shadow_attenuation = mix(shadow_color, vec3(1.0), shadow);
+#undef BIAS_FUNC
+ }
+#else
+ // Soft shadow disabled version
+
+ if (directional_lights.data[i].shadow_enabled) {
+ float depth_z = -vertex.z;
+
+ vec4 pssm_coord;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
+
+#define BIAS_FUNC(m_var, m_idx) \
+ m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \
+ vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \
+ normal_bias -= light_dir * dot(light_dir, normal_bias); \
+ m_var.xyz += normal_bias;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 0)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 1)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 2)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+
+ } else {
+ vec4 v = vec4(vertex, 1.0);
+
+ BIAS_FUNC(v, 3)
+
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+#ifdef LIGHT_TRANSMITTANCE_USED
+ {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+ }
+
+ pssm_coord /= pssm_coord.w;
+
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+
+ if (directional_lights.data[i].blend_splits) {
+ float pssm_blend;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 1)
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 2)
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ vec4 v = vec4(vertex, 1.0);
+ BIAS_FUNC(v, 3)
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ } else {
+ pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+ }
+
+ pssm_coord /= pssm_coord.w;
+
+ float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ shadow = mix(shadow, shadow2, pssm_blend);
+ }
+
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
#undef BIAS_FUNC
}
+#endif
+
+ if (i < 4) {
+ shadow0 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << (i * 8);
+ } else {
+ shadow1 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << ((i - 4) * 8);
+ }
+ }
+
+ for (uint i = 0; i < 8; i++) {
+ if (i >= scene_data.directional_light_count) {
+ break;
+ }
+
+ if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
- light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].size, directional_lights.data[i].color * directional_lights.data[i].energy, 1.0, shadow_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity,
+#ifdef LIGHT_TRANSMITTANCE_USED
+ float transmittance_z = transmittance_depth;
+
+ if (directional_lights.data[i].shadow_enabled) {
+ float depth_z = -vertex.z;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.x, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix1 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.x;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.x;
+
+ transmittance_z = z - shadow_z;
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.y, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix2 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.y;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.y;
+
+ transmittance_z = z - shadow_z;
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.z, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix3 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.z;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.z;
+
+ transmittance_z = z - shadow_z;
+
+ } else {
+ vec4 trans_vertex = vec4(vertex - normalize(normal_interp) * directional_lights.data[i].shadow_transmittance_bias.w, 1.0);
+ vec4 trans_coord = directional_lights.data[i].shadow_matrix4 * trans_vertex;
+ trans_coord /= trans_coord.w;
+
+ float shadow_z = textureLod(sampler2D(directional_shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), trans_coord.xy, 0.0).r;
+ shadow_z *= directional_lights.data[i].shadow_transmittance_z_scale.w;
+ float z = trans_coord.z * directional_lights.data[i].shadow_transmittance_z_scale.w;
+
+ transmittance_z = z - shadow_z;
+ }
+#endif
+
+ float shadow = 1.0;
+
+ if (i < 4) {
+ shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
+ } else {
+ shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
+ }
+
+ blur_shadow(shadow);
+
+ light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_curve,
- transmittance_boost,
- transmittance_z,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
+ transmittance_z,
#endif
#ifdef LIGHT_RIM_USED
- rim, rim_tint,
+ rim, rim_tint, albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
+ clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
- binormal, tangent, anisotropy,
+ binormal, tangent, anisotropy,
+#endif
+#ifdef USE_SOFT_SHADOW
+ directional_lights.data[i].size,
#endif
#ifdef USE_SHADOW_TO_OPACITY
- alpha,
+ alpha,
#endif
- diffuse_light,
- specular_light);
+ diffuse_light,
+ specular_light);
+ }
}
- }
- { //omni lights
+ { //omni lights
- uint omni_light_count = cluster_cell.x >> CLUSTER_COUNTER_SHIFT;
- uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK;
+ uint cluster_omni_offset = cluster_offset;
- for (uint i = 0; i < omni_light_count; i++) {
- uint light_index = cluster_data.indices[omni_light_pointer + i];
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
- if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
+ cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, albedo, roughness, metallic, specular, specular_blob_intensity,
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_omni_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+ uint light_index = 32 * i + bit;
+
+ if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
+
+ float shadow = light_process_omni_shadow(light_index, vertex, view);
+
+ shadow = blur_shadow(shadow);
+
+ light_process_omni(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_curve,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
+ rim,
+ rim_tint,
+ albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
+ clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
+ tangent, binormal, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
- alpha,
+ alpha,
#endif
- diffuse_light, specular_light);
+ diffuse_light, specular_light);
+ }
+ }
}
- }
- { //spot lights
- uint spot_light_count = cluster_cell.y >> CLUSTER_COUNTER_SHIFT;
- uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK;
+ { //spot lights
- for (uint i = 0; i < spot_light_count; i++) {
- uint light_index = cluster_data.indices[spot_light_pointer + i];
+ uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size;
- if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) {
- continue; //not masked
- }
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, albedo, roughness, metallic, specular, specular_blob_intensity,
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_spot_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+
+ uint light_index = 32 * i + bit;
+
+ if (!bool(spot_lights.data[light_index].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
+
+ float shadow = light_process_spot_shadow(light_index, vertex, view);
+
+ shadow = blur_shadow(shadow);
+
+ light_process_spot(light_index, vertex, view, normal, vertex_ddx, vertex_ddy, f0, orms, shadow,
#ifdef LIGHT_BACKLIGHT_USED
- backlight,
+ backlight,
#endif
#ifdef LIGHT_TRANSMITTANCE_USED
- transmittance_color,
- transmittance_depth,
- transmittance_curve,
- transmittance_boost,
+ transmittance_color,
+ transmittance_depth,
+ transmittance_curve,
+ transmittance_boost,
#endif
#ifdef LIGHT_RIM_USED
- rim,
- rim_tint,
+ rim,
+ rim_tint,
+ albedo,
#endif
#ifdef LIGHT_CLEARCOAT_USED
- clearcoat, clearcoat_gloss,
+ clearcoat, clearcoat_gloss,
#endif
#ifdef LIGHT_ANISOTROPY_USED
- tangent, binormal, anisotropy,
+ tangent, binormal, anisotropy,
#endif
#ifdef USE_SHADOW_TO_OPACITY
- alpha,
+ alpha,
#endif
- diffuse_light, specular_light);
+ diffuse_light, specular_light);
+ }
+ }
}
- }
#ifdef USE_SHADOW_TO_OPACITY
- alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
+ alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0));
#if defined(ALPHA_SCISSOR_USED)
- if (alpha < alpha_scissor) {
- discard;
- }
+ if (alpha < alpha_scissor) {
+ discard;
+ }
#endif // ALPHA_SCISSOR_USED
#ifdef USE_OPAQUE_PREPASS
- if (alpha < opaque_prepass_threshold) {
- discard;
- }
+ if (alpha < opaque_prepass_threshold) {
+ discard;
+ }
#endif // USE_OPAQUE_PREPASS
@@ -2707,173 +3103,149 @@ FRAGMENT_SHADER_CODE
#ifdef MODE_RENDER_SDF
- {
- vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
- ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
-
- uint albedo16 = 0x1; //solid flag
- albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
- albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6;
- albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1;
-
- imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16));
-
- uint facing_bits = 0;
- const vec3 aniso_dir[6] = vec3[](
- vec3(1, 0, 0),
- vec3(0, 1, 0),
- vec3(0, 0, 1),
- vec3(-1, 0, 0),
- vec3(0, -1, 0),
- vec3(0, 0, -1));
-
- vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp);
-
- float closest_dist = -1e20;
-
- for (uint i = 0; i < 6; i++) {
- float d = dot(cam_normal, aniso_dir[i]);
- if (d > closest_dist) {
- closest_dist = d;
- facing_bits = (1 << i);
+ {
+ vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
+ ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
+
+ uint albedo16 = 0x1; //solid flag
+ albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
+ albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6;
+ albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1;
+
+ imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16));
+
+ uint facing_bits = 0;
+ const vec3 aniso_dir[6] = vec3[](
+ vec3(1, 0, 0),
+ vec3(0, 1, 0),
+ vec3(0, 0, 1),
+ vec3(-1, 0, 0),
+ vec3(0, -1, 0),
+ vec3(0, 0, -1));
+
+ vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp);
+
+ float closest_dist = -1e20;
+
+ for (uint i = 0; i < 6; i++) {
+ float d = dot(cam_normal, aniso_dir[i]);
+ if (d > closest_dist) {
+ closest_dist = d;
+ facing_bits = (1 << i);
+ }
}
- }
- imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
+ imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits
- if (length(emission) > 0.001) {
- float lumas[6];
- vec3 light_total = vec3(0);
+ if (length(emission) > 0.001) {
+ float lumas[6];
+ vec3 light_total = vec3(0);
- for (int i = 0; i < 6; i++) {
- float strength = max(0.0, dot(cam_normal, aniso_dir[i]));
- vec3 light = emission * strength;
- light_total += light;
- lumas[i] = max(light.r, max(light.g, light.b));
- }
+ for (int i = 0; i < 6; i++) {
+ float strength = max(0.0, dot(cam_normal, aniso_dir[i]));
+ vec3 light = emission * strength;
+ light_total += light;
+ lumas[i] = max(light.r, max(light.g, light.b));
+ }
- float luma_total = max(light_total.r, max(light_total.g, light_total.b));
+ float luma_total = max(light_total.r, max(light_total.g, light_total.b));
- uint light_aniso = 0;
+ uint light_aniso = 0;
- for (int i = 0; i < 6; i++) {
- light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
- }
+ for (int i = 0; i < 6; i++) {
+ light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5);
+ }
- //compress to RGBE9995 to save space
+ //compress to RGBE9995 to save space
- const float pow2to9 = 512.0f;
- const float B = 15.0f;
- const float N = 9.0f;
- const float LN2 = 0.6931471805599453094172321215;
+ const float pow2to9 = 512.0f;
+ const float B = 15.0f;
+ const float N = 9.0f;
+ const float LN2 = 0.6931471805599453094172321215;
- float cRed = clamp(light_total.r, 0.0, 65408.0);
- float cGreen = clamp(light_total.g, 0.0, 65408.0);
- float cBlue = clamp(light_total.b, 0.0, 65408.0);
+ float cRed = clamp(light_total.r, 0.0, 65408.0);
+ float cGreen = clamp(light_total.g, 0.0, 65408.0);
+ float cBlue = clamp(light_total.b, 0.0, 65408.0);
- float cMax = max(cRed, max(cGreen, cBlue));
+ float cMax = max(cRed, max(cGreen, cBlue));
- float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
+ float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B;
- float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
+ float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f);
- float exps = expp + 1.0f;
+ float exps = expp + 1.0f;
- if (0.0 <= sMax && sMax < pow2to9) {
- exps = expp;
- }
+ if (0.0 <= sMax && sMax < pow2to9) {
+ exps = expp;
+ }
- 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
- uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
+ 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
+ uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
- imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
- imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
+ imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
+ imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
+ }
}
- }
#endif
#ifdef MODE_RENDER_MATERIAL
- albedo_output_buffer.rgb = albedo;
- albedo_output_buffer.a = alpha;
+ albedo_output_buffer.rgb = albedo;
+ albedo_output_buffer.a = alpha;
- normal_output_buffer.rgb = normal * 0.5 + 0.5;
- normal_output_buffer.a = 0.0;
- depth_output_buffer.r = -vertex.z;
+ normal_output_buffer.rgb = normal * 0.5 + 0.5;
+ normal_output_buffer.a = 0.0;
+ depth_output_buffer.r = -vertex.z;
-#if defined(AO_USED)
- orm_output_buffer.r = ao;
-#else
- orm_output_buffer.r = 0.0;
-#endif
- orm_output_buffer.g = roughness;
- orm_output_buffer.b = metallic;
- orm_output_buffer.a = sss_strength;
+ orm_output_buffer.r = ao;
+ orm_output_buffer.g = roughness;
+ orm_output_buffer.b = metallic;
+ orm_output_buffer.a = sss_strength;
- emission_output_buffer.rgb = emission;
- emission_output_buffer.a = 0.0;
+ emission_output_buffer.rgb = emission;
+ emission_output_buffer.a = 0.0;
#endif
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
- normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
+ normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
#ifdef MODE_RENDER_GIPROBE
- if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
- uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- uint index2 = instances.data[instance_index].gi_offset >> 16;
- giprobe_buffer.x = index1 & 0xFF;
- giprobe_buffer.y = index2 & 0xFF;
- } else {
- giprobe_buffer.x = 0xFF;
- giprobe_buffer.y = 0xFF;
- }
+ if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes
+ uint index1 = draw_call.gi_offset & 0xFFFF;
+ uint index2 = draw_call.gi_offset >> 16;
+ giprobe_buffer.x = index1 & 0xFF;
+ giprobe_buffer.y = index2 & 0xFF;
+ } else {
+ giprobe_buffer.x = 0xFF;
+ giprobe_buffer.y = 0xFF;
+ }
#endif
-#endif //MODE_RENDER_NORMAL
+#endif //MODE_RENDER_NORMAL_ROUGHNESS
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else
- specular_light *= scene_data.reflection_multiplier;
- ambient_light *= albedo; //ambient must be multiplied by albedo at the end
-
-//ambient occlusion
-#if defined(AO_USED)
-
-#ifndef LOW_END_MODE
- if (scene_data.ssao_enabled && scene_data.ssao_ao_affect > 0.0) {
- float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
- ao = mix(ao, min(ao, ssao), scene_data.ssao_ao_affect);
- ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect);
- }
-#endif //LOW_END_MODE
-
- ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao);
- ao_light_affect = mix(1.0, ao, ao_light_affect);
- specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect);
- diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect);
-#else
-
-#ifndef LOW_END_MODE
- if (scene_data.ssao_enabled) {
- float ao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
- ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao);
- float ao_light_affect = mix(1.0, ao, scene_data.ssao_light_affect);
- specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect);
- diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect);
- }
-#endif //LOW_END_MODE
+ // multiply by albedo
+ diffuse_light *= albedo; // ambient must be multiplied by albedo at the end
-#endif // AO_USED
+ // apply direct light AO
+ ao = unpackUnorm4x8(orms).x;
+ specular_light *= ao;
+ diffuse_light *= ao;
- // base color remapping
- diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point
+ // apply metallic
+ metallic = unpackUnorm4x8(orms).z;
+ diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic;
+ //restore fog
+ fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
+
#ifdef MODE_MULTIPLE_RENDER_TARGETS
#ifdef MODE_UNSHADED
@@ -2889,25 +3261,8 @@ FRAGMENT_SHADER_CODE
specular_buffer = vec4(specular_light, metallic);
#endif
- // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
- if (scene_data.fog_enabled) {
- vec4 fog = fog_process(vertex);
- diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
- specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
- }
-
-#ifndef LOW_END_MODE
- if (scene_data.volumetric_fog_enabled) {
- vec4 fog = volumetric_fog_process(screen_uv, -vertex.z);
- diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
- specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
- }
-#endif // LOW_END_MODE
-
-#if defined(CUSTOM_FOG_USED)
- diffuse_buffer.rgb = mix(diffuse_buffer.rgb, custom_fog.rgb, custom_fog.a);
- specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), custom_fog.a);
-#endif //CUSTOM_FOG_USED
+ diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
+ specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
#else //MODE_MULTIPLE_RENDER_TARGETS
@@ -2919,22 +3274,9 @@ FRAGMENT_SHADER_CODE
#endif //USE_NO_SHADING
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
- if (scene_data.fog_enabled) {
- vec4 fog = fog_process(vertex);
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
- }
-#ifndef LOW_END_MODE
- if (scene_data.volumetric_fog_enabled) {
- vec4 fog = volumetric_fog_process(screen_uv, -vertex.z);
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
- }
-#endif
-
-#if defined(CUSTOM_FOG_USED)
- frag_color.rgb = mix(frag_color.rgb, custom_fog.rgb, custom_fog.a);
-#endif //CUSTOM_FOG_USED
+ frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
#endif //MODE_MULTIPLE_RENDER_TARGETS
#endif //MODE_RENDER_DEPTH
-}
+ }
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
index fdc9941bba..e9b79e1560 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl
@@ -3,18 +3,30 @@
#define MAX_GI_PROBES 8
+#if defined(GL_KHR_shader_subgroup_ballot) && defined(GL_KHR_shader_subgroup_arithmetic)
+
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_KHR_shader_subgroup_arithmetic : enable
+
+#define USE_SUBGROUPS
+
+#endif
+
#include "cluster_data_inc.glsl"
-#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_GIPROBE) || defined(TANGENT_USED) || defined(NORMALMAP_USED)
+#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_GIPROBE) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED)
#ifndef NORMAL_USED
#define NORMAL_USED
#endif
#endif
layout(push_constant, binding = 0, std430) uniform DrawCall {
- uint instance_index;
- uint pad; //16 bits minimum size
- vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise
+ mat4 transform;
+ uint flags;
+ uint instance_uniforms_ofs; //base offset in global buffer for instance variables
+ uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
+ uint layer_mask;
+ vec4 lightmap_uv_scale;
}
draw_call;
@@ -49,6 +61,11 @@ layout(set = 0, binding = 3, std140) uniform SceneData {
vec2 viewport_size;
vec2 screen_pixel_size;
+ uint cluster_shift;
+ uint cluster_width;
+ uint cluster_type_size;
+ uint max_cluster_element_count_div_32;
+
//use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
vec4 directional_penumbra_shadow_kernel[32];
vec4 directional_soft_shadow_kernel[32];
@@ -134,26 +151,17 @@ scene_data;
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
#define INSTANCE_FLAGS_SKELETON (1 << 19)
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 20)
-struct InstanceData {
- mat4 transform;
- mat4 normal_transform;
- uint flags;
- uint instance_uniforms_ofs; //base offset in global buffer for instance variables
- uint gi_offset; //GI information when using lightmapping (VCT or lightmap index)
- uint layer_mask;
- vec4 lightmap_uv_scale;
-};
-
-layout(set = 0, binding = 4, std430) restrict readonly buffer Instances {
- InstanceData data[];
+layout(set = 0, binding = 4, std430) restrict readonly buffer OmniLights {
+ LightData data[];
}
-instances;
+omni_lights;
-layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {
+layout(set = 0, binding = 5, std430) restrict readonly buffer SpotLights {
LightData data[];
}
-lights;
+spot_lights;
layout(set = 0, binding = 6) buffer restrict readonly ReflectionProbeData {
ReflectionData data[];
@@ -172,40 +180,29 @@ struct Lightmap {
mat3 normal_xform;
};
-layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {
+layout(set = 0, binding = 8, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
lightmaps;
-layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
-
struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 9, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 13) uniform texture2D decal_atlas;
-layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 10) uniform texture2D decal_atlas;
+layout(set = 0, binding = 11) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 15, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 12, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 16) uniform utexture3D cluster_texture;
-
-layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData {
- uint indices[];
-}
-cluster_data;
-
-layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas;
-
-layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 13, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -219,7 +216,7 @@ struct SDFGIProbeCascadeData {
float to_cell; // 1/bounds * grid_size
};
-layout(set = 0, binding = 20, std140) uniform SDFGI {
+layout(set = 0, binding = 14, std140) uniform SDFGI {
vec3 grid_size;
uint max_cascades;
@@ -269,18 +266,27 @@ layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas;
layout(set = 1, binding = 2) uniform texture2D shadow_atlas;
+layout(set = 1, binding = 3) uniform texture2D directional_shadow_atlas;
+
+layout(set = 1, binding = 4) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+
#ifndef LOW_END_MODE
-layout(set = 1, binding = 3) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
+layout(set = 1, binding = 5) uniform texture3D gi_probe_textures[MAX_GI_PROBES];
#endif
+layout(set = 1, binding = 6, std430) buffer restrict readonly ClusterBuffer {
+ uint data[];
+}
+cluster_buffer;
+
/* Set 3, Render Buffers */
#ifdef MODE_RENDER_SDF
-layout(r16ui, set = 1, binding = 4) uniform restrict writeonly uimage3D albedo_volume_grid;
-layout(r32ui, set = 1, binding = 5) uniform restrict writeonly uimage3D emission_grid;
-layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_aniso_grid;
-layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;
+layout(r16ui, set = 1, binding = 7) uniform restrict writeonly uimage3D albedo_volume_grid;
+layout(r32ui, set = 1, binding = 8) uniform restrict writeonly uimage3D emission_grid;
+layout(r32ui, set = 1, binding = 9) uniform restrict writeonly uimage3D emission_aniso_grid;
+layout(r32ui, set = 1, binding = 10) uniform restrict uimage3D geom_facing_grid;
//still need to be present for shaders that use it, so remap them to something
#define depth_buffer shadow_atlas
@@ -289,17 +295,17 @@ layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;
#else
-layout(set = 1, binding = 4) uniform texture2D depth_buffer;
-layout(set = 1, binding = 5) uniform texture2D color_buffer;
+layout(set = 1, binding = 7) uniform texture2D depth_buffer;
+layout(set = 1, binding = 8) uniform texture2D color_buffer;
#ifndef LOW_END_MODE
-layout(set = 1, binding = 6) uniform texture2D normal_roughness_buffer;
-layout(set = 1, binding = 7) uniform texture2D ao_buffer;
-layout(set = 1, binding = 8) uniform texture2D ambient_buffer;
-layout(set = 1, binding = 9) uniform texture2D reflection_buffer;
-layout(set = 1, binding = 10) uniform texture2DArray sdfgi_lightprobe_texture;
-layout(set = 1, binding = 11) uniform texture3D sdfgi_occlusion_cascades;
+layout(set = 1, binding = 9) uniform texture2D normal_roughness_buffer;
+layout(set = 1, binding = 10) uniform texture2D ao_buffer;
+layout(set = 1, binding = 11) uniform texture2D ambient_buffer;
+layout(set = 1, binding = 12) uniform texture2D reflection_buffer;
+layout(set = 1, binding = 13) uniform texture2DArray sdfgi_lightprobe_texture;
+layout(set = 1, binding = 14) uniform texture3D sdfgi_occlusion_cascades;
struct GIProbeData {
mat4 xform;
@@ -317,12 +323,12 @@ struct GIProbeData {
uint mipmaps;
};
-layout(set = 1, binding = 12, std140) uniform GIProbes {
+layout(set = 1, binding = 15, std140) uniform GIProbes {
GIProbeData data[MAX_GI_PROBES];
}
gi_probes;
-layout(set = 1, binding = 13) uniform texture3D volumetric_fog_texture;
+layout(set = 1, binding = 16) uniform texture3D volumetric_fog_texture;
#endif // LOW_END_MODE
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl
index 813ea29fa1..e4c3f3a84b 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl
@@ -97,6 +97,8 @@ void main() {
float blend = 0.0;
#if 1
+ // No interpolation
+
vec3 inv_dir = 1.0 / ray_dir;
float rough = 0.5;
@@ -161,114 +163,11 @@ void main() {
hit_light *= (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0)));
- if (blend > 0.0) {
- light = mix(light, hit_light, blend);
- blend = 0.0;
- } else {
- light = hit_light;
-
- //process blend
- float blend_from = (float(params.probe_axis_size - 1) / 2.0) - 2.5;
- float blend_to = blend_from + 2.0;
-
- vec3 cam_pos = params.cam_transform[3].xyz - cascades.data[i].offset;
- cam_pos *= cascades.data[i].to_cell;
-
- pos += ray_dir * min(advance, max_advance);
- vec3 inner_pos = pos - cam_pos;
-
- inner_pos = inner_pos * float(params.probe_axis_size - 1) / params.grid_size.x;
-
- float len = length(inner_pos);
-
- inner_pos = abs(normalize(inner_pos));
- len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z));
-
- if (len >= blend_from) {
- blend = smoothstep(blend_from, blend_to, len);
-
- pos /= cascades.data[i].to_cell;
- pos += cascades.data[i].offset;
- ray_pos = pos;
- hit = false; //continue trace for blend
-
- continue;
- }
- }
+ light = hit_light;
break;
}
- light = mix(light, vec3(0.0), blend);
-
-#else
-
- vec3 inv_dir = 1.0 / ray_dir;
-
- bool hit = false;
- vec4 light_accum = vec4(0.0);
-
- float blend_size = (params.grid_size.x / float(params.probe_axis_size - 1)) * 0.5;
-
- float radius_sizes[MAX_CASCADES];
- for (uint i = 0; i < params.max_cascades; i++) {
- radius_sizes[i] = (1.0 / cascades.data[i].to_cell) * (params.grid_size.x * 0.5 - blend_size);
- }
-
- float max_distance = radius_sizes[params.max_cascades - 1];
- float advance = 0;
- while (advance < max_distance) {
- for (uint i = 0; i < params.max_cascades; i++) {
- if (advance < radius_sizes[i]) {
- vec3 pos = (ray_pos + ray_dir * advance) - cascades.data[i].offset;
- pos *= cascades.data[i].to_cell * pos_to_uvw;
-
- float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.0;
-
- vec4 hit_light = vec4(0.0);
- if (distance < 1.0) {
- hit_light.a = max(0.0, 1.0 - distance);
- hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb;
- hit_light.rgb *= hit_light.a;
- }
-
- distance /= cascades.data[i].to_cell;
-
- if (i < (params.max_cascades - 1)) {
- pos = (ray_pos + ray_dir * advance) - cascades.data[i + 1].offset;
- pos *= cascades.data[i + 1].to_cell * pos_to_uvw;
-
- float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.0;
-
- vec4 hit_light2 = vec4(0.0);
- if (distance2 < 1.0) {
- hit_light2.a = max(0.0, 1.0 - distance2);
- hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb;
- hit_light2.rgb *= hit_light2.a;
- }
-
- float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1];
- float blend = (advance - prev_radius) / (radius_sizes[i] - prev_radius);
-
- distance2 /= cascades.data[i + 1].to_cell;
-
- hit_light = mix(hit_light, hit_light2, blend);
- distance = mix(distance, distance2, blend);
- }
-
- light_accum += hit_light;
- advance += distance;
- break;
- }
- }
-
- if (light_accum.a > 0.98) {
- break;
- }
- }
-
- light = light_accum.rgb / light_accum.a;
-
#endif
imageStore(screen_buffer, screen_pos, vec4(linear_to_srgb(light), 1.0));
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
index 61e4bf5e18..bcdfe8cc85 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
@@ -112,11 +112,23 @@ vec2 octahedron_encode(vec3 n) {
return n.xy;
}
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
void main() {
uint voxel_index = uint(gl_GlobalInvocationID.x);
//used for skipping voxels every N frames
- voxel_index = params.process_offset + voxel_index * params.process_increment;
+ if (params.process_increment > 1) {
+ voxel_index *= params.process_increment;
+ voxel_index += params.process_offset;
+ }
if (voxel_index >= dispatch_data.total_count) {
return;
@@ -134,10 +146,78 @@ void main() {
uint voxel_albedo = process_voxels.data[voxel_index].albedo;
vec3 albedo = vec3(uvec3(voxel_albedo >> 10, voxel_albedo >> 5, voxel_albedo) & uvec3(0x1F)) / float(0x1F);
- vec3 light_accum[6];
-
+ vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
uint valid_aniso = (voxel_albedo >> 15) & 0x3F;
+ const vec3 aniso_dir[6] = vec3[](
+ vec3(1, 0, 0),
+ vec3(0, 1, 0),
+ vec3(0, 0, 1),
+ vec3(-1, 0, 0),
+ vec3(0, -1, 0),
+ vec3(0, 0, -1));
+
+ // Add indirect light first, in order to save computation resources
+#ifdef MODE_PROCESS_DYNAMIC
+ if (params.multibounce) {
+ vec3 pos = (vec3(positioni) + vec3(0.5)) * float(params.probe_axis_size - 1) / params.grid_size;
+ ivec3 probe_base_pos = ivec3(pos);
+
+ float weight_accum[6] = float[](0, 0, 0, 0, 0, 0);
+
+ ivec3 tex_pos = ivec3(probe_base_pos.xy, int(params.cascade));
+ tex_pos.x += probe_base_pos.z * int(params.probe_axis_size);
+
+ tex_pos.xy = tex_pos.xy * (OCT_SIZE + 2) + ivec2(1);
+
+ vec3 base_tex_posf = vec3(tex_pos);
+ vec2 tex_pixel_size = 1.0 / vec2(ivec2((OCT_SIZE + 2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE + 2) * params.probe_axis_size));
+ vec3 probe_uv_offset = (ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
+
+ for (uint j = 0; j < 8; j++) {
+ ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
+ ivec3 probe_posi = probe_base_pos;
+ probe_posi += offset;
+
+ // Compute weight
+
+ vec3 probe_pos = vec3(probe_posi);
+ vec3 probe_to_pos = pos - probe_pos;
+ vec3 probe_dir = normalize(-probe_to_pos);
+
+ // Compute lightprobe texture position
+
+ vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
+
+ for (uint k = 0; k < 6; k++) {
+ if (bool(valid_aniso & (1 << k))) {
+ vec3 n = aniso_dir[k];
+ float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(n, probe_dir));
+
+ vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
+ tex_posf.xy *= tex_pixel_size;
+
+ vec3 pos_uvw = tex_posf;
+ pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
+ pos_uvw.x += float(offset.z) * probe_uv_offset.z;
+ vec3 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
+
+ light_accum[k] += indirect_light * weight;
+ weight_accum[k] += weight;
+ }
+ }
+ }
+
+ for (uint k = 0; k < 6; k++) {
+ if (weight_accum[k] > 0.0) {
+ light_accum[k] /= weight_accum[k];
+ light_accum[k] *= albedo;
+ }
+ }
+ }
+
+#endif
+
{
uint rgbe = process_voxels.data[voxel_index].light;
@@ -153,18 +233,10 @@ void main() {
uint aniso = process_voxels.data[voxel_index].light_aniso;
for (uint i = 0; i < 6; i++) {
float strength = ((aniso >> (i * 5)) & 0x1F) / float(0x1F);
- light_accum[i] = l * strength;
+ light_accum[i] += l * strength;
}
}
- const vec3 aniso_dir[6] = vec3[](
- vec3(1, 0, 0),
- vec3(0, 1, 0),
- vec3(0, 0, 1),
- vec3(-1, 0, 0),
- vec3(0, -1, 0),
- vec3(0, 0, -1));
-
// Raytrace light
vec3 pos_to_uvw = 1.0 / params.grid_size;
@@ -184,14 +256,15 @@ void main() {
direction = normalize(rel_vec);
light_distance = length(rel_vec);
rel_vec.y /= params.y_mult;
- attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
+ attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
+
} break;
case LIGHT_TYPE_SPOT: {
vec3 rel_vec = lights.data[i].position - position;
direction = normalize(rel_vec);
light_distance = length(rel_vec);
rel_vec.y /= params.y_mult;
- attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation);
+ attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);
float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction));
if (angle > lights.data[i].spot_angle) {
@@ -282,65 +355,6 @@ void main() {
}
}
- // Add indirect light
-
- if (params.multibounce) {
- vec3 pos = (vec3(positioni) + vec3(0.5)) * float(params.probe_axis_size - 1) / params.grid_size;
- ivec3 probe_base_pos = ivec3(pos);
-
- vec4 probe_accum[6] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0));
- float weight_accum[6] = float[](0, 0, 0, 0, 0, 0);
-
- ivec3 tex_pos = ivec3(probe_base_pos.xy, int(params.cascade));
- tex_pos.x += probe_base_pos.z * int(params.probe_axis_size);
-
- tex_pos.xy = tex_pos.xy * (OCT_SIZE + 2) + ivec2(1);
-
- vec3 base_tex_posf = vec3(tex_pos);
- vec2 tex_pixel_size = 1.0 / vec2(ivec2((OCT_SIZE + 2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE + 2) * params.probe_axis_size));
- vec3 probe_uv_offset = (ivec3(OCT_SIZE + 2, OCT_SIZE + 2, (OCT_SIZE + 2) * params.probe_axis_size)) * tex_pixel_size.xyx;
-
- for (uint j = 0; j < 8; j++) {
- ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
- ivec3 probe_posi = probe_base_pos;
- probe_posi += offset;
-
- // Compute weight
-
- vec3 probe_pos = vec3(probe_posi);
- vec3 probe_to_pos = pos - probe_pos;
- vec3 probe_dir = normalize(-probe_to_pos);
-
- // Compute lightprobe texture position
-
- vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
-
- for (uint k = 0; k < 6; k++) {
- if (bool(valid_aniso & (1 << k))) {
- vec3 n = aniso_dir[k];
- float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(n, probe_dir));
-
- vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0);
- tex_posf.xy *= tex_pixel_size;
-
- vec3 pos_uvw = tex_posf;
- pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy;
- pos_uvw.x += float(offset.z) * probe_uv_offset.z;
- vec4 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0);
-
- probe_accum[k] += indirect_light * weight;
- weight_accum[k] += weight;
- }
- }
- }
-
- for (uint k = 0; k < 6; k++) {
- if (weight_accum[k] > 0.0) {
- light_accum[k] += probe_accum[k].rgb * albedo / weight_accum[k];
- }
- }
- }
-
// Store the light in the light texture
float lumas[6];
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
index d516ab22c3..d122e7a38a 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
@@ -136,12 +136,24 @@ uint rgbe_encode(vec3 color) {
return (uint(sRed) & 0x1FF) | ((uint(sGreen) & 0x1FF) << 9) | ((uint(sBlue) & 0x1FF) << 18) | ((uint(exps) & 0x1F) << 27);
}
+struct SH {
+#if (SH_SIZE == 16)
+ float c[48];
+#else
+ float c[28];
+#endif
+};
+
+shared SH sh_accum[64]; //8x8
+
void main() {
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
if (any(greaterThanEqual(pos, params.image_size))) { //too large, do nothing
return;
}
+ uint probe_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 8;
+
#ifdef MODE_PROCESS
float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
@@ -154,27 +166,9 @@ void main() {
vec3 probe_pos = cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size;
vec3 pos_to_uvw = 1.0 / params.grid_size;
- vec4 probe_sh_accum[SH_SIZE] = vec4[](
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0)
-#if (SH_SIZE == 16)
- ,
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0),
- vec4(0.0)
-#endif
- );
+ for (uint i = 0; i < SH_SIZE * 3; i++) {
+ sh_accum[probe_index].c[i] = 0.0;
+ }
// quickly ensure each probe has a different "offset" for the vogel function, based on integer world position
uvec3 h3 = hash3(uvec3(params.world_offset + probe_cell));
@@ -195,14 +189,12 @@ void main() {
vec3 inv_dir = 1.0 / ray_dir;
bool hit = false;
- vec3 hit_normal;
- vec3 hit_light;
- vec3 hit_aniso0;
- vec3 hit_aniso1;
+ uint hit_cascade;
float bias = params.ray_bias;
vec3 abs_ray_dir = abs(ray_dir);
ray_pos += ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) * bias / cascades.data[params.cascade].to_cell;
+ vec3 uvw;
for (uint j = params.cascade; j < params.max_cascades; j++) {
//convert to local bounds
@@ -221,14 +213,12 @@ void main() {
float advance = 0.0;
- vec3 uvw;
-
while (advance < max_advance) {
//read how much to advance from SDF
uvw = (pos + ray_dir * advance) * pos_to_uvw;
float distance = texture(sampler3D(sdf_cascades[j], linear_sampler), uvw).r * 255.0 - 1.0;
- if (distance < 0.001) {
+ if (distance < 0.05) {
//consider hit
hit = true;
break;
@@ -238,17 +228,7 @@ void main() {
}
if (hit) {
- const float EPSILON = 0.001;
- hit_normal = normalize(vec3(
- texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r,
- texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r,
- texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r));
-
- hit_light = texture(sampler3D(light_cascades[j], linear_sampler), uvw).rgb;
- vec4 aniso0 = texture(sampler3D(aniso0_cascades[j], linear_sampler), uvw);
- hit_aniso0 = aniso0.rgb;
- hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[j], linear_sampler), uvw).rg);
-
+ hit_cascade = j;
break;
}
@@ -261,6 +241,17 @@ void main() {
vec4 light;
if (hit) {
+ const float EPSILON = 0.001;
+ vec3 hit_normal = normalize(vec3(
+ texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r,
+ texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r,
+ texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[hit_cascade], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r));
+
+ vec3 hit_light = texture(sampler3D(light_cascades[hit_cascade], linear_sampler), uvw).rgb;
+ vec4 aniso0 = texture(sampler3D(aniso0_cascades[hit_cascade], linear_sampler), uvw);
+ vec3 hit_aniso0 = aniso0.rgb;
+ vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[hit_cascade], linear_sampler), uvw).rg);
+
//one liner magic
light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0)));
light.a = 1.0;
@@ -278,33 +269,33 @@ void main() {
}
vec3 ray_dir2 = ray_dir * ray_dir;
- float c[SH_SIZE] = float[](
-
- 0.282095, //l0
- 0.488603 * ray_dir.y, //l1n1
- 0.488603 * ray_dir.z, //l1n0
- 0.488603 * ray_dir.x, //l1p1
- 1.092548 * ray_dir.x * ray_dir.y, //l2n2
- 1.092548 * ray_dir.y * ray_dir.z, //l2n1
- 0.315392 * (3.0 * ray_dir2.z - 1.0), //l20
- 1.092548 * ray_dir.x * ray_dir.z, //l2p1
- 0.546274 * (ray_dir2.x - ray_dir2.y) //l2p2
+
+#define SH_ACCUM(m_idx, m_value) \
+ { \
+ vec3 l = light.rgb * (m_value); \
+ sh_accum[probe_index].c[m_idx * 3 + 0] += l.r; \
+ sh_accum[probe_index].c[m_idx * 3 + 1] += l.g; \
+ sh_accum[probe_index].c[m_idx * 3 + 2] += l.b; \
+ }
+ SH_ACCUM(0, 0.282095); //l0
+ SH_ACCUM(1, 0.488603 * ray_dir.y); //l1n1
+ SH_ACCUM(2, 0.488603 * ray_dir.z); //l1n0
+ SH_ACCUM(3, 0.488603 * ray_dir.x); //l1p1
+ SH_ACCUM(4, 1.092548 * ray_dir.x * ray_dir.y); //l2n2
+ SH_ACCUM(5, 1.092548 * ray_dir.y * ray_dir.z); //l2n1
+ SH_ACCUM(6, 0.315392 * (3.0 * ray_dir2.z - 1.0)); //l20
+ SH_ACCUM(7, 1.092548 * ray_dir.x * ray_dir.z); //l2p1
+ SH_ACCUM(8, 0.546274 * (ray_dir2.x - ray_dir2.y)); //l2p2
#if (SH_SIZE == 16)
- ,
- 0.590043 * ray_dir.y * (3.0f * ray_dir2.x - ray_dir2.y),
- 2.890611 * ray_dir.y * ray_dir.x * ray_dir.z,
- 0.646360 * ray_dir.y * (-1.0f + 5.0f * ray_dir2.z),
- 0.373176 * (5.0f * ray_dir2.z * ray_dir.z - 3.0f * ray_dir.z),
- 0.457045 * ray_dir.x * (-1.0f + 5.0f * ray_dir2.z),
- 1.445305 * (ray_dir2.x - ray_dir2.y) * ray_dir.z,
- 0.590043 * ray_dir.x * (ray_dir2.x - 3.0f * ray_dir2.y)
+ SH_ACCUM(9, 0.590043 * ray_dir.y * (3.0f * ray_dir2.x - ray_dir2.y));
+ SH_ACCUM(10, 2.890611 * ray_dir.y * ray_dir.x * ray_dir.z);
+ SH_ACCUM(11, 0.646360 * ray_dir.y * (-1.0f + 5.0f * ray_dir2.z));
+ SH_ACCUM(12, 0.373176 * (5.0f * ray_dir2.z * ray_dir.z - 3.0f * ray_dir.z));
+ SH_ACCUM(13, 0.457045 * ray_dir.x * (-1.0f + 5.0f * ray_dir2.z));
+ SH_ACCUM(14, 1.445305 * (ray_dir2.x - ray_dir2.y) * ray_dir.z);
+ SH_ACCUM(15, 0.590043 * ray_dir.x * (ray_dir2.x - 3.0f * ray_dir2.y));
#endif
- );
-
- for (uint j = 0; j < SH_SIZE; j++) {
- probe_sh_accum[j] += light * c[j];
- }
}
for (uint i = 0; i < SH_SIZE; i++) {
@@ -312,7 +303,7 @@ void main() {
ivec3 prev_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(params.history_index));
ivec2 average_pos = prev_pos.xy;
- vec4 value = probe_sh_accum[i] * 4.0 / float(params.ray_count);
+ vec4 value = vec4(sh_accum[probe_index].c[i * 3 + 0], sh_accum[probe_index].c[i * 3 + 1], sh_accum[probe_index].c[i * 3 + 2], 1.0) * 4.0 / float(params.ray_count);
ivec4 ivalue = clamp(ivec4(value * float(1 << HISTORY_BITS)), -32768, 32767); //clamp to 16 bits, so higher values don't break average
@@ -344,37 +335,11 @@ void main() {
ivec2 oct_pos = (pos / OCT_SIZE) * (OCT_SIZE + 2) + ivec2(1);
ivec2 local_pos = pos % OCT_SIZE;
- //fill the spherical harmonic
- vec4 sh[SH_SIZE];
-
- for (uint i = 0; i < SH_SIZE; i++) {
- // store in history texture
- ivec2 average_pos = sh_pos + ivec2(0, i);
- ivec4 average = imageLoad(lightprobe_average_texture, average_pos);
-
- sh[i] = (vec4(average) / float(params.history_size)) / float(1 << HISTORY_BITS);
- }
-
//compute the octahedral normal for this texel
vec3 normal = octahedron_encode(vec2(local_pos) / float(OCT_SIZE));
- /*
+
// read the spherical harmonic
- const float c1 = 0.429043;
- const float c2 = 0.511664;
- const float c3 = 0.743125;
- const float c4 = 0.886227;
- const float c5 = 0.247708;
- vec4 light = (c1 * sh[8] * (normal.x * normal.x - normal.y * normal.y) +
- c3 * sh[6] * normal.z * normal.z +
- c4 * sh[0] -
- c5 * sh[6] +
- 2.0 * c1 * sh[4] * normal.x * normal.y +
- 2.0 * c1 * sh[7] * normal.x * normal.z +
- 2.0 * c1 * sh[5] * normal.y * normal.z +
- 2.0 * c2 * sh[3] * normal.x +
- 2.0 * c2 * sh[1] * normal.y +
- 2.0 * c2 * sh[2] * normal.z);
-*/
+
vec3 normal2 = normal * normal;
float c[SH_SIZE] = float[](
@@ -426,7 +391,14 @@ void main() {
vec3 radiance = vec3(0.0);
for (uint i = 0; i < SH_SIZE; i++) {
- vec3 m = sh[i].rgb * c[i] * 4.0;
+ // store in history texture
+ ivec2 average_pos = sh_pos + ivec2(0, i);
+ ivec4 average = imageLoad(lightprobe_average_texture, average_pos);
+
+ vec4 sh = (vec4(average) / float(params.history_size)) / float(1 << HISTORY_BITS);
+
+ vec3 m = sh.rgb * c[i] * 4.0;
+
irradiance += m * l_mult[i];
radiance += m;
}
@@ -515,13 +487,15 @@ void main() {
//can't scroll, must look for position in parent cascade
//to global coords
- float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell;
+ float cell_to_probe = float(params.grid_size.x / float(params.probe_axis_size - 1));
+
+ float probe_cell_size = cell_to_probe / cascades.data[params.cascade].to_cell;
vec3 probe_pos = cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size;
//to parent local coords
+ float probe_cell_size_next = cell_to_probe / cascades.data[params.cascade + 1].to_cell;
probe_pos -= cascades.data[params.cascade + 1].offset;
- probe_pos *= cascades.data[params.cascade + 1].to_cell;
- probe_pos = probe_pos * float(params.probe_axis_size - 1) / float(params.grid_size.x);
+ probe_pos /= probe_cell_size_next;
ivec3 probe_posi = ivec3(probe_pos);
//add up all light, no need to use occlusion here, since occlusion will do its work afterwards
@@ -574,20 +548,28 @@ void main() {
}
} else {
- // clear and let it re-raytrace, only for the last cascade, which happens very un-often
- //scroll
+ //scroll at the edge of the highest cascade, just copy what is there,
+ //since its the closest we have anyway
+
for (uint j = 0; j < params.history_size; j++) {
+ ivec2 tex_pos;
+ tex_pos = probe_cell.xy;
+ tex_pos.x += probe_cell.z * int(params.probe_axis_size);
+
for (int i = 0; i < SH_SIZE; i++) {
// copy from history texture
+ ivec3 src_pos = ivec3(tex_pos.x, tex_pos.y * SH_SIZE + i, int(j));
ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j));
- imageStore(lightprobe_history_scroll_texture, dst_pos, ivec4(0));
+ ivec4 value = imageLoad(lightprobe_history_texture, dst_pos);
+ imageStore(lightprobe_history_scroll_texture, dst_pos, value);
}
}
for (int i = 0; i < SH_SIZE; i++) {
// copy from average texture
- ivec2 dst_pos = ivec2(pos.x, pos.y * SH_SIZE + i);
- imageStore(lightprobe_average_scroll_texture, dst_pos, ivec4(0));
+ ivec2 spos = ivec2(pos.x, pos.y * SH_SIZE + i);
+ ivec4 average = imageLoad(lightprobe_average_texture, spos);
+ imageStore(lightprobe_average_scroll_texture, spos, average);
}
}
diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/ssao.glsl
index 315ef8fa13..231f8f91ec 100644
--- a/servers/rendering/renderer_rd/shaders/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssao.glsl
@@ -88,7 +88,7 @@ counter;
layout(rg8, set = 2, binding = 0) uniform restrict writeonly image2D dest_image;
// This push_constant is full - 128 bytes - if you need to add more data, consider adding to the uniform buffer instead
-layout(push_constant, binding = 1, std430) uniform Params {
+layout(push_constant, binding = 3, std430) uniform Params {
ivec2 screen_size;
int pass;
int quality;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
index 13b162f0c9..aa32809a06 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
@@ -4,6 +4,15 @@
VERSION_DEFINES
+/* Do not use subgroups here, seems there is not much advantage and causes glitches
+#extension GL_KHR_shader_subgroup_ballot: enable
+#extension GL_KHR_shader_subgroup_arithmetic: enable
+
+#if defined(GL_KHR_shader_subgroup_ballot) && defined(GL_KHR_shader_subgroup_arithmetic)
+#define USE_SUBGROUPS
+#endif
+*/
+
#if defined(MODE_FOG) || defined(MODE_FILTER)
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
@@ -23,22 +32,25 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
layout(set = 0, binding = 1) uniform texture2D shadow_atlas;
layout(set = 0, binding = 2) uniform texture2D directional_shadow_atlas;
-layout(set = 0, binding = 3, std430) restrict readonly buffer Lights {
+layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
LightData data[];
}
-lights;
+omni_lights;
-layout(set = 0, binding = 4, std140) uniform DirectionalLights {
+layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+ LightData data[];
+}
+spot_lights;
+
+layout(set = 0, binding = 5, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
-layout(set = 0, binding = 5) uniform utexture3D cluster_texture;
-
-layout(set = 0, binding = 6, std430) restrict readonly buffer ClusterData {
- uint indices[];
+layout(set = 0, binding = 6, std430) buffer restrict readonly ClusterBuffer {
+ uint data[];
}
-cluster_data;
+cluster_buffer;
layout(set = 0, binding = 7) uniform sampler linear_sampler;
@@ -132,7 +144,7 @@ layout(set = 1, binding = 2) uniform texture3D sdfgi_occlusion_texture;
#endif //SDFGI
-layout(push_constant, binding = 0, std430) uniform Params {
+layout(set = 0, binding = 14, std140) uniform Params {
vec2 fog_frustum_size_begin;
vec2 fog_frustum_size_end;
@@ -150,7 +162,14 @@ layout(push_constant, binding = 0, std430) uniform Params {
float detail_spread;
float gi_inject;
uint max_gi_probes;
- uint pad;
+ uint cluster_type_size;
+
+ vec2 screen_size;
+ uint cluster_shift;
+ uint cluster_width;
+
+ uvec3 cluster_pad;
+ uint max_cluster_element_count_div_32;
mat3x4 cam_rotation;
}
@@ -169,6 +188,31 @@ vec3 hash3f(uvec3 x) {
return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));
}
+float get_omni_attenuation(float distance, float inv_range, float decay) {
+ float nd = distance * inv_range;
+ nd *= nd;
+ nd *= nd; // nd^4
+ nd = max(1.0 - nd, 0.0);
+ nd *= nd; // nd^2
+ return nd * pow(max(distance, 0.0001), -decay);
+}
+
+void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
+ uint item_min_max = cluster_buffer.data[p_offset];
+ item_min = item_min_max & 0xFFFF;
+ item_max = item_min_max >> 16;
+ ;
+
+ item_from = item_min >> 5;
+ item_to = (item_max == 0) ? 0 : ((item_max - 1) >> 5) + 1; //side effect of how it is stored, as item_max 0 means no elements
+}
+
+uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
+ int local_min = clamp(int(z_min) - int(i) * 32, 0, 31);
+ int mask_width = min(int(z_max) - int(z_min), 32 - local_min);
+ return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
+}
+
void main() {
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
@@ -184,6 +228,12 @@ void main() {
//posf += mix(vec3(0.0),vec3(1.0),0.3) * hash3f(uvec3(pos)) * 2.0 - 1.0;
vec3 fog_unit_pos = posf * fog_cell_size + fog_cell_size * 0.5; //center of voxels
+
+ uvec2 screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
+ uvec2 cluster_pos = screen_pos >> params.cluster_shift;
+ uint cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
+ //positions in screen are too spread apart, no hopes for optimizing with subgroups
+
fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);
vec3 view_pos;
@@ -191,6 +241,8 @@ void main() {
view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
+ uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));
+
vec3 total_light = params.light_color;
float total_density = params.base_density;
@@ -257,108 +309,160 @@ void main() {
//compute lights from cluster
- vec3 cluster_pos;
- cluster_pos.xy = fog_unit_pos.xy;
- cluster_pos.z = clamp((abs(view_pos.z) - params.z_near) / (params.z_far - params.z_near), 0.0, 1.0);
+ { //omni lights
- uvec4 cluster_cell = texture(usampler3D(cluster_texture, linear_sampler), cluster_pos);
+ uint cluster_omni_offset = cluster_offset;
- uint omni_light_count = cluster_cell.x >> CLUSTER_COUNTER_SHIFT;
- uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK;
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
- for (uint i = 0; i < omni_light_count; i++) {
- uint light_index = cluster_data.indices[omni_light_pointer + i];
+ cluster_get_item_range(cluster_omni_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
- vec3 light_pos = lights.data[i].position;
- float d = distance(lights.data[i].position, view_pos) * lights.data[i].inv_radius;
- vec3 shadow_attenuation = vec3(1.0);
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
- if (d < 1.0) {
- vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);
- vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular);
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_omni_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
+
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
+ uint light_index = 32 * i + bit;
- float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x);
+ //if (!bool(omni_omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ // continue; //not masked
+ //}
- vec3 light = attenuation_energy.y * color_specular.rgb / M_PI;
+ vec3 light_pos = omni_lights.data[light_index].position;
+ float d = distance(omni_lights.data[light_index].position, view_pos);
+ float shadow_attenuation = 1.0;
- vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[i].shadow_color_enabled);
+ if (d * omni_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
- if (shadow_color_enabled.a > 0.5) {
- //has shadow
- vec4 v = vec4(view_pos, 1.0);
+ vec3 light = omni_lights.data[light_index].color / M_PI;
- vec4 splane = (lights.data[i].shadow_matrix * v);
- float shadow_len = length(splane.xyz); //need to remember shadow len from here
+ if (omni_lights.data[light_index].shadow_enabled) {
+ //has shadow
+ vec4 v = vec4(view_pos, 1.0);
- splane.xyz = normalize(splane.xyz);
- vec4 clamp_rect = lights.data[i].atlas_rect;
+ vec4 splane = (omni_lights.data[light_index].shadow_matrix * v);
+ float shadow_len = length(splane.xyz); //need to remember shadow len from here
- if (splane.z >= 0.0) {
- splane.z += 1.0;
+ splane.xyz = normalize(splane.xyz);
+ vec4 clamp_rect = omni_lights.data[light_index].atlas_rect;
- clamp_rect.y += clamp_rect.w;
+ if (splane.z >= 0.0) {
+ splane.z += 1.0;
- } else {
- splane.z = 1.0 - splane.z;
- }
+ clamp_rect.y += clamp_rect.w;
+
+ } else {
+ splane.z = 1.0 - splane.z;
+ }
- splane.xy /= splane.z;
+ splane.xy /= splane.z;
- splane.xy = splane.xy * 0.5 + 0.5;
- splane.z = shadow_len * lights.data[i].inv_radius;
- splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
- splane.w = 1.0; //needed? i think it should be 1 already
+ splane.xy = splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * omni_lights.data[light_index].inv_radius;
+ splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
+ splane.w = 1.0; //needed? i think it should be 1 already
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
- float shadow = exp(min(0.0, (depth - splane.z)) / lights.data[i].inv_radius * lights.data[i].shadow_volumetric_fog_fade);
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
- shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+ shadow_attenuation = exp(min(0.0, (depth - splane.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
+ total_light += light * attenuation * shadow_attenuation;
+ }
}
- total_light += light * attenuation * shadow_attenuation;
}
}
- uint spot_light_count = cluster_cell.y >> CLUSTER_COUNTER_SHIFT;
- uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK;
+ { //spot lights
- for (uint i = 0; i < spot_light_count; i++) {
- uint light_index = cluster_data.indices[spot_light_pointer + i];
+ uint cluster_spot_offset = cluster_offset + params.cluster_type_size;
- vec3 light_pos = lights.data[i].position;
- vec3 light_rel_vec = lights.data[i].position - view_pos;
- float d = length(light_rel_vec) * lights.data[i].inv_radius;
- vec3 shadow_attenuation = vec3(1.0);
+ uint item_min;
+ uint item_max;
+ uint item_from;
+ uint item_to;
+
+ cluster_get_item_range(cluster_spot_offset + params.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+
+#ifdef USE_SUBGROUPS
+ item_from = subgroupBroadcastFirst(subgroupMin(item_from));
+ item_to = subgroupBroadcastFirst(subgroupMax(item_to));
+#endif
+
+ for (uint i = item_from; i < item_to; i++) {
+ uint mask = cluster_buffer.data[cluster_spot_offset + i];
+ mask &= cluster_get_range_clip_mask(i, item_min, item_max);
+#ifdef USE_SUBGROUPS
+ uint merged_mask = subgroupBroadcastFirst(subgroupOr(mask));
+#else
+ uint merged_mask = mask;
+#endif
- if (d < 1.0) {
- vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);
- vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular);
+ while (merged_mask != 0) {
+ uint bit = findMSB(merged_mask);
+ merged_mask &= ~(1 << bit);
+#ifdef USE_SUBGROUPS
+ if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ continue;
+ }
+#endif
- float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x);
+ //if (!bool(omni_lights.data[light_index].mask & draw_call.layer_mask)) {
+ // continue; //not masked
+ //}
- vec3 spot_dir = lights.data[i].direction;
- vec2 spot_att_angle = unpackHalf2x16(lights.data[i].cone_attenuation_angle);
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
- attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
+ uint light_index = 32 * i + bit;
- vec3 light = attenuation_energy.y * color_specular.rgb / M_PI;
+ vec3 light_pos = omni_lights.data[light_index].position;
+ vec3 light_rel_vec = omni_lights.data[light_index].position - view_pos;
+ float d = length(light_rel_vec);
+ float shadow_attenuation = 1.0;
- vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[i].shadow_color_enabled);
+ if (d * omni_lights.data[light_index].inv_radius < 1.0) {
+ float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
- if (shadow_color_enabled.a > 0.5) {
- //has shadow
- vec4 v = vec4(view_pos, 1.0);
+ vec3 spot_dir = omni_lights.data[light_index].direction;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), omni_lights.data[light_index].cone_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - omni_lights.data[light_index].cone_angle));
+ attenuation *= 1.0 - pow(spot_rim, omni_lights.data[light_index].cone_attenuation);
- vec4 splane = (lights.data[i].shadow_matrix * v);
- splane /= splane.w;
+ vec3 light = omni_lights.data[light_index].color / M_PI;
- float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
- float shadow = exp(min(0.0, (depth - splane.z)) / lights.data[i].inv_radius * lights.data[i].shadow_volumetric_fog_fade);
+ if (omni_lights.data[light_index].shadow_enabled) {
+ //has shadow
+ vec4 v = vec4(view_pos, 1.0);
- shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
- }
+ vec4 splane = (omni_lights.data[light_index].shadow_matrix * v);
+ splane /= splane.w;
- total_light += light * attenuation * shadow_attenuation;
+ float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
+
+ shadow_attenuation = exp(min(0.0, (depth - splane.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ }
+
+ total_light += light * attenuation * shadow_attenuation;
+ }
+ }
}
}
diff --git a/servers/rendering/renderer_scene.cpp b/servers/rendering/renderer_scene.cpp
index 1da8fc59de..dd544d4f3f 100644
--- a/servers/rendering/renderer_scene.cpp
+++ b/servers/rendering/renderer_scene.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 22af720ae7..d92642886c 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -95,7 +95,7 @@ public:
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0;
- virtual void directional_shadow_atlas_set_size(int p_size) = 0;
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) = 0;
/* SKY API */
@@ -140,6 +140,7 @@ public:
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
+ virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
@@ -172,7 +173,7 @@ public:
virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
virtual RID shadow_atlas_create() = 0;
- virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0;
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = false) = 0;
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
/* Render Buffers */
@@ -180,6 +181,8 @@ public:
virtual RID render_buffers_create() = 0;
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
+ virtual void gi_set_use_half_resolution(bool p_enable) = 0;
+
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 6ece46645c..e1f179aa3b 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -135,7 +135,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
}
- } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -147,7 +147,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;
}
- } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -174,7 +174,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
}
- } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -195,7 +195,8 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
gi_probe->lights.insert(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
- RSG::storage->particles_add_collision(A->base, B);
+ InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
+ RSG::storage->particles_add_collision(A->base, collision->instance);
}
}
@@ -225,7 +226,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
}
- } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -237,7 +238,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
idata.flags |= InstanceData::FLAG_GEOM_REFLECTION_DIRTY;
}
- } else if (self->pair_volumes_to_mesh && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && B->base_type == RS::INSTANCE_DECAL && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -255,7 +256,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
if (A->dynamic_gi) {
geom->lightmap_captures.erase(B);
- if (geom->lightmap_captures.empty() && A->scenario && A->array_index >= 0) {
+ if (geom->lightmap_captures.is_empty() && A->scenario && A->array_index >= 0) {
InstanceData &idata = A->scenario->instance_data[A->array_index];
idata.flags &= ~uint32_t(InstanceData::FLAG_LIGHTMAP_CAPTURE);
}
@@ -264,7 +265,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
((RendererSceneCull *)self)->_instance_queue_update(A, false, false); //need to update capture
}
- } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
+ } else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_GI_PROBE) && B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
@@ -284,7 +285,8 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(B->base_data);
gi_probe->lights.erase(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
- RSG::storage->particles_remove_collision(A->base, B);
+ InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
+ RSG::storage->particles_remove_collision(A->base, collision->instance);
}
}
@@ -386,6 +388,9 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
p_instance->mesh_instance = RID();
}
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance);
+
if (p_instance->scenario && p_instance->array_index >= 0) {
InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
if (p_instance->mesh_instance.is_valid()) {
@@ -421,10 +426,17 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
switch (instance->base_type) {
+ case RS::INSTANCE_MESH:
+ case RS::INSTANCE_MULTIMESH:
+ case RS::INSTANCE_IMMEDIATE:
+ case RS::INSTANCE_PARTICLES: {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_free(geom->geometry_instance);
+ } break;
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (scenario && instance->visible && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
scenario->dynamic_lights.erase(light->instance);
}
@@ -439,6 +451,10 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
scene_render->free(light->instance);
} break;
+ case RS::INSTANCE_PARTICLES_COLLISION: {
+ InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
+ RSG::storage->free(collision->instance);
+ } break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
scene_render->free(reflection_probe->instance);
@@ -457,6 +473,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
while (lightmap_data->users.front()) {
instance_geometry_set_lightmap(lightmap_data->users.front()->get()->self, RID(), Rect2(), 0);
}
+ scene_render->free(lightmap_data->instance);
} break;
case RS::INSTANCE_GI_PROBE: {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
@@ -514,8 +531,29 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
+ geom->geometry_instance = scene_render->geometry_instance_create(p_base);
+
+ scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
+ scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
+ scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
+ scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
+ scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
+ scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias);
+ scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light);
+ scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
+ scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+ scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ if (instance->lightmap_sh.size() == 9) {
+ scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
+ }
} break;
+ case RS::INSTANCE_PARTICLES_COLLISION: {
+ InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);
+ collision->instance = RSG::storage->particles_collision_instance_create(p_base);
+ RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
+ instance->base_data = collision;
+ } break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
reflection_probe->owner = instance;
@@ -533,7 +571,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_LIGHTMAP: {
InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
instance->base_data = lightmap_data;
- //lightmap_data->instance = scene_render->lightmap_data_instance_create(p_base);
+ lightmap_data->instance = scene_render->lightmap_instance_create(p_base);
} break;
case RS::INSTANCE_GI_PROBE: {
InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData);
@@ -558,7 +596,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
- RSG::storage->base_update_dependency(p_base, instance);
+ RSG::storage->base_update_dependency(p_base, &instance->dependency_tracker);
}
_instance_queue_update(instance, true, true);
@@ -659,6 +697,11 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
if (instance->scenario && instance->array_index >= 0) {
instance->scenario->instance_data[instance->array_index].layer_mask = p_mask;
}
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask);
+ }
}
void RendererSceneCull::instance_set_transform(RID p_instance, const Transform &p_transform) {
@@ -739,6 +782,22 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
} else if (instance->indexer_id.is_valid()) {
_unpair_instance(instance);
}
+
+ if (instance->base_type == RS::INSTANCE_LIGHT) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
+ if (instance->scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (p_visible) {
+ instance->scenario->dynamic_lights.push_back(light->instance);
+ } else {
+ instance->scenario->dynamic_lights.erase(light->instance);
+ }
+ }
+ }
+
+ if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+ InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
+ RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible);
+ }
}
inline bool is_geometry_instance(RenderingServer::InstanceType p_type) {
@@ -782,12 +841,17 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
if (p_skeleton.is_valid()) {
//update the dependency now, so if cleared, we remove it
- RSG::storage->skeleton_update_dependency(p_skeleton, instance);
+ RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
}
- _instance_update_mesh_instance(instance);
-
_instance_queue_update(instance, true, true);
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ _instance_update_mesh_instance(instance);
+
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton);
+ }
}
void RendererSceneCull::instance_set_exterior(RID p_instance, bool p_enabled) {
@@ -892,6 +956,11 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
}
}
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled);
+ }
+
} break;
case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: {
if (p_enabled == instance->dynamic_gi) {
@@ -907,6 +976,11 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
//once out of octree, can be changed
instance->dynamic_gi = p_enabled;
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled);
+ }
+
} break;
case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: {
instance->redraw_if_visible = p_enabled;
@@ -948,6 +1022,11 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
}
}
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+ }
+
_instance_queue_update(instance, false, true);
}
@@ -957,6 +1036,11 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
instance->material_override = p_material;
_instance_queue_update(instance, false, true);
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material);
+ }
}
void RendererSceneCull::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
@@ -981,9 +1065,17 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
instance->lightmap_uv_scale = p_lightmap_uv_scale;
instance->lightmap_slice_index = p_slice_index;
+ RID lightmap_instance_rid;
+
if (lightmap_instance) {
InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(lightmap_instance->base_data);
lightmap_data->users.insert(instance);
+ lightmap_instance_rid = lightmap_data->instance;
+ }
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
}
}
@@ -992,16 +1084,21 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l
ERR_FAIL_COND(!instance);
instance->lod_bias = p_lod_bias;
+
+ if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias);
+ }
}
void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
- Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
+ Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.find(p_parameter);
if (!E) {
- RendererSceneRender::InstanceBase::InstanceShaderParameter isp;
+ Instance::InstanceShaderParameter isp;
isp.index = -1;
isp.info = PropertyInfo();
isp.value = p_value;
@@ -1042,7 +1139,7 @@ void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instan
const_cast<RendererSceneCull *>(this)->update_dirty_instances();
Vector<StringName> names;
- for (Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
+ for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = instance->instance_shader_parameters.front(); E; E = E->next()) {
names.push_back(E->key());
}
names.sort_custom<StringName::AlphCompare>();
@@ -1064,13 +1161,13 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base);
if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
- if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
p_instance->scenario->dynamic_lights.erase(light->instance);
}
light->bake_mode = bake_mode;
- if (p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
p_instance->scenario->dynamic_lights.push_back(light->instance);
}
}
@@ -1079,9 +1176,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
}
- }
-
- if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
+ } else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
@@ -1090,35 +1185,49 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;
}
- }
-
- if (p_instance->base_type == RS::INSTANCE_DECAL) {
+ } else if (p_instance->base_type == RS::INSTANCE_DECAL) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
- }
+ } else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+ InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);
- if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
+ scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform);
+ } else if (p_instance->base_type == RS::INSTANCE_GI_PROBE) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(p_instance->base_data);
scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform);
- }
-
- if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
+ } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
- }
+ } else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
+ InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);
- if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
//remove materials no longer used and un-own them
if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
heightfield_particle_colliders_update_list.insert(p_instance);
}
+ RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
}
if (p_instance->aabb.has_no_surface()) {
return;
}
+ if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
+ //if this moved, update the captured objects
+ InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);
+ //erase dependencies, since no longer a lightmap
+
+ for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
+ Instance *geom = E->get();
+ _instance_queue_update(geom, true, false);
+ }
+ }
+
+ AABB new_aabb;
+ new_aabb = p_instance->transform.xform(p_instance->aabb);
+ p_instance->transformed_aabb = new_aabb;
+
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
//make sure lights are updated if it casts shadow
@@ -1134,32 +1243,16 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
//affected by lightmap captures, must update capture info!
_update_instance_lightmap_captures(p_instance);
} else {
- if (!p_instance->lightmap_sh.empty()) {
+ if (!p_instance->lightmap_sh.is_empty()) {
p_instance->lightmap_sh.clear(); //don't need SH
p_instance->lightmap_target_sh.clear(); //don't need SH
+ scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr);
}
}
- }
-
- if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
- //if this moved, update the captured objects
- InstanceLightmapData *lightmap_data = static_cast<InstanceLightmapData *>(p_instance->base_data);
- //erase dependencies, since no longer a lightmap
- for (Set<Instance *>::Element *E = lightmap_data->geometries.front(); E; E = E->next()) {
- Instance *geom = E->get();
- _instance_queue_update(geom, true, false);
- }
+ scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
}
- p_instance->mirror = p_instance->transform.basis.determinant() < 0.0;
-
- AABB new_aabb;
-
- new_aabb = p_instance->transform.xform(p_instance->aabb);
-
- p_instance->transformed_aabb = new_aabb;
-
if (p_instance->scenario == nullptr || !p_instance->visible || Math::is_zero_approx(p_instance->transform.basis.determinant())) {
p_instance->prev_transformed_aabb = p_instance->transformed_aabb;
return;
@@ -1195,17 +1288,26 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
idata.flags = p_instance->base_type; //changing it means de-indexing, so this never needs to be changed later
idata.base_rid = p_instance->base;
switch (p_instance->base_type) {
+ case RS::INSTANCE_MESH:
+ case RS::INSTANCE_MULTIMESH:
+ case RS::INSTANCE_IMMEDIATE:
+ case RS::INSTANCE_PARTICLES: {
+ idata.instance_geometry = static_cast<InstanceGeometryData *>(p_instance->base_data)->geometry_instance;
+ } break;
case RS::INSTANCE_LIGHT: {
- idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance;
+ idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id();
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
- idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance;
+ idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id();
} break;
case RS::INSTANCE_DECAL: {
- idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance;
+ idata.instance_data_rid = static_cast<InstanceDecalData *>(p_instance->base_data)->instance.get_id();
+ } break;
+ case RS::INSTANCE_LIGHTMAP: {
+ idata.instance_data_rid = static_cast<InstanceLightmapData *>(p_instance->base_data)->instance.get_id();
} break;
case RS::INSTANCE_GI_PROBE: {
- idata.instance_data_rid = static_cast<InstanceGIProbeData *>(p_instance->base_data)->probe_instance;
+ idata.instance_data_rid = static_cast<InstanceGIProbeData *>(p_instance->base_data)->probe_instance.get_id();
} break;
default: {
}
@@ -1258,10 +1360,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
pair.pair_mask |= 1 << RS::INSTANCE_GI_PROBE;
pair.pair_mask |= 1 << RS::INSTANCE_LIGHTMAP;
- if (pair_volumes_to_mesh) {
- pair.pair_mask |= 1 << RS::INSTANCE_DECAL;
- pair.pair_mask |= 1 << RS::INSTANCE_REFLECTION_PROBE;
- }
+ pair.pair_mask |= geometry_instance_pair_mask;
+
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
} else if (p_instance->base_type == RS::INSTANCE_LIGHT) {
pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;
@@ -1271,7 +1371,10 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
pair.pair_mask |= (1 << RS::INSTANCE_GI_PROBE);
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
}
- } else if (pair_volumes_to_mesh && (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_DECAL)) {
+ } 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];
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
@@ -1325,10 +1428,12 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
p_instance->array_index = -1;
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
// Clear these now because the InstanceData containing the dirty flags is gone
- p_instance->light_instances.clear();
- p_instance->reflection_probe_instances.clear();
- //p_instance->decal_instances.clear(); will implement later
- p_instance->gi_probe_instances.clear();
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+
+ scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0);
+ scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
+ scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
+ scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, nullptr, 0);
}
}
@@ -1486,6 +1591,8 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
}
}
}
+
+ scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr());
}
void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
@@ -1674,10 +1781,10 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
real_t unit = radius * 2.0 / texture_size;
- x_max_cam = Math::stepify(x_max_cam, unit);
- x_min_cam = Math::stepify(x_min_cam, unit);
- y_max_cam = Math::stepify(y_max_cam, unit);
- y_min_cam = Math::stepify(y_min_cam, unit);
+ x_max_cam = Math::snapped(x_max_cam, unit);
+ x_min_cam = Math::snapped(x_min_cam, unit);
+ y_max_cam = Math::snapped(y_max_cam, unit);
+ y_min_cam = Math::snapped(y_min_cam, unit);
}
}
@@ -1849,7 +1956,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
}
- geometry_instances_to_shadow_render.push_back(instance);
+ geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
RSG::storage->update_mesh_instances();
@@ -1922,7 +2029,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
}
- geometry_instances_to_shadow_render.push_back(instance);
+ geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
RSG::storage->update_mesh_instances();
@@ -1980,7 +2087,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
- geometry_instances_to_shadow_render.push_back(instance);
+ geometry_instances_to_shadow_render.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
RSG::storage->update_mesh_instances();
@@ -2128,6 +2235,222 @@ void RendererSceneCull::render_camera(RID p_render_buffers, Ref<XRInterface> &p_
_render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1, p_screen_lod_threshold);
};
+void RendererSceneCull::_frustum_cull_threaded(uint32_t p_thread, FrustumCullData *cull_data) {
+ uint32_t cull_total = cull_data->scenario->instance_data.size();
+ uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t cull_from = p_thread * cull_total / total_threads;
+ uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);
+
+ _frustum_cull(*cull_data, frustum_cull_result_threads[p_thread], cull_from, cull_to);
+}
+
+void RendererSceneCull::_frustum_cull(FrustumCullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
+ uint64_t frame_number = RSG::rasterizer->get_frame_number();
+ float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
+
+ uint32_t sdfgi_last_light_index = 0xFFFFFFFF;
+ uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;
+
+ RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
+
+ for (uint64_t i = p_from; i < p_to; i++) {
+ bool mesh_visible = false;
+
+ if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->frustum)) {
+ InstanceData &idata = cull_data.scenario->instance_data[i];
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+
+ if ((cull_data.visible_layers & idata.layer_mask) == 0) {
+ //failure
+ } else if (base_type == RS::INSTANCE_LIGHT) {
+ cull_result.lights.push_back(idata.instance);
+ cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
+ if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
+ scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
+ }
+
+ } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
+ if (cull_data.render_reflection_probe != idata.instance) {
+ //avoid entering The Matrix
+
+ if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
+ cull_data.cull->lock.lock();
+ if (!reflection_probe->update_list.in_list()) {
+ reflection_probe->render_step = 0;
+ reflection_probe_render_list.add_last(&reflection_probe->update_list);
+ }
+ cull_data.cull->lock.unlock();
+
+ idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
+ }
+
+ if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
+ cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));
+ }
+ }
+ } else if (base_type == RS::INSTANCE_DECAL) {
+ cull_result.decals.push_back(RID::from_uint64(idata.instance_data_rid));
+
+ } else if (base_type == RS::INSTANCE_GI_PROBE) {
+ InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(idata.instance->base_data);
+ cull_data.cull->lock.lock();
+ if (!gi_probe->update_element.in_list()) {
+ gi_probe_update_list.add(&gi_probe->update_element);
+ }
+ cull_data.cull->lock.unlock();
+ cull_result.gi_probes.push_back(RID::from_uint64(idata.instance_data_rid));
+
+ } else if (base_type == RS::INSTANCE_LIGHTMAP) {
+ cull_result.gi_probes.push_back(RID::from_uint64(idata.instance_data_rid));
+ } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
+ bool keep = true;
+
+ if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {
+ RenderingServerDefault::redraw_request();
+ }
+
+ if (base_type == RS::INSTANCE_MESH) {
+ mesh_visible = true;
+ } else if (base_type == RS::INSTANCE_PARTICLES) {
+ //particles visible? process them
+ if (RSG::storage->particles_is_inactive(idata.base_rid)) {
+ //but if nothing is going on, don't do it.
+ keep = false;
+ } else {
+ cull_data.cull->lock.lock();
+ RSG::storage->particles_request_process(idata.base_rid);
+ cull_data.cull->lock.unlock();
+ RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized());
+ //particles visible? request redraw
+ RenderingServerDefault::redraw_request();
+ }
+ }
+
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
+
+ for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+ instance_pair_buffer[idx++] = light->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
+ }
+
+ scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
+ }
+
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
+
+ for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+
+ instance_pair_buffer[idx++] = reflection_probe->instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
+ }
+
+ scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
+ }
+
+ if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
+ //InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ //todo for GLES3
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
+ /*for (Set<Instance *>::Element *E = geom->dec.front(); E; E = E->next()) {
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
+
+ instance_pair_buffer[idx++] = reflection_probe->instance;
+ if (idx==MAX_INSTANCE_PAIRS) {
+ break;
+ }
+ }*/
+ //scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, light_instances, idx);
+ }
+
+ if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ uint32_t idx = 0;
+ for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
+ InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
+
+ instance_pair_buffer[idx++] = gi_probe->probe_instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
+ }
+
+ scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
+ }
+
+ if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.is_empty() && !idata.instance->lightmap_sh.is_empty()) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
+ Color *sh = idata.instance->lightmap_sh.ptrw();
+ const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
+ for (uint32_t j = 0; j < 9; j++) {
+ sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
+ }
+ scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
+ idata.instance->last_frame_pass = frame_number;
+ }
+
+ if (keep) {
+ cull_result.geometry_instances.push_back(idata.instance_geometry);
+ }
+ }
+ }
+
+ for (uint32_t j = 0; j < cull_data.cull->shadow_count; j++) {
+ for (uint32_t k = 0; k < cull_data.cull->shadows[j].cascade_count; k++) {
+ if (cull_data.scenario->instance_aabbs[i].in_frustum(cull_data.cull->shadows[j].cascades[k].frustum)) {
+ InstanceData &idata = cull_data.scenario->instance_data[i];
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+
+ if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
+ cull_result.directional_shadows[j].cascade_geometry_instances[k].push_back(idata.instance_geometry);
+ mesh_visible = true;
+ }
+ }
+ }
+ }
+
+ for (uint32_t j = 0; j < cull_data.cull->sdfgi.region_count; j++) {
+ if (cull_data.scenario->instance_aabbs[i].in_aabb(cull_data.cull->sdfgi.region_aabb[j])) {
+ InstanceData &idata = cull_data.scenario->instance_data[i];
+ uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+
+ if (base_type == RS::INSTANCE_LIGHT) {
+ InstanceLightData *instance_light = (InstanceLightData *)idata.instance->base_data;
+ if (instance_light->bake_mode == RS::LIGHT_BAKE_STATIC && cull_data.cull->sdfgi.region_cascade[j] <= instance_light->max_sdfgi_cascade) {
+ if (sdfgi_last_light_index != i || sdfgi_last_light_cascade != cull_data.cull->sdfgi.region_cascade[j]) {
+ sdfgi_last_light_index = i;
+ sdfgi_last_light_cascade = cull_data.cull->sdfgi.region_cascade[j];
+ cull_result.sdfgi_cascade_lights[sdfgi_last_light_cascade].push_back(instance_light->instance);
+ }
+ }
+ } else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) {
+ cull_result.sdfgi_region_geometry_instances[j].push_back(idata.instance_geometry);
+ mesh_visible = true;
+ }
+ }
+ }
+ }
+
+ if (mesh_visible && cull_data.scenario->instance_data[i].flags & InstanceData::FLAG_USES_MESH_INSTANCE) {
+ cull_result.mesh_instances.push_back(cull_data.scenario->instance_data[i].instance->mesh_instance);
+ }
+ }
+}
+
void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows) {
// Note, in stereo rendering:
// - p_cam_transform will be a transform in the middle of our two eyes
@@ -2153,9 +2476,6 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized());
- uint64_t frame_number = RSG::rasterizer->get_frame_number();
- float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
-
/* STEP 2 - CULL */
cull.frustum = Frustum(planes);
@@ -2163,13 +2483,6 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
Vector<RID> directional_lights;
// directional lights
{
- //reset shadows
- for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
- for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
- cull.shadows[i].cascades[j].cull_result.clear();
- }
- }
-
cull.shadow_count = 0;
Vector<Instance *> lights_with_shadow;
@@ -2206,18 +2519,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
{ //sdfgi
cull.sdfgi.region_count = 0;
- for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
- cull.sdfgi.region_cull_result[i].clear();
- }
-
- for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
- cull.sdfgi.cascade_lights[i].clear();
- }
-
if (p_render_buffers.is_valid()) {
- for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
- cull.sdfgi.cascade_lights[i].clear();
- }
cull.sdfgi.cascade_light_count = 0;
uint32_t prev_cascade = 0xFFFFFFFF;
@@ -2239,209 +2541,53 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
- {
- //pre-clear results
- geometry_instances_to_render.clear();
- light_cull_result.clear();
- lightmap_cull_result.clear();
- reflection_probe_instance_cull_result.clear();
- light_instance_cull_result.clear();
- gi_probe_instance_cull_result.clear();
- lightmap_cull_result.clear();
- decal_instance_cull_result.clear();
- mesh_instance_cull_result.clear();
- }
+ frustum_cull_result.clear();
{
- uint64_t cull_count = scenario->instance_data.size();
- uint32_t sdfgi_last_light_index = 0xFFFFFFFF;
- uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;
-
- for (uint64_t i = 0; i < cull_count; i++) {
- bool mesh_visible = false;
-
- if (scenario->instance_aabbs[i].in_frustum(cull.frustum)) {
- InstanceData &idata = scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
-
- if ((p_visible_layers & idata.layer_mask) == 0) {
- //failure
- } else if (base_type == RS::INSTANCE_LIGHT) {
- light_cull_result.push_back(idata.instance);
- light_instance_cull_result.push_back(idata.instance_data_rid);
- if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
- scene_render->light_instance_mark_visible(idata.instance_data_rid); //mark it visible for shadow allocation later
- }
-
- } else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
- if (render_reflection_probe != idata.instance) {
- //avoid entering The Matrix
-
- if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(idata.instance_data_rid)) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
- cull.lock.lock();
- if (!reflection_probe->update_list.in_list()) {
- reflection_probe->render_step = 0;
- reflection_probe_render_list.add_last(&reflection_probe->update_list);
- }
- cull.lock.unlock();
-
- idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
- }
-
- if (scene_render->reflection_probe_instance_has_reflection(idata.instance_data_rid)) {
- reflection_probe_instance_cull_result.push_back(idata.instance_data_rid);
- }
- }
- } else if (base_type == RS::INSTANCE_DECAL) {
- decal_instance_cull_result.push_back(idata.instance_data_rid);
-
- } else if (base_type == RS::INSTANCE_GI_PROBE) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(idata.instance->base_data);
- cull.lock.lock();
- if (!gi_probe->update_element.in_list()) {
- gi_probe_update_list.add(&gi_probe->update_element);
- }
- cull.lock.unlock();
- gi_probe_instance_cull_result.push_back(idata.instance_data_rid);
-
- } else if (base_type == RS::INSTANCE_LIGHTMAP) {
- lightmap_cull_result.push_back(idata.instance);
- } else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
- bool keep = true;
-
- if (idata.flags & InstanceData::FLAG_REDRAW_IF_VISIBLE) {
- RenderingServerDefault::redraw_request();
- }
-
- if (base_type == RS::INSTANCE_MESH) {
- mesh_visible = true;
- } else if (base_type == RS::INSTANCE_PARTICLES) {
- //particles visible? process them
- if (RSG::storage->particles_is_inactive(idata.base_rid)) {
- //but if nothing is going on, don't do it.
- keep = false;
- } else {
- cull.lock.lock();
- RSG::storage->particles_request_process(idata.base_rid);
- cull.lock.unlock();
- RSG::storage->particles_set_view_axis(idata.base_rid, -p_cam_transform.basis.get_axis(2).normalized());
- //particles visible? request redraw
- RenderingServerDefault::redraw_request();
- }
- }
-
- if (pair_volumes_to_mesh && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- int l = 0;
- //only called when lights AABB enter/exit this geometry
- idata.instance->light_instances.resize(geom->lights.size());
-
- for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
- InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
-
- idata.instance->light_instances.write[l++] = light->instance;
- }
-
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
- }
-
- if (pair_volumes_to_mesh && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- int l = 0;
- //only called when reflection probe AABB enter/exit this geometry
- idata.instance->reflection_probe_instances.resize(geom->reflection_probes.size());
-
- for (Set<Instance *>::Element *E = geom->reflection_probes.front(); E; E = E->next()) {
- InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
-
- idata.instance->reflection_probe_instances.write[l++] = reflection_probe->instance;
- }
-
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
- }
-
- if (pair_volumes_to_mesh && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
- //InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- //todo for GLES3
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
- }
-
- if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) {
- InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- int l = 0;
- //only called when reflection probe AABB enter/exit this geometry
- idata.instance->gi_probe_instances.resize(geom->gi_probes.size());
-
- for (Set<Instance *>::Element *E = geom->gi_probes.front(); E; E = E->next()) {
- InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(E->get()->base_data);
-
- idata.instance->gi_probe_instances.write[l++] = gi_probe->probe_instance;
- }
-
- idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
- }
-
- if ((idata.flags & InstanceData::FLAG_LIGHTMAP_CAPTURE) && idata.instance->last_frame_pass != frame_number && !idata.instance->lightmap_target_sh.empty() && !idata.instance->lightmap_sh.empty()) {
- Color *sh = idata.instance->lightmap_sh.ptrw();
- const Color *target_sh = idata.instance->lightmap_target_sh.ptr();
- for (uint32_t j = 0; j < 9; j++) {
- sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
- }
- idata.instance->last_frame_pass = frame_number;
- }
-
- if (keep) {
- geometry_instances_to_render.push_back(idata.instance);
- }
- }
- }
-
- for (uint32_t j = 0; j < cull.shadow_count; j++) {
- for (uint32_t k = 0; k < cull.shadows[j].cascade_count; k++) {
- if (scenario->instance_aabbs[i].in_frustum(cull.shadows[j].cascades[k].frustum)) {
- InstanceData &idata = scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
-
- if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && idata.flags & InstanceData::FLAG_CAST_SHADOWS) {
- cull.shadows[j].cascades[k].cull_result.push_back(idata.instance);
- mesh_visible = true;
- }
- }
- }
+ uint64_t cull_from = 0;
+ uint64_t cull_to = scenario->instance_data.size();
+
+ FrustumCullData cull_data;
+
+ //prepare for eventual thread usage
+ cull_data.cull = &cull;
+ cull_data.scenario = scenario;
+ cull_data.shadow_atlas = p_shadow_atlas;
+ cull_data.cam_transform = p_cam_transform;
+ cull_data.visible_layers = p_visible_layers;
+ cull_data.render_reflection_probe = render_reflection_probe;
+//#define DEBUG_CULL_TIME
+#ifdef DEBUG_CULL_TIME
+ uint64_t time_from = OS::get_singleton()->get_ticks_usec();
+#endif
+ if (cull_to > thread_cull_threshold) {
+ //multiple threads
+ for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
+ frustum_cull_result_threads[i].clear();
}
- for (uint32_t j = 0; j < cull.sdfgi.region_count; j++) {
- if (scenario->instance_aabbs[i].in_aabb(cull.sdfgi.region_aabb[j])) {
- InstanceData &idata = scenario->instance_data[i];
- uint32_t base_type = idata.flags & InstanceData::FLAG_BASE_TYPE_MASK;
+ RendererThreadPool::singleton->thread_work_pool.do_work(frustum_cull_result_threads.size(), this, &RendererSceneCull::_frustum_cull_threaded, &cull_data);
- if (base_type == RS::INSTANCE_LIGHT) {
- InstanceLightData *instance_light = (InstanceLightData *)idata.instance->base_data;
- if (instance_light->bake_mode == RS::LIGHT_BAKE_STATIC && cull.sdfgi.region_cascade[j] <= instance_light->max_sdfgi_cascade) {
- if (sdfgi_last_light_index != i || sdfgi_last_light_cascade != cull.sdfgi.region_cascade[j]) {
- sdfgi_last_light_index = i;
- sdfgi_last_light_cascade = cull.sdfgi.region_cascade[j];
- cull.sdfgi.cascade_lights[sdfgi_last_light_cascade].push_back(instance_light->instance);
- }
- }
- } else if ((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- if (idata.flags & InstanceData::FLAG_USES_BAKED_LIGHT) {
- cull.sdfgi.region_cull_result[j].push_back(idata.instance);
- mesh_visible = true;
- }
- }
- }
+ for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
+ frustum_cull_result.append_from(frustum_cull_result_threads[i]);
}
- if (mesh_visible && scenario->instance_data[i].flags & InstanceData::FLAG_USES_MESH_INSTANCE) {
- mesh_instance_cull_result.push_back(scenario->instance_data[i].instance->mesh_instance);
- }
+ } else {
+ //single threaded
+ _frustum_cull(cull_data, frustum_cull_result, cull_from, cull_to);
}
- if (mesh_instance_cull_result.size()) {
- for (uint64_t i = 0; i < mesh_instance_cull_result.size(); i++) {
- RSG::storage->mesh_instance_check_for_update(mesh_instance_cull_result[i]);
+#ifdef DEBUG_CULL_TIME
+ static float time_avg = 0;
+ static uint32_t time_count = 0;
+ time_avg += double(OS::get_singleton()->get_ticks_usec() - time_from) / 1000.0;
+ time_count++;
+ print_line("time taken: " + rtos(time_avg / time_count));
+#endif
+
+ if (frustum_cull_result.mesh_instances.size()) {
+ for (uint64_t i = 0; i < frustum_cull_result.mesh_instances.size(); i++) {
+ RSG::storage->mesh_instance_check_for_update(frustum_cull_result.mesh_instances[i]);
}
RSG::storage->update_mesh_instances();
}
@@ -2454,7 +2600,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j];
// print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size()));
scene_render->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale);
- scene_render->render_shadow(cull.shadows[i].light_instance, p_shadow_atlas, j, c.cull_result, near_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
+ scene_render->render_shadow(cull.shadows[i].light_instance, p_shadow_atlas, j, frustum_cull_result.directional_shadows[i].cascade_geometry_instances[j], near_plane, p_cam_projection.get_lod_multiplier(), p_screen_lod_threshold);
}
}
@@ -2464,19 +2610,19 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
if (cull.sdfgi.region_count > 0) {
//update regions
for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
- scene_render->render_sdfgi(p_render_buffers, i, cull.sdfgi.region_cull_result[i]);
+ scene_render->render_sdfgi(p_render_buffers, i, frustum_cull_result.sdfgi_region_geometry_instances[i]);
}
//check if static lights were culled
bool static_lights_culled = false;
for (uint32_t i = 0; i < cull.sdfgi.cascade_light_count; i++) {
- if (cull.sdfgi.cascade_lights[i].size()) {
+ if (frustum_cull_result.sdfgi_cascade_lights[i].size()) {
static_lights_culled = true;
break;
}
}
if (static_lights_culled) {
- scene_render->render_sdfgi_static_lights(p_render_buffers, cull.sdfgi.cascade_light_count, cull.sdfgi.cascade_light_index, cull.sdfgi.cascade_lights);
+ scene_render->render_sdfgi_static_lights(p_render_buffers, cull.sdfgi.cascade_light_count, cull.sdfgi.cascade_light_index, frustum_cull_result.sdfgi_cascade_lights);
}
}
@@ -2505,8 +2651,8 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
//SortArray<Instance*,_InstanceLightsort> sorter;
//sorter.sort(light_cull_result,light_cull_count);
- for (uint32_t i = 0; i < (uint32_t)light_cull_result.size(); i++) {
- Instance *ins = light_cull_result[i];
+ for (uint32_t i = 0; i < (uint32_t)frustum_cull_result.lights.size(); i++) {
+ Instance *ins = frustum_cull_result.lights[i];
if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
continue;
@@ -2602,7 +2748,7 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
//append the directional lights to the lights culled
for (int i = 0; i < directional_lights.size(); i++) {
- light_instance_cull_result.push_back(directional_lights[i]);
+ frustum_cull_result.light_instances.push_back(directional_lights[i]);
}
}
@@ -2639,7 +2785,7 @@ void RendererSceneCull::_render_scene(RID p_render_buffers, const Transform p_ca
/* PROCESS GEOMETRY AND DRAW SCENE */
RENDER_TIMESTAMP("Render Scene ");
- scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, geometry_instances_to_render, light_instance_cull_result, reflection_probe_instance_cull_result, gi_probe_instance_cull_result, decal_instance_cull_result, lightmap_cull_result, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
+ scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, frustum_cull_result.geometry_instances, frustum_cull_result.light_instances, frustum_cull_result.reflections, frustum_cull_result.gi_probes, frustum_cull_result.decals, frustum_cull_result.lightmaps, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_lod_threshold);
}
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
@@ -2654,7 +2800,7 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
environment = scenario->fallback_environment;
}
RENDER_TIMESTAMP("Render Empty Scene ");
- scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::InstanceBase *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RendererSceneRender::InstanceBase *>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
+ scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0, 0);
#endif
}
@@ -2929,7 +3075,9 @@ void RendererSceneCull::render_probes() {
update_lights = true;
}
- geometry_instances_to_render.clear();
+ frustum_cull_result.geometry_instances.clear();
+
+ RID instance_pair_buffer[MAX_INSTANCE_PAIRS];
for (Set<Instance *>::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) {
Instance *ins = E->get();
@@ -2939,24 +3087,25 @@ void RendererSceneCull::render_probes() {
InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data;
if (ins->scenario && ins->array_index >= 0 && (ins->scenario->instance_data[ins->array_index].flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY)) {
- //giprobes may be dirty, so update
- int l = 0;
- //only called when reflection probe AABB enter/exit this geometry
- ins->gi_probe_instances.resize(geom->gi_probes.size());
-
+ uint32_t idx = 0;
for (Set<Instance *>::Element *F = geom->gi_probes.front(); F; F = F->next()) {
InstanceGIProbeData *gi_probe2 = static_cast<InstanceGIProbeData *>(F->get()->base_data);
- ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance;
+ instance_pair_buffer[idx++] = gi_probe2->probe_instance;
+ if (idx == MAX_INSTANCE_PAIRS) {
+ break;
+ }
}
+ scene_render->geometry_instance_pair_gi_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+
ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_GI_PROBE_DIRTY);
}
- geometry_instances_to_render.push_back(E->get());
+ frustum_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
- scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, geometry_instances_to_render);
+ scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, frustum_cull_result.geometry_instances);
gi_probe_update_list.remove(gi_probe);
@@ -2971,7 +3120,7 @@ void RendererSceneCull::render_particle_colliders() {
if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
//update heightfield
instance_cull_result.clear();
- geometry_instances_to_render.clear();
+ frustum_cull_result.geometry_instances.clear();
struct CullAABB {
PagedArray<Instance *> *result;
@@ -2992,16 +3141,17 @@ void RendererSceneCull::render_particle_colliders() {
if (!instance || !((1 << instance->base_type) & (RS::INSTANCE_GEOMETRY_MASK & (~(1 << RS::INSTANCE_PARTICLES))))) { //all but particles to avoid self collision
continue;
}
- geometry_instances_to_render.push_back(instance);
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ frustum_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
- scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, geometry_instances_to_render);
+ scene_render->render_particle_collider_heightfield(hfpc->base, hfpc->transform, frustum_cull_result.geometry_instances);
}
heightfield_particle_colliders_update_list.erase(heightfield_particle_colliders_update_list.front());
}
}
-void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material) {
+void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
List<RendererStorage::InstanceShaderParam> plist;
RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
for (List<RendererStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
@@ -3016,7 +3166,7 @@ void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<Str
continue; //first one found always has priority
}
- RendererSceneRender::InstanceBase::InstanceShaderParameter isp;
+ Instance::InstanceShaderParameter isp;
isp.index = E->get().index;
isp.info = E->get().info;
isp.default_value = E->get().default_value;
@@ -3035,14 +3185,14 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->update_dependencies) {
- p_instance->instance_increase_version();
+ p_instance->dependency_tracker.update_begin();
if (p_instance->base.is_valid()) {
- RSG::storage->base_update_dependency(p_instance->base, p_instance);
+ RSG::storage->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);
}
if (p_instance->material_override.is_valid()) {
- RSG::storage->material_update_dependency(p_instance->material_override, p_instance);
+ RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
}
if (p_instance->base_type == RS::INSTANCE_MESH) {
@@ -3059,7 +3209,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
bool can_cast_shadows = true;
bool is_animated = false;
- Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> isparams;
+ Map<StringName, Instance::InstanceShaderParameter> isparams;
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) {
can_cast_shadows = false;
@@ -3094,7 +3244,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- RSG::storage->material_update_dependency(mat, p_instance);
+ RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
@@ -3125,7 +3275,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- RSG::storage->material_update_dependency(mat, p_instance);
+ RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
@@ -3133,7 +3283,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false;
}
- RSG::storage->base_update_dependency(mesh, p_instance);
+ RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker);
}
} else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) {
RID mat = RSG::storage->immediate_get_material(p_instance->base);
@@ -3151,7 +3301,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (mat.is_valid()) {
- RSG::storage->material_update_dependency(mat, p_instance);
+ RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
@@ -3182,7 +3332,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
- RSG::storage->material_update_dependency(mat, p_instance);
+ RSG::storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
}
}
@@ -3210,7 +3360,9 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
if (p_instance->instance_allocated_shader_parameters) {
p_instance->instance_allocated_shader_parameters_offset = RSG::storage->global_variables_instance_allocate(p_instance->self);
- for (Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
+ scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
+
+ for (Map<StringName, Instance::InstanceShaderParameter>::Element *E = p_instance->instance_shader_parameters.front(); E; E = E->next()) {
if (E->get().value.get_type() != Variant::NIL) {
RSG::storage->global_variables_instance_update(p_instance->self, E->get().index, E->get().value);
}
@@ -3218,15 +3370,21 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
} else {
RSG::storage->global_variables_instance_free(p_instance->self);
p_instance->instance_allocated_shader_parameters_offset = -1;
+ scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
}
}
}
if (p_instance->skeleton.is_valid()) {
- RSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance);
+ RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
}
- p_instance->clean_up_dependencies();
+ p_instance->dependency_tracker.update_end();
+
+ if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials);
+ }
}
_instance_update_list.remove(&p_instance->update_item);
@@ -3322,70 +3480,40 @@ TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RI
RendererSceneCull *RendererSceneCull::singleton = nullptr;
+void RendererSceneCull::set_scene_render(RendererSceneRender *p_scene_render) {
+ scene_render = p_scene_render;
+ geometry_instance_pair_mask = scene_render->geometry_instance_get_pair_mask();
+}
+
RendererSceneCull::RendererSceneCull() {
render_pass = 1;
singleton = this;
- pair_volumes_to_mesh = false;
instance_cull_result.set_page_pool(&instance_cull_page_pool);
- mesh_instance_cull_result.set_page_pool(&rid_cull_page_pool);
instance_shadow_cull_result.set_page_pool(&instance_cull_page_pool);
- instance_sdfgi_cull_result.set_page_pool(&instance_cull_page_pool);
- light_cull_result.set_page_pool(&instance_cull_page_pool);
- geometry_instances_to_render.set_page_pool(&base_instance_cull_page_pool);
- geometry_instances_to_shadow_render.set_page_pool(&base_instance_cull_page_pool);
- lightmap_cull_result.set_page_pool(&base_instance_cull_page_pool);
-
- reflection_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
- light_instance_cull_result.set_page_pool(&rid_cull_page_pool);
- gi_probe_instance_cull_result.set_page_pool(&rid_cull_page_pool);
- decal_instance_cull_result.set_page_pool(&rid_cull_page_pool);
-
- for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
- for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
- cull.shadows[i].cascades[j].cull_result.set_page_pool(&base_instance_cull_page_pool);
- }
- }
+ geometry_instances_to_shadow_render.set_page_pool(&geometry_instance_cull_page_pool);
- for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
- cull.sdfgi.region_cull_result[i].set_page_pool(&base_instance_cull_page_pool);
- }
-
- for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
- cull.sdfgi.cascade_lights[i].set_page_pool(&rid_cull_page_pool);
+ frustum_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
+ frustum_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
+ frustum_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/spatial_indexer/update_iterations_per_frame");
+ thread_cull_threshold = GLOBAL_GET("rendering/spatial_indexer/threaded_cull_minimum_instances");
+ thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU
}
RendererSceneCull::~RendererSceneCull() {
instance_cull_result.reset();
- mesh_instance_cull_result.reset();
instance_shadow_cull_result.reset();
- instance_sdfgi_cull_result.reset();
- light_cull_result.reset();
- geometry_instances_to_render.reset();
geometry_instances_to_shadow_render.reset();
- lightmap_cull_result.reset();
-
- reflection_probe_instance_cull_result.reset();
- light_instance_cull_result.reset();
- gi_probe_instance_cull_result.reset();
- decal_instance_cull_result.reset();
-
- for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
- for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
- cull.shadows[i].cascades[j].cull_result.reset();
- }
- }
-
- for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
- cull.sdfgi.region_cull_result[i].reset();
- }
- for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
- cull.sdfgi.cascade_lights[i].reset();
+ frustum_cull_result.reset();
+ for (uint32_t i = 0; i < frustum_cull_result_threads.size(); i++) {
+ frustum_cull_result_threads[i].reset();
}
+ frustum_cull_result_threads.clear();
}
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index b755efd877..2ffaf48675 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -53,7 +53,8 @@ public:
enum {
SDFGI_MAX_CASCADES = 8,
- SDFGI_MAX_REGIONS_PER_CASCADE = 3
+ SDFGI_MAX_REGIONS_PER_CASCADE = 3,
+ MAX_INSTANCE_PAIRS = 32
};
uint64_t render_pass;
@@ -249,7 +250,10 @@ public:
uint32_t flags = 0;
uint32_t layer_mask = 0; //for fast layer-mask discard
RID base_rid;
- RID instance_data_rid;
+ union {
+ uint64_t instance_data_rid;
+ RendererSceneRender::GeometryInstance *instance_geometry;
+ };
Instance *instance = nullptr;
};
@@ -296,7 +300,7 @@ public:
static void _instance_pair(Instance *p_A, Instance *p_B);
static void _instance_unpair(Instance *p_A, Instance *p_B);
- static void _instance_update_mesh_instance(Instance *p_instance);
+ void _instance_update_mesh_instance(Instance *p_instance);
virtual RID scenario_create();
@@ -325,7 +329,55 @@ public:
virtual ~InstanceBaseData() {}
};
- struct Instance : RendererSceneRender::InstanceBase {
+ struct Instance {
+ RS::InstanceType base_type;
+ RID base;
+
+ RID skeleton;
+ RID material_override;
+
+ RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist
+
+ Transform transform;
+
+ float lod_bias;
+
+ Vector<RID> materials;
+
+ RS::ShadowCastingSetting cast_shadows;
+
+ uint32_t layer_mask;
+ //fit in 32 bits
+ bool mirror : 8;
+ bool receive_shadows : 8;
+ bool visible : 8;
+ bool baked_light : 2; //this flag is only to know if it actually did use baked light
+ bool dynamic_gi : 2; //same above for dynamic objects
+ bool redraw_if_visible : 4;
+
+ Instance *lightmap;
+ Rect2 lightmap_uv_scale;
+ int lightmap_slice_index;
+ uint32_t lightmap_cull_index;
+ Vector<Color> lightmap_sh; //spherical harmonic
+
+ AABB aabb;
+ AABB transformed_aabb;
+ AABB prev_transformed_aabb;
+
+ struct InstanceShaderParameter {
+ int32_t index = -1;
+ Variant value;
+ Variant default_value;
+ PropertyInfo info;
+ };
+
+ Map<StringName, InstanceShaderParameter> instance_shader_parameters;
+ bool instance_allocated_shader_parameters = false;
+ int32_t instance_allocated_shader_parameters_offset = -1;
+
+ //
+
RID self;
//scenario stuff
DynamicBVH::ID indexer_id;
@@ -360,23 +412,61 @@ public:
SelfList<InstancePair>::List pairs;
uint64_t pair_check;
- virtual void dependency_deleted(RID p_dependency) {
- if (p_dependency == base) {
- singleton->instance_set_base(self, RID());
- } else if (p_dependency == skeleton) {
- singleton->instance_attach_skeleton(self, RID());
- } else {
- singleton->_instance_queue_update(this, false, true);
+ RendererStorage::DependencyTracker dependency_tracker;
+
+ static void dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *tracker) {
+ Instance *instance = (Instance *)tracker->userdata;
+ switch (p_notification) {
+ case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA:
+ case RendererStorage::DEPENDENCY_CHANGED_AABB: {
+ singleton->_instance_queue_update(instance, true, false);
+
+ } break;
+ case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: {
+ singleton->_instance_queue_update(instance, false, true);
+ } break;
+ case RendererStorage::DEPENDENCY_CHANGED_MESH:
+ case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
+ case RendererStorage::DEPENDENCY_CHANGED_DECAL:
+ case RendererStorage::DEPENDENCY_CHANGED_LIGHT:
+ case RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
+ singleton->_instance_queue_update(instance, true, true);
+ } break;
+ case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
+ case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: {
+ //ignored
+ } break;
}
}
- virtual void dependency_changed(bool p_aabb, bool p_dependencies) {
- singleton->_instance_queue_update(this, p_aabb, p_dependencies);
+ static void dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *tracker) {
+ Instance *instance = (Instance *)tracker->userdata;
+
+ if (p_dependency == instance->base) {
+ singleton->instance_set_base(instance->self, RID());
+ } else if (p_dependency == instance->skeleton) {
+ singleton->instance_attach_skeleton(instance->self, RID());
+ } else {
+ singleton->_instance_queue_update(instance, false, true);
+ }
}
Instance() :
scenario_item(this),
update_item(this) {
+ base_type = RS::INSTANCE_NONE;
+ cast_shadows = RS::SHADOW_CASTING_SETTING_ON;
+ receive_shadows = true;
+ visible = true;
+ layer_mask = 1;
+ baked_light = false;
+ dynamic_gi = false;
+ redraw_if_visible = false;
+ lightmap_slice_index = 0;
+ lightmap = nullptr;
+ lightmap_cull_index = 0;
+ lod_bias = 1.0;
+
scenario = nullptr;
update_aabb = false;
@@ -399,6 +489,10 @@ public:
pair_check = 0;
array_index = -1;
+
+ dependency_tracker.userdata = this;
+ dependency_tracker.changed_callback = dependency_changed;
+ dependency_tracker.deleted_callback = dependency_deleted;
}
~Instance() {
@@ -415,6 +509,7 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
+ RendererSceneRender::GeometryInstance *geometry_instance = nullptr;
Set<Instance *> lights;
bool can_cast_shadows;
bool material_is_animated;
@@ -458,6 +553,10 @@ public:
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
+ struct InstanceParticlesCollisionData : public InstanceBaseData {
+ RID instance;
+ };
+
struct InstanceLightData : public InstanceBaseData {
RID instance;
uint64_t last_version;
@@ -523,6 +622,7 @@ public:
SelfList<InstanceGIProbeData>::List gi_probe_update_list;
struct InstanceLightmapData : public InstanceBaseData {
+ RID instance;
Set<Instance *> geometries;
Set<Instance *> users;
@@ -588,38 +688,139 @@ public:
}
};
- struct CullResult {
- PagedArray<Instance *> *result;
- _FORCE_INLINE_ bool operator()(void *p_data) {
- Instance *p_instance = (Instance *)p_data;
- result->push_back(p_instance);
- return false;
- }
- };
-
Set<Instance *> heightfield_particle_colliders_update_list;
PagedArrayPool<Instance *> instance_cull_page_pool;
- PagedArrayPool<RendererSceneRender::InstanceBase *> base_instance_cull_page_pool;
+ PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool;
PagedArrayPool<RID> rid_cull_page_pool;
PagedArray<Instance *> instance_cull_result;
- PagedArray<RID> mesh_instance_cull_result;
- PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_render;
PagedArray<Instance *> instance_shadow_cull_result;
- PagedArray<RendererSceneRender::InstanceBase *> geometry_instances_to_shadow_render;
- PagedArray<Instance *> instance_sdfgi_cull_result;
- PagedArray<Instance *> light_cull_result;
- PagedArray<RendererSceneRender::InstanceBase *> lightmap_cull_result;
- PagedArray<RID> reflection_probe_instance_cull_result;
- PagedArray<RID> light_instance_cull_result;
+ PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances_to_shadow_render;
+
+ struct FrustumCullResult {
+ PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
+ PagedArray<Instance *> lights;
+ PagedArray<RID> light_instances;
+ PagedArray<RID> lightmaps;
+ PagedArray<RID> reflections;
+ PagedArray<RID> decals;
+ PagedArray<RID> gi_probes;
+ PagedArray<RID> mesh_instances;
+
+ struct DirectionalShadow {
+ PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
+ } directional_shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS];
+
+ PagedArray<RendererSceneRender::GeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
+ PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
+
+ void clear() {
+ geometry_instances.clear();
+ lights.clear();
+ light_instances.clear();
+ lightmaps.clear();
+ reflections.clear();
+ decals.clear();
+ gi_probes.clear();
+ mesh_instances.clear();
+ for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
+ for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
+ directional_shadows[i].cascade_geometry_instances[j].clear();
+ }
+ }
- PagedArray<RID> gi_probe_instance_cull_result;
- PagedArray<RID> decal_instance_cull_result;
+ for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
+ sdfgi_region_geometry_instances[i].clear();
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].clear();
+ }
+ }
+
+ void reset() {
+ geometry_instances.reset();
+ lights.reset();
+ light_instances.reset();
+ lightmaps.reset();
+ reflections.reset();
+ decals.reset();
+ gi_probes.reset();
+ mesh_instances.reset();
+ for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
+ for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
+ directional_shadows[i].cascade_geometry_instances[j].reset();
+ }
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
+ sdfgi_region_geometry_instances[i].reset();
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].reset();
+ }
+ }
+
+ void append_from(FrustumCullResult &p_cull_result) {
+ geometry_instances.merge_unordered(p_cull_result.geometry_instances);
+ lights.merge_unordered(p_cull_result.lights);
+ light_instances.merge_unordered(p_cull_result.light_instances);
+ lightmaps.merge_unordered(p_cull_result.lightmaps);
+ reflections.merge_unordered(p_cull_result.reflections);
+ decals.merge_unordered(p_cull_result.decals);
+ gi_probes.merge_unordered(p_cull_result.gi_probes);
+ mesh_instances.merge_unordered(p_cull_result.mesh_instances);
+
+ for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
+ for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
+ directional_shadows[i].cascade_geometry_instances[j].merge_unordered(p_cull_result.directional_shadows[i].cascade_geometry_instances[j]);
+ }
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
+ sdfgi_region_geometry_instances[i].merge_unordered(p_cull_result.sdfgi_region_geometry_instances[i]);
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].merge_unordered(p_cull_result.sdfgi_cascade_lights[i]);
+ }
+ }
+
+ void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RendererSceneRender::GeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
+ geometry_instances.set_page_pool(p_geometry_instance_pool);
+ light_instances.set_page_pool(p_rid_pool);
+ lights.set_page_pool(p_instance_pool);
+ lightmaps.set_page_pool(p_rid_pool);
+ reflections.set_page_pool(p_rid_pool);
+ decals.set_page_pool(p_rid_pool);
+ gi_probes.set_page_pool(p_rid_pool);
+ mesh_instances.set_page_pool(p_rid_pool);
+ for (int i = 0; i < RendererSceneRender::MAX_DIRECTIONAL_LIGHTS; i++) {
+ for (int j = 0; j < RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES; j++) {
+ directional_shadows[i].cascade_geometry_instances[j].set_page_pool(p_geometry_instance_pool);
+ }
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE; i++) {
+ sdfgi_region_geometry_instances[i].set_page_pool(p_geometry_instance_pool);
+ }
+
+ for (int i = 0; i < SDFGI_MAX_CASCADES; i++) {
+ sdfgi_cascade_lights[i].set_page_pool(p_rid_pool);
+ }
+ }
+ };
+
+ FrustumCullResult frustum_cull_result;
+ LocalVector<FrustumCullResult> frustum_cull_result_threads;
+
+ uint32_t thread_cull_threshold = 200;
RID_PtrOwner<Instance> instance_owner;
- bool pair_volumes_to_mesh; // used in traditional forward, unnecesary on clustered
+ uint32_t geometry_instance_pair_mask; // used in traditional forward, unnecesary on clustered
virtual RID instance_create();
@@ -653,7 +854,7 @@ public:
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
- void _update_instance_shader_parameters_from_material(Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &isparams, const Map<StringName, RendererSceneRender::InstanceBase::InstanceShaderParameter> &existing_isparams, RID p_material);
+ void _update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
@@ -687,8 +888,6 @@ public:
real_t range_begin;
Vector2 uv_scale;
- PagedArray<RendererSceneRender::InstanceBase *> cull_result;
-
} cascades[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES]; //max 4 cascades
uint32_t cascade_count;
@@ -698,12 +897,10 @@ public:
struct SDFGI {
//have arrays here because SDFGI functions expects this, plus regions can have areas
- PagedArray<RendererSceneRender::InstanceBase *> region_cull_result[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
AABB region_aabb[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
uint32_t region_cascade[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE]; //max 3 regions per cascade
uint32_t region_count = 0;
- PagedArray<RID> cascade_lights[SDFGI_MAX_CASCADES];
uint32_t cascade_light_index[SDFGI_MAX_CASCADES];
uint32_t cascade_light_count = 0;
@@ -714,6 +911,18 @@ public:
Frustum frustum;
} cull;
+ struct FrustumCullData {
+ Cull *cull;
+ Scenario *scenario;
+ RID shadow_atlas;
+ Transform cam_transform;
+ uint32_t visible_layers;
+ Instance *render_reflection_probe;
+ };
+
+ void _frustum_cull_threaded(uint32_t p_thread, FrustumCullData *cull_data);
+ void _frustum_cull(FrustumCullData &cull_data, FrustumCullResult &cull_result, uint64_t p_from, uint64_t p_to);
+
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, float p_screen_lod_threshold, bool p_using_shadows = true);
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold);
@@ -738,7 +947,7 @@ public:
#define PASSBASE scene_render
- PASS1(directional_shadow_atlas_set_size, int)
+ PASS2(directional_shadow_atlas_set_size, int, bool)
PASS1(gi_probe_set_quality, RS::GIProbeQuality)
/* SKY API */
@@ -787,6 +996,7 @@ public:
PASS11(environment_set_sdfgi, RID, bool, RS::EnvironmentSDFGICascades, float, RS::EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
+ PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight)
PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
PASS1RC(int, environment_get_canvas_max_layer, RID)
@@ -816,10 +1026,11 @@ public:
PASS0R(RID, render_buffers_create)
PASS7(render_buffers_configure, RID, RID, int, int, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool)
+ PASS1(gi_set_use_half_resolution, bool)
/* Shadow Atlas */
PASS0R(RID, shadow_atlas_create)
- PASS2(shadow_atlas_set_size, RID, int)
+ PASS3(shadow_atlas_set_size, RID, int, bool)
PASS3(shadow_atlas_set_quadrant_subdivision, RID, int, int)
PASS1(set_debug_draw_mode, RS::ViewportDebugDraw)
@@ -828,6 +1039,8 @@ public:
bool free(RID p_rid);
+ void set_scene_render(RendererSceneRender *p_scene_render);
+
RendererSceneCull();
virtual ~RendererSceneCull();
};
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 2c36c5c59d..f27bdc6798 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index d5e8f391cd..ecec03db94 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,22 +41,48 @@ public:
MAX_DIRECTIONAL_LIGHTS = 8,
MAX_DIRECTIONAL_LIGHT_CASCADES = 4
};
+
+ struct GeometryInstance {
+ virtual ~GeometryInstance() {}
+ };
+
+ virtual GeometryInstance *geometry_instance_create(RID p_base) = 0;
+ virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0;
+ virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
+ virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
+ virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
+ virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
+ virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
+ virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
+ virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+ virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+ virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
+ virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0;
+ virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0;
+ virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+
+ virtual uint32_t geometry_instance_get_pair_mask() = 0;
+ virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
+ virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
+ virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
+ virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) = 0;
+
+ virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
+
/* SHADOW ATLAS API */
virtual RID
shadow_atlas_create() = 0;
- virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0;
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = false) = 0;
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
- virtual void directional_shadow_atlas_set_size(int p_size) = 0;
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = false) = 0;
virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
virtual void set_directional_shadow_count(int p_count) = 0;
/* SDFGI UPDATE */
- struct InstanceBase;
-
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
@@ -110,6 +136,7 @@ public:
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
+ virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
@@ -134,83 +161,6 @@ public:
virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
- struct InstanceBase : public RendererStorage::InstanceBaseDependency {
- RS::InstanceType base_type;
- RID base;
-
- RID skeleton;
- RID material_override;
-
- RID mesh_instance; //only used for meshes and when skeleton/blendshapes exist
-
- Transform transform;
-
- float lod_bias;
-
- int depth_layer;
- uint32_t layer_mask;
-
- //RID sampled_light;
-
- Vector<RID> materials;
- Vector<RID> light_instances;
- Vector<RID> reflection_probe_instances;
- Vector<RID> gi_probe_instances;
-
- RS::ShadowCastingSetting cast_shadows;
-
- //fit in 32 bits
- bool mirror : 8;
- bool receive_shadows : 8;
- bool visible : 8;
- bool baked_light : 2; //this flag is only to know if it actually did use baked light
- bool dynamic_gi : 2; //this flag is only to know if it actually did use baked light
- bool redraw_if_visible : 4;
-
- float depth; //used for sorting
-
- InstanceBase *lightmap;
- Rect2 lightmap_uv_scale;
- int lightmap_slice_index;
- uint32_t lightmap_cull_index;
- Vector<Color> lightmap_sh; //spherical harmonic
-
- AABB aabb;
- AABB transformed_aabb;
- AABB prev_transformed_aabb;
-
- struct InstanceShaderParameter {
- int32_t index = -1;
- Variant value;
- Variant default_value;
- PropertyInfo info;
- };
-
- Map<StringName, InstanceShaderParameter> instance_shader_parameters;
- bool instance_allocated_shader_parameters = false;
- int32_t instance_allocated_shader_parameters_offset = -1;
-
- InstanceBase() {
- base_type = RS::INSTANCE_NONE;
- cast_shadows = RS::SHADOW_CASTING_SETTING_ON;
- receive_shadows = true;
- visible = true;
- depth_layer = 0;
- layer_mask = 1;
- instance_version = 0;
- baked_light = false;
- dynamic_gi = false;
- redraw_if_visible = false;
- lightmap_slice_index = 0;
- lightmap = nullptr;
- lightmap_cull_index = 0;
- lod_bias = 1.0;
- }
-
- virtual ~InstanceBase() {
- }
- };
-
virtual RID light_instance_create(RID p_light) = 0;
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
@@ -235,20 +185,23 @@ public:
virtual RID decal_instance_create(RID p_decal) = 0;
virtual void decal_instance_set_transform(RID p_decal, const Transform &p_transform) = 0;
+ virtual RID lightmap_instance_create(RID p_lightmap) = 0;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) = 0;
+
virtual RID gi_probe_instance_create(RID p_gi_probe) = 0;
virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0;
virtual bool gi_probe_needs_update(RID p_probe) const = 0;
- virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects) = 0;
+ virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0;
- virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
+ virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) = 0;
- virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
- virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) = 0;
+ virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0) = 0;
+ virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_lights) = 0;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) = 0;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time, double p_step) = 0;
@@ -256,6 +209,7 @@ public:
virtual RID render_buffers_create() = 0;
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0;
+ virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
virtual bool screen_space_roughness_limiter_is_active() const = 0;
diff --git a/servers/rendering/renderer_storage.cpp b/servers/rendering/renderer_storage.cpp
index 1b2773e404..a402ecc668 100644
--- a/servers/rendering/renderer_storage.cpp
+++ b/servers/rendering/renderer_storage.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,28 +32,31 @@
RendererStorage *RendererStorage::base_singleton = nullptr;
-void RendererStorage::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) {
- for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
- E->key()->dependency_changed(p_aabb, p_dependencies);
+void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p_notification) {
+ for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
+ if (E->key()->changed_callback) {
+ E->key()->changed_callback(p_notification, E->key());
+ }
}
}
-void RendererStorage::InstanceDependency::instance_notify_deleted(RID p_deleted) {
- for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
- E->key()->dependency_deleted(p_deleted);
+void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
+ for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
+ if (E->key()->deleted_callback) {
+ E->key()->deleted_callback(p_rid, E->key());
+ }
}
- for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
+ for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this);
}
-
instances.clear();
}
-RendererStorage::InstanceDependency::~InstanceDependency() {
+RendererStorage::Dependency::~Dependency() {
#ifdef DEBUG_ENABLED
if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
- for (Map<InstanceBaseDependency *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
+ for (Map<DependencyTracker *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
E->key()->dependencies.erase(this);
}
}
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 895a7a5be8..7a80c2b0bf 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,43 +37,59 @@ class RendererStorage {
Color default_clear_color;
public:
- struct InstanceBaseDependency;
+ enum DependencyChangedNotification {
+ DEPENDENCY_CHANGED_AABB,
+ DEPENDENCY_CHANGED_MATERIAL,
+ DEPENDENCY_CHANGED_MESH,
+ DEPENDENCY_CHANGED_MULTIMESH,
+ DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES,
+ DEPENDENCY_CHANGED_DECAL,
+ DEPENDENCY_CHANGED_SKELETON_DATA,
+ DEPENDENCY_CHANGED_SKELETON_BONES,
+ DEPENDENCY_CHANGED_LIGHT,
+ DEPENDENCY_CHANGED_REFLECTION_PROBE,
+ };
+
+ struct DependencyTracker;
- struct InstanceDependency {
- void instance_notify_changed(bool p_aabb, bool p_dependencies);
- void instance_notify_deleted(RID p_deleted);
+protected:
+ struct Dependency {
+ void changed_notify(DependencyChangedNotification p_notification);
+ void deleted_notify(const RID &p_rid);
- ~InstanceDependency();
+ ~Dependency();
private:
- friend struct InstanceBaseDependency;
- Map<InstanceBaseDependency *, uint32_t> instances;
+ friend struct DependencyTracker;
+ Map<DependencyTracker *, uint32_t> instances;
};
- struct InstanceBaseDependency {
- uint32_t instance_version;
- Set<InstanceDependency *> dependencies;
+public:
+ struct DependencyTracker {
+ void *userdata = nullptr;
+ typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
+ typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
- virtual void dependency_deleted(RID p_dependency) {}
- virtual void dependency_changed(bool p_aabb, bool p_dependencies) {}
+ ChangedCallback changed_callback = nullptr;
+ DeletedCallback deleted_callback = nullptr;
- void instance_increase_version() {
+ void update_begin() { // call before updating dependencies
instance_version++;
}
- void update_dependency(InstanceDependency *p_dependency) {
+ void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
dependencies.insert(p_dependency);
p_dependency->instances[this] = instance_version;
}
- void clean_up_dependencies() {
- List<Pair<InstanceDependency *, Map<InstanceBaseDependency *, uint32_t>::Element *>> to_clean_up;
- for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) {
- InstanceDependency *dep = E->get();
- Map<InstanceBaseDependency *, uint32_t>::Element *F = dep->instances.find(this);
+ void update_end() { //call after updating dependencies
+ List<Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *>> to_clean_up;
+ for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) {
+ Dependency *dep = E->get();
+ Map<DependencyTracker *, uint32_t>::Element *F = dep->instances.find(this);
ERR_CONTINUE(!F);
if (F->get() != instance_version) {
- Pair<InstanceDependency *, Map<InstanceBaseDependency *, uint32_t>::Element *> p;
+ Pair<Dependency *, Map<DependencyTracker *, uint32_t>::Element *> p;
p.first = dep;
p.second = F;
to_clean_up.push_back(p);
@@ -86,15 +102,20 @@ public:
}
}
- void clear_dependencies() {
- for (Set<InstanceDependency *>::Element *E = dependencies.front(); E; E = E->next()) {
- InstanceDependency *dep = E->get();
+ void clear() { // clear all dependencies
+ for (Set<Dependency *>::Element *E = dependencies.front(); E; E = E->next()) {
+ Dependency *dep = E->get();
dep->instances.erase(this);
}
dependencies.clear();
}
- virtual ~InstanceBaseDependency() { clear_dependencies(); }
+ ~DependencyTracker() { clear(); }
+
+ private:
+ friend struct Dependency;
+ uint32_t instance_version = 0;
+ Set<Dependency *> dependencies;
};
/* TEXTURE API */
@@ -158,6 +179,8 @@ public:
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
+ virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
+
/* COMMON MATERIAL API */
virtual RID material_create() = 0;
@@ -181,7 +204,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
- virtual void material_update_dependency(RID p_material, InstanceBaseDependency *p_instance) = 0;
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
/* MESH API */
@@ -211,6 +234,8 @@ public:
virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0;
+
virtual void mesh_clear(RID p_mesh) = 0;
virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0;
@@ -349,8 +374,8 @@ public:
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
virtual float reflection_probe_get_lod_threshold(RID p_probe) const = 0;
- virtual void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) = 0;
- virtual void skeleton_update_dependency(RID p_base, InstanceBaseDependency *p_instance) = 0;
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
+ virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* DECAL API */
@@ -474,8 +499,8 @@ public:
virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis) = 0;
- virtual void particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance) = 0;
- virtual void particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance) = 0;
+ virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+ virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
virtual void update_particles() = 0;
@@ -496,6 +521,11 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+ //used from 2D and 3D
+ virtual RID particles_collision_instance_create(RID p_collision) = 0;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) = 0;
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
+
/* GLOBAL VARIABLES */
virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/renderer_thread_pool.cpp
new file mode 100644
index 0000000000..98050dd508
--- /dev/null
+++ b/servers/rendering/renderer_thread_pool.cpp
@@ -0,0 +1,42 @@
+/*************************************************************************/
+/* renderer_thread_pool.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "renderer_thread_pool.h"
+
+RendererThreadPool *RendererThreadPool::singleton = nullptr;
+
+RendererThreadPool::RendererThreadPool() {
+ singleton = this;
+ thread_work_pool.init();
+}
+
+RendererThreadPool::~RendererThreadPool() {
+ thread_work_pool.finish();
+}
diff --git a/servers/rendering/renderer_thread_pool.h b/servers/rendering/renderer_thread_pool.h
new file mode 100644
index 0000000000..ae25415a0d
--- /dev/null
+++ b/servers/rendering/renderer_thread_pool.h
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* renderer_thread_pool.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 RENDERERTHREADPOOL_H
+#define RENDERERTHREADPOOL_H
+
+#include "core/templates/thread_work_pool.h"
+
+class RendererThreadPool {
+public:
+ ThreadWorkPool thread_work_pool;
+
+ static RendererThreadPool *singleton;
+ RendererThreadPool();
+ ~RendererThreadPool();
+};
+
+#endif // RENDERERTHREADPOOL_H
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index ea95eb1189..d52da5b331 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -831,13 +831,14 @@ void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas
viewport->canvas_map[p_canvas].sublayer = p_sublayer;
}
-void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
+void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) {
Viewport *viewport = viewport_owner.getornull(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->shadow_atlas_size = p_size;
+ viewport->shadow_atlas_16_bits = p_16_bits;
- RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size);
+ RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits);
}
void RendererViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index e836d05dfc..979cbb095b 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -81,6 +81,7 @@ public:
RID shadow_atlas;
int shadow_atlas_size;
+ bool shadow_atlas_16_bits = false;
bool sdf_active;
@@ -217,7 +218,7 @@ public:
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
- void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
+ void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = false);
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index ba30670082..9a254c5a7a 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -68,7 +68,7 @@ RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const
Vector<Vector<uint8_t>> data;
for (int i = 0; i < p_data.size(); i++) {
Vector<uint8_t> byte_slice = p_data[i];
- ERR_FAIL_COND_V(byte_slice.empty(), RID());
+ ERR_FAIL_COND_V(byte_slice.is_empty(), RID());
data.push_back(byte_slice);
}
return texture_create(p_format->base, p_view->base, data);
@@ -154,7 +154,7 @@ RID RenderingDevice::shader_create_from_bytecode(const Ref<RDShaderBytecode> &p_
String error = p_bytecode->get_stage_compile_error(stage);
ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
sd.spir_v = p_bytecode->get_stage_bytecode(stage);
- if (sd.spir_v.empty()) {
+ if (sd.spir_v.is_empty()) {
continue;
}
stage_data.push_back(sd);
@@ -262,10 +262,10 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "sync_with_draw"), &RenderingDevice::texture_resolve_multisample, DEFVAL(false));
ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments"), &RenderingDevice::_framebuffer_format_create);
- ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "size"), &RenderingDevice::framebuffer_format_create_empty);
+ ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "samples"), &RenderingDevice::framebuffer_format_create_empty, DEFVAL(TEXTURE_SAMPLES_1));
ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format"), &RenderingDevice::framebuffer_format_get_texture_samples);
ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID));
- ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(INVALID_FORMAT_ID));
+ ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
@@ -288,6 +288,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid);
ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "sync_with_draw"), &RenderingDevice::_buffer_update, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "sync_with_draw"), &RenderingDevice::_buffer_update, DEFVAL(true));
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags"), &RenderingDevice::_render_pipeline_create, DEFVAL(0));
@@ -342,6 +343,12 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device);
+ ClassDB::bind_method(D_METHOD("set_resource_name"), &RenderingDevice::set_resource_name);
+
+ ClassDB::bind_method(D_METHOD("draw_command_begin_label", "name", "color"), &RenderingDevice::draw_command_begin_label);
+ ClassDB::bind_method(D_METHOD("draw_command_insert_label", "name", "color"), &RenderingDevice::draw_command_insert_label);
+ ClassDB::bind_method(D_METHOD("draw_command_end_label"), &RenderingDevice::draw_command_end_label);
+
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4_UNORM_PACK8);
BIND_ENUM_CONSTANT(DATA_FORMAT_R4G4B4A4_UNORM_PACK16);
BIND_ENUM_CONSTANT(DATA_FORMAT_B4G4R4A4_UNORM_PACK16);
@@ -744,6 +751,7 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(DYNAMIC_STATE_STENCIL_REFERENCE);
BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR); //start rendering and clear the framebuffer (supply params)
+ BIND_ENUM_CONSTANT(INITIAL_ACTION_CLEAR_REGION); //start rendering and clear the framebuffer (supply params)
BIND_ENUM_CONSTANT(INITIAL_ACTION_KEEP); //start rendering); but keep attached color texture contents (depth will be cleared)
BIND_ENUM_CONSTANT(INITIAL_ACTION_DROP); //start rendering); ignore what is there); just write above it
BIND_ENUM_CONSTANT(INITIAL_ACTION_CONTINUE); //continue rendering (framebuffer must have been left in "continue" state as final action previously)
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index b3d4e66f6c..4e499b72d4 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -468,11 +468,11 @@ public:
// This ID is warranted to be unique for the same formats, does not need to be freed
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format) = 0;
- virtual FramebufferFormatID framebuffer_format_create_empty(const Size2i &p_size) = 0;
+ virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0;
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0;
- virtual RID framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check = INVALID_ID) = 0;
+ virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
@@ -650,6 +650,7 @@ public:
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the beginning of the frame, unless sync with draw is used, which is used to mix updates with draw calls
+ virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, bool p_sync_with_draw = false) = 0;
virtual Vector<uint8_t> buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving
/*************************/
@@ -930,7 +931,8 @@ public:
/********************/
enum InitialAction {
- INITIAL_ACTION_CLEAR, //start rendering and clear the framebuffer (supply params)
+ INITIAL_ACTION_CLEAR, //start rendering and clear the whole framebuffer (region or not) (supply params)
+ INITIAL_ACTION_CLEAR_REGION, //start rendering and clear the framebuffer in the specified region (supply params)
INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared)
INITIAL_ACTION_DROP, //start rendering, ignore what is there, just write above it
INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously)
@@ -1058,6 +1060,12 @@ public:
virtual RenderingDevice *create_local_device() = 0;
+ virtual void set_resource_name(RID p_id, const String p_name) = 0;
+
+ virtual void draw_command_begin_label(String p_label_name, const Color p_color = Color(1, 1, 1, 1)) = 0;
+ virtual void draw_command_insert_label(String p_label_name, const Color p_color = Color(1, 1, 1, 1)) = 0;
+ virtual void draw_command_end_label() = 0;
+
static RenderingDevice *get_singleton();
RenderingDevice();
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index af9ecef0dd..2f11360364 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -163,7 +163,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "When writing compute shaders, [compute] mustbe the only stage present.");
}
- if (version_texts.empty()) {
+ if (version_texts.is_empty()) {
version_texts[""] = ""; //make sure a default version exists
}
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index 5deeec3ffe..e43c3669b5 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index da6c3ef6f4..360b333454 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -162,6 +162,51 @@ void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
}
frame_profile_frame = RSG::storage->get_captured_timestamps_frame();
+
+ if (print_gpu_profile) {
+ if (print_frame_profile_ticks_from == 0) {
+ print_frame_profile_ticks_from = OS::get_singleton()->get_ticks_usec();
+ }
+ float total_time = 0.0;
+
+ for (int i = 0; i < frame_profile.size() - 1; i++) {
+ String name = frame_profile[i].name;
+ if (name[0] == '<' || name[0] == '>') {
+ continue;
+ }
+
+ float time = frame_profile[i + 1].gpu_msec - frame_profile[i].gpu_msec;
+
+ if (name[0] != '<' && name[0] != '>') {
+ if (print_gpu_profile_task_time.has(name)) {
+ print_gpu_profile_task_time[name] += time;
+ } else {
+ print_gpu_profile_task_time[name] = time;
+ }
+ }
+ }
+
+ if (frame_profile.size()) {
+ total_time = frame_profile[frame_profile.size() - 1].gpu_msec;
+ }
+
+ uint64_t ticks_elapsed = OS::get_singleton()->get_ticks_usec() - print_frame_profile_ticks_from;
+ print_frame_profile_frame_count++;
+ if (ticks_elapsed > 1000000) {
+ print_line("GPU PROFILE (total " + rtos(total_time) + "ms): ");
+
+ float print_threshold = 0.01;
+ for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) {
+ float time = E.value() / float(print_frame_profile_frame_count);
+ if (time > print_threshold) {
+ print_line("\t-" + E.key() + ": " + rtos(time) + "ms");
+ }
+ }
+ print_gpu_profile_task_time.clear();
+ print_frame_profile_ticks_from = OS::get_singleton()->get_ticks_usec();
+ print_frame_profile_frame_count = 0;
+ }
+ }
}
float RenderingServerDefault::get_frame_setup_time_cpu() const {
@@ -232,6 +277,11 @@ void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_posit
RSG::scene->sdfgi_set_debug_probe_select(p_position, p_dir);
}
+void RenderingServerDefault::set_print_gpu_profile(bool p_enable) {
+ RSG::storage->capturing_timestamps = p_enable;
+ print_gpu_profile = p_enable;
+}
+
RID RenderingServerDefault::get_test_cube() {
if (!test_cube.is_valid()) {
test_cube = _make_test_cube();
@@ -267,7 +317,7 @@ RenderingServerDefault::RenderingServerDefault() {
RSG::rasterizer = RendererCompositor::create();
RSG::storage = RSG::rasterizer->get_storage();
RSG::canvas_render = RSG::rasterizer->get_canvas();
- sr->scene_render = RSG::rasterizer->get_scene();
+ sr->set_scene_render(RSG::rasterizer->get_scene());
frame_profile_frame = 0;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 922cf08f3b..83afd9096d 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,7 @@
#define RENDERING_SERVER_DEFAULT_H
#include "core/math/octree.h"
+#include "core/templates/ordered_hash_map.h"
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
#include "renderer_viewport.h"
@@ -74,6 +75,12 @@ class RenderingServerDefault : public RenderingServer {
float frame_setup_time = 0;
+ //for printing
+ bool print_gpu_profile = false;
+ OrderedHashMap<String, float> print_gpu_profile_task_time;
+ uint64_t print_frame_profile_ticks_from = 0;
+ uint32_t print_frame_profile_frame_count = 0;
+
public:
//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
//#define DEBUG_CHANGES
@@ -219,6 +226,8 @@ public:
BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
BIND2RC(Variant, shader_get_param_default, RID, const StringName &)
+ BIND1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
+
/* COMMON MATERIAL API */
BIND0R(RID, material_create)
@@ -265,6 +274,8 @@ public:
BIND2(mesh_set_custom_aabb, RID, const AABB &)
BIND1RC(AABB, mesh_get_custom_aabb, RID)
+ BIND2(mesh_set_shadow_mesh, RID, RID)
+
BIND1(mesh_clear, RID)
/* MULTIMESH API */
@@ -542,7 +553,7 @@ public:
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
- BIND2(viewport_set_shadow_atlas_size, RID, int)
+ BIND3(viewport_set_shadow_atlas_size, RID, int, bool)
BIND3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
BIND2(viewport_set_msaa, RID, ViewportMSAA)
@@ -563,7 +574,7 @@ public:
//from now on, calls forwarded to this singleton
#define BINDBASE RSG::scene
- BIND1(directional_shadow_atlas_set_size, int)
+ BIND2(directional_shadow_atlas_set_size, int, bool)
BIND1(gi_probe_set_quality, GIProbeQuality)
/* SKY API */
@@ -614,6 +625,7 @@ public:
BIND11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
BIND1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
BIND1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
+ BIND1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
BIND3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
@@ -686,6 +698,8 @@ public:
BIND3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
+ BIND1(gi_set_use_half_resolution, bool)
+
#undef BINDBASE
//from now on, calls forwarded to this singleton
#define BINDBASE RSG::canvas
@@ -863,6 +877,8 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir);
+ virtual void set_print_gpu_profile(bool p_enable);
+
RenderingServerDefault();
~RenderingServerDefault();
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index b9df36e93a..c0d9988e85 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 580526f7e0..a28a0f5180 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp
index 40ad228fd0..3572c4dc78 100644
--- a/servers/rendering/rendering_server_wrap_mt.cpp
+++ b/servers/rendering/rendering_server_wrap_mt.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index 1e6c3b8f71..2f76577474 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -129,6 +129,8 @@ public:
FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
+ FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
+
/* COMMON MATERIAL API */
FUNCRID(material)
@@ -170,6 +172,7 @@ public:
FUNC2(mesh_set_custom_aabb, RID, const AABB &)
FUNC1RC(AABB, mesh_get_custom_aabb, RID)
+ FUNC2(mesh_set_shadow_mesh, RID, RID)
FUNC1(mesh_clear, RID)
/* MULTIMESH API */
@@ -443,7 +446,7 @@ public:
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
- FUNC2(viewport_set_shadow_atlas_size, RID, int)
+ FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
@@ -468,7 +471,7 @@ public:
return rendering_server->viewport_get_measured_render_time_gpu(p_viewport);
}
- FUNC1(directional_shadow_atlas_set_size, int)
+ FUNC2(directional_shadow_atlas_set_size, int, bool)
/* SKY API */
@@ -505,6 +508,7 @@ public:
FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float)
FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount)
FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge)
+ FUNC1(environment_set_sdfgi_frames_to_update_light, EnvironmentSDFGIFramesToUpdateLight)
FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float)
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
@@ -742,6 +746,8 @@ public:
return rendering_server->get_video_adapter_vendor();
}
+ FUNC1(gi_set_use_half_resolution, bool)
+
FUNC4(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
FUNC1(set_default_clear_color, const Color &)
@@ -784,6 +790,10 @@ public:
rendering_server->sdfgi_set_debug_probe_select(p_position, p_dir);
}
+ virtual void set_print_gpu_profile(bool p_enable) {
+ rendering_server->set_print_gpu_profile(p_enable);
+ }
+
RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread);
~RenderingServerWrapMT();
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index c6eef48dfa..2fa3355d2f 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -3818,7 +3818,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (index_expression->type == Node::TYPE_CONSTANT) {
ConstantNode *cnode = (ConstantNode *)index_expression;
if (cnode) {
- if (!cnode->values.empty()) {
+ if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
_set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
@@ -4210,7 +4210,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (index_expression->type == Node::TYPE_CONSTANT) {
ConstantNode *cnode = (ConstantNode *)index_expression;
if (cnode) {
- if (!cnode->values.empty()) {
+ if (!cnode->values.is_empty()) {
int value = cnode->values[0].sint;
if (value < 0 || value >= array_size) {
_set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
@@ -5504,7 +5504,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (flow->flow_op == FLOW_OP_CASE) {
if (flow->expressions[0]->type == Node::TYPE_CONSTANT) {
ConstantNode *cn = static_cast<ConstantNode *>(flow->expressions[0]);
- if (!cn || cn->values.empty()) {
+ if (!cn || cn->values.is_empty()) {
return ERR_PARSE_ERROR;
}
if (constants.has(cn->values[0].sint)) {
@@ -6305,7 +6305,9 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
uniform2.texture_order = -1;
- uniform2.order = uniforms++;
+ if (uniform_scope != ShaderNode::Uniform::SCOPE_INSTANCE) {
+ uniform2.order = uniforms++;
+ }
}
uniform2.type = type;
uniform2.scope = uniform_scope;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index d8fc316f47..27767378f9 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 0c9b2ddf2f..e99b8504bb 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -94,8 +94,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_MAP"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_MAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
@@ -242,8 +242,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["LIGHT_VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_MAP"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_MAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
@@ -347,7 +347,7 @@ ShaderTypes::ShaderTypes() {
emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("custom", ShaderLanguage::TYPE_VEC4));
emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("flags", ShaderLanguage::TYPE_UINT));
emit_vertex_func.return_type = ShaderLanguage::TYPE_BOOL; //whether it could emit
- shader_modes[RS::SHADER_PARTICLES].functions["compute"].stage_functions["emit_particle"] = emit_vertex_func;
+ shader_modes[RS::SHADER_PARTICLES].functions["compute"].stage_functions["emit_subparticle"] = emit_vertex_func;
}
shader_modes[RS::SHADER_PARTICLES].modes.push_back("collision_use_scale");
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 50f910babb..e59cef6b79 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */