summaryrefslogtreecommitdiffstats
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp19
-rw-r--r--servers/rendering/renderer_rd/effects/debug_effects.cpp56
-rw-r--r--servers/rendering/renderer_rd/effects/debug_effects.h14
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp73
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp10
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp11
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp1
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp18
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp18
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl80
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/particles_copy.glsl25
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp85
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h15
19 files changed, 352 insertions, 123 deletions
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 64950c6991..7554e478bb 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -58,6 +58,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
afs.push_back(RD::AttachmentFormat());
afs.write[0].usage_flags = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
fb_format = RD::get_singleton()->framebuffer_format_create(afs);
+ blend_state = RD::PipelineColorBlendState::create_blend();
defines = "\n#define USE_ATTACHMENT\n";
}
@@ -94,7 +95,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
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] = {
+ static const uint16_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
};
@@ -105,10 +106,10 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
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);
+ index_data.resize(sizeof(uint16_t) * icosphere_triangle_count * 3);
memcpy(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);
+ sphere_index_buffer = RD::get_singleton()->index_buffer_create(icosphere_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT16, index_data);
Vector<RID> buffers;
buffers.push_back(sphere_vertex_buffer);
@@ -138,7 +139,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
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] = {
+ static const uint16_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
};
@@ -149,10 +150,10 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
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);
+ index_data.resize(sizeof(uint16_t) * cone_triangle_count * 3);
memcpy(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);
+ cone_index_buffer = RD::get_singleton()->index_buffer_create(cone_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT16, index_data);
Vector<RID> buffers;
buffers.push_back(cone_vertex_buffer);
@@ -192,7 +193,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
-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] = {
+ static const uint16_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
};
@@ -203,10 +204,10 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
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);
+ index_data.resize(sizeof(uint16_t) * box_triangle_count * 3);
memcpy(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);
+ box_index_buffer = RD::get_singleton()->index_buffer_create(box_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT16, index_data);
Vector<RID> buffers;
buffers.push_back(box_vertex_buffer);
diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp
index 8cd3c22483..357d035ae9 100644
--- a/servers/rendering/renderer_rd/effects/debug_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp
@@ -51,6 +51,17 @@ DebugEffects::DebugEffects() {
raster_state.wireframe = true;
shadow_frustum.pipelines[SFP_WIREFRAME].setup(shadow_frustum.shader.version_get_shader(shadow_frustum.shader_version, 0), RD::RENDER_PRIMITIVE_LINES, raster_state, RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}
+
+ {
+ // Motion Vectors debug shader.
+ Vector<String> modes;
+ modes.push_back("");
+
+ motion_vectors.shader.initialize(modes);
+ motion_vectors.shader_version = motion_vectors.shader.version_create();
+
+ motion_vectors.pipeline.setup(motion_vectors.shader.version_get_shader(motion_vectors.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0);
+ }
}
void DebugEffects::_create_frustum_arrays() {
@@ -74,7 +85,7 @@ void DebugEffects::_create_frustum_arrays() {
}
if (frustum.index_buffer.is_null()) {
- uint32_t indices[6 * 2 * 3] = {
+ uint16_t indices[6 * 2 * 3] = {
// Far
0, 1, 2, // FLT, FLB, FRT
1, 3, 2, // FLB, FRB, FRT
@@ -100,19 +111,19 @@ void DebugEffects::_create_frustum_arrays() {
data.resize(6 * 2 * 3 * 4);
{
uint8_t *w = data.ptrw();
- int *p32 = (int *)w;
+ uint16_t *p16 = (uint16_t *)w;
for (int i = 0; i < 6 * 2 * 3; i++) {
- *p32 = indices[i];
- p32++;
+ *p16 = indices[i];
+ p16++;
}
}
- frustum.index_buffer = RD::get_singleton()->index_buffer_create(6 * 2 * 3, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, data);
+ frustum.index_buffer = RD::get_singleton()->index_buffer_create(6 * 2 * 3, RenderingDevice::INDEX_BUFFER_FORMAT_UINT16, data);
frustum.index_array = RD::get_singleton()->index_array_create(frustum.index_buffer, 0, 6 * 2 * 3);
}
if (frustum.lines_buffer.is_null()) {
- uint32_t indices[12 * 2] = {
+ uint16_t indices[12 * 2] = {
0, 1, // FLT - FLB
1, 3, // FLB - FRB
3, 2, // FRB - FRT
@@ -134,14 +145,14 @@ void DebugEffects::_create_frustum_arrays() {
data.resize(12 * 2 * 4);
{
uint8_t *w = data.ptrw();
- int *p32 = (int *)w;
+ uint16_t *p16 = (uint16_t *)w;
for (int i = 0; i < 12 * 2; i++) {
- *p32 = indices[i];
- p32++;
+ *p16 = indices[i];
+ p16++;
}
}
- frustum.lines_buffer = RD::get_singleton()->index_buffer_create(12 * 2, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, data);
+ frustum.lines_buffer = RD::get_singleton()->index_buffer_create(12 * 2, RenderingDevice::INDEX_BUFFER_FORMAT_UINT16, data);
frustum.lines_array = RD::get_singleton()->index_array_create(frustum.lines_buffer, 0, 12 * 2);
}
}
@@ -163,6 +174,8 @@ DebugEffects::~DebugEffects() {
if (frustum.lines_buffer.is_valid()) {
RD::get_singleton()->free(frustum.lines_buffer); // Array gets freed as dependency.
}
+
+ motion_vectors.shader.version_free(motion_vectors.shader_version);
}
void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_projection, const Transform3D &p_cam_transform, RID p_dest_fb, const Rect2 p_rect) {
@@ -326,3 +339,26 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj
}
}
}
+
+void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_dest_fb, Size2i p_velocity_size) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ RD::Uniform u_source_velocity(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_velocity }));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass()));
+
+ motion_vectors.push_constant.velocity_resolution[0] = p_velocity_size.width;
+ motion_vectors.push_constant.velocity_resolution[1] = p_velocity_size.height;
+
+ RID shader = motion_vectors.shader.version_get_shader(motion_vectors.shader_version, 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_velocity), 0);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &motion_vectors.push_constant, sizeof(MotionVectorsPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
+ RD::get_singleton()->draw_list_end();
+}
diff --git a/servers/rendering/renderer_rd/effects/debug_effects.h b/servers/rendering/renderer_rd/effects/debug_effects.h
index 21b7b03f84..ae32d94912 100644
--- a/servers/rendering/renderer_rd/effects/debug_effects.h
+++ b/servers/rendering/renderer_rd/effects/debug_effects.h
@@ -32,6 +32,7 @@
#define DEBUG_EFFECTS_RD_H
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/shadow_frustum.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -70,6 +71,18 @@ private:
PipelineCacheRD pipelines[SFP_MAX];
} shadow_frustum;
+ struct MotionVectorsPushConstant {
+ float velocity_resolution[2];
+ float pad[2];
+ };
+
+ struct {
+ MotionVectorsShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipeline;
+ MotionVectorsPushConstant push_constant;
+ } motion_vectors;
+
void _create_frustum_arrays();
protected:
@@ -78,6 +91,7 @@ public:
~DebugEffects();
void draw_shadow_frustum(RID p_light, const Projection &p_cam_projection, const Transform3D &p_cam_transform, RID p_dest_fb, const Rect2 p_rect);
+ void draw_motion_vectors(RID p_velocity, RID p_dest_fb, Size2i p_velocity_size);
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 991ccf984e..d623553273 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -395,6 +395,16 @@ Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
////////////////////////////////////////////////////////////////////////////////
// SDFGI
+static RID create_clear_texture(const RD::TextureFormat &p_format, const String &p_name) {
+ RID texture = RD::get_singleton()->texture_create(p_format, RD::TextureView());
+ ERR_FAIL_COND_V_MSG(texture.is_null(), RID(), String("Cannot create texture: ") + p_name);
+
+ RD::get_singleton()->set_resource_name(texture, p_name);
+ RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, p_format.mipmaps, 0, p_format.array_layers);
+
+ return texture;
+}
+
void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -424,39 +434,31 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
{
RD::TextureFormat tf_render = tf_sdf;
tf_render.format = RD::DATA_FORMAT_R16_UINT;
- render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo");
+ render_albedo = create_clear_texture(tf_render, "SDFGI Render Albedo");
+
tf_render.format = RD::DATA_FORMAT_R32_UINT;
- render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission");
- render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso");
+ render_emission = create_clear_texture(tf_render, "SDFGI Render Emission");
+ render_emission_aniso = create_clear_texture(tf_render, "SDFGI Render Emission Aniso");
tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
for (int i = 0; i < 8; i++) {
- render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i));
+ render_occlusion[i] = create_clear_texture(tf_render, String("SDFGI Render Occlusion ") + itos(i));
}
tf_render.format = RD::DATA_FORMAT_R32_UINT;
- render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing");
+ render_geom_facing = create_clear_texture(tf_render, "SDFGI Render Geometry Facing");
tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
- render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0");
- render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1");
+ render_sdf[0] = create_clear_texture(tf_render, "SDFGI Render SDF 0");
+ render_sdf[1] = create_clear_texture(tf_render, "SDFGI Render SDF 1");
tf_render.width /= 2;
tf_render.height /= 2;
tf_render.depth /= 2;
- render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0");
- render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
- RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1");
+ render_sdf_half[0] = create_clear_texture(tf_render, "SDFGI Render SDF Half 0");
+ render_sdf_half[1] = create_clear_texture(tf_render, "SDFGI Render SDF Half 1");
}
RD::TextureFormat tf_occlusion = tf_sdf;
@@ -496,10 +498,8 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
tf_probe_average.format = RD::DATA_FORMAT_R32G32B32A32_SINT; //signed integer because SH are signed
tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
- lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
- RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll");
- lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
- RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll");
+ lightprobe_history_scroll = create_clear_texture(tf_probe_history, "SDFGI LightProbe History Scroll");
+ lightprobe_average_scroll = create_clear_texture(tf_probe_average, "SDFGI LightProbe Average Scroll");
{
//octahedral lightprobes
@@ -512,8 +512,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32);
//lightprobe texture is an octahedral texture
- lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
- RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data");
+ lightprobe_data = create_clear_texture(tf_octprobes, "SDFGI LightProbe Data");
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
@@ -526,14 +525,12 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
tf_ambient.height = probe_axis_count;
tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
//lightprobe texture is an octahedral texture
- ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
- RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture");
+ ambient_texture = create_clear_texture(tf_ambient, "SDFGI Ambient Texture");
}
cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
- occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
- RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data");
+ occlusion_data = create_clear_texture(tf_occlusion, "SDFGI Occlusion Data");
{
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
@@ -543,25 +540,17 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
for (SDFGI::Cascade &cascade : cascades) {
/* 3D Textures */
- cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
- RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture");
+ cascade.sdf_tex = create_clear_texture(tf_sdf, "SDFGI Cascade SDF Texture");
- cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
- RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data");
+ cascade.light_data = create_clear_texture(tf_light, "SDFGI Cascade Light Data");
- cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
- RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture");
- cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
- RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture");
+ cascade.light_aniso_0_tex = create_clear_texture(tf_aniso0, "SDFGI Cascade Light Aniso 0 Texture");
+ cascade.light_aniso_1_tex = create_clear_texture(tf_aniso1, "SDFGI Cascade Light Aniso 1 Texture");
{
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
cascade.light_tex = RD::get_singleton()->texture_create_shared(tv, cascade.light_data);
-
- RD::get_singleton()->texture_clear(cascade.light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(cascade.light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
- RD::get_singleton()->texture_clear(cascade.light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1);
}
cascade.cell_size = base_cell_size;
@@ -579,11 +568,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
/* Probe History */
cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
- RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture");
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "SDFGI Cascade LightProbe History Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
- RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture");
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "SDFGI Cascade LightProbe Average Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
/* Buffers */
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index c98752fb39..2e64946fd2 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -252,6 +252,7 @@ bool RenderForwardClustered::free(RID p_rid) {
template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags>
void RenderForwardClustered::_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) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -477,7 +478,9 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
prev_material_uniform_set = material_uniform_set;
}
- if ((surf->owner->base_flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH) {
+ if (surf->owner->base_flags & INSTANCE_DATA_FLAG_PARTICLES) {
+ particles_storage->particles_get_instance_buffer_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
+ } else if (surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) {
mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
} else {
push_constant.multimesh_motion_vectors_current_offset = 0;
@@ -3716,6 +3719,10 @@ void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p
// Particles haven't been cleared or updated, update once now to ensure they are ready to render.
particles_storage->update_particles();
}
+
+ if (ginstance->data->dirty_dependencies) {
+ particles_storage->particles_update_dependency(ginstance->data->base, &ginstance->data->dependency_tracker);
+ }
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
@@ -3755,6 +3762,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
case Dependency::DEPENDENCY_CHANGED_MATERIAL:
case Dependency::DEPENDENCY_CHANGED_MESH:
case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES_INSTANCES:
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 12f8f6a366..509072bbec 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -707,6 +707,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
+ actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 90d770399e..3f01ffa3c9 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -752,7 +752,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
bool draw_sky = false;
bool draw_sky_fog_only = false;
// We invert luminance_multiplier for sky so that we can combine it with exposure value.
- float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
+ float inverse_luminance_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
+ float sky_energy_multiplier = inverse_luminance_multiplier;
Color clear_color = p_default_bg_color;
bool keep_color = false;
@@ -899,14 +900,14 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// regular forward for now
Vector<Color> c;
{
- Color cc = clear_color.srgb_to_linear();
+ Color cc = clear_color.srgb_to_linear() * inverse_luminance_multiplier;
if (rb_data.is_valid()) {
cc.a = 0; // For transparent viewport backgrounds.
}
c.push_back(cc); // Our render buffer.
if (rb_data.is_valid()) {
if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
- c.push_back(clear_color.srgb_to_linear()); // Our resolve buffer.
+ c.push_back(clear_color.srgb_to_linear() * inverse_luminance_multiplier); // Our resolve buffer.
}
if (using_subpass_post_process) {
c.push_back(Color()); // Our 2D buffer we're copying into.
@@ -2614,6 +2615,10 @@ void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_ge
// Particles haven't been cleared or updated, update once now to ensure they are ready to render.
particles_storage->update_particles();
}
+
+ if (ginstance->data->dirty_dependencies) {
+ particles_storage->particles_update_dependency(ginstance->data->base, &ginstance->data->dependency_tracker);
+ }
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 32d2289f75..ffbe7f7e59 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -610,6 +610,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
+ actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index d8c035a51c..b1ad7e16ed 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -2587,18 +2587,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
{ // default index buffer
Vector<uint8_t> pv;
- pv.resize(6 * 4);
+ pv.resize(6 * 2);
{
uint8_t *w = pv.ptrw();
- int *p32 = (int *)w;
- p32[0] = 0;
- p32[1] = 1;
- p32[2] = 2;
- p32[3] = 0;
- p32[4] = 2;
- p32[5] = 3;
+ uint16_t *p16 = (uint16_t *)w;
+ p16[0] = 0;
+ p16[1] = 1;
+ p16[2] = 2;
+ p16[3] = 0;
+ p16[4] = 2;
+ p16[5] = 3;
}
- shader.quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ shader.quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT16, pv);
shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6);
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 4ccd2aa322..7eb8cbd02f 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -126,18 +126,18 @@ void RendererCompositorRD::initialize() {
//create index array for copy shader
Vector<uint8_t> pv;
- pv.resize(6 * 4);
+ pv.resize(6 * 2);
{
uint8_t *w = pv.ptrw();
- int *p32 = (int *)w;
- p32[0] = 0;
- p32[1] = 1;
- p32[2] = 2;
- p32[3] = 0;
- p32[4] = 2;
- p32[5] = 3;
+ uint16_t *p16 = (uint16_t *)w;
+ p16[0] = 0;
+ p16[1] = 1;
+ p16[2] = 2;
+ p16[3] = 0;
+ p16[4] = 2;
+ p16[5] = 3;
}
- blit.index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ blit.index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT16, pv);
blit.array = RD::get_singleton()->index_array_create(blit.index_buffer, 0, 6);
blit.sampler = RD::get_singleton()->sampler_create(RD::SamplerState());
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 9d4d266a7a..20e24dba0e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -745,8 +745,7 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(const RenderDataRD *p_ren
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(rb).is_valid()) {
- Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(rb), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
+ debug_effects->draw_motion_vectors(_render_buffers_get_velocity_texture(rb), texture_storage->render_target_get_rd_framebuffer(render_target), rb->get_internal_size());
}
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl b/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl
new file mode 100644
index 0000000000..80e4f51565
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl
@@ -0,0 +1,80 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(location = 0) out vec2 uv_interp;
+
+void main() {
+ vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
+ gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+layout(location = 0) in vec2 uv_interp;
+
+layout(set = 0, binding = 0) uniform sampler2D source_velocity;
+
+layout(location = 0) out vec4 frag_color;
+
+layout(push_constant, std430) uniform Params {
+ vec2 resolution;
+}
+params;
+
+// Based on distance to line segment from https://www.shadertoy.com/view/3tdSDj
+
+float line_segment(in vec2 p, in vec2 a, in vec2 b) {
+ vec2 aspect = vec2(params.resolution.x / params.resolution.y, 1.0f);
+ vec2 ba = (b - a) * aspect;
+ vec2 pa = (p - a) * aspect;
+ float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0f, 1.0f);
+ return length(pa - h * ba) * (params.resolution.y / 2.0f);
+}
+
+void main() {
+ // Retrieve motion vector data.
+ float cell_size = 32.0f;
+ float circle_radius = 2.0f;
+ vec3 nan_color = vec3(1.0f, 0.0f, 0.0f);
+ vec3 active_color = vec3(1.0f, 0.8f, 0.1f);
+ vec3 inactive_color = vec3(0.5f, 0.5f, 0.5f);
+ vec2 pos_pixel = uv_interp * params.resolution;
+ vec2 cell_pos_pixel = floor(pos_pixel / cell_size) * cell_size + (cell_size * 0.5f);
+ vec2 cell_pos_uv = cell_pos_pixel / params.resolution;
+ vec2 cell_pos_previous_uv = cell_pos_uv + textureLod(source_velocity, cell_pos_uv, 0.0f).xy;
+
+ // Draw the shapes.
+ float epsilon = 1e-6f;
+ vec2 cell_pos_delta_uv = cell_pos_uv - cell_pos_previous_uv;
+ bool motion_active = length(cell_pos_delta_uv) > epsilon;
+ vec3 color;
+ if (any(isnan(cell_pos_delta_uv))) {
+ color = nan_color;
+ } else if (motion_active) {
+ color = active_color;
+ } else {
+ color = inactive_color;
+ }
+
+ float alpha;
+ if (length(cell_pos_pixel - pos_pixel) <= circle_radius) {
+ // Circle center.
+ alpha = 1.0f;
+ } else if (motion_active) {
+ // Motion vector line.
+ alpha = 1.0f - line_segment(uv_interp, cell_pos_uv, cell_pos_previous_uv);
+ } else {
+ // Ignore pixel.
+ alpha = 0.0f;
+ }
+
+ frag_color = vec4(color, alpha);
+}
diff --git a/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl
index 02566d8e35..e50397cc5d 100644
--- a/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl
@@ -320,7 +320,7 @@ vec3 temporal_antialiasing(uvec2 pos_group_top_left, uvec2 pos_group, uvec2 pos_
vec2 velocity = imageLoad(velocity_buffer, ivec2(pos_screen)).xy;
// Get reprojected uv
- vec2 uv_reprojected = uv - velocity;
+ vec2 uv_reprojected = uv + velocity;
// Get input color
vec3 color_input = load_color(pos_group);
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index d1cfda515f..cfba408fe1 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -802,7 +802,9 @@ void fragment_shader(in SceneData scene_data) {
float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
+#ifndef FOG_DISABLED
vec4 fog = vec4(0.0);
+#endif // !FOG_DISABLED
#if defined(CUSTOM_RADIANCE_USED)
vec4 custom_radiance = vec4(0.0);
#endif
@@ -962,6 +964,7 @@ void fragment_shader(in SceneData scene_data) {
/////////////////////// FOG //////////////////////
#ifndef MODE_RENDER_DEPTH
+#ifndef FOG_DISABLED
#ifndef CUSTOM_FOG_USED
// fog must be processed as early as possible and then packed.
// to maximize VGPR usage
@@ -997,6 +1000,7 @@ void fragment_shader(in SceneData scene_data) {
uint fog_rg = packHalf2x16(fog.rg);
uint fog_ba = packHalf2x16(fog.ba);
+#endif //!FOG_DISABLED
#endif //!MODE_RENDER_DEPTH
/////////////////////// DECALS ////////////////////////////////
@@ -2250,8 +2254,10 @@ void fragment_shader(in SceneData scene_data) {
diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic;
+#ifndef FOG_DISABLED
//restore fog
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
+#endif //!FOG_DISABLED
#ifdef MODE_SEPARATE_SPECULAR
@@ -2268,8 +2274,10 @@ void fragment_shader(in SceneData scene_data) {
specular_buffer = vec4(specular_light, metallic);
#endif
+#ifndef FOG_DISABLED
diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
+#endif //!FOG_DISABLED
#else //MODE_SEPARATE_SPECULAR
@@ -2280,8 +2288,10 @@ void fragment_shader(in SceneData scene_data) {
//frag_color = vec4(1.0);
#endif //USE_NO_SHADING
+#ifndef FOG_DISABLED
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+#endif //!FOG_DISABLED
#endif //MODE_SEPARATE_SPECULAR
@@ -2293,7 +2303,7 @@ void fragment_shader(in SceneData scene_data) {
vec2 position_uv = position_clip * vec2(0.5, 0.5);
vec2 prev_position_uv = prev_position_clip * vec2(0.5, 0.5);
- motion_vector = position_uv - prev_position_uv;
+ motion_vector = prev_position_uv - position_uv;
#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index b63eea1401..cdf81bb6ec 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -694,7 +694,9 @@ void main() {
float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
+#ifndef FOG_DISABLED
vec4 fog = vec4(0.0);
+#endif // !FOG_DISABLED
#if defined(CUSTOM_RADIANCE_USED)
vec4 custom_radiance = vec4(0.0);
#endif
@@ -860,6 +862,7 @@ void main() {
/////////////////////// FOG //////////////////////
#ifndef MODE_RENDER_DEPTH
+#ifndef FOG_DISABLED
#ifndef CUSTOM_FOG_USED
// fog must be processed as early as possible and then packed.
// to maximize VGPR usage
@@ -874,6 +877,7 @@ void main() {
uint fog_rg = packHalf2x16(fog.rg);
uint fog_ba = packHalf2x16(fog.ba);
+#endif //!FOG_DISABLED
#endif //!MODE_RENDER_DEPTH
/////////////////////// DECALS ////////////////////////////////
@@ -899,6 +903,10 @@ void main() {
break;
}
+ if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {
+ continue; //not masked
+ }
+
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
@@ -1740,8 +1748,10 @@ void main() {
diffuse_light *= 1.0 - metallic;
ambient_light *= 1.0 - metallic;
+#ifndef FOG_DISABLED
//restore fog
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
+#endif // !FOG_DISABLED
#ifdef MODE_MULTIPLE_RENDER_TARGETS
@@ -1758,8 +1768,10 @@ void main() {
specular_buffer = vec4(specular_light, metallic);
#endif // MODE_UNSHADED
+#ifndef FOG_DISABLED
diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
+#endif // !FOG_DISABLED
#else //MODE_MULTIPLE_RENDER_TARGETS
@@ -1769,8 +1781,10 @@ void main() {
frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha);
#endif // MODE_UNSHADED
+#ifndef FOG_DISABLED
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+#endif // !FOG_DISABLED
// On mobile we use a UNORM buffer with 10bpp which results in a range from 0.0 - 1.0 resulting in HDR breaking
// We divide by sc_luminance_multiplier to support a range from 0.0 - 2.0 both increasing precision on bright and darker images
diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl
index 67a894b86f..93c4d1009d 100644
--- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl
@@ -45,6 +45,9 @@ layout(set = 2, binding = 0, std430) restrict readonly buffer TrailBindPoses {
}
trail_bind_poses;
+#define PARAMS_FLAG_ORDER_BY_LIFETIME 1
+#define PARAMS_FLAG_COPY_MODE_2D 2
+
layout(push_constant, std430) uniform Params {
vec3 sort_direction;
uint total_particles;
@@ -57,10 +60,10 @@ layout(push_constant, std430) uniform Params {
vec3 align_up;
uint align_mode;
- bool order_by_lifetime;
uint lifetime_split;
bool lifetime_reverse;
- bool copy_mode_2d;
+ uint motion_vectors_current_offset;
+ uint flags;
mat4 inv_emission_transform;
}
@@ -103,7 +106,7 @@ void main() {
particle = uint(sort_buffer.data[particle].y); //use index from sort buffer
}
#else
- if (params.order_by_lifetime) {
+ if (bool(params.flags & PARAMS_FLAG_ORDER_BY_LIFETIME)) {
if (params.trail_size > 1) {
uint limit = (params.total_particles / params.trail_size) - params.lifetime_split;
@@ -179,7 +182,6 @@ void main() {
case TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY: {
vec3 v = particles.data[particle].velocity;
vec3 sv = v - params.sort_direction * dot(params.sort_direction, v); //screen velocity
- float s = (length(txform[0]) + length(txform[1]) + length(txform[2])) / 3.0;
if (length(sv) == 0) {
sv = params.align_up;
@@ -187,9 +189,9 @@ void main() {
sv = normalize(sv);
- txform[0].xyz = normalize(cross(sv, params.sort_direction)) * s;
- txform[1].xyz = sv * s;
- txform[2].xyz = params.sort_direction * s;
+ txform[0].xyz = normalize(cross(sv, params.sort_direction)) * length(txform[0]);
+ txform[1].xyz = sv * length(txform[1]);
+ txform[2].xyz = params.sort_direction * length(txform[2]);
} break;
}
@@ -201,7 +203,7 @@ void main() {
txform = txform * trail_bind_poses.data[part_ofs];
}
- if (params.copy_mode_2d) {
+ if (bool(params.flags & PARAMS_FLAG_COPY_MODE_2D)) {
// In global mode, bring 2D particles to local coordinates
// as they will be drawn with the node position as origin.
txform = params.inv_emission_transform * txform;
@@ -213,15 +215,16 @@ void main() {
}
txform = transpose(txform);
- if (params.copy_mode_2d) {
- uint write_offset = gl_GlobalInvocationID.x * (2 + 1 + 1); //xform + color + custom
+ uint instance_index = gl_GlobalInvocationID.x + params.motion_vectors_current_offset;
+ if (bool(params.flags & PARAMS_FLAG_COPY_MODE_2D)) {
+ uint write_offset = instance_index * (2 + 1 + 1); //xform + color + custom
instances.data[write_offset + 0] = txform[0];
instances.data[write_offset + 1] = txform[1];
instances.data[write_offset + 2] = particles.data[particle].color;
instances.data[write_offset + 3] = particles.data[particle].custom;
} else {
- uint write_offset = gl_GlobalInvocationID.x * (3 + 1 + 1); //xform + color + custom
+ uint write_offset = instance_index * (3 + 1 + 1); //xform + color + custom
instances.data[write_offset + 0] = txform[0];
instances.data[write_offset + 1] = txform[1];
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index fda341bbc9..5c4fa1a47c 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -1191,18 +1191,18 @@ MaterialStorage::MaterialStorage() {
// buffers
{ //create index array for copy shaders
Vector<uint8_t> pv;
- pv.resize(6 * 4);
+ pv.resize(6 * 2);
{
uint8_t *w = pv.ptrw();
- int *p32 = (int *)w;
- p32[0] = 0;
- p32[1] = 1;
- p32[2] = 2;
- p32[3] = 0;
- p32[4] = 2;
- p32[5] = 3;
+ uint16_t *p16 = (uint16_t *)w;
+ p16[0] = 0;
+ p16[1] = 1;
+ p16[2] = 2;
+ p16[3] = 0;
+ p16[4] = 2;
+ p16[5] = 3;
}
- quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
+ quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT16, pv);
quad_index_array = RD::get_singleton()->index_array_create(quad_index_buffer, 0, 6);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 0a91672544..3a415e97e0 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -666,6 +666,19 @@ RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass)
return particles->draw_passes[p_pass];
}
+void ParticlesStorage::particles_update_dependency(RID p_particles, DependencyTracker *p_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ p_instance->update_dependency(&particles->dependency);
+}
+
+void ParticlesStorage::particles_get_instance_buffer_motion_vectors_offsets(RID p_particles, uint32_t &r_current_offset, uint32_t &r_prev_offset) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ r_current_offset = particles->instance_motion_vectors_current_offset;
+ r_prev_offset = particles->instance_motion_vectors_previous_offset;
+}
+
void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
@@ -1185,6 +1198,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
copy_push_constant.lifetime_split = (MIN(int(particles->amount * particles->phase), particles->amount - 1) + 1) % particles->amount;
copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+ copy_push_constant.motion_vectors_current_offset = particles->instance_motion_vectors_current_offset;
copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
copy_push_constant.total_particles = particles->amount;
@@ -1252,28 +1266,50 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) {
userdata_count = particle_shader_data->userdata_count;
}
+ bool uses_motion_vectors = RSG::viewport->get_num_viewports_with_motion_vectors() > 0;
+ bool index_draw_order = particles->draw_order == RS::ParticlesDrawOrder::PARTICLES_DRAW_ORDER_INDEX;
+ bool enable_motion_vectors = uses_motion_vectors && index_draw_order && !particles->instance_motion_vectors_enabled;
+ bool only_instances_changed = false;
+
if (userdata_count != particles->userdata_count) {
- // Mismatch userdata, re-create buffers.
+ // Mismatch userdata, re-create all buffers.
_particles_free_data(particles);
+ } else if (enable_motion_vectors) {
+ // Only motion vectors are required, release the transforms buffer and uniform set.
+ if (particles->particle_instance_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->particle_instance_buffer);
+ particles->particle_instance_buffer = RID();
+ }
+
+ particles->particles_transforms_buffer_uniform_set = RID();
+ only_instances_changed = true;
+ } else if (!particles->particle_buffer.is_null()) {
+ // No operation is required because a buffer already exists, return early.
+ return;
}
- if (particles->amount > 0 && particles->particle_buffer.is_null()) {
+ if (particles->amount > 0) {
int total_amount = particles->amount;
if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
total_amount *= particles->trail_bind_poses.size();
}
uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
-
- particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
-
- particles->userdata_count = userdata_count;
+ if (particles->particle_buffer.is_null()) {
+ particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
+ particles->userdata_count = userdata_count;
+ }
PackedByteArray data;
- data.resize_zeroed(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount);
+ uint32_t particle_instance_buffer_size = total_amount * (xform_size + 1 + 1) * sizeof(float) * 4;
+ if (uses_motion_vectors) {
+ particle_instance_buffer_size *= 2;
+ particles->instance_motion_vectors_enabled = true;
+ }
- particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount, data);
- //needs to clear it
+ data.resize_zeroed(particle_instance_buffer_size);
+
+ particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(particle_instance_buffer_size, data);
{
Vector<RD::Uniform> uniforms;
@@ -1295,9 +1331,20 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) {
particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0);
}
+
+ particles->instance_motion_vectors_current_offset = 0;
+ particles->instance_motion_vectors_previous_offset = 0;
+ particles->instance_motion_vectors_last_change = -1;
+
+ if (only_instances_changed) {
+ // Notify the renderer the instances uniform must be retrieved again, as it's the only element that has been changed because motion vectors were enabled.
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES_INSTANCES);
+ }
}
}
void ParticlesStorage::update_particles() {
+ uint32_t frame = RSG::rasterizer->get_frame_number();
+ bool uses_motion_vectors = RSG::viewport->get_num_viewports_with_motion_vectors() > 0;
while (particle_update_list) {
//use transform feedback to process particles
@@ -1461,16 +1508,25 @@ void ParticlesStorage::update_particles() {
// Ensure that memory is initialized (the code above should ensure that _particles_process is always called at least once upon clearing).
DEV_ASSERT(!particles->clear);
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ // Swap offsets for motion vectors. Motion vectors can only be used when the draw order keeps the indices consistent across frames.
+ bool index_draw_order = particles->draw_order == RS::ParticlesDrawOrder::PARTICLES_DRAW_ORDER_INDEX;
+ particles->instance_motion_vectors_previous_offset = particles->instance_motion_vectors_current_offset;
+ if (uses_motion_vectors && index_draw_order && particles->instance_motion_vectors_enabled && (frame - particles->instance_motion_vectors_last_change) == 1) {
+ particles->instance_motion_vectors_current_offset = total_amount - particles->instance_motion_vectors_current_offset;
+ }
+
+ particles->instance_motion_vectors_last_change = frame;
+
// Copy particles to instance buffer.
if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
//does not need view dependent operation, do copy here
ParticlesShader::CopyPushConstant copy_push_constant;
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
// Affect 2D only.
if (particles->use_local_coords) {
// In local mode, particle positions are calculated locally (relative to the node position)
@@ -1506,6 +1562,7 @@ void ParticlesStorage::update_particles() {
copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
copy_push_constant.lifetime_split = (MIN(int(particles->amount * particles->phase), particles->amount - 1) + 1) % particles->amount;
copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+ copy_push_constant.motion_vectors_current_offset = particles->instance_motion_vectors_current_offset;
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 612420a36c..7cea706a8c 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -225,6 +225,11 @@ private:
double frame_remainder = 0;
real_t collision_base_size = 0.01;
+ uint32_t instance_motion_vectors_current_offset = 0;
+ uint32_t instance_motion_vectors_previous_offset = 0;
+ uint64_t instance_motion_vectors_last_change = -1;
+ bool instance_motion_vectors_enabled = false;
+
bool clear = true;
bool force_sub_emit = false;
@@ -288,10 +293,13 @@ private:
float align_up[3];
uint32_t align_mode;
- uint32_t order_by_lifetime;
uint32_t lifetime_split;
uint32_t lifetime_reverse;
- uint32_t copy_mode_2d;
+ uint32_t motion_vectors_current_offset;
+ struct {
+ uint32_t order_by_lifetime : 1;
+ uint32_t copy_mode_2d : 1;
+ };
float inv_emission_transform[16];
};
@@ -521,12 +529,15 @@ public:
return particles->particles_transforms_buffer_uniform_set;
}
+ void particles_get_instance_buffer_motion_vectors_offsets(RID p_particles, uint32_t &r_current_offset, uint32_t &r_prev_offset);
+
virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
virtual void update_particles() override;
+ void particles_update_dependency(RID p_particles, DependencyTracker *p_instance);
Dependency *particles_get_dependency(RID p_particles) const;
/* Particles Collision */