summaryrefslogtreecommitdiffstats
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/debugger/servers_debugger.cpp2
-rw-r--r--servers/register_server_types.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp17
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h5
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp4
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h1
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl11
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl11
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_data_inc.glsl13
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp5
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h13
-rw-r--r--servers/rendering/renderer_scene_cull.h9
-rw-r--r--servers/rendering/renderer_scene_render.cpp26
-rw-r--r--servers/rendering/renderer_scene_render.h9
-rw-r--r--servers/rendering/rendering_method.h10
-rw-r--r--servers/rendering/rendering_server_default.h4
-rw-r--r--servers/rendering/storage/environment_storage.cpp37
-rw-r--r--servers/rendering/storage/environment_storage.h15
-rw-r--r--servers/rendering_server.compat.inc41
-rw-r--r--servers/rendering_server.cpp6
-rw-r--r--servers/rendering_server.h14
-rw-r--r--servers/xr/xr_face_tracker.cpp222
-rw-r--r--servers/xr/xr_face_tracker.h213
-rw-r--r--servers/xr_server.cpp48
-rw-r--r--servers/xr_server.h11
26 files changed, 724 insertions, 29 deletions
diff --git a/servers/debugger/servers_debugger.cpp b/servers/debugger/servers_debugger.cpp
index 8da3a10ce9..06be73acc5 100644
--- a/servers/debugger/servers_debugger.cpp
+++ b/servers/debugger/servers_debugger.cpp
@@ -198,7 +198,7 @@ class ServersDebugger::ScriptsProfiler : public EngineProfiler {
typedef ServersDebugger::ScriptFunctionInfo FunctionInfo;
struct ProfileInfoSort {
bool operator()(ScriptLanguage::ProfilingInfo *A, ScriptLanguage::ProfilingInfo *B) const {
- return A->total_time < B->total_time;
+ return A->total_time > B->total_time;
}
};
Vector<ScriptLanguage::ProfilingInfo> info;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 0ee2984a8c..b42e7bf9bb 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -80,6 +80,7 @@
#include "text/text_server_dummy.h"
#include "text/text_server_extension.h"
#include "text_server.h"
+#include "xr/xr_face_tracker.h"
#include "xr/xr_interface.h"
#include "xr/xr_interface_extension.h"
#include "xr/xr_positional_tracker.h"
@@ -189,6 +190,7 @@ void register_server_types() {
GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
GDREGISTER_CLASS(XRPose);
GDREGISTER_CLASS(XRPositionalTracker);
+ GDREGISTER_CLASS(XRFaceTracker);
GDREGISTER_CLASS(AudioStream);
GDREGISTER_CLASS(AudioStreamPlayback);
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 e972d91072..c454d35d28 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -374,7 +374,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
uint32_t pipeline_color_pass_flags = 0;
- uint32_t pipeline_specialization = 0;
+ uint32_t pipeline_specialization = p_params->spec_constant_base_flags;
if constexpr (p_pass_mode == PASS_MODE_COLOR) {
if (element_info.uses_softshadow) {
@@ -1884,6 +1884,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
+ uint32_t spec_constant_base_flags = 0;
+ {
+ if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
+ spec_constant_base_flags |= 1 << SPEC_CONSTANT_USE_DEPTH_FOG;
+ }
+ }
+
bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
if (depth_pre_pass) { //depth pre pass
@@ -1906,7 +1913,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers);
bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags);
_render_list_with_draw_list(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1972,7 +1979,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
uint32_t opaque_color_pass_flags = using_motion_pass ? (color_pass_flags & ~COLOR_PASS_FLAG_MOTION_VECTORS) : color_pass_flags;
RID opaque_framebuffer = using_motion_pass ? rb_data->get_color_pass_fb(opaque_color_pass_flags) : color_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, opaque_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags);
_render_list_with_draw_list(&render_list_params, opaque_framebuffer, load_color ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, depth_pre_pass ? RD::INITIAL_ACTION_LOAD : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, c, 1.0, 0);
}
@@ -1992,7 +1999,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, samplers, true);
- RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags);
_render_list_with_draw_list(&render_list_params, color_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE);
RD::get_singleton()->draw_command_end_label();
@@ -2125,7 +2132,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, spec_constant_base_flags);
_render_list_with_draw_list(&render_list_params, alpha_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE);
}
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 be55341102..51fd0aaffb 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -72,6 +72,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
SPEC_CONSTANT_DECAL_FILTER = 10,
SPEC_CONSTANT_PROJECTOR_FILTER = 11,
+ SPEC_CONSTANT_USE_DEPTH_FOG = 12,
};
enum {
@@ -210,8 +211,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RD::FramebufferFormatID framebuffer_format = 0;
uint32_t element_offset = 0;
bool use_directional_soft_shadow = false;
+ uint32_t spec_constant_base_flags = 0;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_spec_constant_base_flags = 0) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -227,6 +229,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
element_offset = p_element_offset;
use_directional_soft_shadow = p_use_directional_soft_shadows;
+ spec_constant_base_flags = p_spec_constant_base_flags;
}
};
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 29c5deb6c2..fd81430983 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -899,6 +899,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (!is_environment(p_render_data->environment) || !environment_get_fog_enabled(p_render_data->environment)) {
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG;
}
+
+ if (p_render_data->environment.is_valid() && environment_get_fog_mode(p_render_data->environment) == RS::EnvironmentFogMode::ENV_FOG_MODE_DEPTH) {
+ spec_constant_base_flags |= 1 << SPEC_CONSTANT_USE_DEPTH_FOG;
+ }
}
{
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 ba5fefc83f..5c02204627 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -80,6 +80,7 @@ private:
SPEC_CONSTANT_DISABLE_DECALS = 13,
SPEC_CONSTANT_DISABLE_FOG = 14,
+ SPEC_CONSTANT_USE_DEPTH_FOG = 16,
};
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 cb95621219..6eae64c04e 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
@@ -656,6 +656,7 @@ 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;
+layout(constant_id = 12) const bool sc_use_depth_fog = false;
// not used in clustered renderer but we share some code with the mobile renderer that requires this.
const float sc_luminance_multiplier = 1.0;
@@ -848,7 +849,15 @@ vec4 fog_process(vec3 vertex) {
}
}
- float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density));
+ float fog_amount = 0.0;
+
+ if (sc_use_depth_fog) {
+ float fog_z = smoothstep(scene_data_block.data.fog_depth_begin, scene_data_block.data.fog_depth_end, length(vertex));
+ float fog_quad_amount = pow(fog_z, scene_data_block.data.fog_depth_curve) * scene_data_block.data.fog_density;
+ fog_amount = fog_quad_amount;
+ } else {
+ fog_amount = 1 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density));
+ }
if (abs(scene_data_block.data.fog_height_density) >= 0.0001) {
float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y;
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 e9c69058f2..259edc63a0 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
@@ -525,6 +525,7 @@ layout(constant_id = 12) const bool sc_disable_directional_lights = false;
layout(constant_id = 7) const bool sc_decal_use_mipmaps = true;
layout(constant_id = 13) const bool sc_disable_decals = false;
layout(constant_id = 14) const bool sc_disable_fog = false;
+layout(constant_id = 16) const bool sc_use_depth_fog = false;
#endif //!MODE_RENDER_DEPTH
@@ -690,7 +691,15 @@ vec4 fog_process(vec3 vertex) {
}
}
- float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density));
+ float fog_amount = 0.0;
+
+ if (sc_use_depth_fog) {
+ float fog_z = smoothstep(scene_data_block.data.fog_depth_begin, scene_data_block.data.fog_depth_end, length(vertex));
+ float fog_quad_amount = pow(fog_z, scene_data_block.data.fog_depth_curve) * scene_data_block.data.fog_density;
+ fog_amount = fog_quad_amount;
+ } else {
+ fog_amount = 1 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density));
+ }
if (abs(scene_data_block.data.fog_height_density) >= 0.0001) {
float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y;
diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
index 70e670c3f7..67542d61fd 100644
--- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
@@ -49,24 +49,29 @@ struct SceneData {
mediump float opaque_prepass_threshold;
bool fog_enabled;
+ uint fog_mode;
highp float fog_density;
highp float fog_height;
highp float fog_height_density;
+ highp float fog_depth_curve;
+ highp float pad;
+ highp float fog_depth_begin;
+
mediump vec3 fog_light_color;
- mediump float fog_sun_scatter;
+ highp float fog_depth_end;
+ mediump float fog_sun_scatter;
mediump float fog_aerial_perspective;
highp float time;
mediump float reflection_multiplier; // one normally, zero when rendering reflections
- bool material_uv2_mode;
vec2 taa_jitter;
+ bool material_uv2_mode;
float emissive_exposure_normalization;
- float IBL_exposure_normalization;
+ float IBL_exposure_normalization;
bool pancake_shadows;
uint camera_visible_layers;
float pass_alpha_multiplier;
- uint pad3;
};
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 21787b3fcf..1f362ffd21 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -1963,7 +1963,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
//if we have a mesh set, we need to re-generate the AABB from the new data
const float *data = p_buffer.ptr();
- if (multimesh->custom_aabb != AABB()) {
+ if (multimesh->custom_aabb == AABB()) {
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
@@ -2087,7 +2087,7 @@ void MeshStorage::_update_dirty_multimeshes() {
if (multimesh->aabb_dirty) {
//aabb is dirty..
multimesh->aabb_dirty = false;
- if (multimesh->custom_aabb != AABB()) {
+ if (multimesh->custom_aabb == AABB()) {
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
index 506e78bae9..86f0f5acf2 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
@@ -168,11 +168,16 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p
}
ubo.fog_enabled = render_scene_render->environment_get_fog_enabled(p_env);
+ ubo.fog_mode = render_scene_render->environment_get_fog_mode(p_env);
ubo.fog_density = render_scene_render->environment_get_fog_density(p_env);
ubo.fog_height = render_scene_render->environment_get_fog_height(p_env);
ubo.fog_height_density = render_scene_render->environment_get_fog_height_density(p_env);
ubo.fog_aerial_perspective = render_scene_render->environment_get_fog_aerial_perspective(p_env);
+ ubo.fog_depth_curve = render_scene_render->environment_get_fog_depth_curve(p_env);
+ ubo.fog_depth_end = render_scene_render->environment_get_fog_depth_end(p_env) > 0.0 ? render_scene_render->environment_get_fog_depth_end(p_env) : ubo.z_far;
+ ubo.fog_depth_begin = MIN(render_scene_render->environment_get_fog_depth_begin(p_env), ubo.fog_depth_end - 0.001);
+
Color fog_color = render_scene_render->environment_get_fog_light_color(p_env).srgb_to_linear();
float fog_energy = render_scene_render->environment_get_fog_light_energy(p_env);
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
index f93f22816b..9453966a86 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
@@ -131,26 +131,31 @@ private:
// Fog
uint32_t fog_enabled;
+ uint32_t fog_mode;
float fog_density;
float fog_height;
+
float fog_height_density;
+ float fog_depth_curve;
+ float pad;
+ float fog_depth_begin;
float fog_light_color[3];
- float fog_sun_scatter;
+ float fog_depth_end;
+ float fog_sun_scatter;
float fog_aerial_perspective;
float time;
float reflection_multiplier;
- uint32_t material_uv2_mode;
float taa_jitter[2];
+ uint32_t material_uv2_mode;
float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
- float IBL_exposure_normalization; // Adjusts for baked exposure.
+ float IBL_exposure_normalization; // Adjusts for baked exposure.
uint32_t pancake_shadows;
uint32_t camera_visible_layers;
float pass_alpha_multiplier;
- uint32_t pad3;
};
struct UBODATA {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index a09823b008..f48902a4ef 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -1203,7 +1203,7 @@ public:
PASS1RC(float, environment_get_white, RID)
// Fog
- PASS10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float)
+ PASS11(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float, RS::EnvironmentFogMode)
PASS1RC(bool, environment_get_fog_enabled, RID)
PASS1RC(Color, environment_get_fog_light_color, RID)
@@ -1214,10 +1214,17 @@ public:
PASS1RC(float, environment_get_fog_height, RID)
PASS1RC(float, environment_get_fog_height_density, RID)
PASS1RC(float, environment_get_fog_aerial_perspective, RID)
+ PASS1RC(RS::EnvironmentFogMode, environment_get_fog_mode, RID)
PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
+ // Depth Fog
+ PASS4(environment_set_fog_depth, RID, float, float, float)
+ PASS1RC(float, environment_get_fog_depth_curve, RID)
+ PASS1RC(float, environment_get_fog_depth_begin, RID)
+ PASS1RC(float, environment_get_fog_depth_end, RID)
+
// Volumentric Fog
PASS14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float)
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index dce301d87b..95eb29a891 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -310,14 +310,18 @@ float RendererSceneRender::environment_get_white(RID p_env) const {
// Fog
-void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) {
- environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect);
+void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode) {
+ environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, p_mode);
}
bool RendererSceneRender::environment_get_fog_enabled(RID p_env) const {
return environment_storage.environment_get_fog_enabled(p_env);
}
+RS::EnvironmentFogMode RendererSceneRender::environment_get_fog_mode(RID p_env) const {
+ return environment_storage.environment_get_fog_mode(p_env);
+}
+
Color RendererSceneRender::environment_get_fog_light_color(RID p_env) const {
return environment_storage.environment_get_fog_light_color(p_env);
}
@@ -350,6 +354,24 @@ float RendererSceneRender::environment_get_fog_aerial_perspective(RID p_env) con
return environment_storage.environment_get_fog_aerial_perspective(p_env);
}
+// Depth Fog
+
+void RendererSceneRender::environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) {
+ environment_storage.environment_set_fog_depth(p_env, p_curve, p_begin, p_end);
+}
+
+float RendererSceneRender::environment_get_fog_depth_curve(RID p_env) const {
+ return environment_storage.environment_get_fog_depth_curve(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_depth_begin(RID p_env) const {
+ return environment_storage.environment_get_fog_depth_begin(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_depth_end(RID p_env) const {
+ return environment_storage.environment_get_fog_depth_end(p_env);
+}
+
// Volumetric Fog
void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) {
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 9007383641..c6e2c23e91 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -116,8 +116,9 @@ public:
float environment_get_white(RID p_env) const;
// Fog
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode);
bool environment_get_fog_enabled(RID p_env) const;
+ RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const;
Color environment_get_fog_light_color(RID p_env) const;
float environment_get_fog_light_energy(RID p_env) const;
float environment_get_fog_sun_scatter(RID p_env) const;
@@ -127,6 +128,12 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
+ // Depth Fog
+ void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end);
+ float environment_get_fog_depth_curve(RID p_env) const;
+ float environment_get_fog_depth_begin(RID p_env) const;
+ float environment_get_fog_depth_end(RID p_env) const;
+
// Volumetric Fog
void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect);
bool environment_get_volumetric_fog_enabled(RID p_env) const;
diff --git a/servers/rendering/rendering_method.h b/servers/rendering/rendering_method.h
index d1c6c1cbf9..be14a50eec 100644
--- a/servers/rendering/rendering_method.h
+++ b/servers/rendering/rendering_method.h
@@ -154,9 +154,10 @@ public:
virtual float environment_get_white(RID p_env) const = 0;
// Fog
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) = 0;
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode = RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL) = 0;
virtual bool environment_get_fog_enabled(RID p_env) const = 0;
+ virtual RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const = 0;
virtual Color environment_get_fog_light_color(RID p_env) const = 0;
virtual float environment_get_fog_light_energy(RID p_env) const = 0;
virtual float environment_get_fog_sun_scatter(RID p_env) const = 0;
@@ -166,6 +167,13 @@ public:
virtual float environment_get_fog_aerial_perspective(RID p_env) const = 0;
virtual float environment_get_fog_sky_affect(RID p_env) const = 0;
+ // Depth Fog
+ virtual void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) = 0;
+
+ virtual float environment_get_fog_depth_curve(RID p_env) const = 0;
+ virtual float environment_get_fog_depth_begin(RID p_env) const = 0;
+ virtual float environment_get_fog_depth_end(RID p_env) const = 0;
+
// Volumetric Fog
virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 577e9accc0..c218007a78 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -725,7 +725,9 @@ public:
FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
- FUNC10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float)
+ FUNC11(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float, EnvironmentFogMode)
+
+ FUNC4(environment_set_fog_depth, RID, float, float, float)
FUNC14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float)
FUNC2(environment_set_volumetric_fog_volume_size, int, int)
diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp
index 0234f52ca1..ec26e36509 100644
--- a/servers/rendering/storage/environment_storage.cpp
+++ b/servers/rendering/storage/environment_storage.cpp
@@ -205,10 +205,11 @@ float RendererEnvironmentStorage::environment_get_white(RID p_env) const {
// Fog
-void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective, float p_sky_affect) {
+void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode) {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL(env);
env->fog_enabled = p_enable;
+ env->fog_mode = p_mode;
env->fog_light_color = p_light_color;
env->fog_light_energy = p_light_energy;
env->fog_sun_scatter = p_sun_scatter;
@@ -225,6 +226,12 @@ bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const {
return env->fog_enabled;
}
+RS::EnvironmentFogMode RendererEnvironmentStorage::environment_get_fog_mode(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL_V(env, RS::ENV_FOG_MODE_EXPONENTIAL);
+ return env->fog_mode;
+}
+
Color RendererEnvironmentStorage::environment_get_fog_light_color(RID p_env) const {
Environment *env = environment_owner.get_or_null(p_env);
ERR_FAIL_NULL_V(env, Color(0.5, 0.6, 0.7));
@@ -273,6 +280,34 @@ float RendererEnvironmentStorage::environment_get_fog_sky_affect(RID p_env) cons
return env->fog_sky_affect;
}
+// Depth Fog
+
+void RendererEnvironmentStorage::environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL(env);
+ env->fog_depth_curve = p_curve;
+ env->fog_depth_begin = p_begin;
+ env->fog_depth_end = p_end;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_depth_curve(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL_V(env, 0.0);
+ return env->fog_depth_curve;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_depth_begin(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL_V(env, 0.0);
+ return env->fog_depth_begin;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_depth_end(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_NULL_V(env, 0.0);
+ return env->fog_depth_end;
+}
+
// Volumetric Fog
void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) {
diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h
index d677dfc57b..c077e093da 100644
--- a/servers/rendering/storage/environment_storage.h
+++ b/servers/rendering/storage/environment_storage.h
@@ -62,6 +62,7 @@ private:
// Fog
bool fog_enabled = false;
+ RS::EnvironmentFogMode fog_mode = RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL;
Color fog_light_color = Color(0.518, 0.553, 0.608);
float fog_light_energy = 1.0;
float fog_sun_scatter = 0.0;
@@ -71,6 +72,11 @@ private:
float fog_height_density = 0.0; //can be negative to invert effect
float fog_aerial_perspective = 0.0;
+ // Depth Fog
+ float fog_depth_curve = 1.0;
+ float fog_depth_begin = 10.0;
+ float fog_depth_end = 100.0;
+
// Volumetric Fog
bool volumetric_fog_enabled = false;
float volumetric_fog_density = 0.01;
@@ -192,8 +198,9 @@ public:
float environment_get_white(RID p_env) const;
// Fog
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode);
bool environment_get_fog_enabled(RID p_env) const;
+ RS::EnvironmentFogMode environment_get_fog_mode(RID p_env) const;
Color environment_get_fog_light_color(RID p_env) const;
float environment_get_fog_light_energy(RID p_env) const;
float environment_get_fog_sun_scatter(RID p_env) const;
@@ -203,6 +210,12 @@ public:
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;
+ // Depth Fog
+ void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end);
+ float environment_get_fog_depth_curve(RID p_env) const;
+ float environment_get_fog_depth_begin(RID p_env) const;
+ float environment_get_fog_depth_end(RID p_env) const;
+
// Volumetric Fog
void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect);
bool environment_get_volumetric_fog_enabled(RID p_env) const;
diff --git a/servers/rendering_server.compat.inc b/servers/rendering_server.compat.inc
new file mode 100644
index 0000000000..0cef3c906c
--- /dev/null
+++ b/servers/rendering_server.compat.inc
@@ -0,0 +1,41 @@
+/**************************************************************************/
+/* rendering_server.compat.inc */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef DISABLE_DEPRECATED
+
+void RenderingServer::_environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) {
+ environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect, RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL);
+}
+
+void RenderingServer::_bind_compatibility_methods() {
+ ClassDB::bind_compatibility_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::_environment_set_fog_bind_compat_84792);
+}
+
+#endif
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index d03f8113f8..655b748d3f 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -29,6 +29,7 @@
/**************************************************************************/
#include "rendering_server.h"
+#include "rendering_server.compat.inc"
#include "core/config/project_settings.h"
#include "core/object/worker_thread_pool.h"
@@ -2943,7 +2944,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);
ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao);
- ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::environment_set_fog);
+ ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect", "fog_mode"), &RenderingServer::environment_set_fog, DEFVAL(RS::ENV_FOG_MODE_EXPONENTIAL));
ClassDB::bind_method(D_METHOD("environment_set_sdfgi", "env", "enable", "cascades", "min_cell_size", "y_scale", "use_occlusion", "bounce_feedback", "read_sky", "energy", "normal_bias", "probe_bias"), &RenderingServer::environment_set_sdfgi);
ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject", "sky_affect"), &RenderingServer::environment_set_volumetric_fog);
@@ -2986,6 +2987,9 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_REPLACE);
BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_MIX);
+ BIND_ENUM_CONSTANT(ENV_FOG_MODE_EXPONENTIAL);
+ BIND_ENUM_CONSTANT(ENV_FOG_MODE_DEPTH);
+
BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_LINEAR);
BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_REINHARD);
BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_FILMIC);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 19b6c35339..6b00213440 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -71,6 +71,11 @@ protected:
static RenderingServer *(*create_func)();
static void _bind_methods();
+#ifndef DISABLE_DEPRECATED
+ void _environment_set_fog_bind_compat_84792(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ static void _bind_compatibility_methods();
+#endif
+
public:
static RenderingServer *get_singleton();
static RenderingServer *create();
@@ -1178,7 +1183,13 @@ public:
virtual void environment_set_sdfgi_frames_to_update_light(EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) = 0;
+ enum EnvironmentFogMode {
+ ENV_FOG_MODE_EXPONENTIAL,
+ ENV_FOG_MODE_DEPTH,
+ };
+
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, EnvironmentFogMode p_mode = EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL) = 0;
+ virtual void environment_set_fog_depth(RID p_env, float p_curve, float p_begin, float p_end) = 0;
virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
@@ -1730,6 +1741,7 @@ VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentReflectionSource);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentGlowBlendMode);
+VARIANT_ENUM_CAST(RenderingServer::EnvironmentFogMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentToneMapper);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSRRoughnessQuality);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOQuality);
diff --git a/servers/xr/xr_face_tracker.cpp b/servers/xr/xr_face_tracker.cpp
new file mode 100644
index 0000000000..a38ccfd527
--- /dev/null
+++ b/servers/xr/xr_face_tracker.cpp
@@ -0,0 +1,222 @@
+/**************************************************************************/
+/* xr_face_tracker.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "xr_face_tracker.h"
+
+void XRFaceTracker::_bind_methods() {
+ // Base Shapes
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_OUT_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_IN_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_UP_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_DOWN_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_OUT_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_IN_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_UP_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_LOOK_DOWN_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_CLOSED_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_CLOSED_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_SQUINT_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_SQUINT_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_WIDE_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_WIDE_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_DILATION_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_DILATION_LEFT);
+ BIND_ENUM_CONSTANT(FT_EYE_CONSTRICT_RIGHT);
+ BIND_ENUM_CONSTANT(FT_EYE_CONSTRICT_LEFT);
+ BIND_ENUM_CONSTANT(FT_BROW_PINCH_RIGHT);
+ BIND_ENUM_CONSTANT(FT_BROW_PINCH_LEFT);
+ BIND_ENUM_CONSTANT(FT_BROW_LOWERER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_BROW_LOWERER_LEFT);
+ BIND_ENUM_CONSTANT(FT_BROW_INNER_UP_RIGHT);
+ BIND_ENUM_CONSTANT(FT_BROW_INNER_UP_LEFT);
+ BIND_ENUM_CONSTANT(FT_BROW_OUTER_UP_RIGHT);
+ BIND_ENUM_CONSTANT(FT_BROW_OUTER_UP_LEFT);
+ BIND_ENUM_CONSTANT(FT_NOSE_SNEER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_NOSE_SNEER_LEFT);
+ BIND_ENUM_CONSTANT(FT_NASAL_DILATION_RIGHT);
+ BIND_ENUM_CONSTANT(FT_NASAL_DILATION_LEFT);
+ BIND_ENUM_CONSTANT(FT_NASAL_CONSTRICT_RIGHT);
+ BIND_ENUM_CONSTANT(FT_NASAL_CONSTRICT_LEFT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_SQUINT_RIGHT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_SQUINT_LEFT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_PUFF_RIGHT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_PUFF_LEFT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_SUCK_RIGHT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_SUCK_LEFT);
+ BIND_ENUM_CONSTANT(FT_JAW_OPEN);
+ BIND_ENUM_CONSTANT(FT_MOUTH_CLOSED);
+ BIND_ENUM_CONSTANT(FT_JAW_RIGHT);
+ BIND_ENUM_CONSTANT(FT_JAW_LEFT);
+ BIND_ENUM_CONSTANT(FT_JAW_FORWARD);
+ BIND_ENUM_CONSTANT(FT_JAW_BACKWARD);
+ BIND_ENUM_CONSTANT(FT_JAW_CLENCH);
+ BIND_ENUM_CONSTANT(FT_JAW_MANDIBLE_RAISE);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_UPPER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_UPPER_LEFT);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_LOWER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_LOWER_LEFT);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_CORNER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_CORNER_LEFT);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_UPPER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_UPPER_LEFT);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_LOWER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_LOWER_LEFT);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER_UPPER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER_UPPER_LEFT);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER_LOWER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER_LOWER_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_UP_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_UP_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_DOWN_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_DOWN_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_DEEPEN_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_DEEPEN_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_PULL_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_PULL_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_SLANT_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_CORNER_SLANT_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_FROWN_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_FROWN_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_STRETCH_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_STRETCH_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_DIMPLE_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_DIMPLE_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_RAISER_UPPER);
+ BIND_ENUM_CONSTANT(FT_MOUTH_RAISER_LOWER);
+ BIND_ENUM_CONSTANT(FT_MOUTH_PRESS_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_PRESS_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_TIGHTENER_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_TIGHTENER_LEFT);
+ BIND_ENUM_CONSTANT(FT_TONGUE_OUT);
+ BIND_ENUM_CONSTANT(FT_TONGUE_UP);
+ BIND_ENUM_CONSTANT(FT_TONGUE_DOWN);
+ BIND_ENUM_CONSTANT(FT_TONGUE_RIGHT);
+ BIND_ENUM_CONSTANT(FT_TONGUE_LEFT);
+ BIND_ENUM_CONSTANT(FT_TONGUE_ROLL);
+ BIND_ENUM_CONSTANT(FT_TONGUE_BLEND_DOWN);
+ BIND_ENUM_CONSTANT(FT_TONGUE_CURL_UP);
+ BIND_ENUM_CONSTANT(FT_TONGUE_SQUISH);
+ BIND_ENUM_CONSTANT(FT_TONGUE_FLAT);
+ BIND_ENUM_CONSTANT(FT_TONGUE_TWIST_RIGHT);
+ BIND_ENUM_CONSTANT(FT_TONGUE_TWIST_LEFT);
+ BIND_ENUM_CONSTANT(FT_SOFT_PALATE_CLOSE);
+ BIND_ENUM_CONSTANT(FT_THROAT_SWALLOW);
+ BIND_ENUM_CONSTANT(FT_NECK_FLEX_RIGHT);
+ BIND_ENUM_CONSTANT(FT_NECK_FLEX_LEFT);
+ // Blended Shapes
+ BIND_ENUM_CONSTANT(FT_EYE_CLOSED);
+ BIND_ENUM_CONSTANT(FT_EYE_WIDE);
+ BIND_ENUM_CONSTANT(FT_EYE_SQUINT);
+ BIND_ENUM_CONSTANT(FT_EYE_DILATION);
+ BIND_ENUM_CONSTANT(FT_EYE_CONSTRICT);
+ BIND_ENUM_CONSTANT(FT_BROW_DOWN_RIGHT);
+ BIND_ENUM_CONSTANT(FT_BROW_DOWN_LEFT);
+ BIND_ENUM_CONSTANT(FT_BROW_DOWN);
+ BIND_ENUM_CONSTANT(FT_BROW_UP_RIGHT);
+ BIND_ENUM_CONSTANT(FT_BROW_UP_LEFT);
+ BIND_ENUM_CONSTANT(FT_BROW_UP);
+ BIND_ENUM_CONSTANT(FT_NOSE_SNEER);
+ BIND_ENUM_CONSTANT(FT_NASAL_DILATION);
+ BIND_ENUM_CONSTANT(FT_NASAL_CONSTRICT);
+ BIND_ENUM_CONSTANT(FT_CHEEK_PUFF);
+ BIND_ENUM_CONSTANT(FT_CHEEK_SUCK);
+ BIND_ENUM_CONSTANT(FT_CHEEK_SQUINT);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_UPPER);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK_LOWER);
+ BIND_ENUM_CONSTANT(FT_LIP_SUCK);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_UPPER);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL_LOWER);
+ BIND_ENUM_CONSTANT(FT_LIP_FUNNEL);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER_UPPER);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER_LOWER);
+ BIND_ENUM_CONSTANT(FT_LIP_PUCKER);
+ BIND_ENUM_CONSTANT(FT_MOUTH_UPPER_UP);
+ BIND_ENUM_CONSTANT(FT_MOUTH_LOWER_DOWN);
+ BIND_ENUM_CONSTANT(FT_MOUTH_OPEN);
+ BIND_ENUM_CONSTANT(FT_MOUTH_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_SMILE_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_SMILE_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_SMILE);
+ BIND_ENUM_CONSTANT(FT_MOUTH_SAD_RIGHT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_SAD_LEFT);
+ BIND_ENUM_CONSTANT(FT_MOUTH_SAD);
+ BIND_ENUM_CONSTANT(FT_MOUTH_STRETCH);
+ BIND_ENUM_CONSTANT(FT_MOUTH_DIMPLE);
+ BIND_ENUM_CONSTANT(FT_MOUTH_TIGHTENER);
+ BIND_ENUM_CONSTANT(FT_MOUTH_PRESS);
+ BIND_ENUM_CONSTANT(FT_MAX);
+
+ ClassDB::bind_method(D_METHOD("get_blend_shape", "blend_shape"), &XRFaceTracker::get_blend_shape);
+ ClassDB::bind_method(D_METHOD("set_blend_shape", "blend_shape", "weight"), &XRFaceTracker::set_blend_shape);
+
+ ClassDB::bind_method(D_METHOD("get_blend_shapes"), &XRFaceTracker::get_blend_shapes);
+ ClassDB::bind_method(D_METHOD("set_blend_shapes", "weights"), &XRFaceTracker::set_blend_shapes);
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT32_ARRAY, "blend_shapes"), "set_blend_shapes", "get_blend_shapes");
+ ADD_PROPERTY_DEFAULT("blend_shapes", PackedFloat32Array()); // To prevent ludicrously large default values.
+}
+
+float XRFaceTracker::get_blend_shape(BlendShapeEntry p_blend_shape) const {
+ // Fail if the blend shape index is out of range.
+ ERR_FAIL_INDEX_V(p_blend_shape, FT_MAX, 0.0f);
+
+ // Return the blend shape value.
+ return blend_shape_values[p_blend_shape];
+}
+
+void XRFaceTracker::set_blend_shape(BlendShapeEntry p_blend_shape, float p_value) {
+ // Fail if the blend shape index is out of range.
+ ERR_FAIL_INDEX(p_blend_shape, FT_MAX);
+
+ // Save the new blend shape value.
+ blend_shape_values[p_blend_shape] = p_value;
+}
+
+PackedFloat32Array XRFaceTracker::get_blend_shapes() const {
+ // Create a packed float32 array and copy the blend shape values into it.
+ PackedFloat32Array data;
+ data.resize(FT_MAX);
+ memcpy(data.ptrw(), blend_shape_values, sizeof(blend_shape_values));
+
+ // Return the blend shape array.
+ return data;
+}
+
+void XRFaceTracker::set_blend_shapes(const PackedFloat32Array &p_blend_shapes) {
+ // Fail if the blend shape array is not the correct size.
+ ERR_FAIL_COND(p_blend_shapes.size() != FT_MAX);
+
+ // Copy the blend shape values into the blend shape array.
+ memcpy(blend_shape_values, p_blend_shapes.ptr(), sizeof(blend_shape_values));
+}
diff --git a/servers/xr/xr_face_tracker.h b/servers/xr/xr_face_tracker.h
new file mode 100644
index 0000000000..b9f553cba6
--- /dev/null
+++ b/servers/xr/xr_face_tracker.h
@@ -0,0 +1,213 @@
+/**************************************************************************/
+/* xr_face_tracker.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef XR_FACE_TRACKER_H
+#define XR_FACE_TRACKER_H
+
+#include "core/object/ref_counted.h"
+
+/**
+ The XRFaceTracker class provides face blend shape weights.
+
+ The supported blend shapes are based on the Unified Expressions
+ standard, and as such have a well defined mapping to ARKit, SRanipal,
+ and Meta Movement standards.
+ */
+
+class XRFaceTracker : public RefCounted {
+ GDCLASS(XRFaceTracker, RefCounted);
+ _THREAD_SAFE_CLASS_
+
+public:
+ enum BlendShapeEntry {
+ // Base Shapes
+ FT_EYE_LOOK_OUT_RIGHT, // Right eye looks outwards.
+ FT_EYE_LOOK_IN_RIGHT, // Right eye looks inwards.
+ FT_EYE_LOOK_UP_RIGHT, // Right eye looks upwards.
+ FT_EYE_LOOK_DOWN_RIGHT, // Right eye looks downwards.
+ FT_EYE_LOOK_OUT_LEFT, // Left eye looks outwards.
+ FT_EYE_LOOK_IN_LEFT, // Left eye looks inwards.
+ FT_EYE_LOOK_UP_LEFT, // Left eye looks upwards.
+ FT_EYE_LOOK_DOWN_LEFT, // Left eye looks downwards.
+ FT_EYE_CLOSED_RIGHT, // Closes the right eyelid.
+ FT_EYE_CLOSED_LEFT, // Closes the left eyelid.
+ FT_EYE_SQUINT_RIGHT, // Squeezes the right eye socket muscles.
+ FT_EYE_SQUINT_LEFT, // Squeezes the left eye socket muscles.
+ FT_EYE_WIDE_RIGHT, // Right eyelid widens beyond relaxed.
+ FT_EYE_WIDE_LEFT, // Left eyelid widens beyond relaxed.
+ FT_EYE_DILATION_RIGHT, // Dilates the right eye pupil.
+ FT_EYE_DILATION_LEFT, // Dilates the left eye pupil.
+ FT_EYE_CONSTRICT_RIGHT, // Constricts the right eye pupil.
+ FT_EYE_CONSTRICT_LEFT, // Constricts the left eye pupil.
+ FT_BROW_PINCH_RIGHT, // Right eyebrow pinches in.
+ FT_BROW_PINCH_LEFT, // Left eyebrow pinches in.
+ FT_BROW_LOWERER_RIGHT, // Outer right eyebrow pulls down.
+ FT_BROW_LOWERER_LEFT, // Outer left eyebrow pulls down.
+ FT_BROW_INNER_UP_RIGHT, // Inner right eyebrow pulls up.
+ FT_BROW_INNER_UP_LEFT, // Inner left eyebrow pulls up.
+ FT_BROW_OUTER_UP_RIGHT, // Outer right eyebrow pulls up.
+ FT_BROW_OUTER_UP_LEFT, // Outer left eyebrow pulls up.
+ FT_NOSE_SNEER_RIGHT, // Right side face sneers.
+ FT_NOSE_SNEER_LEFT, // Left side face sneers.
+ FT_NASAL_DILATION_RIGHT, // Right side nose canal dilates.
+ FT_NASAL_DILATION_LEFT, // Left side nose canal dilates.
+ FT_NASAL_CONSTRICT_RIGHT, // Right side nose canal constricts.
+ FT_NASAL_CONSTRICT_LEFT, // Left side nose canal constricts.
+ FT_CHEEK_SQUINT_RIGHT, // Raises the right side cheek.
+ FT_CHEEK_SQUINT_LEFT, // Raises the left side cheek.
+ FT_CHEEK_PUFF_RIGHT, // Puffs the right side cheek.
+ FT_CHEEK_PUFF_LEFT, // Puffs the left side cheek.
+ FT_CHEEK_SUCK_RIGHT, // Sucks in the right side cheek.
+ FT_CHEEK_SUCK_LEFT, // Sucks in the left side cheek.
+ FT_JAW_OPEN, // Opens jawbone.
+ FT_MOUTH_CLOSED, // Closes the mouth.
+ FT_JAW_RIGHT, // Pushes jawbone right.
+ FT_JAW_LEFT, // Pushes jawbone left.
+ FT_JAW_FORWARD, // Pushes jawbone forward.
+ FT_JAW_BACKWARD, // Pushes jawbone backward.
+ FT_JAW_CLENCH, // Flexes jaw muscles.
+ FT_JAW_MANDIBLE_RAISE, // Raises the jawbone.
+ FT_LIP_SUCK_UPPER_RIGHT, // Upper right lip part tucks in the mouth.
+ FT_LIP_SUCK_UPPER_LEFT, // Upper left lip part tucks in the mouth.
+ FT_LIP_SUCK_LOWER_RIGHT, // Lower right lip part tucks in the mouth.
+ FT_LIP_SUCK_LOWER_LEFT, // Lower left lip part tucks in the mouth.
+ FT_LIP_SUCK_CORNER_RIGHT, // Right lip corner folds into the mouth.
+ FT_LIP_SUCK_CORNER_LEFT, // Left lip corner folds into the mouth.
+ FT_LIP_FUNNEL_UPPER_RIGHT, // Upper right lip part pushes into a funnel.
+ FT_LIP_FUNNEL_UPPER_LEFT, // Upper left lip part pushes into a funnel.
+ FT_LIP_FUNNEL_LOWER_RIGHT, // Lower right lip part pushes into a funnel.
+ FT_LIP_FUNNEL_LOWER_LEFT, // Lower left lip part pushes into a funnel.
+ FT_LIP_PUCKER_UPPER_RIGHT, // Upper right lip part pushes outwards.
+ FT_LIP_PUCKER_UPPER_LEFT, // Upper left lip part pushes outwards.
+ FT_LIP_PUCKER_LOWER_RIGHT, // Lower right lip part pushes outwards.
+ FT_LIP_PUCKER_LOWER_LEFT, // Lower left lip part pushes outwards.
+ FT_MOUTH_UPPER_UP_RIGHT, // Upper right part of the lip pulls up.
+ FT_MOUTH_UPPER_UP_LEFT, // Upper left part of the lip pulls up.
+ FT_MOUTH_LOWER_DOWN_RIGHT, // Lower right part of the lip pulls up.
+ FT_MOUTH_LOWER_DOWN_LEFT, // Lower left part of the lip pulls up.
+ FT_MOUTH_UPPER_DEEPEN_RIGHT, // Upper right lip part pushes in the cheek.
+ FT_MOUTH_UPPER_DEEPEN_LEFT, // Upper left lip part pushes in the cheek.
+ FT_MOUTH_UPPER_RIGHT, // Moves upper lip right.
+ FT_MOUTH_UPPER_LEFT, // Moves upper lip left.
+ FT_MOUTH_LOWER_RIGHT, // Moves lower lip right.
+ FT_MOUTH_LOWER_LEFT, // Moves lower lip left.
+ FT_MOUTH_CORNER_PULL_RIGHT, // Right lip corner pulls diagonally up and out.
+ FT_MOUTH_CORNER_PULL_LEFT, // Left lip corner pulls diagonally up and out.
+ FT_MOUTH_CORNER_SLANT_RIGHT, // Right corner lip slants up.
+ FT_MOUTH_CORNER_SLANT_LEFT, // Left corner lip slants up.
+ FT_MOUTH_FROWN_RIGHT, // Right corner lip pulls down.
+ FT_MOUTH_FROWN_LEFT, // Left corner lip pulls down.
+ FT_MOUTH_STRETCH_RIGHT, // Mouth corner lip pulls out and down.
+ FT_MOUTH_STRETCH_LEFT, // Mouth corner lip pulls out and down.
+ FT_MOUTH_DIMPLE_RIGHT, // Right lip corner is pushed backwards.
+ FT_MOUTH_DIMPLE_LEFT, // Left lip corner is pushed backwards.
+ FT_MOUTH_RAISER_UPPER, // Raises and slightly pushes out the upper mouth.
+ FT_MOUTH_RAISER_LOWER, // Raises and slightly pushes out the lower mouth.
+ FT_MOUTH_PRESS_RIGHT, // Right side lips press and flatten together vertically.
+ FT_MOUTH_PRESS_LEFT, // Left side lips press and flatten together vertically.
+ FT_MOUTH_TIGHTENER_RIGHT, // Right side lips squeeze together horizontally.
+ FT_MOUTH_TIGHTENER_LEFT, // Left side lips squeeze together horizontally.
+ FT_TONGUE_OUT, // Tongue visibly sticks out of the mouth.
+ FT_TONGUE_UP, // Tongue points upwards.
+ FT_TONGUE_DOWN, // Tongue points downwards.
+ FT_TONGUE_RIGHT, // Tongue points right.
+ FT_TONGUE_LEFT, // Tongue points left.
+ FT_TONGUE_ROLL, // Sides of the tongue funnel, creating a roll.
+ FT_TONGUE_BLEND_DOWN, // Tongue arches up then down inside the mouth.
+ FT_TONGUE_CURL_UP, // Tongue arches down then up inside the mouth.
+ FT_TONGUE_SQUISH, // Tongue squishes together and thickens.
+ FT_TONGUE_FLAT, // Tongue flattens and thins out.
+ FT_TONGUE_TWIST_RIGHT, // Tongue tip rotates clockwise, with the rest following gradually.
+ FT_TONGUE_TWIST_LEFT, // Tongue tip rotates counter-clockwise, with the rest following gradually.
+ FT_SOFT_PALATE_CLOSE, // Inner mouth throat closes.
+ FT_THROAT_SWALLOW, // The Adam's apple visibly swallows.
+ FT_NECK_FLEX_RIGHT, // Right side neck visibly flexes.
+ FT_NECK_FLEX_LEFT, // Left side neck visibly flexes.
+ // Blended Shapes
+ FT_EYE_CLOSED, // Closes both eye lids.
+ FT_EYE_WIDE, // Widens both eye lids.
+ FT_EYE_SQUINT, // Squints both eye lids.
+ FT_EYE_DILATION, // Dilates both pupils.
+ FT_EYE_CONSTRICT, // Constricts both pupils.
+ FT_BROW_DOWN_RIGHT, // Pulls the right eyebrow down and in.
+ FT_BROW_DOWN_LEFT, // Pulls the left eyebrow down and in.
+ FT_BROW_DOWN, // Pulls both eyebrows down and in.
+ FT_BROW_UP_RIGHT, // Right brow appears worried.
+ FT_BROW_UP_LEFT, // Left brow appears worried.
+ FT_BROW_UP, // Both brows appear worried.
+ FT_NOSE_SNEER, // Entire face sneers.
+ FT_NASAL_DILATION, // Both nose canals dilate.
+ FT_NASAL_CONSTRICT, // Both nose canals constrict.
+ FT_CHEEK_PUFF, // Puffs both cheeks.
+ FT_CHEEK_SUCK, // Sucks in both cheeks.
+ FT_CHEEK_SQUINT, // Raises both cheeks.
+ FT_LIP_SUCK_UPPER, // Tucks in the upper lips.
+ FT_LIP_SUCK_LOWER, // Tucks in the lower lips.
+ FT_LIP_SUCK, // Tucks in both lips.
+ FT_LIP_FUNNEL_UPPER, // Funnels in the upper lips.
+ FT_LIP_FUNNEL_LOWER, // Funnels in the lower lips.
+ FT_LIP_FUNNEL, // Funnels in both lips.
+ FT_LIP_PUCKER_UPPER, // Upper lip part pushes outwards.
+ FT_LIP_PUCKER_LOWER, // Lower lip part pushes outwards.
+ FT_LIP_PUCKER, // Lips push outwards.
+ FT_MOUTH_UPPER_UP, // Raises the upper lips.
+ FT_MOUTH_LOWER_DOWN, // Lowers the lower lips.
+ FT_MOUTH_OPEN, // Mouth opens, revealing teeth.
+ FT_MOUTH_RIGHT, // Moves mouth right.
+ FT_MOUTH_LEFT, // Moves mouth left.
+ FT_MOUTH_SMILE_RIGHT, // Right side of the mouth smiles.
+ FT_MOUTH_SMILE_LEFT, // Left side of the mouth smiles.
+ FT_MOUTH_SMILE, // Mouth expresses a smile.
+ FT_MOUTH_SAD_RIGHT, // Right side of the mouth expresses sadness.
+ FT_MOUTH_SAD_LEFT, // Left side of the mouth expresses sadness.
+ FT_MOUTH_SAD, // Mouth expresses sadness.
+ FT_MOUTH_STRETCH, // Mouth stretches.
+ FT_MOUTH_DIMPLE, // Lip corners dimple.
+ FT_MOUTH_TIGHTENER, // Mouth tightens.
+ FT_MOUTH_PRESS, // Mouth presses together.
+ FT_MAX // Maximum blend shape.
+ };
+
+ float get_blend_shape(BlendShapeEntry p_blend_shape) const;
+ void set_blend_shape(BlendShapeEntry p_blend_shape, float p_value);
+
+ PackedFloat32Array get_blend_shapes() const;
+ void set_blend_shapes(const PackedFloat32Array &p_blend_shapes);
+
+protected:
+ static void _bind_methods();
+
+private:
+ float blend_shape_values[FT_MAX] = {};
+};
+
+VARIANT_ENUM_CAST(XRFaceTracker::BlendShapeEntry);
+
+#endif // XR_FACE_TRACKER_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index e7f644d53f..b3bb0a3702 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -30,6 +30,7 @@
#include "xr_server.h"
#include "core/config/project_settings.h"
+#include "xr/xr_face_tracker.h"
#include "xr/xr_interface.h"
#include "xr/xr_positional_tracker.h"
@@ -74,6 +75,11 @@ void XRServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_trackers", "tracker_types"), &XRServer::get_trackers);
ClassDB::bind_method(D_METHOD("get_tracker", "tracker_name"), &XRServer::get_tracker);
+ ClassDB::bind_method(D_METHOD("add_face_tracker", "tracker_name", "face_tracker"), &XRServer::add_face_tracker);
+ ClassDB::bind_method(D_METHOD("remove_face_tracker", "tracker_name"), &XRServer::remove_face_tracker);
+ ClassDB::bind_method(D_METHOD("get_face_trackers"), &XRServer::get_face_trackers);
+ ClassDB::bind_method(D_METHOD("get_face_tracker", "tracker_name"), &XRServer::get_face_tracker);
+
ClassDB::bind_method(D_METHOD("get_primary_interface"), &XRServer::get_primary_interface);
ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &XRServer::set_primary_interface);
@@ -97,6 +103,10 @@ void XRServer::_bind_methods() {
ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type")));
ADD_SIGNAL(MethodInfo("tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type")));
ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type")));
+
+ ADD_SIGNAL(MethodInfo("face_tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::OBJECT, "face_tracker", PROPERTY_HINT_RESOURCE_TYPE, "XRFaceTracker")));
+ ADD_SIGNAL(MethodInfo("face_tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::OBJECT, "face_tracker", PROPERTY_HINT_RESOURCE_TYPE, "XRFaceTracker")));
+ ADD_SIGNAL(MethodInfo("face_tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name")));
};
double XRServer::get_world_scale() const {
@@ -352,6 +362,44 @@ PackedStringArray XRServer::get_suggested_pose_names(const StringName &p_tracker
return arr;
}
+void XRServer::add_face_tracker(const StringName &p_tracker_name, Ref<XRFaceTracker> p_face_tracker) {
+ ERR_FAIL_COND(p_face_tracker.is_null());
+
+ if (!face_trackers.has(p_tracker_name)) {
+ // We don't have a tracker with this name, we're going to add it.
+ face_trackers[p_tracker_name] = p_face_tracker;
+ emit_signal(SNAME("face_tracker_added"), p_tracker_name, p_face_tracker);
+ } else if (face_trackers[p_tracker_name] != p_face_tracker) {
+ // We already have a tracker with this name, we're going to replace it.
+ face_trackers[p_tracker_name] = p_face_tracker;
+ emit_signal(SNAME("face_tracker_updated"), p_tracker_name, p_face_tracker);
+ }
+}
+
+void XRServer::remove_face_tracker(const StringName &p_tracker_name) {
+ // Skip if no face tracker is found.
+ if (!face_trackers.has(p_tracker_name)) {
+ return;
+ }
+
+ // Send the removed signal, then remove the face tracker.
+ emit_signal(SNAME("face_tracker_removed"), p_tracker_name);
+ face_trackers.erase(p_tracker_name);
+}
+
+Dictionary XRServer::get_face_trackers() const {
+ return face_trackers;
+}
+
+Ref<XRFaceTracker> XRServer::get_face_tracker(const StringName &p_tracker_name) const {
+ // Skip if no tracker is found.
+ if (!face_trackers.has(p_tracker_name)) {
+ return Ref<XRFaceTracker>();
+ }
+
+ return face_trackers[p_tracker_name];
+}
+
void XRServer::_process() {
// called from our main game loop before we handle physics and game logic
// note that we can have multiple interfaces active if we have interfaces that purely handle tracking
diff --git a/servers/xr_server.h b/servers/xr_server.h
index fe59fc22cb..0a4e020a1f 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -39,6 +39,7 @@
class XRInterface;
class XRPositionalTracker;
+class XRFaceTracker;
/**
The XR server is a singleton object that gives access to the various
@@ -86,6 +87,8 @@ private:
Vector<Ref<XRInterface>> interfaces;
Dictionary trackers;
+ Dictionary face_trackers;
+
Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */
double world_scale; /* scale by which we multiply our tracker positions */
@@ -183,6 +186,14 @@ public:
PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const;
// Q: Should we add get_suggested_input_names and get_suggested_haptic_names even though we don't use them for the IDE?
+ /*
+ Face trackers are objects that expose the tracked blend shapes of a face.
+ */
+ void add_face_tracker(const StringName &p_tracker_name, Ref<XRFaceTracker> p_face_tracker);
+ void remove_face_tracker(const StringName &p_tracker_name);
+ Dictionary get_face_trackers() const;
+ Ref<XRFaceTracker> get_face_tracker(const StringName &p_tracker_name) const;
+
// Process is called before we handle our physics process and game process. This is where our interfaces will update controller data and such.
void _process();