summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp2
-rw-r--r--platform/osx/os_osx.mm6
-rw-r--r--scene/3d/gi_probe.cpp49
-rw-r--r--scene/3d/gi_probe.h11
-rw-r--r--scene/3d/voxelizer.cpp116
-rw-r--r--scene/3d/voxelizer.h1
-rw-r--r--servers/visual/rasterizer.h10
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp2
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h4
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_scene_rd.h1
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp54
-rw-r--r--servers/visual/rasterizer_rd/rasterizer_storage_rd.h12
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward.glsl66
-rw-r--r--servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl4
-rw-r--r--servers/visual/visual_server_raster.h9
-rw-r--r--servers/visual/visual_server_wrap_mt.h9
-rw-r--r--servers/visual_server.h9
17 files changed, 309 insertions, 56 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index b85641e48f..d74f77c328 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -5277,7 +5277,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin_for_screen(in
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = size_x;
- scissor.extent.height = size_x;
+ scissor.extent.height = size_y;
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 4d2103cbb4..5757cd879d 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -365,6 +365,12 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
OS_OSX::singleton->window_size.width = fbRect.size.width * newDisplayScale;
OS_OSX::singleton->window_size.height = fbRect.size.height * newDisplayScale;
+#if defined(VULKAN_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) {
+ CALayer* layer = [OS_OSX::singleton->window_view layer];
+ layer.contentsScale = OS_OSX::singleton->_display_scale();
+ }
+#endif
//Update context
if (OS_OSX::singleton->main_loop) {
//Force window resize event
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index 52c4efb7f1..2423c0a7a3 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -41,6 +41,7 @@ void GIProbeData::_set_data(const Dictionary &p_data) {
ERR_FAIL_COND(!p_data.has("octree_size"));
ERR_FAIL_COND(!p_data.has("octree_cells"));
ERR_FAIL_COND(!p_data.has("octree_data"));
+ ERR_FAIL_COND(!p_data.has("octree_df"));
ERR_FAIL_COND(!p_data.has("level_counts"));
ERR_FAIL_COND(!p_data.has("to_cell_xform"));
@@ -48,10 +49,11 @@ void GIProbeData::_set_data(const Dictionary &p_data) {
Vector3 octree_size = p_data["octree_size"];
PoolVector<uint8_t> octree_cells = p_data["octree_cells"];
PoolVector<uint8_t> octree_data = p_data["octree_data"];
+ PoolVector<uint8_t> octree_df = p_data["octree_df"];
PoolVector<int> octree_levels = p_data["level_counts"];
Transform to_cell_xform = p_data["to_cell_xform"];
- allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_levels);
+ allocate(to_cell_xform, bounds, octree_size, octree_cells, octree_data, octree_df, octree_levels);
}
Dictionary GIProbeData::_get_data() const {
@@ -60,13 +62,14 @@ Dictionary GIProbeData::_get_data() const {
d["octree_size"] = get_octree_size();
d["octree_cells"] = get_octree_cells();
d["octree_data"] = get_data_cells();
+ d["octree_df"] = get_distance_field();
d["level_counts"] = get_level_counts();
d["to_cell_xform"] = get_to_cell_xform();
return d;
}
-void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) {
- VS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_level_counts);
+void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<uint8_t> &p_distance_field, const PoolVector<int> &p_level_counts) {
+ VS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts);
bounds = p_aabb;
to_cell_xform = p_to_cell_xform;
octree_size = p_octree_size;
@@ -84,6 +87,10 @@ PoolVector<uint8_t> GIProbeData::get_octree_cells() const {
PoolVector<uint8_t> GIProbeData::get_data_cells() const {
return VS::get_singleton()->gi_probe_get_data_cells(probe);
}
+PoolVector<uint8_t> GIProbeData::get_distance_field() const {
+ return VS::get_singleton()->gi_probe_get_distance_field(probe);
+}
+
PoolVector<int> GIProbeData::get_level_counts() const {
return VS::get_singleton()->gi_probe_get_level_counts(probe);
}
@@ -127,6 +134,24 @@ float GIProbeData::get_energy() const {
return energy;
}
+void GIProbeData::set_ao(float p_ao) {
+ VS::get_singleton()->gi_probe_set_ao(probe, p_ao);
+ ao = p_ao;
+}
+
+float GIProbeData::get_ao() const {
+ return ao;
+}
+
+void GIProbeData::set_ao_strength(float p_ao_strength) {
+ VS::get_singleton()->gi_probe_set_ao_strength(probe, p_ao_strength);
+ ao_strength = p_ao_strength;
+}
+
+float GIProbeData::get_ao_strength() const {
+ return ao_strength;
+}
+
void GIProbeData::set_bias(float p_bias) {
VS::get_singleton()->gi_probe_set_bias(probe, p_bias);
bias = p_bias;
@@ -206,6 +231,12 @@ void GIProbeData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_anisotropy_strength", "strength"), &GIProbeData::set_anisotropy_strength);
ClassDB::bind_method(D_METHOD("get_anisotropy_strength"), &GIProbeData::get_anisotropy_strength);
+ ClassDB::bind_method(D_METHOD("set_ao", "ao"), &GIProbeData::set_ao);
+ ClassDB::bind_method(D_METHOD("get_ao"), &GIProbeData::get_ao);
+
+ ClassDB::bind_method(D_METHOD("set_ao_strength", "strength"), &GIProbeData::set_ao_strength);
+ ClassDB::bind_method(D_METHOD("get_ao_strength"), &GIProbeData::get_ao_strength);
+
ClassDB::bind_method(D_METHOD("set_interior", "interior"), &GIProbeData::set_interior);
ClassDB::bind_method(D_METHOD("is_interior"), &GIProbeData::is_interior);
@@ -223,12 +254,16 @@ void GIProbeData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_bias", PROPERTY_HINT_RANGE, "0,8,0.01"), "set_normal_bias", "get_normal_bias");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_propagation", "get_propagation");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "anisotropy_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_anisotropy_strength", "get_anisotropy_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao", "get_ao");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_strength", "get_ao_strength");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_two_bounces"), "set_use_two_bounces", "is_using_two_bounces");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
}
GIProbeData::GIProbeData() {
+ ao = 0.0;
+ ao_strength = 0.5;
dynamic_range = 4;
energy = 1.0;
bias = 1.5;
@@ -406,7 +441,13 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) {
if (probe_data.is_null())
probe_data.instance();
- probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_giprobe_octree_size(), baker.get_giprobe_octree_cells(), baker.get_giprobe_data_cells(), baker.get_giprobe_level_cell_count());
+ if (bake_step_function) {
+ bake_step_function(pmc++, RTR("Generating Distance Field"));
+ }
+
+ PoolVector<uint8_t> df = baker.get_sdf_3d_image();
+
+ probe_data->allocate(baker.get_to_cell_space_xform(), AABB(-extents, extents * 2.0), baker.get_giprobe_octree_size(), baker.get_giprobe_octree_cells(), baker.get_giprobe_data_cells(), df, baker.get_giprobe_level_cell_count());
set_probe_data(probe_data);
probe_data->set_edited(true); //so it gets saved
diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h
index 7cb4b435c5..ac309e82c7 100644
--- a/scene/3d/gi_probe.h
+++ b/scene/3d/gi_probe.h
@@ -53,6 +53,8 @@ class GIProbeData : public Resource {
float normal_bias;
float propagation;
float anisotropy_strength;
+ float ao;
+ float ao_strength;
bool interior;
bool use_two_bounces;
@@ -61,11 +63,12 @@ protected:
void _validate_property(PropertyInfo &property) const;
public:
- void allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts);
+ void allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<uint8_t> &p_distance_field, const PoolVector<int> &p_level_counts);
AABB get_bounds() const;
Vector3 get_octree_size() const;
PoolVector<uint8_t> get_octree_cells() const;
PoolVector<uint8_t> get_data_cells() const;
+ PoolVector<uint8_t> get_distance_field() const;
PoolVector<int> get_level_counts() const;
Transform get_to_cell_xform() const;
@@ -78,6 +81,12 @@ public:
void set_anisotropy_strength(float p_anisotropy_strength);
float get_anisotropy_strength() const;
+ void set_ao(float p_ao);
+ float get_ao() const;
+
+ void set_ao_strength(float p_ao_strength);
+ float get_ao_strength() const;
+
void set_energy(float p_energy);
float get_energy() const;
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index 2aa2f79f43..0e20f606d6 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -981,6 +981,122 @@ PoolVector<int> Voxelizer::get_giprobe_level_cell_count() const {
return level_count;
}
+// euclidean distance computation based on:
+// https://prideout.net/blog/distance_fields/
+
+#define square(m_s) ((m_s) * (m_s))
+#define INF 1e20
+
+/* dt of 1d function using squared distance */
+static void edt(float *f, int stride, int n) {
+
+ float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1));
+ int *v = (int *)&(d[n]);
+ float *z = (float *)&v[n];
+
+ int k = 0;
+ v[0] = 0;
+ z[0] = -INF;
+ z[1] = +INF;
+ for (int q = 1; q <= n - 1; q++) {
+ float s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]);
+ while (s <= z[k]) {
+ k--;
+ s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]);
+ }
+ k++;
+ v[k] = q;
+
+ z[k] = s;
+ z[k + 1] = +INF;
+ }
+
+ k = 0;
+ for (int q = 0; q <= n - 1; q++) {
+ while (z[k + 1] < q)
+ k++;
+ d[q] = square(q - v[k]) + f[v[k] * stride];
+ }
+
+ for (int i = 0; i < n; i++) {
+ f[i * stride] = d[i];
+ }
+}
+
+#undef square
+
+PoolVector<uint8_t> Voxelizer::get_sdf_3d_image() const {
+
+ Vector3i octree_size = get_giprobe_octree_size();
+
+ uint32_t float_count = octree_size.x * octree_size.y * octree_size.z;
+ float *work_memory = memnew_arr(float, float_count);
+ for (uint32_t i = 0; i < float_count; i++) {
+ work_memory[i] = INF;
+ }
+
+ uint32_t y_mult = octree_size.x;
+ uint32_t z_mult = y_mult * octree_size.y;
+
+ //plot solid cells
+ {
+ const Cell *cells = bake_cells.ptr();
+ uint32_t cell_count = bake_cells.size();
+
+ for (uint32_t i = 0; i < cell_count; i++) {
+
+ if (cells[i].level < (cell_subdiv - 1)) {
+ continue; //do not care about this level
+ }
+
+ work_memory[cells[i].x + cells[i].y * y_mult + cells[i].z * z_mult] = 0;
+ }
+ }
+
+ //process in each direction
+
+ //xy->z
+
+ for (int i = 0; i < octree_size.x; i++) {
+ for (int j = 0; j < octree_size.y; j++) {
+ edt(&work_memory[i + j * y_mult], z_mult, octree_size.z);
+ }
+ }
+
+ //xz->y
+
+ for (int i = 0; i < octree_size.x; i++) {
+ for (int j = 0; j < octree_size.z; j++) {
+ edt(&work_memory[i + j * z_mult], y_mult, octree_size.y);
+ }
+ }
+
+ //yz->x
+ for (int i = 0; i < octree_size.y; i++) {
+ for (int j = 0; j < octree_size.z; j++) {
+ edt(&work_memory[i * y_mult + j * z_mult], 1, octree_size.x);
+ }
+ }
+
+ PoolVector<uint8_t> image3d;
+ image3d.resize(float_count);
+ {
+ PoolVector<uint8_t>::Write w = image3d.write();
+ for (uint32_t i = 0; i < float_count; i++) {
+ uint32_t d = uint32_t(Math::sqrt(work_memory[i]));
+ if (d == 0) {
+ w[i] = 0;
+ } else {
+ w[i] = CLAMP(d, 0, 254) + 1;
+ }
+ }
+ }
+
+ return image3d;
+}
+
+#undef INF
+
void Voxelizer::_debug_mesh(int p_idx, int p_level, const AABB &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx) {
if (p_level == cell_subdiv - 1) {
diff --git a/scene/3d/voxelizer.h b/scene/3d/voxelizer.h
index 37de6b782e..5016ff029f 100644
--- a/scene/3d/voxelizer.h
+++ b/scene/3d/voxelizer.h
@@ -135,6 +135,7 @@ public:
PoolVector<uint8_t> get_giprobe_octree_cells() const;
PoolVector<uint8_t> get_giprobe_data_cells() const;
PoolVector<int> get_giprobe_level_cell_count() const;
+ PoolVector<uint8_t> get_sdf_3d_image() const;
Ref<MultiMesh> create_debug_multimesh();
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 5a39a6dbfd..f35b68db47 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -488,12 +488,14 @@ public:
virtual RID gi_probe_create() = 0;
- virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) = 0;
+ virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<uint8_t> &p_distance_field, const PoolVector<int> &p_level_counts) = 0;
virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0;
+ virtual PoolVector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const = 0;
+
virtual PoolVector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0;
virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0;
@@ -506,6 +508,12 @@ public:
virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0;
virtual float gi_probe_get_energy(RID p_gi_probe) const = 0;
+ virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0;
+ virtual float gi_probe_get_ao(RID p_gi_probe) const = 0;
+
+ virtual void gi_probe_set_ao_strength(RID p_gi_probe, float p_strength) = 0;
+ virtual float gi_probe_get_ao_strength(RID p_gi_probe) const = 0;
+
virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0;
virtual float gi_probe_get_bias(RID p_gi_probe) const = 0;
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
index 867120db04..17f6bf8cdb 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.cpp
@@ -1555,6 +1555,8 @@ void RasterizerSceneForwardRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_resul
gi_probe_ubo.blend_ambient = !storage->gi_probe_is_interior(base_probe);
gi_probe_ubo.texture_slot = gi_probe_instance_get_slot(rpi);
gi_probe_ubo.anisotropy_strength = storage->gi_probe_get_anisotropy_strength(base_probe);
+ gi_probe_ubo.ao = storage->gi_probe_get_ao(base_probe);
+ gi_probe_ubo.ao_strength = storage->gi_probe_get_ao_strength(base_probe);
if (gi_probe_is_anisotropic()) {
gi_probe_ubo.texture_slot *= 3;
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
index 6e88a04e6d..ce335287ce 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h
@@ -262,7 +262,9 @@ class RasterizerSceneForwardRD : public RasterizerSceneRD {
uint32_t texture_slot;
float anisotropy_strength;
- uint32_t pad[3];
+ float ao;
+ float ao_strength;
+ uint32_t pad[1];
};
enum {
diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
index 4712ad92c9..c3a647ddb1 100644
--- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h
@@ -229,6 +229,7 @@ private:
bool gi_probe_use_anisotropy = false;
GIProbeQuality gi_probe_quality = GIPROBE_QUALITY_MEDIUM;
bool gi_probe_slots_dirty = true;
+
Vector<RID> gi_probe_slots;
enum {
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
index 4c5b9b94fb..b3f186240a 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp
@@ -3552,7 +3552,7 @@ RID RasterizerStorageRD::gi_probe_create() {
return gi_probe_owner.make_rid(GIProbe());
}
-void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) {
+void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<uint8_t> &p_distance_field, const PoolVector<int> &p_level_counts) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
@@ -3591,7 +3591,19 @@ void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_t
gi_probe->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells);
gi_probe->data_buffer_size = p_data_cells.size();
- {
+ if (p_distance_field.size()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = gi_probe->octree_size.x;
+ tf.height = gi_probe->octree_size.y;
+ tf.depth = gi_probe->octree_size.z;
+ tf.type = RD::TEXTURE_TYPE_3D;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ Vector<PoolVector<uint8_t> > s;
+ s.push_back(p_distance_field);
+ gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
+ }
+#if 0
{
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8_UNORM;
@@ -3659,6 +3671,7 @@ void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_t
RD::get_singleton()->free(uniform_set);
RD::get_singleton()->free(shared_tex);
}
+#endif
}
gi_probe->version++;
@@ -3697,6 +3710,15 @@ PoolVector<uint8_t> RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe)
}
return PoolVector<uint8_t>();
}
+PoolVector<uint8_t> RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const {
+ GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
+ ERR_FAIL_COND_V(!gi_probe, PoolVector<uint8_t>());
+
+ if (gi_probe->data_buffer.is_valid()) {
+ return RD::get_singleton()->texture_get_data(gi_probe->sdf_texture, 0);
+ }
+ return PoolVector<uint8_t>();
+}
PoolVector<int> RasterizerStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND_V(!gi_probe, PoolVector<int>());
@@ -3749,6 +3771,32 @@ float RasterizerStorageRD::gi_probe_get_energy(RID p_gi_probe) const {
return gi_probe->energy;
}
+void RasterizerStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) {
+ GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
+ ERR_FAIL_COND(!gi_probe);
+
+ gi_probe->ao = p_ao;
+}
+float RasterizerStorageRD::gi_probe_get_ao(RID p_gi_probe) const {
+ GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
+ ERR_FAIL_COND_V(!gi_probe, 0);
+ return gi_probe->ao;
+}
+
+void RasterizerStorageRD::gi_probe_set_ao_strength(RID p_gi_probe, float p_strength) {
+
+ GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
+ ERR_FAIL_COND(!gi_probe);
+
+ gi_probe->ao_strength = p_strength;
+}
+
+float RasterizerStorageRD::gi_probe_get_ao_strength(RID p_gi_probe) const {
+ GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
+ ERR_FAIL_COND_V(!gi_probe, 0);
+ return gi_probe->ao_strength;
+}
+
void RasterizerStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) {
GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe);
ERR_FAIL_COND(!gi_probe);
@@ -4341,7 +4389,7 @@ bool RasterizerStorageRD::free(RID p_rid) {
reflection_probe->instance_dependency.instance_notify_deleted(p_rid);
reflection_probe_owner.free(p_rid);
} else if (gi_probe_owner.owns(p_rid)) {
- gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), PoolVector<uint8_t>(), PoolVector<uint8_t>(), PoolVector<int>()); //deallocate
+ gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), PoolVector<uint8_t>(), PoolVector<uint8_t>(), PoolVector<uint8_t>(), PoolVector<int>()); //deallocate
GIProbe *gi_probe = gi_probe_owner.getornull(p_rid);
gi_probe->instance_dependency.instance_notify_deleted(p_rid);
gi_probe_owner.free(p_rid);
diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
index 63713c6add..0708c8d071 100644
--- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
+++ b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h
@@ -423,6 +423,8 @@ private:
float dynamic_range = 4.0;
float energy = 1.0;
+ float ao = 0.0;
+ float ao_strength = 0.5;
float bias = 1.4;
float normal_bias = 0.0;
float propagation = 0.7;
@@ -967,12 +969,14 @@ public:
RID gi_probe_create();
- void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts);
+ void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<uint8_t> &p_distance_field, const PoolVector<int> &p_level_counts);
AABB gi_probe_get_bounds(RID p_gi_probe) const;
Vector3i gi_probe_get_octree_size(RID p_gi_probe) const;
PoolVector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const;
PoolVector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const;
+ PoolVector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const;
+
PoolVector<int> gi_probe_get_level_counts(RID p_gi_probe) const;
Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const;
@@ -985,6 +989,12 @@ public:
void gi_probe_set_energy(RID p_gi_probe, float p_energy);
float gi_probe_get_energy(RID p_gi_probe) const;
+ void gi_probe_set_ao(RID p_gi_probe, float p_ao);
+ float gi_probe_get_ao(RID p_gi_probe) const;
+
+ void gi_probe_set_ao_strength(RID p_gi_probe, float p_strength);
+ float gi_probe_get_ao_strength(RID p_gi_probe) const;
+
void gi_probe_set_bias(RID p_gi_probe, float p_bias);
float gi_probe_get_bias(RID p_gi_probe) const;
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
index 1ffccdc4ee..8c122e6fcb 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward.glsl
@@ -956,37 +956,7 @@ vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction,
return color;
}
-#if 0
-vec4 voxel_cone_trace_skiplod(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
- float dist = p_bias;
- vec4 color = vec4(0.0);
- float skip_lod = 1.0;
-
- while (dist < max_distance && color.a < 0.95) {
- float diameter = max(1.0, 2.0 * tan_half_angle * dist);
- vec3 uvw_pos = (pos + dist * direction) * cell_size;
- float half_diameter = diameter * 0.5;
- //check if outside, then break
- if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
- break;
- }
- vec4 scolor = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter));
- float a = (1.0 - color.a);
- color += a * scolor;
-
- float upper_opacity = textureLod(sampler3D(probe,material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, skip_lod).a;
- float skip_factor = exp2( max( 0.0f, skip_lod * 0.5f - 1.0f ) ) * (1.0f - upper_opacity) + upper_opacity;
-
- skip_factor = mix( skip_factor, 1.0f, min( -1.0 + upper_opacity * probeParams.vctSpecularSdfFactor + tan_half_angle * 50.0f, 1.0f ) );
- skip_lod = clamp( skip_lod + (1.0f - upper_opacity) * 2.0f - 1.0f, 1.0f, probeParams.vctSpecSdfMaxMip );
-
- dist += half_diameter * skip_factor;
- }
-
- return color;
-}
-#endif
#ifndef GI_PROBE_HIGH_QUALITY
//faster version for 45 degrees
@@ -1015,7 +985,8 @@ vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe,texture3D aniso_pos
lod_level+=1.0;
float a = (1.0 - color.a);
- color += a * scolor;
+ scolor *= a;
+ color += scolor;
dist += radius;
radius = max(0.5, tan_half_angle * dist);
@@ -1026,7 +997,7 @@ vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe,texture3D aniso_pos
}
#else
-vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias ) {
float dist = p_bias;
vec4 color = vec4(0.0);
@@ -1044,7 +1015,8 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
lod_level+=1.0;
float a = (1.0 - color.a);
- color += a * scolor;
+ scolor *= a;
+ color += scolor;
dist += radius;
radius = max(0.5, tan_half_angle * dist);
@@ -1060,7 +1032,7 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3
//standard voxel cone trace
-vec4 voxel_cone_trace_anisotropic(texture3D probe,texture3D aniso_pos,texture3D aniso_neg,vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
+vec4 voxel_cone_trace_anisotropic(texture3D probe,texture3D aniso_pos,texture3D aniso_neg,vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias ) {
float dist = p_bias;
vec4 color = vec4(0.0);
@@ -1081,7 +1053,8 @@ vec4 voxel_cone_trace_anisotropic(texture3D probe,texture3D aniso_pos,texture3D
scolor.rgb*=dot(max(vec3(0.0),(normal * aniso_pos)),vec3(1.0)) + dot(max(vec3(0.0),(-normal * aniso_neg)),vec3(1.0));
float a = (1.0 - color.a);
- color += a * scolor;
+ scolor *= a;
+ color += scolor;
dist += half_diameter;
}
@@ -1155,8 +1128,8 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal,vec3 ref_vec, mat3
#endif
vec3 light = vec3(0.0);
- for (int i = 0; i < MAX_CONE_DIRS; i++) {
+ for (int i = 0; i < MAX_CONE_DIRS; i++) {
vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
@@ -1165,11 +1138,14 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal,vec3 ref_vec, mat3
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot],gi_probe_textures[gi_probes.data[index].texture_slot+1],gi_probe_textures[gi_probes.data[index].texture_slot+2],normalize(mix(dir,normal,gi_probes.data[index].anisotropy_strength)),cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
#else
+
vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
+
#endif // GI_PROBE_USE_ANISOTROPY
#else
+
#ifdef GI_PROBE_USE_ANISOTROPY
vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot],gi_probe_textures[gi_probes.data[index].texture_slot+1],gi_probe_textures[gi_probes.data[index].texture_slot+2],normalize(mix(dir,normal,gi_probes.data[index].anisotropy_strength)),cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
#else
@@ -1180,11 +1156,24 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal,vec3 ref_vec, mat3
if (gi_probes.data[index].blend_ambient) {
cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95));
}
+
light+=cone_weights[i] * cone_light.rgb;
+
+
}
light *= gi_probes.data[index].dynamic_range;
+ if (gi_probes.data[index].ambient_occlusion > 0.01) {
+ float ao = 0.0;
+
+ for (int i=0;i<5;i++) {
+ vec3 ofs = (position + normal * float(1<<i) * 1.5) * cell_size;
+ ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot],material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]),ofs,float(i) ).a;
+ light *= mix(max(0.0,1.0-(ao * gi_probes.data[index].ambient_occlusion )),1.0,gi_probes.data[index].ambient_occlusion_strength);
+ }
+ }
+
out_diff += vec4(light * blend, blend);
//irradiance
@@ -1415,13 +1404,12 @@ FRAGMENT_SHADER_CODE
vec4 amb_accum = vec4(0.0);
vec4 spec_accum = vec4(0.0);
-
- gi_probe_compute(index1, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum );
+ gi_probe_compute(index1, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
uint index2 = instances.data[instance_index].gi_offset>>16;
if (index2!=0xFFFF) {
- gi_probe_compute(index2, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum );
+ gi_probe_compute(index2, vertex, normal, ref_vec,normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
}
if (amb_accum.a > 0.0) {
diff --git a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
index c59d5ed756..9e97f76c57 100644
--- a/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
+++ b/servers/visual/rasterizer_rd/shaders/scene_forward_inc.glsl
@@ -207,8 +207,8 @@ struct GIProbeData {
uint texture_slot;
float anisotropy_strength;
- uint pad0;
- uint pad1;
+ float ambient_occlusion;
+ float ambient_occlusion_strength;
uint pad2;
};
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 38f5c1ec58..cd1b805448 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -344,12 +344,13 @@ public:
BIND0R(RID, gi_probe_create)
- BIND7(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<int> &)
+ BIND8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<int> &)
BIND1RC(AABB, gi_probe_get_bounds, RID)
BIND1RC(Vector3i, gi_probe_get_octree_size, RID)
BIND1RC(PoolVector<uint8_t>, gi_probe_get_octree_cells, RID)
BIND1RC(PoolVector<uint8_t>, gi_probe_get_data_cells, RID)
+ BIND1RC(PoolVector<uint8_t>, gi_probe_get_distance_field, RID)
BIND1RC(PoolVector<int>, gi_probe_get_level_counts, RID)
BIND1RC(Transform, gi_probe_get_to_cell_xform, RID)
@@ -362,6 +363,12 @@ public:
BIND2(gi_probe_set_energy, RID, float)
BIND1RC(float, gi_probe_get_energy, RID)
+ BIND2(gi_probe_set_ao, RID, float)
+ BIND1RC(float, gi_probe_get_ao, RID)
+
+ BIND2(gi_probe_set_ao_strength, RID, float)
+ BIND1RC(float, gi_probe_get_ao_strength, RID)
+
BIND2(gi_probe_set_bias, RID, float)
BIND1RC(float, gi_probe_get_bias, RID)
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 37a2fffa7a..34e830e30f 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -268,12 +268,13 @@ public:
FUNCRID(gi_probe)
- FUNC7(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<int> &)
+ FUNC8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<uint8_t> &, const PoolVector<int> &)
FUNC1RC(AABB, gi_probe_get_bounds, RID)
FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
FUNC1RC(PoolVector<uint8_t>, gi_probe_get_octree_cells, RID)
FUNC1RC(PoolVector<uint8_t>, gi_probe_get_data_cells, RID)
+ FUNC1RC(PoolVector<uint8_t>, gi_probe_get_distance_field, RID)
FUNC1RC(PoolVector<int>, gi_probe_get_level_counts, RID)
FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
@@ -286,6 +287,12 @@ public:
FUNC2(gi_probe_set_energy, RID, float)
FUNC1RC(float, gi_probe_get_energy, RID)
+ FUNC2(gi_probe_set_ao, RID, float)
+ FUNC1RC(float, gi_probe_get_ao, RID)
+
+ FUNC2(gi_probe_set_ao_strength, RID, float)
+ FUNC1RC(float, gi_probe_get_ao_strength, RID)
+
FUNC2(gi_probe_set_bias, RID, float)
FUNC1RC(float, gi_probe_get_bias, RID)
diff --git a/servers/visual_server.h b/servers/visual_server.h
index deab05b4da..3867797960 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -465,12 +465,13 @@ public:
virtual RID gi_probe_create() = 0;
- virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<int> &p_level_counts) = 0;
+ virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const PoolVector<uint8_t> &p_octree_cells, const PoolVector<uint8_t> &p_data_cells, const PoolVector<uint8_t> &p_distance_field, const PoolVector<int> &p_level_counts) = 0;
virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0;
virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_octree_cells(RID p_gi_probe) const = 0;
virtual PoolVector<uint8_t> gi_probe_get_data_cells(RID p_gi_probe) const = 0;
+ virtual PoolVector<uint8_t> gi_probe_get_distance_field(RID p_gi_probe) const = 0;
virtual PoolVector<int> gi_probe_get_level_counts(RID p_gi_probe) const = 0;
virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0;
@@ -483,6 +484,12 @@ public:
virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0;
virtual float gi_probe_get_energy(RID p_gi_probe) const = 0;
+ virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0;
+ virtual float gi_probe_get_ao(RID p_gi_probe) const = 0;
+
+ virtual void gi_probe_set_ao_strength(RID p_gi_probe, float p_strength) = 0;
+ virtual float gi_probe_get_ao_strength(RID p_gi_probe) const = 0;
+
virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0;
virtual float gi_probe_get_bias(RID p_gi_probe) const = 0;