From 03890f9e385f066d92b5bd5996c805b5312d6779 Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 15 Mar 2022 19:03:03 +0100 Subject: [PATCH] Removed GIProbes. --- drivers/dummy/rasterizer_dummy.h | 50 - drivers/gles2/rasterizer_scene_gles2.cpp | 14 - drivers/gles2/rasterizer_scene_gles2.h | 7 - drivers/gles2/rasterizer_storage_gles2.cpp | 99 - drivers/gles2/rasterizer_storage_gles2.h | 41 - editor/editor_node.cpp | 2 - editor/plugins/gi_probe_editor_plugin.cpp | 99 - editor/plugins/gi_probe_editor_plugin.h | 68 - editor/plugins/spatial_editor_plugin.cpp | 1 - editor/plugins/spatial_editor_plugin.cpp.orig | 1 - editor/spatial_editor_gizmos.cpp | 171 -- editor/spatial_editor_gizmos.h | 17 - scene/3d/gi_probe.cpp | 531 ------ scene/3d/gi_probe.h | 178 -- scene/3d/voxel_light_baker.cpp | 1601 ----------------- scene/3d/voxel_light_baker.h | 171 -- scene/register_scene_types.cpp | 3 - servers/visual/rasterizer.h | 54 - servers/visual/visual_server_raster.cpp | 1 - servers/visual/visual_server_raster.h | 37 - servers/visual/visual_server_scene.cpp | 1495 ++------------- servers/visual/visual_server_scene.h | 152 -- servers/visual/visual_server_wrap_mt.cpp | 1 - servers/visual/visual_server_wrap_mt.h | 37 - servers/visual_server.cpp | 25 - servers/visual_server.h | 38 - 26 files changed, 161 insertions(+), 4733 deletions(-) delete mode 100644 editor/plugins/gi_probe_editor_plugin.cpp delete mode 100644 editor/plugins/gi_probe_editor_plugin.h delete mode 100644 scene/3d/gi_probe.cpp delete mode 100644 scene/3d/gi_probe.h delete mode 100644 scene/3d/voxel_light_baker.cpp delete mode 100644 scene/3d/voxel_light_baker.h diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 0373bbcc0..b48904864 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -101,11 +101,6 @@ public: bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { return false; } bool reflection_probe_instance_postprocess_step(RID p_instance) { return true; } - RID gi_probe_instance_create() { return RID(); } - void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {} - void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {} - void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) {} - void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {} void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {} @@ -557,51 +552,6 @@ public: void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {} void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) {} - /* GI PROBE API */ - - RID gi_probe_create() { return RID(); } - - void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) {} - AABB gi_probe_get_bounds(RID p_probe) const { return AABB(); } - - void gi_probe_set_cell_size(RID p_probe, float p_range) {} - float gi_probe_get_cell_size(RID p_probe) const { return 0.0; } - - void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) {} - Transform gi_probe_get_to_cell_xform(RID p_probe) const { return Transform(); } - - void gi_probe_set_dynamic_data(RID p_probe, const PoolVector &p_data) {} - PoolVector gi_probe_get_dynamic_data(RID p_probe) const { - PoolVector p; - return p; - } - - void gi_probe_set_dynamic_range(RID p_probe, int p_range) {} - int gi_probe_get_dynamic_range(RID p_probe) const { return 0; } - - void gi_probe_set_energy(RID p_probe, float p_range) {} - float gi_probe_get_energy(RID p_probe) const { return 0.0; } - - void gi_probe_set_bias(RID p_probe, float p_range) {} - float gi_probe_get_bias(RID p_probe) const { return 0.0; } - - void gi_probe_set_normal_bias(RID p_probe, float p_range) {} - float gi_probe_get_normal_bias(RID p_probe) const { return 0.0; } - - void gi_probe_set_propagation(RID p_probe, float p_range) {} - float gi_probe_get_propagation(RID p_probe) const { return 0.0; } - - void gi_probe_set_interior(RID p_probe, bool p_enable) {} - bool gi_probe_is_interior(RID p_probe) const { return false; } - - void gi_probe_set_compress(RID p_probe, bool p_enable) {} - bool gi_probe_is_compressed(RID p_probe) const { return false; } - - uint32_t gi_probe_get_version(RID p_probe) { return 0; } - - RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { return RID(); } - void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {} - /* LIGHTMAP CAPTURE */ struct Instantiable : public RID_Data { SelfList::List instance_list; diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index a85264835..1344f827c 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -982,20 +982,6 @@ void RasterizerSceneGLES2::light_instance_mark_visible(RID p_light_instance) { light_instance->last_scene_pass = scene_pass; } -////////////////////// - -RID RasterizerSceneGLES2::gi_probe_instance_create() { - return RID(); -} - -void RasterizerSceneGLES2::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) { -} -void RasterizerSceneGLES2::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { -} - -void RasterizerSceneGLES2::gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) { -} - //////////////////////////// //////////////////////////// //////////////////////////// diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index d3dfafbcf..8e919ae5c 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -554,13 +554,6 @@ public: int render_directional_lights; int render_light_instance_count; - /* REFLECTION INSTANCE */ - - virtual RID gi_probe_instance_create(); - virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data); - virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform); - virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds); - /* RENDER LIST */ enum LightMode { diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 1bf07eea7..aed722a3b 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -4555,97 +4555,6 @@ int RasterizerStorageGLES2::reflection_probe_get_resolution(RID p_probe) const { return reflection_probe->resolution; } -RID RasterizerStorageGLES2::gi_probe_create() { - return RID(); -} - -void RasterizerStorageGLES2::gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) { -} - -AABB RasterizerStorageGLES2::gi_probe_get_bounds(RID p_probe) const { - return AABB(); -} - -void RasterizerStorageGLES2::gi_probe_set_cell_size(RID p_probe, float p_size) { -} - -float RasterizerStorageGLES2::gi_probe_get_cell_size(RID p_probe) const { - return 0.0; -} - -void RasterizerStorageGLES2::gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) { -} - -Transform RasterizerStorageGLES2::gi_probe_get_to_cell_xform(RID p_probe) const { - return Transform(); -} - -void RasterizerStorageGLES2::gi_probe_set_dynamic_data(RID p_probe, const PoolVector &p_data) { -} - -PoolVector RasterizerStorageGLES2::gi_probe_get_dynamic_data(RID p_probe) const { - return PoolVector(); -} - -void RasterizerStorageGLES2::gi_probe_set_dynamic_range(RID p_probe, int p_range) { -} - -int RasterizerStorageGLES2::gi_probe_get_dynamic_range(RID p_probe) const { - return 0; -} - -void RasterizerStorageGLES2::gi_probe_set_energy(RID p_probe, float p_range) { -} - -void RasterizerStorageGLES2::gi_probe_set_bias(RID p_probe, float p_range) { -} - -void RasterizerStorageGLES2::gi_probe_set_normal_bias(RID p_probe, float p_range) { -} - -void RasterizerStorageGLES2::gi_probe_set_propagation(RID p_probe, float p_range) { -} - -void RasterizerStorageGLES2::gi_probe_set_interior(RID p_probe, bool p_enable) { -} - -bool RasterizerStorageGLES2::gi_probe_is_interior(RID p_probe) const { - return false; -} - -void RasterizerStorageGLES2::gi_probe_set_compress(RID p_probe, bool p_enable) { -} - -bool RasterizerStorageGLES2::gi_probe_is_compressed(RID p_probe) const { - return false; -} -float RasterizerStorageGLES2::gi_probe_get_energy(RID p_probe) const { - return 0; -} - -float RasterizerStorageGLES2::gi_probe_get_bias(RID p_probe) const { - return 0; -} - -float RasterizerStorageGLES2::gi_probe_get_normal_bias(RID p_probe) const { - return 0; -} - -float RasterizerStorageGLES2::gi_probe_get_propagation(RID p_probe) const { - return 0; -} - -uint32_t RasterizerStorageGLES2::gi_probe_get_version(RID p_probe) { - return 0; -} - -RID RasterizerStorageGLES2::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) { - return RID(); -} - -void RasterizerStorageGLES2::gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) { -} - /////// RID RasterizerStorageGLES2::lightmap_capture_create() { @@ -4900,10 +4809,6 @@ void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - /*case VS::INSTANCE_GI_PROBE: { - inst = gi_probe_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break;*/ case VS::INSTANCE_LIGHTMAP_CAPTURE: { inst = lightmap_capture_data_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -4944,10 +4849,6 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - /*case VS::INSTANCE_GI_PROBE: { - inst = gi_probe_owner.getornull(p_base); - ERR_FAIL_COND(!inst); - } break; */ case VS::INSTANCE_LIGHTMAP_CAPTURE: { inst = lightmap_capture_data_owner.getornull(p_base); ERR_FAIL_COND(!inst); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 14bd9db4e..e49fd2818 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -1042,47 +1042,6 @@ public: virtual float reflection_probe_get_origin_max_distance(RID p_probe) const; virtual bool reflection_probe_renders_shadows(RID p_probe) const; - /* GI PROBE API */ - virtual RID gi_probe_create(); - - virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds); - virtual AABB gi_probe_get_bounds(RID p_probe) const; - - virtual void gi_probe_set_cell_size(RID p_probe, float p_size); - virtual float gi_probe_get_cell_size(RID p_probe) const; - - virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform); - virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const; - - virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector &p_data); - virtual PoolVector gi_probe_get_dynamic_data(RID p_probe) const; - - virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range); - virtual int gi_probe_get_dynamic_range(RID p_probe) const; - - virtual void gi_probe_set_energy(RID p_probe, float p_range); - virtual float gi_probe_get_energy(RID p_probe) const; - - virtual void gi_probe_set_bias(RID p_probe, float p_range); - virtual float gi_probe_get_bias(RID p_probe) const; - - virtual void gi_probe_set_normal_bias(RID p_probe, float p_range); - virtual float gi_probe_get_normal_bias(RID p_probe) const; - - virtual void gi_probe_set_propagation(RID p_probe, float p_range); - virtual float gi_probe_get_propagation(RID p_probe) const; - - virtual void gi_probe_set_interior(RID p_probe, bool p_enable); - virtual bool gi_probe_is_interior(RID p_probe) const; - - virtual void gi_probe_set_compress(RID p_probe, bool p_enable); - virtual bool gi_probe_is_compressed(RID p_probe) const; - - virtual uint32_t gi_probe_get_version(RID p_probe); - - virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression); - virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data); - /* LIGHTMAP */ struct LightmapCapture : public Instantiable { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0f6058e19..93809190e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -125,7 +125,6 @@ #include "editor/plugins/cpu_particles_editor_plugin.h" #include "editor/plugins/curve_editor_plugin.h" #include "editor/plugins/editor_preview_plugins.h" -#include "editor/plugins/gi_probe_editor_plugin.h" #include "editor/plugins/gradient_editor_plugin.h" #include "editor/plugins/item_list_editor_plugin.h" #include "editor/plugins/light_occluder_2d_editor_plugin.h" @@ -6947,7 +6946,6 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(SpriteFramesEditorPlugin(this))); add_editor_plugin(memnew(TextureRegionEditorPlugin(this))); add_editor_plugin(memnew(Particles2DEditorPlugin(this))); - add_editor_plugin(memnew(GIProbeEditorPlugin(this))); add_editor_plugin(memnew(RoomManagerEditorPlugin(this))); add_editor_plugin(memnew(RoomEditorPlugin(this))); add_editor_plugin(memnew(OccluderEditorPlugin(this))); diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp deleted file mode 100644 index 897920cf7..000000000 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************/ -/* gi_probe_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gi_probe_editor_plugin.h" - -void GIProbeEditorPlugin::_bake() { - if (gi_probe) { - gi_probe->bake(); - } -} - -void GIProbeEditorPlugin::edit(Object *p_object) { - GIProbe *s = Object::cast_to(p_object); - if (!s) { - return; - } - - gi_probe = s; -} - -bool GIProbeEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("GIProbe"); -} - -void GIProbeEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - bake->show(); - } else { - bake->hide(); - } -} - -EditorProgress *GIProbeEditorPlugin::tmp_progress = nullptr; - -void GIProbeEditorPlugin::bake_func_begin(int p_steps) { - ERR_FAIL_COND(tmp_progress != nullptr); - - tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps)); -} - -void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) { - ERR_FAIL_COND(tmp_progress == nullptr); - tmp_progress->step(p_description, p_step, false); -} - -void GIProbeEditorPlugin::bake_func_end() { - ERR_FAIL_COND(tmp_progress == nullptr); - memdelete(tmp_progress); - tmp_progress = nullptr; -} - -void GIProbeEditorPlugin::_bind_methods() { - ClassDB::bind_method("_bake", &GIProbeEditorPlugin::_bake); -} - -GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { - editor = p_node; - bake = memnew(ToolButton); - bake->set_icon(editor->get_gui_base()->get_icon("Bake", "EditorIcons")); - bake->set_text(TTR("Bake GI Probe")); - bake->hide(); - bake->connect("pressed", this, "_bake"); - add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake); - gi_probe = nullptr; - - GIProbe::bake_begin_function = bake_func_begin; - GIProbe::bake_step_function = bake_func_step; - GIProbe::bake_end_function = bake_func_end; -} - -GIProbeEditorPlugin::~GIProbeEditorPlugin() { -} diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h deleted file mode 100644 index 4bda65634..000000000 --- a/editor/plugins/gi_probe_editor_plugin.h +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************/ -/* gi_probe_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef GIPROBEEDITORPLUGIN_H -#define GIPROBEEDITORPLUGIN_H - -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" -#include "scene/3d/gi_probe.h" -#include "scene/resources/material.h" - -class GIProbeEditorPlugin : public EditorPlugin { - GDCLASS(GIProbeEditorPlugin, EditorPlugin); - - GIProbe *gi_probe; - - ToolButton *bake; - EditorNode *editor; - - static EditorProgress *tmp_progress; - static void bake_func_begin(int p_steps); - static void bake_func_step(int p_step, const String &p_description); - static void bake_func_end(); - - void _bake(); - -protected: - static void _bind_methods(); - -public: - virtual String get_name() const { return "GIProbe"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - - GIProbeEditorPlugin(EditorNode *p_node); - ~GIProbeEditorPlugin(); -}; - -#endif // GIPROBEEDITORPLUGIN_H diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index f09ad8d6b..405163ca6 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -6543,7 +6543,6 @@ void SpatialEditor::_register_all_gizmos() { add_gizmo_plugin(Ref(memnew(ParticlesGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CPUParticlesGizmoPlugin))); add_gizmo_plugin(Ref(memnew(ReflectionProbeGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(GIProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionObjectGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionShapeSpatialGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionPolygonSpatialGizmoPlugin))); diff --git a/editor/plugins/spatial_editor_plugin.cpp.orig b/editor/plugins/spatial_editor_plugin.cpp.orig index b41cdd137..ed2e042b0 100644 --- a/editor/plugins/spatial_editor_plugin.cpp.orig +++ b/editor/plugins/spatial_editor_plugin.cpp.orig @@ -6540,7 +6540,6 @@ void SpatialEditor::_register_all_gizmos() { add_gizmo_plugin(Ref(memnew(ParticlesGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CPUParticlesGizmoPlugin))); add_gizmo_plugin(Ref(memnew(ReflectionProbeGizmoPlugin))); - add_gizmo_plugin(Ref(memnew(GIProbeGizmoPlugin))); add_gizmo_plugin(Ref(memnew(BakedIndirectLightGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionObjectGizmoPlugin))); add_gizmo_plugin(Ref(memnew(CollisionShapeSpatialGizmoPlugin))); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 64c0bdfdc..ad56dc3a8 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -36,7 +36,6 @@ #include "scene/3d/collision_polygon.h" #include "scene/3d/collision_shape.h" #include "scene/3d/cpu_particles.h" -#include "scene/3d/gi_probe.h" #include "scene/3d/light.h" #include "scene/3d/listener.h" #include "scene/3d/mesh_instance.h" @@ -2691,176 +2690,6 @@ void ReflectionProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_handles(handles, get_material("handles")); } -GIProbeGizmoPlugin::GIProbeGizmoPlugin() { - Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/gi_probe", Color(0.5, 1, 0.6)); - - create_material("gi_probe_material", gizmo_color); - - gizmo_color.a = 0.5; - create_material("gi_probe_internal_material", gizmo_color); - - gizmo_color.a = 0.1; - create_material("gi_probe_solid_material", gizmo_color); - - create_icon_material("gi_probe_icon", SpatialEditor::get_singleton()->get_icon("GizmoGIProbe", "EditorIcons")); - create_handle_material("handles"); -} - -bool GIProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) { - return Object::cast_to(p_spatial) != nullptr; -} - -String GIProbeGizmoPlugin::get_name() const { - return "GIProbe"; -} - -int GIProbeGizmoPlugin::get_priority() const { - return -1; -} - -String GIProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - switch (p_idx) { - case 0: - return "Extents X"; - case 1: - return "Extents Y"; - case 2: - return "Extents Z"; - } - - return ""; -} -Variant GIProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); - return probe->get_extents(); -} -void GIProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); - - Transform gt = probe->get_global_transform(); - Transform gi = gt.affine_inverse(); - - Vector3 extents = probe->get_extents(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_idx] = 1.0; - - Vector3 ra, rb; - Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; - if (SpatialEditor::get_singleton()->is_snap_enabled()) { - d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - extents[p_idx] = d; - probe->set_extents(extents); -} - -void GIProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); - - Vector3 restore = p_restore; - - if (p_cancel) { - probe->set_extents(restore); - return; - } - - UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Probe Extents")); - ur->add_do_method(probe, "set_extents", probe->get_extents()); - ur->add_undo_method(probe, "set_extents", restore); - ur->commit_action(); -} - -void GIProbeGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - GIProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); - - Ref material = get_material("gi_probe_material", p_gizmo); - Ref icon = get_material("gi_probe_icon", p_gizmo); - Ref material_internal = get_material("gi_probe_internal_material", p_gizmo); - - p_gizmo->clear(); - - Vector lines; - Vector3 extents = probe->get_extents(); - - static const int subdivs[GIProbe::SUBDIV_MAX] = { 64, 128, 256, 512 }; - - AABB aabb = AABB(-extents, extents * 2); - int subdiv = subdivs[probe->get_subdiv()]; - float cell_size = aabb.get_longest_axis_size() / subdiv; - - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - lines.push_back(a); - lines.push_back(b); - } - - p_gizmo->add_lines(lines, material); - - lines.clear(); - - for (int i = 1; i < subdiv; i++) { - for (int j = 0; j < 3; j++) { - if (cell_size * i > aabb.size[j]) { - continue; - } - - int j_n1 = (j + 1) % 3; - int j_n2 = (j + 2) % 3; - - for (int k = 0; k < 4; k++) { - Vector3 from = aabb.position, to = aabb.position; - from[j] += cell_size * i; - to[j] += cell_size * i; - - if (k & 1) { - to[j_n1] += aabb.size[j_n1]; - } else { - to[j_n2] += aabb.size[j_n2]; - } - - if (k & 2) { - from[j_n1] += aabb.size[j_n1]; - from[j_n2] += aabb.size[j_n2]; - } - - lines.push_back(from); - lines.push_back(to); - } - } - } - - p_gizmo->add_lines(lines, material_internal); - - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } - - if (p_gizmo->is_selected()) { - Ref solid_material = get_material("gi_probe_solid_material", p_gizmo); - p_gizmo->add_solid_box(solid_material, aabb.get_size()); - } - - p_gizmo->add_unscaled_billboard(icon, 0.05); - p_gizmo->add_handles(handles, get_material("handles")); -} - //// CollisionObjectGizmoPlugin::CollisionObjectGizmoPlugin() { diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index ebbbc2129..73803007c 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -283,23 +283,6 @@ public: ReflectionProbeGizmoPlugin(); }; -class GIProbeGizmoPlugin : public EditorSpatialGizmoPlugin { - GDCLASS(GIProbeGizmoPlugin, EditorSpatialGizmoPlugin); - -public: - bool has_gizmo(Spatial *p_spatial); - String get_name() const; - int get_priority() const; - void redraw(EditorSpatialGizmo *p_gizmo); - - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - - GIProbeGizmoPlugin(); -}; - class CollisionObjectGizmoPlugin : public EditorSpatialGizmoPlugin { GDCLASS(CollisionObjectGizmoPlugin, EditorSpatialGizmoPlugin); diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp deleted file mode 100644 index f70d308cb..000000000 --- a/scene/3d/gi_probe.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/*************************************************************************/ -/* gi_probe.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gi_probe.h" - -#include "core/os/os.h" - -#include "mesh_instance.h" -#include "voxel_light_baker.h" - -void GIProbeData::set_bounds(const AABB &p_bounds) { - VS::get_singleton()->gi_probe_set_bounds(probe, p_bounds); -} - -AABB GIProbeData::get_bounds() const { - return VS::get_singleton()->gi_probe_get_bounds(probe); -} - -void GIProbeData::set_cell_size(float p_size) { - VS::get_singleton()->gi_probe_set_cell_size(probe, p_size); -} - -float GIProbeData::get_cell_size() const { - return VS::get_singleton()->gi_probe_get_cell_size(probe); -} - -void GIProbeData::set_to_cell_xform(const Transform &p_xform) { - VS::get_singleton()->gi_probe_set_to_cell_xform(probe, p_xform); -} - -Transform GIProbeData::get_to_cell_xform() const { - return VS::get_singleton()->gi_probe_get_to_cell_xform(probe); -} - -void GIProbeData::set_dynamic_data(const PoolVector &p_data) { - VS::get_singleton()->gi_probe_set_dynamic_data(probe, p_data); -} -PoolVector GIProbeData::get_dynamic_data() const { - return VS::get_singleton()->gi_probe_get_dynamic_data(probe); -} - -void GIProbeData::set_dynamic_range(int p_range) { - VS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range); -} - -void GIProbeData::set_energy(float p_range) { - VS::get_singleton()->gi_probe_set_energy(probe, p_range); -} - -float GIProbeData::get_energy() const { - return VS::get_singleton()->gi_probe_get_energy(probe); -} - -void GIProbeData::set_bias(float p_range) { - VS::get_singleton()->gi_probe_set_bias(probe, p_range); -} - -float GIProbeData::get_bias() const { - return VS::get_singleton()->gi_probe_get_bias(probe); -} - -void GIProbeData::set_normal_bias(float p_range) { - VS::get_singleton()->gi_probe_set_normal_bias(probe, p_range); -} - -float GIProbeData::get_normal_bias() const { - return VS::get_singleton()->gi_probe_get_normal_bias(probe); -} - -void GIProbeData::set_propagation(float p_range) { - VS::get_singleton()->gi_probe_set_propagation(probe, p_range); -} - -float GIProbeData::get_propagation() const { - return VS::get_singleton()->gi_probe_get_propagation(probe); -} - -void GIProbeData::set_interior(bool p_enable) { - VS::get_singleton()->gi_probe_set_interior(probe, p_enable); -} - -bool GIProbeData::is_interior() const { - return VS::get_singleton()->gi_probe_is_interior(probe); -} - -bool GIProbeData::is_compressed() const { - return VS::get_singleton()->gi_probe_is_compressed(probe); -} - -void GIProbeData::set_compress(bool p_enable) { - VS::get_singleton()->gi_probe_set_compress(probe, p_enable); -} - -int GIProbeData::get_dynamic_range() const { - return VS::get_singleton()->gi_probe_get_dynamic_range(probe); -} - -RID GIProbeData::get_rid() const { - return probe; -} - -void GIProbeData::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &GIProbeData::set_bounds); - ClassDB::bind_method(D_METHOD("get_bounds"), &GIProbeData::get_bounds); - - ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &GIProbeData::set_cell_size); - ClassDB::bind_method(D_METHOD("get_cell_size"), &GIProbeData::get_cell_size); - - ClassDB::bind_method(D_METHOD("set_to_cell_xform", "to_cell_xform"), &GIProbeData::set_to_cell_xform); - ClassDB::bind_method(D_METHOD("get_to_cell_xform"), &GIProbeData::get_to_cell_xform); - - ClassDB::bind_method(D_METHOD("set_dynamic_data", "dynamic_data"), &GIProbeData::set_dynamic_data); - ClassDB::bind_method(D_METHOD("get_dynamic_data"), &GIProbeData::get_dynamic_data); - - ClassDB::bind_method(D_METHOD("set_dynamic_range", "dynamic_range"), &GIProbeData::set_dynamic_range); - ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbeData::get_dynamic_range); - - ClassDB::bind_method(D_METHOD("set_energy", "energy"), &GIProbeData::set_energy); - ClassDB::bind_method(D_METHOD("get_energy"), &GIProbeData::get_energy); - - ClassDB::bind_method(D_METHOD("set_bias", "bias"), &GIProbeData::set_bias); - ClassDB::bind_method(D_METHOD("get_bias"), &GIProbeData::get_bias); - - ClassDB::bind_method(D_METHOD("set_normal_bias", "bias"), &GIProbeData::set_normal_bias); - ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbeData::get_normal_bias); - - ClassDB::bind_method(D_METHOD("set_propagation", "propagation"), &GIProbeData::set_propagation); - ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbeData::get_propagation); - - ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior); - ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior); - - ClassDB::bind_method(D_METHOD("set_compress", "compress"), &GIProbeData::set_compress); - ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbeData::is_compressed); - - ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_size", "get_cell_size"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "to_cell_xform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_to_cell_xform", "get_to_cell_xform"); - - ADD_PROPERTY(PropertyInfo(Variant::POOL_INT_ARRAY, "dynamic_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_data", "get_dynamic_data"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_dynamic_range", "get_dynamic_range"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_energy", "get_energy"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bias", "get_bias"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_normal_bias", "get_normal_bias"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_propagation", "get_propagation"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_interior", "is_interior"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_compress", "is_compressed"); -} - -GIProbeData::GIProbeData() { - probe = RID_PRIME(VS::get_singleton()->gi_probe_create()); -} - -GIProbeData::~GIProbeData() { - VS::get_singleton()->free(probe); -} - -////////////////////// -////////////////////// - -void GIProbe::set_probe_data(const Ref &p_data) { - if (p_data.is_valid()) { - VS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid()); - } else { - VS::get_singleton()->instance_set_base(get_instance(), RID()); - } - - probe_data = p_data; -} - -Ref GIProbe::get_probe_data() const { - return probe_data; -} - -void GIProbe::set_subdiv(Subdiv p_subdiv) { - ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX); - subdiv = p_subdiv; - update_gizmo(); -} - -GIProbe::Subdiv GIProbe::get_subdiv() const { - return subdiv; -} - -void GIProbe::set_extents(const Vector3 &p_extents) { - extents = p_extents; - update_gizmo(); - _change_notify("extents"); -} - -Vector3 GIProbe::get_extents() const { - return extents; -} - -void GIProbe::set_dynamic_range(int p_dynamic_range) { - dynamic_range = p_dynamic_range; -} -int GIProbe::get_dynamic_range() const { - return dynamic_range; -} - -void GIProbe::set_energy(float p_energy) { - energy = p_energy; - if (probe_data.is_valid()) { - probe_data->set_energy(energy); - } -} -float GIProbe::get_energy() const { - return energy; -} - -void GIProbe::set_bias(float p_bias) { - bias = p_bias; - if (probe_data.is_valid()) { - probe_data->set_bias(bias); - } -} -float GIProbe::get_bias() const { - return bias; -} - -void GIProbe::set_normal_bias(float p_normal_bias) { - normal_bias = p_normal_bias; - if (probe_data.is_valid()) { - probe_data->set_normal_bias(normal_bias); - } -} -float GIProbe::get_normal_bias() const { - return normal_bias; -} - -void GIProbe::set_propagation(float p_propagation) { - propagation = p_propagation; - if (probe_data.is_valid()) { - probe_data->set_propagation(propagation); - } -} -float GIProbe::get_propagation() const { - return propagation; -} - -void GIProbe::set_interior(bool p_enable) { - interior = p_enable; - if (probe_data.is_valid()) { - probe_data->set_interior(p_enable); - } -} - -bool GIProbe::is_interior() const { - return interior; -} - -void GIProbe::set_compress(bool p_enable) { - compress = p_enable; - if (probe_data.is_valid()) { - probe_data->set_compress(p_enable); - } - - update_configuration_warning(); -} - -bool GIProbe::is_compressed() const { - return compress; -} - -void GIProbe::_find_meshes(Node *p_at_node, List &plot_meshes) { - MeshInstance *mi = Object::cast_to(p_at_node); - if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { - Ref mesh = mi->get_mesh(); - if (mesh.is_valid()) { - AABB aabb = mesh->get_aabb(); - - Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); - - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { - PlotMesh pm; - pm.local_xform = xf; - pm.mesh = mesh; - for (int i = 0; i < mesh->get_surface_count(); i++) { - pm.instance_materials.push_back(mi->get_surface_material(i)); - } - pm.override_material = mi->get_material_override(); - plot_meshes.push_back(pm); - } - } - } - - Spatial *s = Object::cast_to(p_at_node); - if (s) { - if (s->is_visible_in_tree()) { - Array meshes = p_at_node->call("get_meshes"); - for (int i = 0; i < meshes.size(); i += 2) { - Transform mxf = meshes[i]; - Ref mesh = meshes[i + 1]; - if (!mesh.is_valid()) { - continue; - } - - AABB aabb = mesh->get_aabb(); - - Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); - - if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { - PlotMesh pm; - pm.local_xform = xf; - pm.mesh = mesh; - plot_meshes.push_back(pm); - } - } - } - } - - for (int i = 0; i < p_at_node->get_child_count(); i++) { - Node *child = p_at_node->get_child(i); - _find_meshes(child, plot_meshes); - } -} - -GIProbe::BakeBeginFunc GIProbe::bake_begin_function = nullptr; -GIProbe::BakeStepFunc GIProbe::bake_step_function = nullptr; -GIProbe::BakeEndFunc GIProbe::bake_end_function = nullptr; - -void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { - static const int subdiv_value[SUBDIV_MAX] = { 7, 8, 9, 10 }; - - p_from_node = p_from_node ? p_from_node : get_parent(); - ERR_FAIL_NULL(p_from_node); - - VoxelLightBaker baker; - - baker.begin_bake(subdiv_value[subdiv], AABB(-extents, extents * 2.0)); - - List mesh_list; - - _find_meshes(p_from_node, mesh_list); - - if (bake_begin_function) { - bake_begin_function(mesh_list.size() + 1); - } - - int pmc = 0; - - for (List::Element *E = mesh_list.front(); E; E = E->next()) { - if (bake_step_function) { - bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size())); - } - - pmc++; - - baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material); - } - if (bake_step_function) { - bake_step_function(pmc++, RTR("Finishing Plot")); - } - - baker.end_bake(); - - //create the data for visual server - - PoolVector data = baker.create_gi_probe_data(); - - if (p_create_visual_debug) { - MultiMeshInstance *mmi = memnew(MultiMeshInstance); - mmi->set_multimesh(baker.create_debug_multimesh()); - add_child(mmi); -#ifdef TOOLS_ENABLED - if (is_inside_tree() && get_tree()->get_edited_scene_root() == this) { - mmi->set_owner(this); - } else { - mmi->set_owner(get_owner()); - } -#else - mmi->set_owner(get_owner()); -#endif - - } else { - Ref probe_data = get_probe_data(); - - if (probe_data.is_null()) { - probe_data.instance(); - } - - probe_data->set_bounds(AABB(-extents, extents * 2.0)); - probe_data->set_cell_size(baker.get_cell_size()); - probe_data->set_dynamic_data(data); - probe_data->set_dynamic_range(dynamic_range); - probe_data->set_energy(energy); - probe_data->set_bias(bias); - probe_data->set_normal_bias(normal_bias); - probe_data->set_propagation(propagation); - probe_data->set_interior(interior); - probe_data->set_compress(compress); - probe_data->set_to_cell_xform(baker.get_to_cell_space_xform()); - - set_probe_data(probe_data); - } - - if (bake_end_function) { - bake_end_function(); - } -} - -void GIProbe::_debug_bake() { - bake(nullptr, true); -} - -AABB GIProbe::get_aabb() const { - return AABB(-extents, extents * 2); -} - -PoolVector GIProbe::get_faces(uint32_t p_usage_flags) const { - return PoolVector(); -} - -String GIProbe::get_configuration_warning() const { - String warning = VisualInstance::get_configuration_warning(); - if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) { - if (warning != String()) { - warning += "\n\n"; - } - warning += TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); - } - - if (is_compressed()) { - if (warning != String()) { - warning += "\n\n"; - } - warning += TTR("The GIProbe Compress property has been deprecated due to known bugs and no longer has any effect.\nTo remove this warning, disable the GIProbe's Compress property."); - } - - return warning; -} - -void GIProbe::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_probe_data", "data"), &GIProbe::set_probe_data); - ClassDB::bind_method(D_METHOD("get_probe_data"), &GIProbe::get_probe_data); - - ClassDB::bind_method(D_METHOD("set_subdiv", "subdiv"), &GIProbe::set_subdiv); - ClassDB::bind_method(D_METHOD("get_subdiv"), &GIProbe::get_subdiv); - - ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GIProbe::set_extents); - ClassDB::bind_method(D_METHOD("get_extents"), &GIProbe::get_extents); - - ClassDB::bind_method(D_METHOD("set_dynamic_range", "max"), &GIProbe::set_dynamic_range); - ClassDB::bind_method(D_METHOD("get_dynamic_range"), &GIProbe::get_dynamic_range); - - ClassDB::bind_method(D_METHOD("set_energy", "max"), &GIProbe::set_energy); - ClassDB::bind_method(D_METHOD("get_energy"), &GIProbe::get_energy); - - ClassDB::bind_method(D_METHOD("set_bias", "max"), &GIProbe::set_bias); - ClassDB::bind_method(D_METHOD("get_bias"), &GIProbe::get_bias); - - ClassDB::bind_method(D_METHOD("set_normal_bias", "max"), &GIProbe::set_normal_bias); - ClassDB::bind_method(D_METHOD("get_normal_bias"), &GIProbe::get_normal_bias); - - ClassDB::bind_method(D_METHOD("set_propagation", "max"), &GIProbe::set_propagation); - ClassDB::bind_method(D_METHOD("get_propagation"), &GIProbe::get_propagation); - - ClassDB::bind_method(D_METHOD("set_interior", "enable"), &GIProbe::set_interior); - ClassDB::bind_method(D_METHOD("is_interior"), &GIProbe::is_interior); - - ClassDB::bind_method(D_METHOD("set_compress", "enable"), &GIProbe::set_compress); - ClassDB::bind_method(D_METHOD("is_compressed"), &GIProbe::is_compressed); - - ClassDB::bind_method(D_METHOD("bake", "from_node", "create_visual_debug"), &GIProbe::bake, DEFVAL(Variant()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("debug_bake"), &GIProbe::_debug_bake); - ClassDB::set_method_flags(get_class_static(), _scs_create("debug_bake"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "subdiv", PROPERTY_HINT_ENUM, "64,128,256,512"), "set_subdiv", "get_subdiv"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "dynamic_range", PROPERTY_HINT_RANGE, "1,16,1"), "set_dynamic_range", "get_dynamic_range"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_bias", "get_bias"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,4,0.001"), "set_normal_bias", "get_normal_bias"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "compress"), "set_compress", "is_compressed"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "data", PROPERTY_HINT_RESOURCE_TYPE, "GIProbeData", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE), "set_probe_data", "get_probe_data"); - - BIND_ENUM_CONSTANT(SUBDIV_64); - BIND_ENUM_CONSTANT(SUBDIV_128); - BIND_ENUM_CONSTANT(SUBDIV_256); - BIND_ENUM_CONSTANT(SUBDIV_512); - BIND_ENUM_CONSTANT(SUBDIV_MAX); -} - -GIProbe::GIProbe() { - subdiv = SUBDIV_128; - dynamic_range = 4; - energy = 1.0; - bias = 1.5; - normal_bias = 0.0; - propagation = 0.7; - extents = Vector3(10, 10, 10); - interior = false; - compress = false; - - gi_probe = RID_PRIME(VS::get_singleton()->gi_probe_create()); - set_disable_scale(true); -} - -GIProbe::~GIProbe() { - VS::get_singleton()->free(gi_probe); -} diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h deleted file mode 100644 index 0f310b871..000000000 --- a/scene/3d/gi_probe.h +++ /dev/null @@ -1,178 +0,0 @@ -/*************************************************************************/ -/* gi_probe.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef GIPROBE_H -#define GIPROBE_H - -#include "multimesh_instance.h" -#include "scene/3d/visual_instance.h" - -class GIProbeData : public Resource { - GDCLASS(GIProbeData, Resource); - - RID probe; - -protected: - static void _bind_methods(); - -public: - void set_bounds(const AABB &p_bounds); - AABB get_bounds() const; - - void set_cell_size(float p_size); - float get_cell_size() const; - - void set_to_cell_xform(const Transform &p_xform); - Transform get_to_cell_xform() const; - - void set_dynamic_data(const PoolVector &p_data); - PoolVector get_dynamic_data() const; - - void set_dynamic_range(int p_range); - int get_dynamic_range() const; - - void set_propagation(float p_range); - float get_propagation() const; - - void set_energy(float p_range); - float get_energy() const; - - void set_bias(float p_range); - float get_bias() const; - - void set_normal_bias(float p_range); - float get_normal_bias() const; - - void set_interior(bool p_enable); - bool is_interior() const; - - void set_compress(bool p_enable); - bool is_compressed() const; - - virtual RID get_rid() const; - - GIProbeData(); - ~GIProbeData(); -}; - -class GIProbe : public VisualInstance { - GDCLASS(GIProbe, VisualInstance); - -public: - enum Subdiv { - SUBDIV_64, - SUBDIV_128, - SUBDIV_256, - SUBDIV_512, - SUBDIV_MAX - - }; - - typedef void (*BakeBeginFunc)(int); - typedef void (*BakeStepFunc)(int, const String &); - typedef void (*BakeEndFunc)(); - -private: - Ref probe_data; - - RID gi_probe; - - Subdiv subdiv; - Vector3 extents; - int dynamic_range; - float energy; - float bias; - float normal_bias; - float propagation; - bool interior; - bool compress; - - struct PlotMesh { - Ref override_material; - Vector> instance_materials; - Ref mesh; - Transform local_xform; - }; - - void _find_meshes(Node *p_at_node, List &plot_meshes); - void _debug_bake(); - -protected: - static void _bind_methods(); - -public: - static BakeBeginFunc bake_begin_function; - static BakeStepFunc bake_step_function; - static BakeEndFunc bake_end_function; - - void set_probe_data(const Ref &p_data); - Ref get_probe_data() const; - - void set_subdiv(Subdiv p_subdiv); - Subdiv get_subdiv() const; - - void set_extents(const Vector3 &p_extents); - Vector3 get_extents() const; - - void set_dynamic_range(int p_dynamic_range); - int get_dynamic_range() const; - - void set_energy(float p_energy); - float get_energy() const; - - void set_bias(float p_bias); - float get_bias() const; - - void set_normal_bias(float p_normal_bias); - float get_normal_bias() const; - - void set_propagation(float p_propagation); - float get_propagation() const; - - void set_interior(bool p_enable); - bool is_interior() const; - - void set_compress(bool p_enable); - bool is_compressed() const; - - void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false); - - virtual AABB get_aabb() const; - virtual PoolVector get_faces(uint32_t p_usage_flags) const; - - virtual String get_configuration_warning() const; - - GIProbe(); - ~GIProbe(); -}; - -VARIANT_ENUM_CAST(GIProbe::Subdiv) - -#endif // GIPROBE_H diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp deleted file mode 100644 index 676ca5d9b..000000000 --- a/scene/3d/voxel_light_baker.cpp +++ /dev/null @@ -1,1601 +0,0 @@ -/*************************************************************************/ -/* voxel_light_baker.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "voxel_light_baker.h" - -#include "core/os/os.h" -#include "core/os/threaded_array_processor.h" - -#include - -#define FINDMINMAX(x0, x1, x2, min, max) \ - min = max = x0; \ - if (x1 < min) \ - min = x1; \ - if (x1 > max) \ - max = x1; \ - if (x2 < min) \ - min = x2; \ - if (x2 > max) \ - max = x2; - -static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { - int q; - Vector3 vmin, vmax; - for (q = 0; q <= 2; q++) { - if (normal[q] > 0.0f) { - vmin[q] = -maxbox[q]; - vmax[q] = maxbox[q]; - } else { - vmin[q] = maxbox[q]; - vmax[q] = -maxbox[q]; - } - } - if (normal.dot(vmin) + d > 0.0f) { - return false; - } - if (normal.dot(vmax) + d >= 0.0f) { - return true; - } - - return false; -} - -/*======================== X-tests ========================*/ -#define AXISTEST_X01(a, b, fa, fb) \ - p0 = a * v0.y - b * v0.z; \ - p2 = a * v2.y - b * v2.z; \ - if (p0 < p2) { \ - min = p0; \ - max = p2; \ - } else { \ - min = p2; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -#define AXISTEST_X2(a, b, fa, fb) \ - p0 = a * v0.y - b * v0.z; \ - p1 = a * v1.y - b * v1.z; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -/*======================== Y-tests ========================*/ -#define AXISTEST_Y02(a, b, fa, fb) \ - p0 = -a * v0.x + b * v0.z; \ - p2 = -a * v2.x + b * v2.z; \ - if (p0 < p2) { \ - min = p0; \ - max = p2; \ - } else { \ - min = p2; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -#define AXISTEST_Y1(a, b, fa, fb) \ - p0 = -a * v0.x + b * v0.z; \ - p1 = -a * v1.x + b * v1.z; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ - if (min > rad || max < -rad) \ - return false; - -/*======================== Z-tests ========================*/ - -#define AXISTEST_Z12(a, b, fa, fb) \ - p1 = a * v1.x - b * v1.y; \ - p2 = a * v2.x - b * v2.y; \ - if (p2 < p1) { \ - min = p2; \ - max = p1; \ - } else { \ - min = p1; \ - max = p2; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ - if (min > rad || max < -rad) \ - return false; - -#define AXISTEST_Z0(a, b, fa, fb) \ - p0 = a * v0.x - b * v0.y; \ - p1 = a * v1.x - b * v1.y; \ - if (p0 < p1) { \ - min = p0; \ - max = p1; \ - } else { \ - min = p1; \ - max = p0; \ - } \ - rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ - if (min > rad || max < -rad) \ - return false; - -static bool fast_tri_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) { - /* use separating axis theorem to test overlap between triangle and box */ - /* need to test for overlap in these directions: */ - /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ - /* we do not even need to test these) */ - /* 2) normal of the triangle */ - /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ - /* this gives 3x3=9 more tests */ - Vector3 v0, v1, v2; - float min, max, d, p0, p1, p2, rad, fex, fey, fez; - Vector3 normal, e0, e1, e2; - - /* This is the fastest branch on Sun */ - /* move everything so that the boxcenter is in (0,0,0) */ - - v0 = triverts[0] - boxcenter; - v1 = triverts[1] - boxcenter; - v2 = triverts[2] - boxcenter; - - /* compute triangle edges */ - e0 = v1 - v0; /* tri edge 0 */ - e1 = v2 - v1; /* tri edge 1 */ - e2 = v0 - v2; /* tri edge 2 */ - - /* Bullet 3: */ - /* test the 9 tests first (this was faster) */ - fex = Math::abs(e0.x); - fey = Math::abs(e0.y); - fez = Math::abs(e0.z); - AXISTEST_X01(e0.z, e0.y, fez, fey); - AXISTEST_Y02(e0.z, e0.x, fez, fex); - AXISTEST_Z12(e0.y, e0.x, fey, fex); - - fex = Math::abs(e1.x); - fey = Math::abs(e1.y); - fez = Math::abs(e1.z); - AXISTEST_X01(e1.z, e1.y, fez, fey); - AXISTEST_Y02(e1.z, e1.x, fez, fex); - AXISTEST_Z0(e1.y, e1.x, fey, fex); - - fex = Math::abs(e2.x); - fey = Math::abs(e2.y); - fez = Math::abs(e2.z); - AXISTEST_X2(e2.z, e2.y, fez, fey); - AXISTEST_Y1(e2.z, e2.x, fez, fex); - AXISTEST_Z12(e2.y, e2.x, fey, fex); - - /* Bullet 1: */ - /* first test overlap in the {x,y,z}-directions */ - /* find min, max of the triangle each direction, and test for overlap in */ - /* that direction -- this is equivalent to testing a minimal AABB around */ - /* the triangle against the AABB */ - - /* test in X-direction */ - FINDMINMAX(v0.x, v1.x, v2.x, min, max); - if (min > boxhalfsize.x || max < -boxhalfsize.x) { - return false; - } - - /* test in Y-direction */ - FINDMINMAX(v0.y, v1.y, v2.y, min, max); - if (min > boxhalfsize.y || max < -boxhalfsize.y) { - return false; - } - - /* test in Z-direction */ - FINDMINMAX(v0.z, v1.z, v2.z, min, max); - if (min > boxhalfsize.z || max < -boxhalfsize.z) { - return false; - } - - /* Bullet 2: */ - /* test if the box intersects the plane of the triangle */ - /* compute plane equation of triangle: normal*x+d=0 */ - normal = e0.cross(e1); - d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ - return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */ -} - -static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) { - if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) { - r_uv = p_uv[0]; - r_normal = p_normal[0]; - return; - } - if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) { - r_uv = p_uv[1]; - r_normal = p_normal[1]; - return; - } - if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) { - r_uv = p_uv[2]; - r_normal = p_normal[2]; - return; - } - - Vector3 v0 = p_vtx[1] - p_vtx[0]; - Vector3 v1 = p_vtx[2] - p_vtx[0]; - Vector3 v2 = p_pos - p_vtx[0]; - - float d00 = v0.dot(v0); - float d01 = v0.dot(v1); - float d11 = v1.dot(v1); - float d20 = v2.dot(v0); - float d21 = v2.dot(v1); - float denom = (d00 * d11 - d01 * d01); - if (denom == 0) { - r_uv = p_uv[0]; - r_normal = p_normal[0]; - return; - } - float v = (d11 * d20 - d01 * d21) / denom; - float w = (d00 * d21 - d01 * d20) / denom; - float u = 1.0f - v - w; - - r_uv = p_uv[0] * u + p_uv[1] * v + p_uv[2] * w; - r_normal = (p_normal[0] * u + p_normal[1] * v + p_normal[2] * w).normalized(); -} - -void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb) { - if (p_level == cell_subdiv - 1) { - //plot the face by guessing its albedo and emission value - - //find best axis to map to, for scanning values - int closest_axis = 0; - float closest_dot = 0; - - Plane plane = Plane(p_vtx[0], p_vtx[1], p_vtx[2]); - Vector3 normal = plane.normal; - - for (int i = 0; i < 3; i++) { - Vector3 axis; - axis[i] = 1.0; - float dot = ABS(normal.dot(axis)); - if (i == 0 || dot > closest_dot) { - closest_axis = i; - closest_dot = dot; - } - } - - Vector3 axis; - axis[closest_axis] = 1.0; - Vector3 t1; - t1[(closest_axis + 1) % 3] = 1.0; - Vector3 t2; - t2[(closest_axis + 2) % 3] = 1.0; - - t1 *= p_aabb.size[(closest_axis + 1) % 3] / float(color_scan_cell_width); - t2 *= p_aabb.size[(closest_axis + 2) % 3] / float(color_scan_cell_width); - - Color albedo_accum; - Color emission_accum; - Vector3 normal_accum; - - float alpha = 0.0; - - //map to a grid average in the best axis for this face - for (int i = 0; i < color_scan_cell_width; i++) { - Vector3 ofs_i = float(i) * t1; - - for (int j = 0; j < color_scan_cell_width; j++) { - Vector3 ofs_j = float(j) * t2; - - Vector3 from = p_aabb.position + ofs_i + ofs_j; - Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis]; - Vector3 half = (to - from) * 0.5; - - //is in this cell? - if (!fast_tri_box_overlap(from + half, half, p_vtx)) { - continue; //face does not span this cell - } - - //go from -size to +size*2 to avoid skipping collisions - Vector3 ray_from = from + (t1 + t2) * 0.5 - axis * p_aabb.size[closest_axis]; - Vector3 ray_to = ray_from + axis * p_aabb.size[closest_axis] * 2; - - if (normal.dot(ray_from - ray_to) < 0) { - SWAP(ray_from, ray_to); - } - - Vector3 intersection; - - if (!plane.intersects_segment(ray_from, ray_to, &intersection)) { - if (ABS(plane.distance_to(ray_from)) < ABS(plane.distance_to(ray_to))) { - intersection = plane.project(ray_from); - } else { - intersection = plane.project(ray_to); - } - } - - intersection = Face3(p_vtx[0], p_vtx[1], p_vtx[2]).get_closest_point_to(intersection); - - Vector2 uv; - Vector3 lnormal; - get_uv_and_normal(intersection, p_vtx, p_uv, p_normal, uv, lnormal); - if (lnormal == Vector3()) { //just in case normal as nor provided - lnormal = normal; - } - - int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1); - int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1); - - int ofs = uv_y * bake_texture_size + uv_x; - albedo_accum.r += p_material.albedo[ofs].r; - albedo_accum.g += p_material.albedo[ofs].g; - albedo_accum.b += p_material.albedo[ofs].b; - albedo_accum.a += p_material.albedo[ofs].a; - - emission_accum.r += p_material.emission[ofs].r; - emission_accum.g += p_material.emission[ofs].g; - emission_accum.b += p_material.emission[ofs].b; - - normal_accum += lnormal; - - alpha += 1.0; - } - } - - if (alpha == 0) { - //could not in any way get texture information.. so use closest point to center - - Face3 f(p_vtx[0], p_vtx[1], p_vtx[2]); - Vector3 inters = f.get_closest_point_to(p_aabb.position + p_aabb.size * 0.5); - - Vector3 lnormal; - Vector2 uv; - get_uv_and_normal(inters, p_vtx, p_uv, p_normal, uv, normal); - if (lnormal == Vector3()) { //just in case normal as nor provided - lnormal = normal; - } - - int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); - int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1); - - int ofs = uv_y * bake_texture_size + uv_x; - - alpha = 1.0 / (color_scan_cell_width * color_scan_cell_width); - - albedo_accum.r = p_material.albedo[ofs].r * alpha; - albedo_accum.g = p_material.albedo[ofs].g * alpha; - albedo_accum.b = p_material.albedo[ofs].b * alpha; - albedo_accum.a = p_material.albedo[ofs].a * alpha; - - emission_accum.r = p_material.emission[ofs].r * alpha; - emission_accum.g = p_material.emission[ofs].g * alpha; - emission_accum.b = p_material.emission[ofs].b * alpha; - - normal_accum = lnormal * alpha; - - } else { - float accdiv = 1.0 / (color_scan_cell_width * color_scan_cell_width); - alpha *= accdiv; - - albedo_accum.r *= accdiv; - albedo_accum.g *= accdiv; - albedo_accum.b *= accdiv; - albedo_accum.a *= accdiv; - - emission_accum.r *= accdiv; - emission_accum.g *= accdiv; - emission_accum.b *= accdiv; - - normal_accum *= accdiv; - } - - //put this temporarily here, corrected in a later step - bake_cells.write[p_idx].albedo[0] += albedo_accum.r; - bake_cells.write[p_idx].albedo[1] += albedo_accum.g; - bake_cells.write[p_idx].albedo[2] += albedo_accum.b; - bake_cells.write[p_idx].emission[0] += emission_accum.r; - bake_cells.write[p_idx].emission[1] += emission_accum.g; - bake_cells.write[p_idx].emission[2] += emission_accum.b; - bake_cells.write[p_idx].normal[0] += normal_accum.x; - bake_cells.write[p_idx].normal[1] += normal_accum.y; - bake_cells.write[p_idx].normal[2] += normal_accum.z; - bake_cells.write[p_idx].alpha += alpha; - - } else { - //go down - - int half = (1 << (cell_subdiv - 1)) >> (p_level + 1); - for (int i = 0; i < 8; i++) { - AABB aabb = p_aabb; - aabb.size *= 0.5; - - int nx = p_x; - int ny = p_y; - int nz = p_z; - - if (i & 1) { - aabb.position.x += aabb.size.x; - nx += half; - } - if (i & 2) { - aabb.position.y += aabb.size.y; - ny += half; - } - if (i & 4) { - aabb.position.z += aabb.size.z; - nz += half; - } - //make sure to not plot beyond limits - if (nx < 0 || nx >= axis_cell_size[0] || ny < 0 || ny >= axis_cell_size[1] || nz < 0 || nz >= axis_cell_size[2]) { - continue; - } - - { - AABB test_aabb = aabb; - //test_aabb.grow_by(test_aabb.get_longest_axis_size()*0.05); //grow a bit to avoid numerical error in real-time - Vector3 qsize = test_aabb.size * 0.5; //quarter size, for fast aabb test - - if (!fast_tri_box_overlap(test_aabb.position + qsize, qsize, p_vtx)) { - //if (!Face3(p_vtx[0],p_vtx[1],p_vtx[2]).intersects_aabb2(aabb)) { - //does not fit in child, go on - continue; - } - } - - if (bake_cells[p_idx].children[i] == CHILD_EMPTY) { - //sub cell must be created - - uint32_t child_idx = bake_cells.size(); - bake_cells.write[p_idx].children[i] = child_idx; - bake_cells.resize(bake_cells.size() + 1); - bake_cells.write[child_idx].level = p_level + 1; - } - - _plot_face(bake_cells[p_idx].children[i], p_level + 1, nx, ny, nz, p_vtx, p_normal, p_uv, p_material, aabb); - } - } -} - -Vector VoxelLightBaker::_get_bake_texture(Ref p_image, const Color &p_color_mul, const Color &p_color_add) { - Vector ret; - - if (p_image.is_null() || p_image->empty()) { - ret.resize(bake_texture_size * bake_texture_size); - for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { - ret.write[i] = p_color_add; - } - - return ret; - } - p_image = p_image->duplicate(); - - if (p_image->is_compressed()) { - p_image->decompress(); - } - p_image->convert(Image::FORMAT_RGBA8); - p_image->resize(bake_texture_size, bake_texture_size, Image::INTERPOLATE_CUBIC); - - PoolVector::Read r = p_image->get_data().read(); - ret.resize(bake_texture_size * bake_texture_size); - - for (int i = 0; i < bake_texture_size * bake_texture_size; i++) { - Color c; - c.r = (r[i * 4 + 0] / 255.0) * p_color_mul.r + p_color_add.r; - c.g = (r[i * 4 + 1] / 255.0) * p_color_mul.g + p_color_add.g; - c.b = (r[i * 4 + 2] / 255.0) * p_color_mul.b + p_color_add.b; - - c.a = r[i * 4 + 3] / 255.0; - - ret.write[i] = c; - } - - return ret; -} - -VoxelLightBaker::MaterialCache VoxelLightBaker::_get_material_cache(Ref p_material) { - //this way of obtaining materials is inaccurate and also does not support some compressed formats very well - Ref mat = p_material; - - Ref material = mat; //hack for now - - if (material_cache.has(material)) { - return material_cache[material]; - } - - MaterialCache mc; - - Ref empty; - - if (mat.is_valid()) { - Ref albedo_tex = mat->get_texture(SpatialMaterial::TEXTURE_ALBEDO); - - Ref img_albedo; - if (albedo_tex.is_valid()) { - img_albedo = albedo_tex->get_data(); - mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo(), Color(0, 0, 0)); // albedo texture, color is multiplicative - } else { - mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive - } - - if (mat->get_feature(SpatialMaterial::FEATURE_EMISSION)) { - Ref emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION); - - Color emission_col = mat->get_emission(); - float emission_energy = mat->get_emission_energy(); - - Ref img_emission; - - if (emission_tex.is_valid()) { - img_emission = emission_tex->get_data(); - } - - if (mat->get_emission_operator() == SpatialMaterial::EMISSION_OP_ADD) { - mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy); - } else { - mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0)); - } - } else { - mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0)); - } - - } else { - mc.albedo = _get_bake_texture(empty, Color(0, 0, 0), Color(1, 1, 1)); - mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0)); - } - - material_cache[p_material] = mc; - return mc; -} - -void VoxelLightBaker::plot_mesh(const Transform &p_xform, Ref &p_mesh, const Vector> &p_materials, const Ref &p_override_material) { - for (int i = 0; i < p_mesh->get_surface_count(); i++) { - if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { - continue; //only triangles - } - - Ref src_material; - - if (p_override_material.is_valid()) { - src_material = p_override_material; - } else if (i < p_materials.size() && p_materials[i].is_valid()) { - src_material = p_materials[i]; - } else { - src_material = p_mesh->surface_get_material(i); - } - MaterialCache material = _get_material_cache(src_material); - - Array a = p_mesh->surface_get_arrays(i); - - PoolVector vertices = a[Mesh::ARRAY_VERTEX]; - PoolVector::Read vr = vertices.read(); - PoolVector uv = a[Mesh::ARRAY_TEX_UV]; - PoolVector::Read uvr; - PoolVector normals = a[Mesh::ARRAY_NORMAL]; - PoolVector::Read nr; - PoolVector index = a[Mesh::ARRAY_INDEX]; - - bool read_uv = false; - bool read_normals = false; - - if (uv.size()) { - uvr = uv.read(); - read_uv = true; - } - - if (normals.size()) { - read_normals = true; - nr = normals.read(); - } - - if (index.size()) { - int facecount = index.size() / 3; - PoolVector::Read ir = index.read(); - - for (int j = 0; j < facecount; j++) { - Vector3 vtxs[3]; - Vector2 uvs[3]; - Vector3 normal[3]; - - for (int k = 0; k < 3; k++) { - vtxs[k] = p_xform.xform(vr[ir[j * 3 + k]]); - } - - if (read_uv) { - for (int k = 0; k < 3; k++) { - uvs[k] = uvr[ir[j * 3 + k]]; - } - } - - if (read_normals) { - for (int k = 0; k < 3; k++) { - normal[k] = nr[ir[j * 3 + k]]; - } - } - - //test against original bounds - if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) { - continue; - } - //plot - _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds); - } - - } else { - int facecount = vertices.size() / 3; - - for (int j = 0; j < facecount; j++) { - Vector3 vtxs[3]; - Vector2 uvs[3]; - Vector3 normal[3]; - - for (int k = 0; k < 3; k++) { - vtxs[k] = p_xform.xform(vr[j * 3 + k]); - } - - if (read_uv) { - for (int k = 0; k < 3; k++) { - uvs[k] = uvr[j * 3 + k]; - } - } - - if (read_normals) { - for (int k = 0; k < 3; k++) { - normal[k] = nr[j * 3 + k]; - } - } - - //test against original bounds - if (!fast_tri_box_overlap(original_bounds.position + original_bounds.size * 0.5, original_bounds.size * 0.5, vtxs)) { - continue; - } - //plot face - _plot_face(0, 0, 0, 0, 0, vtxs, normal, uvs, material, po2_bounds); - } - } - } - - max_original_cells = bake_cells.size(); -} - -void VoxelLightBaker::_init_light_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, uint32_t p_parent) { - bake_light.write[p_idx].x = p_x; - bake_light.write[p_idx].y = p_y; - bake_light.write[p_idx].z = p_z; - - if (p_level == cell_subdiv - 1) { - bake_light.write[p_idx].next_leaf = first_leaf; - first_leaf = p_idx; - } else { - //go down - int half = (1 << (cell_subdiv - 1)) >> (p_level + 1); - for (int i = 0; i < 8; i++) { - uint32_t child = bake_cells[p_idx].children[i]; - - if (child == CHILD_EMPTY) { - continue; - } - - int nx = p_x; - int ny = p_y; - int nz = p_z; - - if (i & 1) { - nx += half; - } - if (i & 2) { - ny += half; - } - if (i & 4) { - nz += half; - } - - _init_light_plot(child, p_level + 1, nx, ny, nz, p_idx); - } - } -} - -void VoxelLightBaker::begin_bake_light(BakeQuality p_quality, float p_propagation) { - _check_init_light(); - propagation = p_propagation; - bake_quality = p_quality; -} - -void VoxelLightBaker::_check_init_light() { - if (bake_light.size() == 0) { - direct_lights_baked = false; - leaf_voxel_count = 0; - _fixup_plot(0, 0); //pre fixup, so normal, albedo, emission, etc. work for lighting. - bake_light.resize(bake_cells.size()); - //memset(bake_light.ptrw(), 0, bake_light.size() * sizeof(Light)); - first_leaf = -1; - _init_light_plot(0, 0, 0, 0, 0, CHILD_EMPTY); - } -} - -static float _get_normal_advance(const Vector3 &p_normal) { - Vector3 normal = p_normal; - Vector3 unorm = normal.abs(); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? Vector3(1.0, 0.0, 0.0) : Vector3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? Vector3(0.0, 1.0, 0.0) : Vector3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? Vector3(0.0, 0.0, 1.0) : Vector3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = Vector3(1.0, 0.0, 0.0); - } - - return 1.0 / normal.dot(unorm); -} - -static const Vector3 aniso_normal[6] = { - Vector3(-1, 0, 0), - Vector3(1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, 1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, 1) -}; - -uint32_t VoxelLightBaker::_find_cell_at_pos(const Cell *cells, int x, int y, int z) { - uint32_t cell = 0; - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - int size = 1 << (cell_subdiv - 1); - int half = size / 2; - - if (x < 0 || x >= size) { - return -1; - } - if (y < 0 || y >= size) { - return -1; - } - if (z < 0 || z >= size) { - return -1; - } - - for (int i = 0; i < cell_subdiv - 1; i++) { - const Cell *bc = &cells[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - cell = bc->children[child]; - if (cell == CHILD_EMPTY) { - return CHILD_EMPTY; - } - - half >>= 1; - } - - return cell; -} -void VoxelLightBaker::plot_light_directional(const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, bool p_direct) { - _check_init_light(); - - float max_len = Vector3(axis_cell_size[0], axis_cell_size[1], axis_cell_size[2]).length() * 1.1; - - if (p_direct) { - direct_lights_baked = true; - } - - Vector3 light_axis = p_direction; - Plane clip[3]; - int clip_planes = 0; - - Light *light_data = bake_light.ptrw(); - const Cell *cells = bake_cells.ptr(); - - for (int i = 0; i < 3; i++) { - if (Math::is_zero_approx(light_axis[i])) { - continue; - } - clip[clip_planes].normal[i] = 1.0; - - if (light_axis[i] < 0) { - clip[clip_planes].d = axis_cell_size[i] + 1; - } else { - clip[clip_planes].d -= 1.0; - } - - clip_planes++; - } - - float distance_adv = _get_normal_advance(light_axis); - - int success_count = 0; - - Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy; - - int idx = first_leaf; - while (idx >= 0) { - Light *light = &light_data[idx]; - - Vector3 to(light->x + 0.5, light->y + 0.5, light->z + 0.5); - to += -light_axis.sign() * 0.47; //make it more likely to receive a ray - - Vector3 from = to - max_len * light_axis; - - for (int j = 0; j < clip_planes; j++) { - clip[j].intersects_segment(from, to, &from); - } - - float distance = (to - from).length(); - distance += distance_adv - Math::fmod(distance, distance_adv); //make it reach the center of the box always - from = to - light_axis * distance; - - uint32_t result = 0xFFFFFFFF; - - while (distance > -distance_adv) { //use this to avoid precision errors - - result = _find_cell_at_pos(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z))); - if (result != 0xFFFFFFFF) { - break; - } - - from += light_axis * distance_adv; - distance -= distance_adv; - } - - if (result == (uint32_t)idx) { - //cell hit itself! hooray! - - Vector3 normal(cells[idx].normal[0], cells[idx].normal[1], cells[idx].normal[2]); - if (normal == Vector3()) { - for (int i = 0; i < 6; i++) { - light->accum[i][0] += light_energy.x * cells[idx].albedo[0]; - light->accum[i][1] += light_energy.y * cells[idx].albedo[1]; - light->accum[i][2] += light_energy.z * cells[idx].albedo[2]; - } - - } else { - for (int i = 0; i < 6; i++) { - float s = MAX(0.0, aniso_normal[i].dot(-normal)); - light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * s; - light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * s; - light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * s; - } - } - - if (p_direct) { - for (int i = 0; i < 6; i++) { - float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct - light->direct_accum[i][0] += light_energy.x * s; - light->direct_accum[i][1] += light_energy.y * s; - light->direct_accum[i][2] += light_energy.z * s; - } - } - success_count++; - } - - idx = light_data[idx].next_leaf; - } -} - -void VoxelLightBaker::plot_light_omni(const Vector3 &p_pos, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, bool p_direct) { - _check_init_light(); - - if (p_direct) { - direct_lights_baked = true; - } - - Plane clip[3]; - int clip_planes = 0; - - // uint64_t us = OS::get_singleton()->get_ticks_usec(); - - Vector3 light_pos = to_cell_space.xform(p_pos) + Vector3(0.5, 0.5, 0.5); - //Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); - - float local_radius = to_cell_space.basis.xform(Vector3(0, 0, 1)).length() * p_radius; - - Light *light_data = bake_light.ptrw(); - const Cell *cells = bake_cells.ptr(); - Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy; - - int idx = first_leaf; - while (idx >= 0) { - Light *light = &light_data[idx]; - - Vector3 to(light->x + 0.5, light->y + 0.5, light->z + 0.5); - to += (light_pos - to).sign() * 0.47; //make it more likely to receive a ray - - Vector3 light_axis = (to - light_pos).normalized(); - float distance_adv = _get_normal_advance(light_axis); - - Vector3 normal(cells[idx].normal[0], cells[idx].normal[1], cells[idx].normal[2]); - - if (normal != Vector3() && normal.dot(-light_axis) < 0.001) { - idx = light_data[idx].next_leaf; - continue; - } - - float att = 1.0; - { - float d = light_pos.distance_to(to); - if (d + distance_adv > local_radius) { - idx = light_data[idx].next_leaf; - continue; // too far away - } - - float dt = CLAMP((d + distance_adv) / local_radius, 0, 1); - att *= powf(1.0 - dt, p_attenutation); - } - - clip_planes = 0; - - for (int c = 0; c < 3; c++) { - if (Math::is_zero_approx(light_axis[c])) { - continue; - } - clip[clip_planes].normal[c] = 1.0; - - if (light_axis[c] < 0) { - clip[clip_planes].d = (1 << (cell_subdiv - 1)) + 1; - } else { - clip[clip_planes].d -= 1.0; - } - - clip_planes++; - } - - Vector3 from = light_pos; - - for (int j = 0; j < clip_planes; j++) { - clip[j].intersects_segment(from, to, &from); - } - - float distance = (to - from).length(); - - distance -= Math::fmod(distance, distance_adv); //make it reach the center of the box always, but this tame make it closer - from = to - light_axis * distance; - to += (light_pos - to).sign() * 0.47; //make it more likely to receive a ray - - uint32_t result = 0xFFFFFFFF; - - while (distance > -distance_adv) { //use this to avoid precision errors - - result = _find_cell_at_pos(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z))); - if (result != 0xFFFFFFFF) { - break; - } - - from += light_axis * distance_adv; - distance -= distance_adv; - } - - if (result == (uint32_t)idx) { - //cell hit itself! hooray! - - if (normal == Vector3()) { - for (int i = 0; i < 6; i++) { - light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * att; - light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * att; - light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * att; - } - - } else { - for (int i = 0; i < 6; i++) { - float s = MAX(0.0, aniso_normal[i].dot(-normal)); - light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * s * att; - light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * s * att; - light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * s * att; - } - } - - if (p_direct) { - for (int i = 0; i < 6; i++) { - float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct - light->direct_accum[i][0] += light_energy.x * s * att; - light->direct_accum[i][1] += light_energy.y * s * att; - light->direct_accum[i][2] += light_energy.z * s * att; - } - } - } - - idx = light_data[idx].next_leaf; - } -} - -void VoxelLightBaker::plot_light_spot(const Vector3 &p_pos, const Vector3 &p_axis, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, float p_spot_angle, float p_spot_attenuation, bool p_direct) { - _check_init_light(); - - if (p_direct) { - direct_lights_baked = true; - } - - Plane clip[3]; - int clip_planes = 0; - - // uint64_t us = OS::get_singleton()->get_ticks_usec(); - - Vector3 light_pos = to_cell_space.xform(p_pos) + Vector3(0.5, 0.5, 0.5); - Vector3 spot_axis = to_cell_space.basis.xform(p_axis).normalized(); - - float local_radius = to_cell_space.basis.xform(Vector3(0, 0, 1)).length() * p_radius; - - Light *light_data = bake_light.ptrw(); - const Cell *cells = bake_cells.ptr(); - Vector3 light_energy = Vector3(p_color.r, p_color.g, p_color.b) * p_energy * p_indirect_energy; - - int idx = first_leaf; - while (idx >= 0) { - Light *light = &light_data[idx]; - - Vector3 to(light->x + 0.5, light->y + 0.5, light->z + 0.5); - - Vector3 light_axis = (to - light_pos).normalized(); - float distance_adv = _get_normal_advance(light_axis); - - Vector3 normal(cells[idx].normal[0], cells[idx].normal[1], cells[idx].normal[2]); - - if (normal != Vector3() && normal.dot(-light_axis) < 0.001) { - idx = light_data[idx].next_leaf; - continue; - } - - float angle = Math::rad2deg(Math::acos(light_axis.dot(-spot_axis))); - if (angle > p_spot_angle) { - idx = light_data[idx].next_leaf; - continue; // too far away - } - - float att = Math::pow(1.0f - angle / p_spot_angle, p_spot_attenuation); - - { - float d = light_pos.distance_to(to); - if (d + distance_adv > local_radius) { - idx = light_data[idx].next_leaf; - continue; // too far away - } - - float dt = CLAMP((d + distance_adv) / local_radius, 0, 1); - att *= powf(1.0 - dt, p_attenutation); - } - - clip_planes = 0; - - for (int c = 0; c < 3; c++) { - if (Math::is_zero_approx(light_axis[c])) { - continue; - } - clip[clip_planes].normal[c] = 1.0; - - if (light_axis[c] < 0) { - clip[clip_planes].d = (1 << (cell_subdiv - 1)) + 1; - } else { - clip[clip_planes].d -= 1.0; - } - - clip_planes++; - } - - Vector3 from = light_pos; - - for (int j = 0; j < clip_planes; j++) { - clip[j].intersects_segment(from, to, &from); - } - - float distance = (to - from).length(); - - distance -= Math::fmod(distance, distance_adv); //make it reach the center of the box always, but this tame make it closer - from = to - light_axis * distance; - - uint32_t result = 0xFFFFFFFF; - - while (distance > -distance_adv) { //use this to avoid precision errors - - result = _find_cell_at_pos(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z))); - if (result != 0xFFFFFFFF) { - break; - } - - from += light_axis * distance_adv; - distance -= distance_adv; - } - - if (result == (uint32_t)idx) { - //cell hit itself! hooray! - - if (normal == Vector3()) { - for (int i = 0; i < 6; i++) { - light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * att; - light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * att; - light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * att; - } - - } else { - for (int i = 0; i < 6; i++) { - float s = MAX(0.0, aniso_normal[i].dot(-normal)); - light->accum[i][0] += light_energy.x * cells[idx].albedo[0] * s * att; - light->accum[i][1] += light_energy.y * cells[idx].albedo[1] * s * att; - light->accum[i][2] += light_energy.z * cells[idx].albedo[2] * s * att; - } - } - - if (p_direct) { - for (int i = 0; i < 6; i++) { - float s = MAX(0.0, aniso_normal[i].dot(-light_axis)); //light depending on normal for direct - light->direct_accum[i][0] += light_energy.x * s * att; - light->direct_accum[i][1] += light_energy.y * s * att; - light->direct_accum[i][2] += light_energy.z * s * att; - } - } - } - - idx = light_data[idx].next_leaf; - } -} - -void VoxelLightBaker::_fixup_plot(int p_idx, int p_level) { - if (p_level == cell_subdiv - 1) { - leaf_voxel_count++; - float alpha = bake_cells[p_idx].alpha; - - bake_cells.write[p_idx].albedo[0] /= alpha; - bake_cells.write[p_idx].albedo[1] /= alpha; - bake_cells.write[p_idx].albedo[2] /= alpha; - - //transfer emission to light - bake_cells.write[p_idx].emission[0] /= alpha; - bake_cells.write[p_idx].emission[1] /= alpha; - bake_cells.write[p_idx].emission[2] /= alpha; - - bake_cells.write[p_idx].normal[0] /= alpha; - bake_cells.write[p_idx].normal[1] /= alpha; - bake_cells.write[p_idx].normal[2] /= alpha; - - Vector3 n(bake_cells[p_idx].normal[0], bake_cells[p_idx].normal[1], bake_cells[p_idx].normal[2]); - if (n.length() < 0.01) { - //too much fight over normal, zero it - bake_cells.write[p_idx].normal[0] = 0; - bake_cells.write[p_idx].normal[1] = 0; - bake_cells.write[p_idx].normal[2] = 0; - } else { - n.normalize(); - bake_cells.write[p_idx].normal[0] = n.x; - bake_cells.write[p_idx].normal[1] = n.y; - bake_cells.write[p_idx].normal[2] = n.z; - } - - bake_cells.write[p_idx].alpha = 1.0; - - /*if (bake_light.size()) { - for(int i=0;i<6;i++) { - - } - }*/ - - } else { - //go down - - bake_cells.write[p_idx].emission[0] = 0; - bake_cells.write[p_idx].emission[1] = 0; - bake_cells.write[p_idx].emission[2] = 0; - bake_cells.write[p_idx].normal[0] = 0; - bake_cells.write[p_idx].normal[1] = 0; - bake_cells.write[p_idx].normal[2] = 0; - bake_cells.write[p_idx].albedo[0] = 0; - bake_cells.write[p_idx].albedo[1] = 0; - bake_cells.write[p_idx].albedo[2] = 0; - if (bake_light.size()) { - for (int j = 0; j < 6; j++) { - bake_light.write[p_idx].accum[j][0] = 0; - bake_light.write[p_idx].accum[j][1] = 0; - bake_light.write[p_idx].accum[j][2] = 0; - } - } - - float alpha_average = 0; - int children_found = 0; - - for (int i = 0; i < 8; i++) { - uint32_t child = bake_cells[p_idx].children[i]; - - if (child == CHILD_EMPTY) { - continue; - } - - _fixup_plot(child, p_level + 1); - alpha_average += bake_cells[child].alpha; - - if (bake_light.size() > 0) { - for (int j = 0; j < 6; j++) { - bake_light.write[p_idx].accum[j][0] += bake_light[child].accum[j][0]; - bake_light.write[p_idx].accum[j][1] += bake_light[child].accum[j][1]; - bake_light.write[p_idx].accum[j][2] += bake_light[child].accum[j][2]; - } - bake_cells.write[p_idx].emission[0] += bake_cells[child].emission[0]; - bake_cells.write[p_idx].emission[1] += bake_cells[child].emission[1]; - bake_cells.write[p_idx].emission[2] += bake_cells[child].emission[2]; - } - - children_found++; - } - - bake_cells.write[p_idx].alpha = alpha_average / 8.0; - if (bake_light.size() && children_found) { - float divisor = Math::lerp(8, children_found, propagation); - for (int j = 0; j < 6; j++) { - bake_light.write[p_idx].accum[j][0] /= divisor; - bake_light.write[p_idx].accum[j][1] /= divisor; - bake_light.write[p_idx].accum[j][2] /= divisor; - } - bake_cells.write[p_idx].emission[0] /= divisor; - bake_cells.write[p_idx].emission[1] /= divisor; - bake_cells.write[p_idx].emission[2] /= divisor; - } - } -} - -void VoxelLightBaker::begin_bake(int p_subdiv, const AABB &p_bounds) { - original_bounds = p_bounds; - cell_subdiv = p_subdiv; - bake_cells.resize(1); - material_cache.clear(); - - //find out the actual real bounds, power of 2, which gets the highest subdivision - po2_bounds = p_bounds; - int longest_axis = po2_bounds.get_longest_axis_index(); - axis_cell_size[longest_axis] = (1 << (cell_subdiv - 1)); - leaf_voxel_count = 0; - - for (int i = 0; i < 3; i++) { - if (i == longest_axis) { - continue; - } - - axis_cell_size[i] = axis_cell_size[longest_axis]; - float axis_size = po2_bounds.size[longest_axis]; - - //shrink until fit subdiv - while (axis_size / 2.0 >= po2_bounds.size[i]) { - axis_size /= 2.0; - axis_cell_size[i] >>= 1; - } - - po2_bounds.size[i] = po2_bounds.size[longest_axis]; - } - - Transform to_bounds; - to_bounds.basis.scale(Vector3(po2_bounds.size[longest_axis], po2_bounds.size[longest_axis], po2_bounds.size[longest_axis])); - to_bounds.origin = po2_bounds.position; - - Transform to_grid; - to_grid.basis.scale(Vector3(axis_cell_size[longest_axis], axis_cell_size[longest_axis], axis_cell_size[longest_axis])); - - to_cell_space = to_grid * to_bounds.affine_inverse(); - - cell_size = po2_bounds.size[longest_axis] / axis_cell_size[longest_axis]; -} - -void VoxelLightBaker::end_bake() { - _fixup_plot(0, 0); -} - -//create the data for visual server - -PoolVector VoxelLightBaker::create_gi_probe_data() { - PoolVector data; - - data.resize(16 + (8 + 1 + 1 + 1 + 1) * bake_cells.size()); //4 for header, rest for rest. - - { - PoolVector::Write w = data.write(); - - uint32_t *w32 = (uint32_t *)w.ptr(); - - w32[0] = 0; //version - w32[1] = cell_subdiv; //subdiv - w32[2] = axis_cell_size[0]; - w32[3] = axis_cell_size[1]; - w32[4] = axis_cell_size[2]; - w32[5] = bake_cells.size(); - w32[6] = leaf_voxel_count; - - int ofs = 16; - - for (int i = 0; i < bake_cells.size(); i++) { - for (int j = 0; j < 8; j++) { - w32[ofs++] = bake_cells[i].children[j]; - } - - { //albedo - uint32_t rgba = uint32_t(CLAMP(bake_cells[i].albedo[0] * 255.0, 0, 255)) << 16; - rgba |= uint32_t(CLAMP(bake_cells[i].albedo[1] * 255.0, 0, 255)) << 8; - rgba |= uint32_t(CLAMP(bake_cells[i].albedo[2] * 255.0, 0, 255)) << 0; - - w32[ofs++] = rgba; - } - { //emission - - Vector3 e(bake_cells[i].emission[0], bake_cells[i].emission[1], bake_cells[i].emission[2]); - float l = e.length(); - if (l > 0) { - e.normalize(); - l = CLAMP(l / 8.0, 0, 1.0); - } - - uint32_t em = uint32_t(CLAMP(e[0] * 255, 0, 255)) << 24; - em |= uint32_t(CLAMP(e[1] * 255, 0, 255)) << 16; - em |= uint32_t(CLAMP(e[2] * 255, 0, 255)) << 8; - em |= uint32_t(CLAMP(l * 255, 0, 255)); - - w32[ofs++] = em; - } - - //w32[ofs++]=bake_cells[i].used_sides; - { //normal - - Vector3 n(bake_cells[i].normal[0], bake_cells[i].normal[1], bake_cells[i].normal[2]); - n = n * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); - uint32_t norm = 0; - - norm |= uint32_t(CLAMP(n.x * 255.0, 0, 255)) << 16; - norm |= uint32_t(CLAMP(n.y * 255.0, 0, 255)) << 8; - norm |= uint32_t(CLAMP(n.z * 255.0, 0, 255)) << 0; - - w32[ofs++] = norm; - } - - { - uint16_t alpha = MIN(uint32_t(bake_cells[i].alpha * 65535.0), 65535); - uint16_t level = bake_cells[i].level; - - w32[ofs++] = (uint32_t(level) << 16) | uint32_t(alpha); - } - } - } - - return data; -} - -void VoxelLightBaker::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref &p_multimesh, int &idx, DebugMode p_mode) { - if (p_level == cell_subdiv - 1) { - Vector3 center = p_aabb.position + p_aabb.size * 0.5; - Transform xform; - xform.origin = center; - xform.basis.scale(p_aabb.size * 0.5); - p_multimesh->set_instance_transform(idx, xform); - Color col; - if (p_mode == DEBUG_ALBEDO) { - col = Color(bake_cells[p_idx].albedo[0], bake_cells[p_idx].albedo[1], bake_cells[p_idx].albedo[2]); - } else if (p_mode == DEBUG_LIGHT) { - for (int i = 0; i < 6; i++) { - col.r += bake_light[p_idx].accum[i][0]; - col.g += bake_light[p_idx].accum[i][1]; - col.b += bake_light[p_idx].accum[i][2]; - col.r += bake_light[p_idx].direct_accum[i][0]; - col.g += bake_light[p_idx].direct_accum[i][1]; - col.b += bake_light[p_idx].direct_accum[i][2]; - } - } - //Color col = Color(bake_cells[p_idx].emission[0], bake_cells[p_idx].emission[1], bake_cells[p_idx].emission[2]); - p_multimesh->set_instance_color(idx, col); - - idx++; - - } else { - for (int i = 0; i < 8; i++) { - uint32_t child = bake_cells[p_idx].children[i]; - - if (child == CHILD_EMPTY || child >= (uint32_t)max_original_cells) { - continue; - } - - AABB aabb = p_aabb; - aabb.size *= 0.5; - - if (i & 1) { - aabb.position.x += aabb.size.x; - } - if (i & 2) { - aabb.position.y += aabb.size.y; - } - if (i & 4) { - aabb.position.z += aabb.size.z; - } - - _debug_mesh(bake_cells[p_idx].children[i], p_level + 1, aabb, p_multimesh, idx, p_mode); - } - } -} - -Ref VoxelLightBaker::create_debug_multimesh(DebugMode p_mode) { - Ref mm; - - ERR_FAIL_COND_V(p_mode == DEBUG_LIGHT && bake_light.size() == 0, mm); - mm.instance(); - - mm->set_transform_format(MultiMesh::TRANSFORM_3D); - mm->set_color_format(MultiMesh::COLOR_8BIT); - mm->set_instance_count(leaf_voxel_count); - - Ref mesh; - mesh.instance(); - - { - Array arr; - arr.resize(Mesh::ARRAY_MAX); - - PoolVector vertices; - PoolVector colors; -#define ADD_VTX(m_idx) \ - ; \ - vertices.push_back(face_points[m_idx]); \ - colors.push_back(Color(1, 1, 1, 1)); - - for (int i = 0; i < 6; i++) { - Vector3 face_points[4]; - - for (int j = 0; j < 4; j++) { - float v[3]; - v[0] = 1.0; - v[1] = 1 - 2 * ((j >> 1) & 1); - v[2] = v[1] * (1 - 2 * (j & 1)); - - for (int k = 0; k < 3; k++) { - if (i < 3) { - face_points[j][(i + k) % 3] = v[k]; - } else { - face_points[3 - j][(i + k) % 3] = -v[k]; - } - } - } - - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); - } - - arr[Mesh::ARRAY_VERTEX] = vertices; - arr[Mesh::ARRAY_COLOR] = colors; - mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr); - } - - { - Ref fsm; - fsm.instance(); - fsm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - fsm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - fsm->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - fsm->set_albedo(Color(1, 1, 1, 1)); - - mesh->surface_set_material(0, fsm); - } - - mm->set_mesh(mesh); - - int idx = 0; - _debug_mesh(0, 0, po2_bounds, mm, idx, p_mode); - - return mm; -} - -struct VoxelLightBakerOctree { - enum { - CHILD_EMPTY = 0xFFFFFFFF - }; - - uint16_t light[6][3]; //anisotropic light - float alpha; - uint32_t children[8]; -}; - -PoolVector VoxelLightBaker::create_capture_octree(int p_subdiv) { - p_subdiv = MIN(p_subdiv, cell_subdiv); // use the smaller one - - Vector remap; - int bc = bake_cells.size(); - remap.resize(bc); - Vector demap; - - int new_size = 0; - for (int i = 0; i < bc; i++) { - uint32_t c = CHILD_EMPTY; - if (bake_cells[i].level < p_subdiv) { - c = new_size; - new_size++; - demap.push_back(i); - } - remap.write[i] = c; - } - - Vector octree; - octree.resize(new_size); - - for (int i = 0; i < new_size; i++) { - octree.write[i].alpha = bake_cells[demap[i]].alpha; - for (int j = 0; j < 6; j++) { - for (int k = 0; k < 3; k++) { - float l = bake_light[demap[i]].accum[j][k]; //add anisotropic light - l += bake_cells[demap[i]].emission[k]; //add emission - octree.write[i].light[j][k] = CLAMP(l * 1024, 0, 65535); //give two more bits to octree - } - } - - for (int j = 0; j < 8; j++) { - uint32_t child = bake_cells[demap[i]].children[j]; - octree.write[i].children[j] = child == CHILD_EMPTY ? CHILD_EMPTY : remap[child]; - } - } - - PoolVector ret; - int ret_bytes = octree.size() * sizeof(VoxelLightBakerOctree); - ret.resize(ret_bytes); - { - PoolVector::Write w = ret.write(); - memcpy(w.ptr(), octree.ptr(), ret_bytes); - } - - return ret; -} - -float VoxelLightBaker::get_cell_size() const { - return cell_size; -} - -Transform VoxelLightBaker::get_to_cell_space_xform() const { - return to_cell_space; -} -VoxelLightBaker::VoxelLightBaker() { - color_scan_cell_width = 4; - bake_texture_size = 128; - propagation = 0.85; -} diff --git a/scene/3d/voxel_light_baker.h b/scene/3d/voxel_light_baker.h deleted file mode 100644 index da5a5e1e1..000000000 --- a/scene/3d/voxel_light_baker.h +++ /dev/null @@ -1,171 +0,0 @@ -/*************************************************************************/ -/* voxel_light_baker.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VOXEL_LIGHT_BAKER_H -#define VOXEL_LIGHT_BAKER_H - -#include "scene/3d/mesh_instance.h" -#include "scene/resources/multimesh.h" - -class VoxelLightBaker { -public: - enum DebugMode { - DEBUG_ALBEDO, - DEBUG_LIGHT - }; - - enum BakeQuality { - BAKE_QUALITY_LOW, - BAKE_QUALITY_MEDIUM, - BAKE_QUALITY_HIGH - }; - - enum BakeMode { - BAKE_MODE_CONE_TRACE, - BAKE_MODE_RAY_TRACE, - }; - -private: - enum { - CHILD_EMPTY = 0xFFFFFFFF - - }; - - struct Cell { - uint32_t children[8]; - float albedo[3]; //albedo in RGB24 - float emission[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast) - float normal[3]; - uint32_t used_sides; - float alpha; //used for upsampling - int level; - - Cell() { - for (int i = 0; i < 8; i++) { - children[i] = CHILD_EMPTY; - } - - for (int i = 0; i < 3; i++) { - emission[i] = 0; - albedo[i] = 0; - normal[i] = 0; - } - alpha = 0; - used_sides = 0; - level = 0; - } - }; - - Vector bake_cells; - int cell_subdiv; - - struct Light { - int x, y, z; - float accum[6][3]; //rgb anisotropic - float direct_accum[6][3]; //for direct bake - int next_leaf; - Light() { - x = y = z = 0; - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 3; j++) { - accum[i][j] = 0; - direct_accum[i][j] = 0; - } - } - next_leaf = 0; - } - }; - - int first_leaf; - - Vector bake_light; - - struct MaterialCache { - //128x128 textures - Vector albedo; - Vector emission; - }; - - Map, MaterialCache> material_cache; - int leaf_voxel_count; - bool direct_lights_baked; - - AABB original_bounds; - AABB po2_bounds; - int axis_cell_size[3]; - - Transform to_cell_space; - - int color_scan_cell_width; - int bake_texture_size; - float cell_size; - float propagation; - - BakeQuality bake_quality; - - int max_original_cells; - - void _init_light_plot(int p_idx, int p_level, int p_x, int p_y, int p_z, uint32_t p_parent); - - Vector _get_bake_texture(Ref p_image, const Color &p_color_mul, const Color &p_color_add); - MaterialCache _get_material_cache(Ref p_material); - - void _plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, const Vector3 *p_vtx, const Vector3 *p_normal, const Vector2 *p_uv, const MaterialCache &p_material, const AABB &p_aabb); - void _fixup_plot(int p_idx, int p_level); - void _debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref &p_multimesh, int &idx, DebugMode p_mode); - void _check_init_light(); - - uint32_t _find_cell_at_pos(const Cell *cells, int x, int y, int z); - -public: - void begin_bake(int p_subdiv, const AABB &p_bounds); - void plot_mesh(const Transform &p_xform, Ref &p_mesh, const Vector> &p_materials, const Ref &p_override_material); - void begin_bake_light(BakeQuality p_quality = BAKE_QUALITY_MEDIUM, float p_propagation = 0.85); - void plot_light_directional(const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, bool p_direct); - void plot_light_omni(const Vector3 &p_pos, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, bool p_direct); - void plot_light_spot(const Vector3 &p_pos, const Vector3 &p_axis, const Color &p_color, float p_energy, float p_indirect_energy, float p_radius, float p_attenutation, float p_spot_angle, float p_spot_attenuation, bool p_direct); - void end_bake(); - - struct LightMapData { - int width; - int height; - PoolVector light; - }; - - PoolVector create_gi_probe_data(); - Ref create_debug_multimesh(DebugMode p_mode = DEBUG_ALBEDO); - PoolVector create_capture_octree(int p_subdiv); - - float get_cell_size() const; - Transform get_to_cell_space_xform() const; - VoxelLightBaker(); -}; - -#endif // VOXEL_LIGHT_BAKER_H diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 7a4d008aa..1e171c659 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -185,7 +185,6 @@ #include "scene/3d/collision_polygon.h" #include "scene/3d/collision_shape.h" #include "scene/3d/cpu_particles.h" -#include "scene/3d/gi_probe.h" #include "scene/3d/immediate_geometry.h" #include "scene/3d/interpolated_camera.h" #include "scene/3d/light.h" @@ -438,8 +437,6 @@ void register_scene_types() { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 71ff30ad6..9992af4cb 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -109,7 +109,6 @@ public: Vector materials; Vector light_instances; Vector reflection_probe_instances; - Vector gi_probe_instances; PoolVector blend_values; @@ -184,11 +183,6 @@ public: virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; - virtual RID gi_probe_instance_create() = 0; - virtual void gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) = 0; - virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0; - virtual void gi_probe_instance_set_bounds(RID p_probe, const Vector3 &p_bounds) = 0; - virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const int p_eye, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0; @@ -522,54 +516,6 @@ public: virtual void instance_add_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; virtual void instance_remove_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; - /* GI PROBE API */ - - virtual RID gi_probe_create() = 0; - - virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0; - virtual AABB gi_probe_get_bounds(RID p_probe) const = 0; - - virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_cell_size(RID p_probe) const = 0; - - virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) = 0; - virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const = 0; - - virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector &p_data) = 0; - virtual PoolVector gi_probe_get_dynamic_data(RID p_probe) const = 0; - - virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range) = 0; - virtual int gi_probe_get_dynamic_range(RID p_probe) const = 0; - - virtual void gi_probe_set_energy(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_energy(RID p_probe) const = 0; - - virtual void gi_probe_set_bias(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_bias(RID p_probe) const = 0; - - virtual void gi_probe_set_normal_bias(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_probe) const = 0; - - virtual void gi_probe_set_propagation(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_probe) const = 0; - - virtual void gi_probe_set_interior(RID p_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_probe) const = 0; - - virtual void gi_probe_set_compress(RID p_probe, bool p_enable) = 0; - virtual bool gi_probe_is_compressed(RID p_probe) const = 0; - - virtual uint32_t gi_probe_get_version(RID p_probe) = 0; - - enum GIProbeCompression { - GI_PROBE_UNCOMPRESSED, - GI_PROBE_S3TC, - GI_PROBE_ETC2 - }; - - virtual RID gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) = 0; - virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) = 0; - /* LIGHTMAP CAPTURE */ struct LightmapCaptureOctree { diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 1dc1263b9..9cdb32de4 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -114,7 +114,6 @@ void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) { VSG::scene->update_dirty_instances(); //update scene stuff VSG::viewport->draw_viewports(); - VSG::scene->render_probes(); _draw_margins(); VSG::rasterizer->end_frame(p_swap_buffers); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 56a643c7f..174b2a47c 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -356,43 +356,6 @@ public: BIND2(reflection_probe_set_cull_mask, RID, uint32_t) BIND2(reflection_probe_set_resolution, RID, int) - /* BAKED LIGHT API */ - - BIND0R(RID, gi_probe_create) - - BIND2(gi_probe_set_bounds, RID, const AABB &) - BIND1RC(AABB, gi_probe_get_bounds, RID) - - BIND2(gi_probe_set_cell_size, RID, float) - BIND1RC(float, gi_probe_get_cell_size, RID) - - BIND2(gi_probe_set_to_cell_xform, RID, const Transform &) - BIND1RC(Transform, gi_probe_get_to_cell_xform, RID) - - BIND2(gi_probe_set_dynamic_range, RID, int) - BIND1RC(int, gi_probe_get_dynamic_range, RID) - - BIND2(gi_probe_set_energy, RID, float) - BIND1RC(float, gi_probe_get_energy, RID) - - BIND2(gi_probe_set_bias, RID, float) - BIND1RC(float, gi_probe_get_bias, RID) - - BIND2(gi_probe_set_normal_bias, RID, float) - BIND1RC(float, gi_probe_get_normal_bias, RID) - - BIND2(gi_probe_set_propagation, RID, float) - BIND1RC(float, gi_probe_get_propagation, RID) - - BIND2(gi_probe_set_interior, RID, bool) - BIND1RC(bool, gi_probe_is_interior, RID) - - BIND2(gi_probe_set_compress, RID, bool) - BIND1RC(bool, gi_probe_is_compressed, RID) - - BIND2(gi_probe_set_dynamic_data, RID, const PoolVector &) - BIND1RC(PoolVector, gi_probe_get_dynamic_data, RID) - /* LIGHTMAP CAPTURE */ BIND0R(RID, lightmap_capture_create) diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 138fb2c16..b74ece23f 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -364,23 +364,6 @@ void *VisualServerScene::_instance_pair(void *p_self, SpatialPartitionID, Instan ((VisualServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - InstanceGIProbeData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->gi_probes.push_back(B); - - List::Element *E = gi_probe->geometries.push_back(pinfo); - - geom->gi_probes_dirty = true; - - return E; //this element should make freeing faster - - } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - return gi_probe->lights.insert(A); } return nullptr; @@ -430,22 +413,6 @@ void VisualServerScene::_instance_unpair(void *p_self, SpatialPartitionID, Insta lightmap_capture->geometries.erase(E); ((VisualServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture - } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - List::Element *E = reinterpret_cast::Element *>(udata); - - geom->gi_probes.erase(E->get().L); - gi_probe->geometries.erase(E); - - geom->gi_probes_dirty = true; - - } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - Set::Element *E = reinterpret_cast::Element *>(udata); - - gi_probe->lights.erase(E); } } @@ -560,23 +527,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { VSG::storage->instance_remove_dependency(instance->base, instance); - if (instance->base_type == VS::INSTANCE_GI_PROBE) { - //if gi probe is baking, wait until done baking, else race condition may happen when removing it - //from octree - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - - //make sure probes are done baking - while (!probe_bake_list.empty()) { - OS::get_singleton()->delay_usec(1); - } - //make sure this one is done baking - - while (gi_probe->dynamic.updating_stage == GI_UPDATE_STAGE_LIGHTING) { - //wait until bake is done if it's baking - OS::get_singleton()->delay_usec(1); - } - } - if (scenario && instance->spatial_partition_id) { scenario->sps->erase(instance->spatial_partition_id); instance->spatial_partition_id = 0; @@ -606,27 +556,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID(), -1, Rect2(0, 0, 1, 1)); } } break; - case VS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); - } - if (gi_probe->dynamic.probe_data.is_valid()) { - VSG::storage->free(gi_probe->dynamic.probe_data); - } - - if (instance->lightmap_capture) { - Instance *capture = (Instance *)instance->lightmap_capture; - InstanceLightmapCaptureData *lightmap_capture = static_cast(capture->base_data); - lightmap_capture->users.erase(instance); - instance->lightmap_capture = nullptr; - instance->lightmap = RID(); - } - - VSG::scene_render->free(gi_probe->probe_instance); - - } break; default: { } } @@ -687,18 +616,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { instance->base_data = lightmap_capture; //lightmap_capture->instance = VSG::scene_render->lightmap_capture_instance_create(p_base); } break; - case VS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); - instance->base_data = gi_probe; - gi_probe->owner = instance; - - if (scenario && !gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - - gi_probe->probe_instance = VSG::scene_render->gi_probe_instance_create(); - - } break; default: { } } @@ -745,12 +662,6 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { InstanceReflectionProbeData *reflection_probe = static_cast(instance->base_data); VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); } break; - case VS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); - } - } break; default: { } } @@ -774,12 +685,6 @@ void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { light->D = scenario->directional_lights.push_back(instance); } } break; - case VS::INSTANCE_GI_PROBE: { - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - } break; default: { } } @@ -1155,12 +1060,6 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) { instance->scenario->sps->set_pairable(instance, p_visible, 1 << VS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? VS::INSTANCE_GEOMETRY_MASK : 0); } - } break; - case VS::INSTANCE_GI_PROBE: { - if (instance->spatial_partition_id && instance->scenario) { - instance->scenario->sps->set_pairable(instance, p_visible, 1 << VS::INSTANCE_GI_PROBE, p_visible ? (VS::INSTANCE_GEOMETRY_MASK | (1 << VS::INSTANCE_LIGHT)) : 0); - } - } break; default: { // if we haven't called set_pairable, we STILL need to do a collision check @@ -2026,12 +1925,6 @@ void VisualServerScene::_update_instance(Instance *p_instance) { pairable = true; } - if (p_instance->base_type == VS::INSTANCE_GI_PROBE) { - //lights and geometries - pairable_mask = p_instance->visible ? VS::INSTANCE_GEOMETRY_MASK | (1 << VS::INSTANCE_LIGHT) : 0; - pairable = true; - } - // not inside octree p_instance->spatial_partition_id = p_instance->scenario->sps->create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask); @@ -2097,10 +1990,6 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { case VisualServer::INSTANCE_REFLECTION_PROBE: { new_aabb = VSG::storage->reflection_probe_get_aabb(p_instance->base); - } break; - case VisualServer::INSTANCE_GI_PROBE: { - new_aabb = VSG::storage->gi_probe_get_bounds(p_instance->base); - } break; case VisualServer::INSTANCE_LIGHTMAP_CAPTURE: { new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base); @@ -2118,6 +2007,167 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { p_instance->aabb = new_aabb; } +void VisualServerScene::_update_dirty_instance(Instance *p_instance) { + if (p_instance->update_aabb) { + _update_instance_aabb(p_instance); + } + + if (p_instance->update_materials) { + if (p_instance->base_type == VS::INSTANCE_MESH) { + //remove materials no longer used and un-own them + + int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base); + for (int i = p_instance->materials.size() - 1; i >= new_mat_count; i--) { + if (p_instance->materials[i].is_valid()) { + VSG::storage->material_remove_instance_owner(p_instance->materials[i], p_instance); + } + } + p_instance->materials.resize(new_mat_count); + + int new_blend_shape_count = VSG::storage->mesh_get_blend_shape_count(p_instance->base); + if (new_blend_shape_count != p_instance->blend_values.size()) { + p_instance->blend_values.resize(new_blend_shape_count); + for (int i = 0; i < new_blend_shape_count; i++) { + p_instance->blend_values.write().ptr()[i] = 0; + } + } + } + + if ((1 << p_instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) { + InstanceGeometryData *geom = static_cast(p_instance->base_data); + + bool can_cast_shadows = true; + bool is_animated = false; + + if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) { + can_cast_shadows = false; + } else if (p_instance->material_override.is_valid()) { + can_cast_shadows = VSG::storage->material_casts_shadows(p_instance->material_override); + is_animated = VSG::storage->material_is_animated(p_instance->material_override); + } else { + if (p_instance->base_type == VS::INSTANCE_MESH) { + RID mesh = p_instance->base; + + if (mesh.is_valid()) { + bool cast_shadows = false; + + for (int i = 0; i < p_instance->materials.size(); i++) { + RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : VSG::storage->mesh_surface_get_material(mesh, i); + + if (!mat.is_valid()) { + cast_shadows = true; + } else { + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + + if (VSG::storage->material_is_animated(mat)) { + is_animated = true; + } + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + + } else if (p_instance->base_type == VS::INSTANCE_MULTIMESH) { + RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base); + if (mesh.is_valid()) { + bool cast_shadows = false; + + int sc = VSG::storage->mesh_get_surface_count(mesh); + for (int i = 0; i < sc; i++) { + RID mat = VSG::storage->mesh_surface_get_material(mesh, i); + + if (!mat.is_valid()) { + cast_shadows = true; + + } else { + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + if (VSG::storage->material_is_animated(mat)) { + is_animated = true; + } + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + } else if (p_instance->base_type == VS::INSTANCE_IMMEDIATE) { + RID mat = VSG::storage->immediate_get_material(p_instance->base); + + can_cast_shadows = !mat.is_valid() || VSG::storage->material_casts_shadows(mat); + + if (mat.is_valid() && VSG::storage->material_is_animated(mat)) { + is_animated = true; + } + } else if (p_instance->base_type == VS::INSTANCE_PARTICLES) { + bool cast_shadows = false; + + int dp = VSG::storage->particles_get_draw_passes(p_instance->base); + + for (int i = 0; i < dp; i++) { + RID mesh = VSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); + if (!mesh.is_valid()) { + continue; + } + + int sc = VSG::storage->mesh_get_surface_count(mesh); + for (int j = 0; j < sc; j++) { + RID mat = VSG::storage->mesh_surface_get_material(mesh, j); + + if (!mat.is_valid()) { + cast_shadows = true; + } else { + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + + if (VSG::storage->material_is_animated(mat)) { + is_animated = true; + } + } + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + } + + if (p_instance->material_overlay.is_valid()) { + can_cast_shadows = can_cast_shadows || VSG::storage->material_casts_shadows(p_instance->material_overlay); + is_animated = is_animated || VSG::storage->material_is_animated(p_instance->material_overlay); + } + + if (can_cast_shadows != geom->can_cast_shadows) { + //ability to cast shadows change, let lights now + for (List::Element *E = geom->lighting.front(); E; E = E->next()) { + InstanceLightData *light = static_cast(E->get()->base_data); + light->shadow_dirty = true; + } + + geom->can_cast_shadows = can_cast_shadows; + } + + geom->material_is_animated = is_animated; + } + } + + _instance_update_list.remove(&p_instance->update_item); + + _update_instance(p_instance); + + p_instance->update_aabb = false; + p_instance->update_materials = false; +} + _FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) { static const Vector3 aniso_normal[6] = { Vector3(-1, 0, 0), @@ -2983,12 +3033,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca } } - } else if (ins->base_type == VS::INSTANCE_GI_PROBE && ins->visible) { - InstanceGIProbeData *gi_probe = static_cast(ins->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - } else if (((1 << ins->base_type) & VS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { keep = true; @@ -3039,20 +3083,6 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca geom->reflection_dirty = false; } - - if (geom->gi_probes_dirty) { - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->gi_probe_instances.resize(geom->gi_probes.size()); - - for (List::Element *E = geom->gi_probes.front(); E; E = E->next()) { - InstanceGIProbeData *gi_probe = static_cast(E->get()->base_data); - - ins->gi_probe_instances.write[l++] = gi_probe->probe_instance; - } - - geom->gi_probes_dirty = false; - } } if (!keep) { @@ -3248,1203 +3278,6 @@ void VisualServerScene::render_empty_scene(RID p_scenario, RID p_shadow_atlas) { #endif } -bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) { - InstanceReflectionProbeData *reflection_probe = static_cast(p_instance->base_data); - Scenario *scenario = p_instance->scenario; - ERR_FAIL_COND_V(!scenario, true); - - VisualServerRaster::redraw_request(); //update, so it updates in editor - - if (p_step == 0) { - if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { - return true; //sorry, all full :( - } - } - - if (p_step >= 0 && p_step < 6) { - static const Vector3 view_normals[6] = { - Vector3(-1, 0, 0), - Vector3(+1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, +1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, +1) - }; - - Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base); - Vector3 origin_offset = VSG::storage->reflection_probe_get_origin_offset(p_instance->base); - float max_distance = VSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); - - Vector3 edge = view_normals[p_step] * extents; - float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit - - max_distance = MAX(max_distance, distance); - - //render cubemap side - CameraMatrix cm; - cm.set_perspective(90, 1, 0.01, max_distance); - - static const Vector3 view_up[6] = { - Vector3(0, -1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, +1), - Vector3(0, -1, 0), - Vector3(0, -1, 0) - }; - - Transform local_view; - local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]); - - Transform xform = p_instance->transform * local_view; - - RID shadow_atlas; - - if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) { - shadow_atlas = scenario->reflection_probe_shadow_atlas; - } - - _prepare_scene(xform, cm, false, RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, reflection_probe->previous_room_id_hint); - - bool async_forbidden_backup = VSG::storage->is_shader_async_hidden_forbidden(); - VSG::storage->set_shader_async_hidden_forbidden(true); - _render_scene(xform, cm, 0, false, RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step); - VSG::storage->set_shader_async_hidden_forbidden(async_forbidden_backup); - - } else { - //do roughness postprocess step until it believes it's done - return VSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); - } - - return false; -} - -void VisualServerScene::_gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell *p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector *prev_cell) { - if ((uint32_t)p_level == p_header->cell_subdiv - 1) { - Vector3 emission; - emission.x = (p_cell[p_idx].emission >> 24) / 255.0; - emission.y = ((p_cell[p_idx].emission >> 16) & 0xFF) / 255.0; - emission.z = ((p_cell[p_idx].emission >> 8) & 0xFF) / 255.0; - float l = (p_cell[p_idx].emission & 0xFF) / 255.0; - l *= 8.0; - - emission *= l; - - p_local_data[p_idx].energy[0] = uint16_t(emission.x * 1024); //go from 0 to 1024 for light - p_local_data[p_idx].energy[1] = uint16_t(emission.y * 1024); //go from 0 to 1024 for light - p_local_data[p_idx].energy[2] = uint16_t(emission.z * 1024); //go from 0 to 1024 for light - } else { - p_local_data[p_idx].energy[0] = 0; - p_local_data[p_idx].energy[1] = 0; - p_local_data[p_idx].energy[2] = 0; - - int half = (1 << (p_header->cell_subdiv - 1)) >> (p_level + 1); - - for (int i = 0; i < 8; i++) { - uint32_t child = p_cell[p_idx].children[i]; - - if (child == 0xFFFFFFFF) { - continue; - } - - int x = p_x; - int y = p_y; - int z = p_z; - - if (i & 1) { - x += half; - } - if (i & 2) { - y += half; - } - if (i & 4) { - z += half; - } - - _gi_probe_fill_local_data(child, p_level + 1, x, y, z, p_cell, p_header, p_local_data, prev_cell); - } - } - - //position for each part of the mipmaped texture - p_local_data[p_idx].pos[0] = p_x >> (p_header->cell_subdiv - p_level - 1); - p_local_data[p_idx].pos[1] = p_y >> (p_header->cell_subdiv - p_level - 1); - p_local_data[p_idx].pos[2] = p_z >> (p_header->cell_subdiv - p_level - 1); - - prev_cell[p_level].push_back(p_idx); -} - -void VisualServerScene::_gi_probe_bake_threads(void *self) { - VisualServerScene *vss = (VisualServerScene *)self; - vss->_gi_probe_bake_thread(); -} - -void VisualServerScene::_setup_gi_probe(Instance *p_instance) { - InstanceGIProbeData *probe = static_cast(p_instance->base_data); - - if (probe->dynamic.probe_data.is_valid()) { - VSG::storage->free(probe->dynamic.probe_data); - probe->dynamic.probe_data = RID(); - } - - probe->dynamic.light_data = VSG::storage->gi_probe_get_dynamic_data(p_instance->base); - - if (probe->dynamic.light_data.size() == 0) { - return; - } - //using dynamic data - PoolVector::Read r = probe->dynamic.light_data.read(); - - const GIProbeDataHeader *header = (GIProbeDataHeader *)r.ptr(); - - probe->dynamic.local_data.resize(header->cell_count); - - int cell_count = probe->dynamic.local_data.size(); - PoolVector::Write ldw = probe->dynamic.local_data.write(); - const GIProbeDataCell *cells = (GIProbeDataCell *)&r[16]; - - probe->dynamic.level_cell_lists.resize(header->cell_subdiv); - - _gi_probe_fill_local_data(0, 0, 0, 0, 0, cells, header, ldw.ptr(), probe->dynamic.level_cell_lists.ptrw()); - - probe->dynamic.compression = RasterizerStorage::GI_PROBE_UNCOMPRESSED; - - probe->dynamic.probe_data = VSG::storage->gi_probe_dynamic_data_create(header->width, header->height, header->depth, probe->dynamic.compression); - - probe->dynamic.bake_dynamic_range = VSG::storage->gi_probe_get_dynamic_range(p_instance->base); - - probe->dynamic.mipmaps_3d.clear(); - probe->dynamic.propagate = VSG::storage->gi_probe_get_propagation(p_instance->base); - - probe->dynamic.grid_size[0] = header->width; - probe->dynamic.grid_size[1] = header->height; - probe->dynamic.grid_size[2] = header->depth; - - int size_limit = 1; - int size_divisor = 1; - - if (probe->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) { - size_limit = 4; - size_divisor = 4; - } - for (int i = 0; i < (int)header->cell_subdiv; i++) { - int x = header->width >> i; - int y = header->height >> i; - int z = header->depth >> i; - - //create and clear mipmap - PoolVector mipmap; - int size = x * y * z * 4; - size /= size_divisor; - mipmap.resize(size); - PoolVector::Write w = mipmap.write(); - memset(w.ptr(), 0, size); - w.release(); - - probe->dynamic.mipmaps_3d.push_back(mipmap); - - if (x <= size_limit || y <= size_limit || z <= size_limit) { - break; - } - } - - probe->dynamic.updating_stage = GI_UPDATE_STAGE_CHECK; - probe->invalid = false; - probe->dynamic.enabled = true; - - Transform cell_to_xform = VSG::storage->gi_probe_get_to_cell_xform(p_instance->base); - AABB bounds = VSG::storage->gi_probe_get_bounds(p_instance->base); - float cell_size = VSG::storage->gi_probe_get_cell_size(p_instance->base); - - probe->dynamic.light_to_cell_xform = cell_to_xform * p_instance->transform.affine_inverse(); - - VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance, p_instance->base, probe->dynamic.probe_data); - VSG::scene_render->gi_probe_instance_set_transform_to_data(probe->probe_instance, probe->dynamic.light_to_cell_xform); - - VSG::scene_render->gi_probe_instance_set_bounds(probe->probe_instance, bounds.size / cell_size); - - probe->base_version = VSG::storage->gi_probe_get_version(p_instance->base); - - //if compression is S3TC, fill it up - if (probe->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) { - //create all blocks - Vector> comp_blocks; - int mipmap_count = probe->dynamic.mipmaps_3d.size(); - comp_blocks.resize(mipmap_count); - - for (int i = 0; i < cell_count; i++) { - const GIProbeDataCell &c = cells[i]; - const InstanceGIProbeData::LocalData &ld = ldw[i]; - int level = c.level_alpha >> 16; - int mipmap = header->cell_subdiv - level - 1; - if (mipmap >= mipmap_count) { - continue; //uninteresting - } - - int blockx = (ld.pos[0] >> 2); - int blocky = (ld.pos[1] >> 2); - int blockz = (ld.pos[2]); //compression is x/y only - - int blockw = (header->width >> mipmap) >> 2; - int blockh = (header->height >> mipmap) >> 2; - - //print_line("cell "+itos(i)+" level "+itos(level)+"mipmap: "+itos(mipmap)+" pos: "+Vector3(blockx,blocky,blockz)+" size "+Vector2(blockw,blockh)); - - uint32_t key = blockz * blockw * blockh + blocky * blockw + blockx; - - Map &cmap = comp_blocks.write[mipmap]; - - if (!cmap.has(key)) { - InstanceGIProbeData::CompBlockS3TC k; - k.offset = key; //use offset as counter first - k.source_count = 0; - cmap[key] = k; - } - - InstanceGIProbeData::CompBlockS3TC &k = cmap[key]; - ERR_CONTINUE(k.source_count == 16); - k.sources[k.source_count++] = i; - } - - //fix the blocks, precomputing what is needed - probe->dynamic.mipmaps_s3tc.resize(mipmap_count); - - for (int i = 0; i < mipmap_count; i++) { - //print_line("S3TC level: " + itos(i) + " blocks: " + itos(comp_blocks[i].size())); - probe->dynamic.mipmaps_s3tc.write[i].resize(comp_blocks[i].size()); - PoolVector::Write w = probe->dynamic.mipmaps_s3tc.write[i].write(); - int block_idx = 0; - - for (Map::Element *E = comp_blocks[i].front(); E; E = E->next()) { - InstanceGIProbeData::CompBlockS3TC k = E->get(); - - //PRECOMPUTE ALPHA - int max_alpha = -100000; - int min_alpha = k.source_count == 16 ? 100000 : 0; //if the block is not completely full, minimum is always 0, (and those blocks will map to 1, which will be zero) - - uint8_t alpha_block[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; - - for (uint32_t j = 0; j < k.source_count; j++) { - int alpha = (cells[k.sources[j]].level_alpha >> 8) & 0xFF; - if (alpha < min_alpha) { - min_alpha = alpha; - } - if (alpha > max_alpha) { - max_alpha = alpha; - } - //fill up alpha block - alpha_block[ldw[k.sources[j]].pos[0] % 4][ldw[k.sources[j]].pos[1] % 4] = alpha; - } - - //use the first mode (8 adjustable levels) - k.alpha[0] = max_alpha; - k.alpha[1] = min_alpha; - - uint64_t alpha_bits = 0; - - if (max_alpha != min_alpha) { - int idx = 0; - - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - //subtract minimum - uint32_t a = uint32_t(alpha_block[x][y]) - min_alpha; - //convert range to 3 bits - a = int((a * 7.0 / (max_alpha - min_alpha)) + 0.5); - a = MIN(a, 7); //just to be sure - a = 7 - a; //because range is inverted in this mode - if (a == 0) { - //do none, remain - } else if (a == 7) { - a = 1; - } else { - a = a + 1; - } - - alpha_bits |= uint64_t(a) << (idx * 3); - idx++; - } - } - } - - k.alpha[2] = (alpha_bits >> 0) & 0xFF; - k.alpha[3] = (alpha_bits >> 8) & 0xFF; - k.alpha[4] = (alpha_bits >> 16) & 0xFF; - k.alpha[5] = (alpha_bits >> 24) & 0xFF; - k.alpha[6] = (alpha_bits >> 32) & 0xFF; - k.alpha[7] = (alpha_bits >> 40) & 0xFF; - - w[block_idx++] = k; - } - } - } -} - -void VisualServerScene::_gi_probe_bake_thread() { - while (true) { - probe_bake_sem.wait(); - if (probe_bake_thread_exit) { - break; - } - - Instance *to_bake = nullptr; - - probe_bake_mutex.lock(); - - if (!probe_bake_list.empty()) { - to_bake = probe_bake_list.front()->get(); - probe_bake_list.pop_front(); - } - probe_bake_mutex.unlock(); - - if (!to_bake) { - continue; - } - - _bake_gi_probe(to_bake); - } -} - -uint32_t VisualServerScene::_gi_bake_find_cell(const GIProbeDataCell *cells, int x, int y, int z, int p_cell_subdiv) { - uint32_t cell = 0; - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - int size = 1 << (p_cell_subdiv - 1); - int half = size / 2; - - if (x < 0 || x >= size) { - return -1; - } - if (y < 0 || y >= size) { - return -1; - } - if (z < 0 || z >= size) { - return -1; - } - - for (int i = 0; i < p_cell_subdiv - 1; i++) { - const GIProbeDataCell *bc = &cells[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - cell = bc->children[child]; - if (cell == 0xFFFFFFFF) { - return 0xFFFFFFFF; - } - - half >>= 1; - } - - return cell; -} - -static float _get_normal_advance(const Vector3 &p_normal) { - Vector3 normal = p_normal; - Vector3 unorm = normal.abs(); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? Vector3(1.0, 0.0, 0.0) : Vector3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? Vector3(0.0, 1.0, 0.0) : Vector3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? Vector3(0.0, 0.0, 1.0) : Vector3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = Vector3(1.0, 0.0, 0.0); - } - - return 1.0 / normal.dot(unorm); -} - -void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header, const GIProbeDataCell *cells, InstanceGIProbeData::LocalData *local_data, const uint32_t *leaves, int p_leaf_count, const InstanceGIProbeData::LightCache &light_cache, int p_sign) { - int light_r = int(light_cache.color.r * light_cache.energy * 1024.0) * p_sign; - int light_g = int(light_cache.color.g * light_cache.energy * 1024.0) * p_sign; - int light_b = int(light_cache.color.b * light_cache.energy * 1024.0) * p_sign; - - float limits[3] = { float(header->width), float(header->height), float(header->depth) }; - Plane clip[3]; - int clip_planes = 0; - - switch (light_cache.type) { - case VS::LIGHT_DIRECTIONAL: { - float max_len = Vector3(limits[0], limits[1], limits[2]).length() * 1.1; - - Vector3 light_axis = -light_cache.transform.basis.get_axis(2).normalized(); - - for (int i = 0; i < 3; i++) { - if (Math::is_zero_approx(light_axis[i])) { - continue; - } - clip[clip_planes].normal[i] = 1.0; - - if (light_axis[i] < 0) { - clip[clip_planes].d = limits[i] + 1; - } else { - clip[clip_planes].d -= 1.0; - } - - clip_planes++; - } - - float distance_adv = _get_normal_advance(light_axis); - - int success_count = 0; - - // uint64_t us = OS::get_singleton()->get_ticks_usec(); - - for (int i = 0; i < p_leaf_count; i++) { - uint32_t idx = leaves[i]; - - const GIProbeDataCell *cell = &cells[idx]; - InstanceGIProbeData::LocalData *light = &local_data[idx]; - - Vector3 to(light->pos[0] + 0.5, light->pos[1] + 0.5, light->pos[2] + 0.5); - to += -light_axis.sign() * 0.47; //make it more likely to receive a ray - - Vector3 norm( - (((cells[idx].normal >> 16) & 0xFF) / 255.0) * 2.0 - 1.0, - (((cells[idx].normal >> 8) & 0xFF) / 255.0) * 2.0 - 1.0, - (((cells[idx].normal >> 0) & 0xFF) / 255.0) * 2.0 - 1.0); - - float att = norm.dot(-light_axis); - if (att < 0.001) { - //not lighting towards this - continue; - } - - Vector3 from = to - max_len * light_axis; - - for (int j = 0; j < clip_planes; j++) { - clip[j].intersects_segment(from, to, &from); - } - - float distance = (to - from).length(); - distance += distance_adv - Math::fmod(distance, distance_adv); //make it reach the center of the box always - from = to - light_axis * distance; - - uint32_t result = 0xFFFFFFFF; - - while (distance > -distance_adv) { //use this to avoid precision errors - - result = _gi_bake_find_cell(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z)), header->cell_subdiv); - if (result != 0xFFFFFFFF) { - break; - } - - from += light_axis * distance_adv; - distance -= distance_adv; - } - - if (result == idx) { - //cell hit itself! hooray! - light->energy[0] += int32_t(light_r * att * ((cell->albedo >> 16) & 0xFF) / 255.0); - light->energy[1] += int32_t(light_g * att * ((cell->albedo >> 8) & 0xFF) / 255.0); - light->energy[2] += int32_t(light_b * att * ((cell->albedo) & 0xFF) / 255.0); - success_count++; - } - } - - // print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - // print_line("valid cells: " + itos(success_count)); - - } break; - case VS::LIGHT_OMNI: - case VS::LIGHT_SPOT: { - // uint64_t us = OS::get_singleton()->get_ticks_usec(); - - Vector3 light_pos = light_cache.transform.origin; - Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); - - float local_radius = light_cache.radius * light_cache.transform.basis.get_axis(2).length(); - - for (int i = 0; i < p_leaf_count; i++) { - uint32_t idx = leaves[i]; - - const GIProbeDataCell *cell = &cells[idx]; - InstanceGIProbeData::LocalData *light = &local_data[idx]; - - Vector3 to(light->pos[0] + 0.5, light->pos[1] + 0.5, light->pos[2] + 0.5); - to += (light_pos - to).sign() * 0.47; //make it more likely to receive a ray - - Vector3 norm( - (((cells[idx].normal >> 16) & 0xFF) / 255.0) * 2.0 - 1.0, - (((cells[idx].normal >> 8) & 0xFF) / 255.0) * 2.0 - 1.0, - (((cells[idx].normal >> 0) & 0xFF) / 255.0) * 2.0 - 1.0); - - Vector3 light_axis = (to - light_pos).normalized(); - float distance_adv = _get_normal_advance(light_axis); - - float att = norm.dot(-light_axis); - if (att < 0.001) { - //not lighting towards this - continue; - } - - { - float d = light_pos.distance_to(to); - if (d + distance_adv > local_radius) { - continue; // too far away - } - - float dt = CLAMP((d + distance_adv) / local_radius, 0, 1); - att *= powf(1.0 - dt, light_cache.attenuation); - } - - if (light_cache.type == VS::LIGHT_SPOT) { - float angle = Math::rad2deg(acos(light_axis.dot(spot_axis))); - if (angle > light_cache.spot_angle) { - continue; - } - - float d = CLAMP(angle / light_cache.spot_angle, 0, 1); - att *= powf(1.0 - d, light_cache.spot_attenuation); - } - - clip_planes = 0; - - for (int c = 0; c < 3; c++) { - if (Math::is_zero_approx(light_axis[c])) { - continue; - } - clip[clip_planes].normal[c] = 1.0; - - if (light_axis[c] < 0) { - clip[clip_planes].d = limits[c] + 1; - } else { - clip[clip_planes].d -= 1.0; - } - - clip_planes++; - } - - Vector3 from = light_pos; - - for (int j = 0; j < clip_planes; j++) { - clip[j].intersects_segment(from, to, &from); - } - - float distance = (to - from).length(); - - distance -= Math::fmod(distance, distance_adv); //make it reach the center of the box always, but this tame make it closer - from = to - light_axis * distance; - - uint32_t result = 0xFFFFFFFF; - - while (distance > -distance_adv) { //use this to avoid precision errors - - result = _gi_bake_find_cell(cells, int(floor(from.x)), int(floor(from.y)), int(floor(from.z)), header->cell_subdiv); - if (result != 0xFFFFFFFF) { - break; - } - - from += light_axis * distance_adv; - distance -= distance_adv; - } - - if (result == idx) { - //cell hit itself! hooray! - - light->energy[0] += int32_t(light_r * att * ((cell->albedo >> 16) & 0xFF) / 255.0); - light->energy[1] += int32_t(light_g * att * ((cell->albedo >> 8) & 0xFF) / 255.0); - light->energy[2] += int32_t(light_b * att * ((cell->albedo) & 0xFF) / 255.0); - } - } - //print_line("BAKE TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - } break; - } -} - -void VisualServerScene::_bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell *p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, float p_propagate) { - //average light to upper level - - float divisor = 0; - float sum[3] = { 0.0, 0.0, 0.0 }; - - for (int i = 0; i < 8; i++) { - uint32_t child = p_cells[p_idx].children[i]; - - if (child == 0xFFFFFFFF) { - continue; - } - - if (p_level + 1 < (int)p_header->cell_subdiv - 1) { - _bake_gi_downscale_light(child, p_level + 1, p_cells, p_header, p_local_data, p_propagate); - } - - sum[0] += p_local_data[child].energy[0]; - sum[1] += p_local_data[child].energy[1]; - sum[2] += p_local_data[child].energy[2]; - divisor += 1.0; - } - - divisor = Math::lerp((float)8.0, divisor, p_propagate); - sum[0] /= divisor; - sum[1] /= divisor; - sum[2] /= divisor; - - //divide by eight for average - p_local_data[p_idx].energy[0] = Math::fast_ftoi(sum[0]); - p_local_data[p_idx].energy[1] = Math::fast_ftoi(sum[1]); - p_local_data[p_idx].energy[2] = Math::fast_ftoi(sum[2]); -} - -void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { - InstanceGIProbeData *probe_data = static_cast(p_gi_probe->base_data); - - PoolVector::Read r = probe_data->dynamic.light_data.read(); - - const GIProbeDataHeader *header = (const GIProbeDataHeader *)r.ptr(); - const GIProbeDataCell *cells = (const GIProbeDataCell *)&r[16]; - - int leaf_count = probe_data->dynamic.level_cell_lists[header->cell_subdiv - 1].size(); - const uint32_t *leaves = probe_data->dynamic.level_cell_lists[header->cell_subdiv - 1].ptr(); - - PoolVector::Write ldw = probe_data->dynamic.local_data.write(); - - InstanceGIProbeData::LocalData *local_data = ldw.ptr(); - - //remove what must be removed - for (Map::Element *E = probe_data->dynamic.light_cache.front(); E; E = E->next()) { - RID rid = E->key(); - const InstanceGIProbeData::LightCache &lc = E->get(); - - if ((!probe_data->dynamic.light_cache_changes.has(rid) || probe_data->dynamic.light_cache_changes[rid] != lc) && lc.visible) { - //erase light data - - _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, -1); - } - } - - //add what must be added - for (Map::Element *E = probe_data->dynamic.light_cache_changes.front(); E; E = E->next()) { - RID rid = E->key(); - const InstanceGIProbeData::LightCache &lc = E->get(); - - if ((!probe_data->dynamic.light_cache.has(rid) || probe_data->dynamic.light_cache[rid] != lc) && lc.visible) { - //add light data - - _bake_gi_probe_light(header, cells, local_data, leaves, leaf_count, lc, 1); - } - } - - SWAP(probe_data->dynamic.light_cache_changes, probe_data->dynamic.light_cache); - - //downscale to lower res levels - _bake_gi_downscale_light(0, 0, cells, header, local_data, probe_data->dynamic.propagate); - - //plot result to 3D texture! - - if (probe_data->dynamic.compression == RasterizerStorage::GI_PROBE_UNCOMPRESSED) { - for (int i = 0; i < (int)header->cell_subdiv; i++) { - int stage = header->cell_subdiv - i - 1; - - if (stage >= probe_data->dynamic.mipmaps_3d.size()) { - continue; //no mipmap for this one - } - - //print_line("generating mipmap stage: " + itos(stage)); - int level_cell_count = probe_data->dynamic.level_cell_lists[i].size(); - const uint32_t *level_cells = probe_data->dynamic.level_cell_lists[i].ptr(); - - PoolVector::Write lw = probe_data->dynamic.mipmaps_3d.write[stage].write(); - uint8_t *mipmapw = lw.ptr(); - - uint32_t sizes[3] = { header->width >> stage, header->height >> stage, header->depth >> stage }; - - for (int j = 0; j < level_cell_count; j++) { - uint32_t idx = level_cells[j]; - - uint32_t r2 = (uint32_t(local_data[idx].energy[0]) / probe_data->dynamic.bake_dynamic_range) >> 2; - uint32_t g = (uint32_t(local_data[idx].energy[1]) / probe_data->dynamic.bake_dynamic_range) >> 2; - uint32_t b = (uint32_t(local_data[idx].energy[2]) / probe_data->dynamic.bake_dynamic_range) >> 2; - uint32_t a = (cells[idx].level_alpha >> 8) & 0xFF; - - uint32_t mm_ofs = sizes[0] * sizes[1] * (local_data[idx].pos[2]) + sizes[0] * (local_data[idx].pos[1]) + (local_data[idx].pos[0]); - mm_ofs *= 4; //for RGBA (4 bytes) - - mipmapw[mm_ofs + 0] = uint8_t(MIN(r2, 255)); - mipmapw[mm_ofs + 1] = uint8_t(MIN(g, 255)); - mipmapw[mm_ofs + 2] = uint8_t(MIN(b, 255)); - mipmapw[mm_ofs + 3] = uint8_t(MIN(a, 255)); - } - } - } else if (probe_data->dynamic.compression == RasterizerStorage::GI_PROBE_S3TC) { - int mipmap_count = probe_data->dynamic.mipmaps_3d.size(); - - for (int mmi = 0; mmi < mipmap_count; mmi++) { - PoolVector::Write mmw = probe_data->dynamic.mipmaps_3d.write[mmi].write(); - int block_count = probe_data->dynamic.mipmaps_s3tc[mmi].size(); - PoolVector::Read mmr = probe_data->dynamic.mipmaps_s3tc[mmi].read(); - - for (int i = 0; i < block_count; i++) { - const InstanceGIProbeData::CompBlockS3TC &b = mmr[i]; - - uint8_t *blockptr = &mmw[b.offset * 16]; - memcpy(blockptr, b.alpha, 8); //copy alpha part, which is precomputed - - Vector3 colors[16]; - - for (uint32_t j = 0; j < b.source_count; j++) { - colors[j].x = (local_data[b.sources[j]].energy[0] / float(probe_data->dynamic.bake_dynamic_range)) / 1024.0; - colors[j].y = (local_data[b.sources[j]].energy[1] / float(probe_data->dynamic.bake_dynamic_range)) / 1024.0; - colors[j].z = (local_data[b.sources[j]].energy[2] / float(probe_data->dynamic.bake_dynamic_range)) / 1024.0; - } - //super quick and dirty compression - //find 2 most further apart - float distance = 0; - Vector3 from, to; - - if (b.source_count == 16) { - //all cells are used so, find minmax between them - int further_apart[2] = { 0, 0 }; - for (uint32_t j = 0; j < b.source_count; j++) { - for (uint32_t k = j + 1; k < b.source_count; k++) { - float d = colors[j].distance_squared_to(colors[k]); - if (d > distance) { - distance = d; - further_apart[0] = j; - further_apart[1] = k; - } - } - } - - from = colors[further_apart[0]]; - to = colors[further_apart[1]]; - - } else { - //if a block is missing, the priority is that this block remains black, - //otherwise the geometry will appear deformed - //correct shape wins over correct color in this case - //average all colors first - Vector3 average; - - for (uint32_t j = 0; j < b.source_count; j++) { - average += colors[j]; - } - average.normalize(); - //find max distance in normal from average - for (uint32_t j = 0; j < b.source_count; j++) { - float d = average.dot(colors[j]); - distance = MAX(d, distance); - } - - from = Vector3(); //from black - to = average * distance; - //find max distance - } - - int indices[16]; - uint16_t color_0 = 0; - color_0 = CLAMP(int(from.x * 31), 0, 31) << 11; - color_0 |= CLAMP(int(from.y * 63), 0, 63) << 5; - color_0 |= CLAMP(int(from.z * 31), 0, 31); - - uint16_t color_1 = 0; - color_1 = CLAMP(int(to.x * 31), 0, 31) << 11; - color_1 |= CLAMP(int(to.y * 63), 0, 63) << 5; - color_1 |= CLAMP(int(to.z * 31), 0, 31); - - if (color_1 > color_0) { - SWAP(color_1, color_0); - SWAP(from, to); - } - - if (distance > 0) { - Vector3 dir = (to - from).normalized(); - - for (uint32_t j = 0; j < b.source_count; j++) { - float d = (colors[j] - from).dot(dir) / distance; - indices[j] = int(d * 3 + 0.5); - - static const int index_swap[4] = { 0, 3, 1, 2 }; - - indices[j] = index_swap[CLAMP(indices[j], 0, 3)]; - } - } else { - for (uint32_t j = 0; j < b.source_count; j++) { - indices[j] = 0; - } - } - - //by default, 1 is black, otherwise it will be overridden by source - - uint32_t index_block[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - - for (uint32_t j = 0; j < b.source_count; j++) { - int x = local_data[b.sources[j]].pos[0] % 4; - int y = local_data[b.sources[j]].pos[1] % 4; - - index_block[y * 4 + x] = indices[j]; - } - - uint32_t encode = 0; - - for (int j = 0; j < 16; j++) { - encode |= index_block[j] << (j * 2); - } - - blockptr[8] = color_0 & 0xFF; - blockptr[9] = (color_0 >> 8) & 0xFF; - blockptr[10] = color_1 & 0xFF; - blockptr[11] = (color_1 >> 8) & 0xFF; - blockptr[12] = encode & 0xFF; - blockptr[13] = (encode >> 8) & 0xFF; - blockptr[14] = (encode >> 16) & 0xFF; - blockptr[15] = (encode >> 24) & 0xFF; - } - } - } - - //send back to main thread to update un little chunks - probe_bake_mutex.lock(); - probe_data->dynamic.updating_stage = GI_UPDATE_STAGE_UPLOADING; - probe_bake_mutex.unlock(); -} - -bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { - InstanceGIProbeData *probe_data = static_cast(p_gi_probe->base_data); - - probe_data->dynamic.light_cache_changes.clear(); - - bool all_equal = true; - - for (List::Element *E = p_gi_probe->scenario->directional_lights.front(); E; E = E->next()) { - if (VSG::storage->light_get_bake_mode(E->get()->base) == VS::LightBakeMode::LIGHT_BAKE_DISABLED) { - continue; - } - - InstanceGIProbeData::LightCache lc; - lc.type = VSG::storage->light_get_type(E->get()->base); - lc.color = VSG::storage->light_get_color(E->get()->base); - lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY) * VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_INDIRECT_ENERGY); - lc.radius = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_RANGE); - lc.attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ATTENUATION); - lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE); - lc.spot_attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ATTENUATION); - lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; - lc.visible = E->get()->visible; - - if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) { - all_equal = false; - } - - probe_data->dynamic.light_cache_changes[E->get()->self] = lc; - } - - for (Set::Element *E = probe_data->lights.front(); E; E = E->next()) { - if (VSG::storage->light_get_bake_mode(E->get()->base) == VS::LightBakeMode::LIGHT_BAKE_DISABLED) { - continue; - } - - InstanceGIProbeData::LightCache lc; - lc.type = VSG::storage->light_get_type(E->get()->base); - lc.color = VSG::storage->light_get_color(E->get()->base); - lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY) * VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_INDIRECT_ENERGY); - lc.radius = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_RANGE); - lc.attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ATTENUATION); - lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE); - lc.spot_attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ATTENUATION); - lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; - lc.visible = E->get()->visible; - - if (!probe_data->dynamic.light_cache.has(E->get()->self) || probe_data->dynamic.light_cache[E->get()->self] != lc) { - all_equal = false; - } - - probe_data->dynamic.light_cache_changes[E->get()->self] = lc; - } - - //lighting changed from after to before, must do some updating - return !all_equal || probe_data->dynamic.light_cache_changes.size() != probe_data->dynamic.light_cache.size(); -} - -void VisualServerScene::render_probes() { - /* REFLECTION PROBES */ - - SelfList *ref_probe = reflection_probe_render_list.first(); - - bool busy = false; - - while (ref_probe) { - SelfList *next = ref_probe->next(); - RID base = ref_probe->self()->owner->base; - - switch (VSG::storage->reflection_probe_get_update_mode(base)) { - case VS::REFLECTION_PROBE_UPDATE_ONCE: { - if (busy) { //already rendering something - break; - } - - bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step); - if (done) { - reflection_probe_render_list.remove(ref_probe); - } else { - ref_probe->self()->render_step++; - } - - busy = true; //do not render another one of this kind - } break; - case VS::REFLECTION_PROBE_UPDATE_ALWAYS: { - int step = 0; - bool done = false; - while (!done) { - done = _render_reflection_probe_step(ref_probe->self()->owner, step); - step++; - } - - reflection_probe_render_list.remove(ref_probe); - } break; - } - - ref_probe = next; - } - - /* GI PROBES */ - - SelfList *gi_probe = gi_probe_update_list.first(); - - while (gi_probe) { - SelfList *next = gi_probe->next(); - - InstanceGIProbeData *probe = gi_probe->self(); - Instance *instance_probe = probe->owner; - - //check if probe must be setup, but don't do if on the lighting thread - - bool force_lighting = false; - - if (probe->invalid || (probe->dynamic.updating_stage == GI_UPDATE_STAGE_CHECK && probe->base_version != VSG::storage->gi_probe_get_version(instance_probe->base))) { - _setup_gi_probe(instance_probe); - force_lighting = true; - } - - float propagate = VSG::storage->gi_probe_get_propagation(instance_probe->base); - - if (probe->dynamic.propagate != propagate) { - probe->dynamic.propagate = propagate; - force_lighting = true; - } - - if (!probe->invalid && probe->dynamic.enabled) { - switch (probe->dynamic.updating_stage) { - case GI_UPDATE_STAGE_CHECK: { - if (_check_gi_probe(instance_probe) || force_lighting) { //send to lighting thread - -#ifndef NO_THREADS - probe_bake_mutex.lock(); - probe->dynamic.updating_stage = GI_UPDATE_STAGE_LIGHTING; - probe_bake_list.push_back(instance_probe); - probe_bake_mutex.unlock(); - probe_bake_sem.post(); - -#else - - _bake_gi_probe(instance_probe); -#endif - } - } break; - case GI_UPDATE_STAGE_LIGHTING: { - //do none, wait til done! - - } break; - case GI_UPDATE_STAGE_UPLOADING: { - //uint64_t us = OS::get_singleton()->get_ticks_usec(); - - for (int i = 0; i < (int)probe->dynamic.mipmaps_3d.size(); i++) { - PoolVector::Read r = probe->dynamic.mipmaps_3d[i].read(); - VSG::storage->gi_probe_dynamic_data_update(probe->dynamic.probe_data, 0, probe->dynamic.grid_size[2] >> i, i, r.ptr()); - } - - probe->dynamic.updating_stage = GI_UPDATE_STAGE_CHECK; - - //print_line("UPLOAD TIME: " + rtos((OS::get_singleton()->get_ticks_usec() - us) / 1000000.0)); - } break; - } - } - //_update_gi_probe(gi_probe->self()->owner); - - gi_probe = next; - } -} - -void VisualServerScene::_update_dirty_instance(Instance *p_instance) { - if (p_instance->update_aabb) { - _update_instance_aabb(p_instance); - } - - if (p_instance->update_materials) { - if (p_instance->base_type == VS::INSTANCE_MESH) { - //remove materials no longer used and un-own them - - int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base); - for (int i = p_instance->materials.size() - 1; i >= new_mat_count; i--) { - if (p_instance->materials[i].is_valid()) { - VSG::storage->material_remove_instance_owner(p_instance->materials[i], p_instance); - } - } - p_instance->materials.resize(new_mat_count); - - int new_blend_shape_count = VSG::storage->mesh_get_blend_shape_count(p_instance->base); - if (new_blend_shape_count != p_instance->blend_values.size()) { - p_instance->blend_values.resize(new_blend_shape_count); - for (int i = 0; i < new_blend_shape_count; i++) { - p_instance->blend_values.write().ptr()[i] = 0; - } - } - } - - if ((1 << p_instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) { - InstanceGeometryData *geom = static_cast(p_instance->base_data); - - bool can_cast_shadows = true; - bool is_animated = false; - - if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) { - can_cast_shadows = false; - } else if (p_instance->material_override.is_valid()) { - can_cast_shadows = VSG::storage->material_casts_shadows(p_instance->material_override); - is_animated = VSG::storage->material_is_animated(p_instance->material_override); - } else { - if (p_instance->base_type == VS::INSTANCE_MESH) { - RID mesh = p_instance->base; - - if (mesh.is_valid()) { - bool cast_shadows = false; - - for (int i = 0; i < p_instance->materials.size(); i++) { - RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : VSG::storage->mesh_surface_get_material(mesh, i); - - if (!mat.is_valid()) { - cast_shadows = true; - } else { - if (VSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - - if (VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - - } else if (p_instance->base_type == VS::INSTANCE_MULTIMESH) { - RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base); - if (mesh.is_valid()) { - bool cast_shadows = false; - - int sc = VSG::storage->mesh_get_surface_count(mesh); - for (int i = 0; i < sc; i++) { - RID mat = VSG::storage->mesh_surface_get_material(mesh, i); - - if (!mat.is_valid()) { - cast_shadows = true; - - } else { - if (VSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - if (VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - } else if (p_instance->base_type == VS::INSTANCE_IMMEDIATE) { - RID mat = VSG::storage->immediate_get_material(p_instance->base); - - can_cast_shadows = !mat.is_valid() || VSG::storage->material_casts_shadows(mat); - - if (mat.is_valid() && VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - } else if (p_instance->base_type == VS::INSTANCE_PARTICLES) { - bool cast_shadows = false; - - int dp = VSG::storage->particles_get_draw_passes(p_instance->base); - - for (int i = 0; i < dp; i++) { - RID mesh = VSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); - if (!mesh.is_valid()) { - continue; - } - - int sc = VSG::storage->mesh_get_surface_count(mesh); - for (int j = 0; j < sc; j++) { - RID mat = VSG::storage->mesh_surface_get_material(mesh, j); - - if (!mat.is_valid()) { - cast_shadows = true; - } else { - if (VSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - - if (VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - } - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - } - - if (p_instance->material_overlay.is_valid()) { - can_cast_shadows = can_cast_shadows || VSG::storage->material_casts_shadows(p_instance->material_overlay); - is_animated = is_animated || VSG::storage->material_is_animated(p_instance->material_overlay); - } - - if (can_cast_shadows != geom->can_cast_shadows) { - //ability to cast shadows change, let lights now - for (List::Element *E = geom->lighting.front(); E; E = E->next()) { - InstanceLightData *light = static_cast(E->get()->base_data); - light->shadow_dirty = true; - } - - geom->can_cast_shadows = can_cast_shadows; - } - - geom->material_is_animated = is_animated; - } - } - - _instance_update_list.remove(&p_instance->update_item); - - _update_instance(p_instance); - - p_instance->update_aabb = false; - p_instance->update_materials = false; -} - void VisualServerScene::update_dirty_instances() { VSG::storage->update_dirty_resources(); @@ -4547,9 +3380,6 @@ bool VisualServerScene::free(RID p_rid) { VisualServerScene *VisualServerScene::singleton = nullptr; VisualServerScene::VisualServerScene() { - probe_bake_thread.start(_gi_probe_bake_threads, this); - probe_bake_thread_exit = false; - render_pass = 1; singleton = this; _use_bvh = GLOBAL_DEF("rendering/quality/spatial_partitioning/use_bvh", true); @@ -4560,7 +3390,4 @@ VisualServerScene::VisualServerScene() { } VisualServerScene::~VisualServerScene() { - probe_bake_thread_exit = true; - probe_bake_sem.post(); - probe_bake_thread.wait_to_finish(); } diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index f1a904079..bc1a3b875 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -423,9 +423,6 @@ public: List reflection_probes; bool reflection_dirty; - List gi_probes; - bool gi_probes_dirty; - List lightmap_captures; InstanceGeometryData() { @@ -433,7 +430,6 @@ public: reflection_dirty = true; can_cast_shadows = true; material_is_animated = true; - gi_probes_dirty = true; } }; @@ -489,108 +485,6 @@ public: } }; - struct InstanceGIProbeData : public InstanceBaseData { - Instance *owner; - - struct PairInfo { - List::Element *L; //gi probe iterator in geometry - Instance *geometry; - }; - - List geometries; - - Set lights; - - struct LightCache { - VS::LightType type; - Transform transform; - Color color; - float energy; - float radius; - float attenuation; - float spot_angle; - float spot_attenuation; - bool visible; - - bool operator==(const LightCache &p_cache) { - return (type == p_cache.type && - transform == p_cache.transform && - color == p_cache.color && - energy == p_cache.energy && - radius == p_cache.radius && - attenuation == p_cache.attenuation && - spot_angle == p_cache.spot_angle && - spot_attenuation == p_cache.spot_attenuation && - visible == p_cache.visible); - } - - bool operator!=(const LightCache &p_cache) { - return !operator==(p_cache); - } - - LightCache() { - type = VS::LIGHT_DIRECTIONAL; - energy = 1.0; - radius = 1.0; - attenuation = 1.0; - spot_angle = 1.0; - spot_attenuation = 1.0; - visible = true; - } - }; - - struct LocalData { - uint16_t pos[3]; - uint16_t energy[3]; //using 0..1024 for float range 0..1. integer is needed for deterministic add/remove of lights - }; - - struct CompBlockS3TC { - uint32_t offset; //offset in mipmap - uint32_t source_count; //sources - uint32_t sources[16]; //id for each source - uint8_t alpha[8]; //alpha block is pre-computed - }; - - struct Dynamic { - Map light_cache; - Map light_cache_changes; - PoolVector light_data; - PoolVector local_data; - Vector> level_cell_lists; - RID probe_data; - bool enabled; - int bake_dynamic_range; - RasterizerStorage::GIProbeCompression compression; - - Vector> mipmaps_3d; - Vector> mipmaps_s3tc; //for s3tc - - int updating_stage; - float propagate; - - int grid_size[3]; - - Transform light_to_cell_xform; - - } dynamic; - - RID probe_instance; - - bool invalid; - uint32_t base_version; - - SelfList update_element; - - InstanceGIProbeData() : - update_element(this) { - invalid = true; - base_version = 0; - dynamic.updating_stage = GI_UPDATE_STAGE_CHECK; - } - }; - - SelfList::List gi_probe_update_list; - struct InstanceLightmapCaptureData : public InstanceBaseData { struct PairInfo { List::Element *L; //iterator in geometry @@ -843,52 +737,6 @@ public: void update_interpolation_tick(Scenario::InterpolationData &r_interpolation_data, bool p_process = true); void update_interpolation_frame(Scenario::InterpolationData &r_interpolation_data, bool p_process = true); - //probes - struct GIProbeDataHeader { - uint32_t version; - uint32_t cell_subdiv; - uint32_t width; - uint32_t height; - uint32_t depth; - uint32_t cell_count; - uint32_t leaf_cell_count; - }; - - struct GIProbeDataCell { - uint32_t children[8]; - uint32_t albedo; - uint32_t emission; - uint32_t normal; - uint32_t level_alpha; - }; - - enum { - GI_UPDATE_STAGE_CHECK, - GI_UPDATE_STAGE_LIGHTING, - GI_UPDATE_STAGE_UPLOADING, - }; - - void _gi_probe_bake_thread(); - static void _gi_probe_bake_threads(void *); - - bool probe_bake_thread_exit; - Thread probe_bake_thread; - Semaphore probe_bake_sem; - Mutex probe_bake_mutex; - List probe_bake_list; - - bool _render_reflection_probe_step(Instance *p_instance, int p_step); - void _gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell *p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector *prev_cell); - - _FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells, int x, int y, int z, int p_cell_subdiv); - void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell *p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, float p_propagate); - void _bake_gi_probe_light(const GIProbeDataHeader *header, const GIProbeDataCell *cells, InstanceGIProbeData::LocalData *local_data, const uint32_t *leaves, int p_leaf_count, const InstanceGIProbeData::LightCache &light_cache, int p_sign); - void _bake_gi_probe(Instance *p_gi_probe); - bool _check_gi_probe(Instance *p_gi_probe); - void _setup_gi_probe(Instance *p_instance); - - void render_probes(); - bool free(RID p_rid); private: diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp index 54102875e..95425f29c 100644 --- a/servers/visual/visual_server_wrap_mt.cpp +++ b/servers/visual/visual_server_wrap_mt.cpp @@ -158,7 +158,6 @@ void VisualServerWrapMT::finish() { omni_light_free_cached_ids(); spot_light_free_cached_ids(); reflection_probe_free_cached_ids(); - gi_probe_free_cached_ids(); lightmap_capture_free_cached_ids(); particles_free_cached_ids(); camera_free_cached_ids(); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index e2c97cab3..78e1f05ae 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -286,43 +286,6 @@ public: FUNC2(reflection_probe_set_cull_mask, RID, uint32_t) FUNC2(reflection_probe_set_resolution, RID, int) - /* BAKED LIGHT API */ - - FUNCRID(gi_probe) - - FUNC2(gi_probe_set_bounds, RID, const AABB &) - FUNC1RC(AABB, gi_probe_get_bounds, RID) - - FUNC2(gi_probe_set_cell_size, RID, float) - FUNC1RC(float, gi_probe_get_cell_size, RID) - - FUNC2(gi_probe_set_to_cell_xform, RID, const Transform &) - FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID) - - FUNC2(gi_probe_set_dynamic_range, RID, int) - FUNC1RC(int, gi_probe_get_dynamic_range, RID) - - FUNC2(gi_probe_set_energy, RID, float) - FUNC1RC(float, gi_probe_get_energy, RID) - - FUNC2(gi_probe_set_bias, RID, float) - FUNC1RC(float, gi_probe_get_bias, RID) - - FUNC2(gi_probe_set_normal_bias, RID, float) - FUNC1RC(float, gi_probe_get_normal_bias, RID) - - FUNC2(gi_probe_set_propagation, RID, float) - FUNC1RC(float, gi_probe_get_propagation, RID) - - FUNC2(gi_probe_set_interior, RID, bool) - FUNC1RC(bool, gi_probe_is_interior, RID) - - FUNC2(gi_probe_set_compress, RID, bool) - FUNC1RC(bool, gi_probe_is_compressed, RID) - - FUNC2(gi_probe_set_dynamic_data, RID, const PoolVector &) - FUNC1RC(PoolVector, gi_probe_get_dynamic_data, RID) - /* LIGHTMAP CAPTURE */ FUNCRID(lightmap_capture) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index ccbd27d87..aa1587321 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1990,30 +1990,6 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &VisualServer::reflection_probe_set_enable_shadows); ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &VisualServer::reflection_probe_set_cull_mask); - ClassDB::bind_method(D_METHOD("gi_probe_create"), &VisualServer::gi_probe_create); - ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &VisualServer::gi_probe_set_bounds); - ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &VisualServer::gi_probe_get_bounds); - ClassDB::bind_method(D_METHOD("gi_probe_set_cell_size", "probe", "range"), &VisualServer::gi_probe_set_cell_size); - ClassDB::bind_method(D_METHOD("gi_probe_get_cell_size", "probe"), &VisualServer::gi_probe_get_cell_size); - ClassDB::bind_method(D_METHOD("gi_probe_set_to_cell_xform", "probe", "xform"), &VisualServer::gi_probe_set_to_cell_xform); - ClassDB::bind_method(D_METHOD("gi_probe_get_to_cell_xform", "probe"), &VisualServer::gi_probe_get_to_cell_xform); - ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_data", "probe", "data"), &VisualServer::gi_probe_set_dynamic_data); - ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_data", "probe"), &VisualServer::gi_probe_get_dynamic_data); - ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_range", "probe", "range"), &VisualServer::gi_probe_set_dynamic_range); - ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_range", "probe"), &VisualServer::gi_probe_get_dynamic_range); - ClassDB::bind_method(D_METHOD("gi_probe_set_energy", "probe", "energy"), &VisualServer::gi_probe_set_energy); - ClassDB::bind_method(D_METHOD("gi_probe_get_energy", "probe"), &VisualServer::gi_probe_get_energy); - ClassDB::bind_method(D_METHOD("gi_probe_set_bias", "probe", "bias"), &VisualServer::gi_probe_set_bias); - ClassDB::bind_method(D_METHOD("gi_probe_get_bias", "probe"), &VisualServer::gi_probe_get_bias); - ClassDB::bind_method(D_METHOD("gi_probe_set_normal_bias", "probe", "bias"), &VisualServer::gi_probe_set_normal_bias); - ClassDB::bind_method(D_METHOD("gi_probe_get_normal_bias", "probe"), &VisualServer::gi_probe_get_normal_bias); - ClassDB::bind_method(D_METHOD("gi_probe_set_propagation", "probe", "propagation"), &VisualServer::gi_probe_set_propagation); - ClassDB::bind_method(D_METHOD("gi_probe_get_propagation", "probe"), &VisualServer::gi_probe_get_propagation); - ClassDB::bind_method(D_METHOD("gi_probe_set_interior", "probe", "enable"), &VisualServer::gi_probe_set_interior); - ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &VisualServer::gi_probe_is_interior); - ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &VisualServer::gi_probe_set_compress); - ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &VisualServer::gi_probe_is_compressed); - ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &VisualServer::lightmap_capture_create); ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &VisualServer::lightmap_capture_set_bounds); ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &VisualServer::lightmap_capture_get_bounds); @@ -2424,7 +2400,6 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(INSTANCE_PARTICLES); BIND_ENUM_CONSTANT(INSTANCE_LIGHT); BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); - BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP_CAPTURE); BIND_ENUM_CONSTANT(INSTANCE_MAX); BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); diff --git a/servers/visual_server.h b/servers/visual_server.h index 356e7148e..d956b1b65 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -526,43 +526,6 @@ public: virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; - /* GI PROBE API */ - - virtual RID gi_probe_create() = 0; - - virtual void gi_probe_set_bounds(RID p_probe, const AABB &p_bounds) = 0; - virtual AABB gi_probe_get_bounds(RID p_probe) const = 0; - - virtual void gi_probe_set_cell_size(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_cell_size(RID p_probe) const = 0; - - virtual void gi_probe_set_to_cell_xform(RID p_probe, const Transform &p_xform) = 0; - virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const = 0; - - virtual void gi_probe_set_dynamic_data(RID p_probe, const PoolVector &p_data) = 0; - virtual PoolVector gi_probe_get_dynamic_data(RID p_probe) const = 0; - - virtual void gi_probe_set_dynamic_range(RID p_probe, int p_range) = 0; - virtual int gi_probe_get_dynamic_range(RID p_probe) const = 0; - - virtual void gi_probe_set_energy(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_energy(RID p_probe) const = 0; - - virtual void gi_probe_set_bias(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_bias(RID p_probe) const = 0; - - virtual void gi_probe_set_normal_bias(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_probe) const = 0; - - virtual void gi_probe_set_propagation(RID p_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_probe) const = 0; - - virtual void gi_probe_set_interior(RID p_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_probe) const = 0; - - virtual void gi_probe_set_compress(RID p_probe, bool p_enable) = 0; - virtual bool gi_probe_is_compressed(RID p_probe) const = 0; - /* LIGHTMAP CAPTURE */ virtual RID lightmap_capture_create() = 0; @@ -850,7 +813,6 @@ public: INSTANCE_PARTICLES, INSTANCE_LIGHT, INSTANCE_REFLECTION_PROBE, - INSTANCE_GI_PROBE, INSTANCE_LIGHTMAP_CAPTURE, INSTANCE_MAX,