diff options
Diffstat (limited to 'servers')
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(); |
