diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index fbd257cdbaa..c3ef9f24250 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1569,12 +1569,16 @@
Lower-end override for [member rendering/shadows/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
+
+
Sets the maximum number of samples to take when using anisotropic filtering on textures (as a power of two). A higher sample count will result in sharper textures at oblique angles, but is more expensive to compute. A value of [code]0[/code] forcibly disables anisotropic filtering, even on materials where it is enabled.
If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
+
+
If [code]true[/code], the texture importer will import lossless textures using the PNG format. Otherwise, it will default to using WebP.
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 6b45653bf21..31ced67ac49 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -1209,6 +1209,14 @@
+
+
+
+
+
+
+
+
@@ -2153,6 +2161,14 @@
Sets whether to use a dual paraboloid or a cubemap for the shadow map. Dual paraboloid is faster but may suffer from artifacts. Equivalent to [member OmniLight3D.omni_shadow_mode].
+
+
+
+
+
+
+
+
@@ -4865,6 +4881,16 @@
Use [Transform3D] to store MultiMesh transform.
+
+
+
+
+
+
+
+
+
+
Is a directional (sun) light.
@@ -4986,6 +5012,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 712e571e579..4ff6410cddb 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -508,6 +508,9 @@ void EditorNode::_update_from_settings() {
float lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
scene_root->set_lod_threshold(lod_threshold);
+
+ RS::get_singleton()->decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
+ RS::get_singleton()->light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
}
void EditorNode::_notification(int p_what) {
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index 3f751cfbe8a..b7cf0983af8 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -201,6 +201,9 @@ public:
void update() override {}
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
+ virtual void decals_set_filter(RS::DecalFilter p_filter) override {}
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override {}
+
RasterizerSceneDummy() {}
~RasterizerSceneDummy() {}
};
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 b457f5d1220..ac20515c28d 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -589,11 +589,6 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
- scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
- scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
- scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
- scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
-
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;
@@ -1942,15 +1937,54 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_omni_light_buffer());
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ RID sampler;
+ switch (decals_get_filter()) {
+ case RS::DECAL_FILTER_NEAREST: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_LINEAR: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
uniforms.push_back(u);
}
+
{
RD::Uniform u;
u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_spot_light_buffer());
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ RID sampler;
+ switch (light_projectors_get_filter()) {
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
uniforms.push_back(u);
}
@@ -1958,33 +1992,48 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_reflection_probe_buffer());
+ u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(get_spot_light_buffer());
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 7;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(get_reflection_probe_buffer());
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 9;
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 = 8;
+ u.binding = 10;
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 = 9;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -1992,7 +2041,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -2000,7 +2049,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -2009,7 +2058,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 12;
+ u.binding = 14;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2017,7 +2066,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 13;
+ u.binding = 15;
u.ids.push_back(sdfgi_get_ubo());
uniforms.push_back(u);
}
@@ -2939,6 +2988,48 @@ void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(
_geometry_instance_mark_dirty(ginstance);
}
+void RenderForwardClustered::_update_shader_quality_settings() {
+ Vector spec_constants;
+
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+
+ sc.constant_id = SPEC_CONSTANT_SOFT_SHADOW_SAMPLES;
+ sc.int_value = soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES;
+ sc.int_value = directional_soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = directional_penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ scene_shader.set_default_specialization_constants(spec_constants);
+
+ _base_uniforms_changed(); //also need this
+}
+
RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
@@ -2976,6 +3067,8 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
}
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
+
+ _update_shader_quality_settings();
}
RenderForwardClustered::~RenderForwardClustered() {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index b70cefd9804..6682c5e9b06 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -50,6 +50,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
MATERIAL_UNIFORM_SET = 3
};
+ enum {
+ SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6,
+ SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7,
+ SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8,
+ SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
+ SPEC_CONSTANT_DECAL_FILTER = 10,
+ SPEC_CONSTANT_PROJECTOR_FILTER = 11,
+ };
+
enum {
SDFGI_MAX_CASCADES = 8,
MAX_VOXEL_GI_INSTANCESS = 8,
@@ -222,11 +231,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float penumbra_shadow_kernel[128];
float soft_shadow_kernel[128];
- uint32_t directional_penumbra_shadow_samples;
- uint32_t directional_soft_shadow_samples;
- uint32_t penumbra_shadow_samples;
- uint32_t soft_shadow_samples;
-
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -573,6 +577,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RenderList render_list[RENDER_LIST_MAX];
+ virtual void _update_shader_quality_settings() override;
+
protected:
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 706a75e6410..5113a3d5dbf 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
@@ -324,7 +324,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
}
}
@@ -408,7 +408,8 @@ RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_s
return shader_singleton->shader.version_get_native_source_code(version);
}
-SceneShaderForwardClustered::ShaderData::ShaderData() {
+SceneShaderForwardClustered::ShaderData::ShaderData() :
+ shader_list_element(this) {
valid = false;
uses_screen_texture = false;
}
@@ -424,6 +425,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
RendererStorageRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
+ singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
}
@@ -728,3 +730,16 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
}
+
+void SceneShaderForwardClustered::set_default_specialization_constants(const Vector &p_constants) {
+ default_specialization_constants = p_constants;
+ for (SelfList *E = shader_list.first(); E; E = E->next()) {
+ for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
+ for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
+ for (int k = 0; k < SHADER_VERSION_MAX; k++) {
+ E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
+ }
+ }
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 8dfd18cca54..8d75f30a208 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -160,10 +160,13 @@ public:
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SelfList shader_list_element;
ShaderData();
virtual ~ShaderData();
};
+ SelfList::List shader_list;
+
RendererStorageRD::ShaderData *_create_shader_func();
static RendererStorageRD::ShaderData *_create_shader_funcs() {
return static_cast(singleton)->_create_shader_func();
@@ -209,10 +212,12 @@ public:
RID overdraw_material_uniform_set;
ShaderData *overdraw_material_shader_ptr = nullptr;
+ Vector default_specialization_constants;
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
void init(RendererStorageRD *p_storage, const String p_defines);
+ void set_default_specialization_constants(const Vector &p_constants);
};
} // namespace RendererSceneRenderImplementation
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 4985fd1687b..438bbff53c1 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -899,15 +899,54 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_omni_light_buffer());
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ RID sampler;
+ switch (decals_get_filter()) {
+ case RS::DECAL_FILTER_NEAREST: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_LINEAR: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
uniforms.push_back(u);
}
+
{
RD::Uniform u;
u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_spot_light_buffer());
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ RID sampler;
+ switch (light_projectors_get_filter()) {
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
+ sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
+ }
+
+ u.ids.push_back(sampler);
uniforms.push_back(u);
}
@@ -915,33 +954,48 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.ids.push_back(get_reflection_probe_buffer());
+ u.ids.push_back(get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(get_spot_light_buffer());
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.binding = 7;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.ids.push_back(get_reflection_probe_buffer());
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
u.ids.push_back(get_directional_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 9;
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 = 8;
+ u.binding = 10;
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 = 9;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture();
u.ids.push_back(decal_atlas);
@@ -949,7 +1003,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID decal_atlas = storage->decal_atlas_get_texture_srgb();
u.ids.push_back(decal_atlas);
@@ -957,7 +1011,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
}
{
RD::Uniform u;
- u.binding = 11;
+ u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.ids.push_back(get_decal_buffer());
uniforms.push_back(u);
@@ -966,7 +1020,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 12;
+ u.binding = 14;
u.ids.push_back(storage->global_variables_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1203,11 +1257,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
- scene_state.ubo.directional_penumbra_shadow_samples = directional_penumbra_shadow_samples_get();
- scene_state.ubo.directional_soft_shadow_samples = directional_soft_shadow_samples_get();
- scene_state.ubo.penumbra_shadow_samples = penumbra_shadow_samples_get();
- scene_state.ubo.soft_shadow_samples = soft_shadow_samples_get();
-
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;
@@ -2237,6 +2286,48 @@ uint32_t RenderForwardMobile::get_max_elements() const {
RenderForwardMobile *RenderForwardMobile::singleton = nullptr;
+void RenderForwardMobile::_update_shader_quality_settings() {
+ Vector spec_constants;
+
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+
+ sc.constant_id = SPEC_CONSTANT_SOFT_SHADOW_SAMPLES;
+ sc.int_value = soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES;
+ sc.int_value = directional_soft_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES;
+ sc.int_value = directional_penumbra_shadow_samples_get();
+
+ spec_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+
+ spec_constants.push_back(sc);
+
+ scene_shader.set_default_specialization_constants(spec_constants);
+
+ _base_uniforms_changed(); //also need this
+}
+
RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
RendererSceneRenderRD(p_storage) {
singleton = this;
@@ -2272,6 +2363,8 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
// !BAS! maybe we need a mobile version of this setting?
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
+
+ _update_shader_quality_settings();
}
RenderForwardMobile::~RenderForwardMobile() {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 5d28cdb5d39..973925d562a 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -64,6 +64,15 @@ protected:
MATERIAL_UNIFORM_SET = 3
};
+ enum {
+ SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6,
+ SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7,
+ SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8,
+ SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
+ SPEC_CONSTANT_DECAL_FILTER = 10,
+ SPEC_CONSTANT_PROJECTOR_FILTER = 11,
+ };
+
enum {
MAX_LIGHTMAPS = 8,
MAX_RDL_CULL = 8, // maximum number of reflection probes, decals or lights we can cull per geometry instance
@@ -228,11 +237,6 @@ protected:
float penumbra_shadow_kernel[128];
float soft_shadow_kernel[128];
- uint32_t directional_penumbra_shadow_samples;
- uint32_t directional_soft_shadow_samples;
- uint32_t penumbra_shadow_samples;
- uint32_t soft_shadow_samples;
-
float ambient_light_color_energy[4];
float ambient_color_sky_mix;
@@ -569,6 +573,8 @@ protected:
_FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, const GeometryInstanceForwardMobile *p_instance);
+ void _update_shader_quality_settings() override;
+
public:
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);
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 7709c8aadc8..3f4c69270ff 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
@@ -318,7 +318,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
}
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
}
}
@@ -402,7 +402,8 @@ RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_sour
return shader_singleton->shader.version_get_native_source_code(version);
}
-SceneShaderForwardMobile::ShaderData::ShaderData() {
+SceneShaderForwardMobile::ShaderData::ShaderData() :
+ shader_list_element(this) {
valid = false;
uses_screen_texture = false;
}
@@ -418,6 +419,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
+ singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
}
@@ -718,6 +720,19 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
+void SceneShaderForwardMobile::set_default_specialization_constants(const Vector &p_constants) {
+ default_specialization_constants = p_constants;
+ for (SelfList *E = shader_list.first(); E; E = E->next()) {
+ for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
+ for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
+ for (int k = 0; k < SHADER_VERSION_MAX; k++) {
+ E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
+ }
+ }
+ }
+ }
+}
+
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
RD::get_singleton()->free(default_vec4_xform_buffer);
RD::get_singleton()->free(shadow_sampler);
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 5c9e35fd0d2..e1c10f02069 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -151,6 +151,8 @@ public:
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SelfList shader_list_element;
+
ShaderData();
virtual ~ShaderData();
};
@@ -174,6 +176,8 @@ public:
virtual ~MaterialData();
};
+ SelfList::List shader_list;
+
RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
return static_cast(singleton)->_create_material_func(static_cast(p_shader));
@@ -202,7 +206,10 @@ public:
SceneShaderForwardMobile();
~SceneShaderForwardMobile();
+ Vector default_specialization_constants;
+
void init(RendererStorageRD *p_storage, const String p_defines);
+ void set_default_specialization_constants(const Vector &p_constants);
};
} // namespace RendererSceneRenderImplementation
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index 2bdd5239205..aefe926cb02 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -68,6 +68,9 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
}
void PipelineCacheRD::_clear() {
+#ifndef _MSC_VER
+#warning Clear should probably recompile all the variants already compiled instead to avoid stalls? needs discussion
+#endif
if (versions) {
for (uint32_t i = 0; i < version_count; i++) {
//shader may be gone, so this may not be valid
@@ -94,6 +97,10 @@ void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const
dynamic_state_flags = p_dynamic_state_flags;
base_specialization_constants = p_base_specialization_constants;
}
+void PipelineCacheRD::update_specialization_constants(const Vector &p_base_specialization_constants) {
+ base_specialization_constants = p_base_specialization_constants;
+ _clear();
+}
void PipelineCacheRD::update_shader(RID p_shader) {
ERR_FAIL_COND(p_shader.is_null());
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 71e26283e1c..e52f47fa47a 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -66,6 +66,7 @@ class PipelineCacheRD {
public:
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, const Vector &p_base_specialization_constants = Vector());
+ void update_specialization_constants(const Vector &p_base_specialization_constants);
void update_shader(RID p_shader);
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0, uint32_t p_bool_specializations = 0) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 7b5f448c18e..4870f5f397e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2259,6 +2259,8 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
get_vogel_disk(penumbra_shadow_kernel, penumbra_shadow_samples);
get_vogel_disk(soft_shadow_kernel, soft_shadow_samples);
}
+
+ _update_shader_quality_settings();
}
void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
@@ -2299,6 +2301,23 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q
get_vogel_disk(directional_penumbra_shadow_kernel, directional_penumbra_shadow_samples);
get_vogel_disk(directional_soft_shadow_kernel, directional_soft_shadow_samples);
}
+
+ _update_shader_quality_settings();
+}
+
+void RendererSceneRenderRD::decals_set_filter(RenderingServer::DecalFilter p_filter) {
+ if (decals_filter == p_filter) {
+ return;
+ }
+ decals_filter = p_filter;
+ _update_shader_quality_settings();
+}
+void RendererSceneRenderRD::light_projectors_set_filter(RenderingServer::LightProjectorFilter p_filter) {
+ if (light_projectors_filter == p_filter) {
+ return;
+ }
+ light_projectors_filter = p_filter;
+ _update_shader_quality_settings();
}
int RendererSceneRenderRD::get_roughness_layers() const {
@@ -4287,6 +4306,9 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));
+ decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
+ light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
+
cull_argument.set_page_pool(&cull_argument_pool);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index cd2056d390a..5e0281002d2 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -165,6 +165,8 @@ protected:
virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) {}
virtual bool _uses_forward_ids() const { return false; }
+ virtual void _update_shader_quality_settings() {}
+
private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
static RendererSceneRenderRD *singleton;
@@ -305,6 +307,8 @@ private:
int directional_soft_shadow_samples = 0;
int penumbra_shadow_samples = 0;
int soft_shadow_samples = 0;
+ RS::DecalFilter decals_filter = RS::DECAL_FILTER_LINEAR_MIPMAPS;
+ RS::LightProjectorFilter light_projectors_filter = RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS;
/* DIRECTIONAL SHADOW */
@@ -1197,6 +1201,10 @@ public:
virtual void shadows_quality_set(RS::ShadowQuality p_quality) override;
virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override;
+
+ virtual void decals_set_filter(RS::DecalFilter p_filter) override;
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
+
_FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
_FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
_FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
@@ -1212,6 +1220,9 @@ public:
_FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; }
_FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; }
+ _FORCE_INLINE_ RS::LightProjectorFilter light_projectors_get_filter() const { return light_projectors_filter; }
+ _FORCE_INLINE_ RS::DecalFilter decals_get_filter() const { return decals_filter; }
+
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 763c3895a91..ef1c9bacfb1 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -356,13 +356,24 @@ void main() {
#VERSION_DEFINES
-/* Specialization Constants */
+/* Specialization Constants (Toggles) */
layout(constant_id = 0) const bool sc_use_forward_gi = false;
layout(constant_id = 1) const bool sc_use_light_projector = false;
layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
+/* Specialization Constants (Values) */
+
+layout(constant_id = 6) const uint sc_soft_shadow_samples = 4;
+layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4;
+
+layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4;
+layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
+
+layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
+layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
+
#include "scene_forward_clustered_inc.glsl"
/* Varyings */
@@ -796,25 +807,35 @@ void main() {
continue; //out of decal
}
- //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);
}
+ //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;
+
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);
+ vec4 decal_albedo;
+ if (sc_decal_use_mipmaps) {
+ decal_albedo = textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), 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);
+ } else {
+ decal_albedo = textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].albedo_rect.zw + decals.data[decal_index].albedo_rect.xy, 0.0);
+ }
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;
+ vec3 decal_normal;
+ if (sc_decal_use_mipmaps) {
+ decal_normal = textureGrad(sampler2D(decal_atlas, decal_sampler), 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;
+ } else {
+ decal_normal = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].normal_rect.zw + decals.data[decal_index].normal_rect.xy, 0.0).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
@@ -824,7 +845,12 @@ void main() {
}
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;
+ vec3 decal_orm;
+ if (sc_decal_use_mipmaps) {
+ decal_orm = textureGrad(sampler2D(decal_atlas, decal_sampler), 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;
+ } else {
+ decal_orm = textureLod(sampler2D(decal_atlas, decal_sampler), uv_local.xz * decals.data[decal_index].orm_rect.zw + decals.data[decal_index].orm_rect.xy, 0.0).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);
@@ -833,7 +859,11 @@ void main() {
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 (sc_decal_use_mipmaps) {
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), 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;
+ } else {
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ }
}
}
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index 6599a42bab7..3a052756529 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -52,6 +52,10 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
+layout(set = 0, binding = 3) uniform sampler decal_sampler;
+
+layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
+
#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
@@ -67,22 +71,22 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
-layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
+layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights {
LightData data[];
}
omni_lights;
-layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+layout(set = 0, binding = 6, std430) restrict readonly buffer SpotLights {
LightData data[];
}
spot_lights;
-layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData {
+layout(set = 0, binding = 7, std430) restrict readonly buffer ReflectionProbeData {
ReflectionData data[];
}
reflections;
-layout(set = 0, binding = 6, std140) uniform DirectionalLights {
+layout(set = 0, binding = 8, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
@@ -94,7 +98,7 @@ struct Lightmap {
mat3 normal_xform;
};
-layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
+layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
lightmaps;
@@ -103,20 +107,20 @@ struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 9) uniform texture2D decal_atlas;
-layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 11) uniform texture2D decal_atlas;
+layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -128,7 +132,7 @@ struct SDFVoxelGICascadeData {
float to_cell; // 1/bounds * grid_size
};
-layout(set = 0, binding = 13, std140) uniform SDFGI {
+layout(set = 0, binding = 15, std140) uniform SDFGI {
vec3 grid_size;
uint max_cascades;
@@ -179,11 +183,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
vec4 penumbra_shadow_kernel[32];
vec4 soft_shadow_kernel[32];
- uint directional_penumbra_shadow_samples;
- uint directional_soft_shadow_samples;
- uint penumbra_shadow_samples;
- uint soft_shadow_samples;
-
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 79790b1bfe5..7039ea29429 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -301,7 +301,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (scene_data.directional_soft_shadow_samples == 1) {
+ if (sc_directional_soft_shadow_samples == 1) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -315,11 +315,11 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float avg = 0.0;
- for (uint i = 0; i < scene_data.directional_soft_shadow_samples; i++) {
+ for (uint i = 0; i < sc_directional_soft_shadow_samples; i++) {
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0));
}
- return avg * (1.0 / float(scene_data.directional_soft_shadow_samples));
+ return avg * (1.0 / float(sc_directional_soft_shadow_samples));
}
float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
@@ -327,7 +327,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (scene_data.soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 1) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -341,11 +341,11 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) {
float avg = 0.0;
- for (uint i = 0; i < scene_data.soft_shadow_samples; i++) {
+ for (uint i = 0; i < sc_soft_shadow_samples; i++) {
avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0));
}
- return avg * (1.0 / float(scene_data.soft_shadow_samples));
+ return avg * (1.0 / float(sc_soft_shadow_samples));
}
float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex_scale) {
@@ -361,7 +361,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
disk_rotation = mat2(vec2(cr, -sr), vec2(sr, cr));
}
- for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) {
vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
if (d < pssm_coord.z) {
@@ -377,12 +377,12 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
tex_scale *= penumbra;
float s = 0.0;
- for (uint i = 0; i < scene_data.directional_penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) {
vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale;
s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0));
}
- return s / float(scene_data.directional_penumbra_shadow_samples);
+ return s / float(sc_directional_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -448,7 +448,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
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++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
@@ -485,7 +485,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
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++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy;
vec3 pos = splane.xyz + tangent * disk.x + bitangent * disk.y;
@@ -506,7 +506,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(pos.xy, z_norm, 1.0));
}
- shadow /= float(scene_data.penumbra_shadow_samples);
+ shadow /= float(sc_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -626,40 +626,45 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
local_v.xy = local_v.xy * 0.5 + 0.5;
vec2 proj_uv = local_v.xy * atlas_rect.zw;
- 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);
+ if (sc_projector_use_mipmaps) {
+ 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);
- if (local_v_ddx.z >= 0.0) {
- local_v_ddx.z += 1.0;
- } else {
- local_v_ddx.z = 1.0 - local_v_ddx.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_ddx.xy /= local_v_ddx.z;
+ local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
+
+ proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
+
+ vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
+ local_v_ddy = normalize(local_v_ddy);
+
+ if (local_v_ddy.z >= 0.0) {
+ local_v_ddy.z += 1.0;
+ } else {
+ local_v_ddy.z = 1.0 - local_v_ddy.z;
+ }
+
+ 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;
}
- local_v_ddx.xy /= local_v_ddx.z;
- local_v_ddx.xy = local_v_ddx.xy * 0.5 + 0.5;
-
- proj_uv_ddx = local_v_ddx.xy * atlas_rect.zw - proj_uv;
-
- vec3 local_v_ddy = (omni_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0)).xyz;
- local_v_ddy = normalize(local_v_ddy);
-
- if (local_v_ddy.z >= 0.0) {
- local_v_ddy.z += 1.0;
- } else {
- local_v_ddy.z = 1.0 - local_v_ddy.z;
- }
-
- 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;
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ color *= proj.rgb * proj.a;
+ } else {
+ vec4 proj = textureLod(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + atlas_rect.xy, 0.0);
+ color *= proj.rgb * proj.a;
}
-
- 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);
- color *= proj.rgb * proj.a;
}
light_attenuation *= shadow;
@@ -736,7 +741,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
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++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
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;
@@ -753,13 +758,13 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
uv_size *= penumbra;
shadow = 0.0;
- for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
+ for (uint i = 0; i < sc_penumbra_shadow_samples; i++) {
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0));
}
- shadow /= float(scene_data.penumbra_shadow_samples);
+ shadow /= float(sc_penumbra_shadow_samples);
} else {
//no blockers found, so no shadow
@@ -861,17 +866,22 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
vec2 proj_uv = normal_to_panorama(splane.xyz) * spot_lights.data[idx].projector_rect.zw;
- //ensure we have proper mipmaps
- vec4 splane_ddx = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
- splane_ddx /= splane_ddx.w;
- vec2 proj_uv_ddx = normal_to_panorama(splane_ddx.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
+ if (sc_projector_use_mipmaps) {
+ //ensure we have proper mipmaps
+ vec4 splane_ddx = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
+ splane_ddx /= splane_ddx.w;
+ vec2 proj_uv_ddx = normal_to_panorama(splane_ddx.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
- vec4 splane_ddy = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
- splane_ddy /= splane_ddy.w;
- vec2 proj_uv_ddy = normal_to_panorama(splane_ddy.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
+ vec4 splane_ddy = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
+ splane_ddy /= splane_ddy.w;
+ vec2 proj_uv_ddy = normal_to_panorama(splane_ddy.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
- vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + spot_lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
- color *= proj.rgb * proj.a;
+ vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + spot_lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
+ color *= proj.rgb * proj.a;
+ } else {
+ vec4 proj = textureLod(sampler2D(decal_atlas_srgb, light_projector_sampler), proj_uv + spot_lights.data[idx].projector_rect.xy, 0.0);
+ color *= proj.rgb * proj.a;
+ }
}
light_attenuation *= shadow;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index c28493d9e33..7e72ece5dc5 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -372,10 +372,23 @@ void main() {
/* Specialization Constants */
-//unused but there for compatibility
+/* Specialization Constants (Toggles) */
+
layout(constant_id = 0) const bool sc_use_forward_gi = false;
layout(constant_id = 1) const bool sc_use_light_projector = false;
layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
+layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
+
+/* Specialization Constants (Values) */
+
+layout(constant_id = 6) const uint sc_soft_shadow_samples = 4;
+layout(constant_id = 7) const uint sc_penumbra_shadow_samples = 4;
+
+layout(constant_id = 8) const uint sc_directional_soft_shadow_samples = 4;
+layout(constant_id = 9) const uint sc_directional_penumbra_shadow_samples = 4;
+
+layout(constant_id = 10) const bool sc_decal_use_mipmaps = true;
+layout(constant_id = 11) const bool sc_projector_use_mipmaps = true;
/* Include our forward mobile UBOs definitions etc. */
#include "scene_forward_mobile_inc.glsl"
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index d4ebcbeec4f..1b8e21551c6 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -51,6 +51,9 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12];
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
+layout(set = 0, binding = 3) uniform sampler decal_sampler;
+layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
+
#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
@@ -66,22 +69,22 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
//3 bits of stride
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
-layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
+layout(set = 0, binding = 5, std430) restrict readonly buffer OmniLights {
LightData data[];
}
omni_lights;
-layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
+layout(set = 0, binding = 6, std430) restrict readonly buffer SpotLights {
LightData data[];
}
spot_lights;
-layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData {
+layout(set = 0, binding = 7, std430) restrict readonly buffer ReflectionProbeData {
ReflectionData data[];
}
reflections;
-layout(set = 0, binding = 6, std140) uniform DirectionalLights {
+layout(set = 0, binding = 8, std140) uniform DirectionalLights {
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
}
directional_lights;
@@ -93,7 +96,7 @@ struct Lightmap {
mat3 normal_xform;
};
-layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
+layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
Lightmap data[];
}
lightmaps;
@@ -102,20 +105,20 @@ struct LightmapCapture {
vec4 sh[9];
};
-layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
+layout(set = 0, binding = 10, std140) restrict readonly buffer LightmapCaptures {
LightmapCapture data[];
}
lightmap_captures;
-layout(set = 0, binding = 9) uniform texture2D decal_atlas;
-layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
+layout(set = 0, binding = 11) uniform texture2D decal_atlas;
+layout(set = 0, binding = 12) uniform texture2D decal_atlas_srgb;
-layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
+layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
DecalData data[];
}
decals;
-layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
@@ -141,11 +144,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
vec4 penumbra_shadow_kernel[32];
vec4 soft_shadow_kernel[32];
- uint directional_penumbra_shadow_samples;
- uint directional_soft_shadow_samples;
- uint penumbra_shadow_samples;
- uint soft_shadow_samples;
-
vec4 ambient_light_color_energy;
float ambient_color_sky_mix;
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h
index 8273e53d466..972637d183d 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/renderer_scene.h
@@ -212,6 +212,9 @@ public:
virtual void render_probes() = 0;
virtual void update_visibility_notifiers() = 0;
+ virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
+
virtual bool free(RID p_rid) = 0;
RendererScene();
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index b9009c9f599..96fe6ce25c9 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -1143,6 +1143,9 @@ public:
PASS1(set_debug_draw_mode, RS::ViewportDebugDraw)
+ PASS1(decals_set_filter, RS::DecalFilter)
+ PASS1(light_projectors_set_filter, RS::LightProjectorFilter)
+
virtual void update();
bool free(RID p_rid);
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 0cf34773ef1..2000afa0d32 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -262,6 +262,9 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
+ virtual void decals_set_filter(RS::DecalFilter p_filter) = 0;
+ virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) = 0;
+
virtual void update() = 0;
virtual ~RendererSceneRender() {}
};
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 79665dcdd21..282b0564da1 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -656,6 +656,8 @@ public:
FUNC1(shadows_quality_set, ShadowQuality);
FUNC1(directional_shadow_quality_set, ShadowQuality);
+ FUNC1(decals_set_filter, RS::DecalFilter);
+ FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
/* SCENARIO API */
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 748b372c624..41aa09e2b8c 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1854,6 +1854,14 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits);
ClassDB::bind_method(D_METHOD("light_directional_set_sky_only", "light", "enable"), &RenderingServer::light_directional_set_sky_only);
+ ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
+
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
+
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
BIND_ENUM_CONSTANT(LIGHT_OMNI);
BIND_ENUM_CONSTANT(LIGHT_SPOT);
@@ -1939,12 +1947,20 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("decal_set_fade", "decal", "above", "below"), &RenderingServer::decal_set_fade);
ClassDB::bind_method(D_METHOD("decal_set_normal_fade", "decal", "fade"), &RenderingServer::decal_set_normal_fade);
+ ClassDB::bind_method(D_METHOD("decals_set_filter", "filter"), &RenderingServer::decals_set_filter);
+
BIND_ENUM_CONSTANT(DECAL_TEXTURE_ALBEDO);
BIND_ENUM_CONSTANT(DECAL_TEXTURE_NORMAL);
BIND_ENUM_CONSTANT(DECAL_TEXTURE_ORM);
BIND_ENUM_CONSTANT(DECAL_TEXTURE_EMISSION);
BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
+
/* VOXEL GI API */
ClassDB::bind_method(D_METHOD("voxel_gi_create"), &RenderingServer::voxel_gi_create);
@@ -2814,6 +2830,11 @@ RenderingServer::RenderingServer() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/amount", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/limit", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
+ GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+
GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512);
GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/occlusion_culling/bvh_build_quality", PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"));
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index e13b81f6988..28aee1b5754 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -483,6 +483,17 @@ public:
virtual void shadows_quality_set(ShadowQuality p_quality) = 0;
virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0;
+
+ enum LightProjectorFilter {
+ LIGHT_PROJECTOR_FILTER_NEAREST,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_LINEAR,
+ LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
+ };
+
+ virtual void light_projectors_set_filter(LightProjectorFilter p_filter) = 0;
+
/* PROBE API */
virtual RID reflection_probe_create() = 0;
@@ -535,6 +546,16 @@ public:
virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
+ enum DecalFilter {
+ DECAL_FILTER_NEAREST,
+ DECAL_FILTER_NEAREST_MIPMAPS,
+ DECAL_FILTER_LINEAR,
+ DECAL_FILTER_LINEAR_MIPMAPS,
+ DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
+ };
+
+ virtual void decals_set_filter(DecalFilter p_quality) = 0;
+
/* VOXEL GI API */
virtual RID voxel_gi_create() = 0;
@@ -1499,10 +1520,12 @@ VARIANT_ENUM_CAST(RenderingServer::LightParam);
VARIANT_ENUM_CAST(RenderingServer::LightBakeMode);
VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode);
VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode);
+VARIANT_ENUM_CAST(RenderingServer::LightProjectorFilter);
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeAmbientMode);
VARIANT_ENUM_CAST(RenderingServer::VoxelGIQuality);
VARIANT_ENUM_CAST(RenderingServer::DecalTexture);
+VARIANT_ENUM_CAST(RenderingServer::DecalFilter);
VARIANT_ENUM_CAST(RenderingServer::ParticlesMode);
VARIANT_ENUM_CAST(RenderingServer::ParticlesTransformAlign);
VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder);