summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/3d/voxel_light_baker.cpp54
-rw-r--r--scene/3d/voxel_light_baker.h2
-rw-r--r--scene/main/viewport.cpp12
3 files changed, 51 insertions, 17 deletions
diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp
index bc3f62cfd1..bf0f801e32 100644
--- a/scene/3d/voxel_light_baker.cpp
+++ b/scene/3d/voxel_light_baker.cpp
@@ -32,6 +32,10 @@
#include "os/os.h"
#include <stdlib.h>
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
#define FINDMINMAX(x0, x1, x2, min, max) \
min = max = x0; \
if (x1 < min) min = x1; \
@@ -1675,19 +1679,17 @@ Vector3 VoxelLightBaker::_compute_pixel_light_at_pos(const Vector3 &p_pos, const
return accum;
}
-uint32_t xorshiftstate[] = { 123 }; // anything non-zero will do here
-
-_ALWAYS_INLINE_ uint32_t xorshift32(uint32_t *seed) {
+_ALWAYS_INLINE_ uint32_t xorshift32(uint32_t *state) {
/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
- uint32_t x = *seed;
+ uint32_t x = *state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
- *seed = x;
+ *state = x;
return x;
}
-Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal) {
+Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal, uint32_t *rng_state) {
int samples_per_quality[3] = { 48, 128, 512 };
@@ -1709,16 +1711,14 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V
const Light *light = bake_light.ptr();
const Cell *cells = bake_cells.ptr();
- uint32_t seed = 0;
- while (seed == 0) {
- seed = rand(); //system rand is thread safe, do not replace by Math:: random.
- }
+ // Prevent false sharing when running on OpenMP
+ uint32_t local_rng_state = *rng_state;
for (int i = 0; i < samples; i++) {
- float random_angle1 = (((xorshift32(&seed) % 65535) / 65535.0) * 2.0 - 1.0) * spread;
+ float random_angle1 = (((xorshift32(&local_rng_state) % 65535) / 65535.0) * 2.0 - 1.0) * spread;
Vector3 axis(0, sin(random_angle1), cos(random_angle1));
- float random_angle2 = ((xorshift32(&seed) % 65535) / 65535.0) * Math_PI * 2.0;
+ float random_angle2 = ((xorshift32(&local_rng_state) % 65535) / 65535.0) * Math_PI * 2.0;
Basis rot(Vector3(0, 0, 1), random_angle2);
axis = rot.xform(axis);
@@ -1795,6 +1795,8 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V
}
}
+ // Make sure we don't reset this thread's RNG state
+ *rng_state = local_rng_state;
return accum / samples;
}
@@ -1852,21 +1854,43 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
_plot_triangle(uv, vertex, normal, lightmap.ptrw(), width, height);
}
}
- //step 3 perform voxel cone trace on lightmap pixels
+ //step 3 perform voxel cone trace on lightmap pixels
{
LightMap *lightmap_ptr = lightmap.ptrw();
uint64_t begin_time = OS::get_singleton()->get_ticks_usec();
volatile int lines = 0;
+ // make sure our OS-level rng is seeded
+ srand(OS::get_singleton()->get_ticks_usec());
+
+ // setup an RNG state for each OpenMP thread
+ uint32_t threadcount = 1;
+ uint32_t threadnum = 0;
+#ifdef _OPENMP
+ threadcount = omp_get_max_threads();
+#endif
+ Vector<uint32_t> rng_states;
+ rng_states.resize(threadcount);
+ for (uint32_t i = 0; i < threadcount; i++) {
+ do {
+ rng_states[i] = rand();
+ } while (rng_states[i] == 0);
+ }
+ uint32_t *rng_states_p = rng_states.ptrw();
+
for (int i = 0; i < height; i++) {
//print_line("bake line " + itos(i) + " / " + itos(height));
#ifdef _OPENMP
-#pragma omp parallel for schedule(dynamic, 1)
+#pragma omp parallel for schedule(dynamic, 1) private(threadnum)
#endif
for (int j = 0; j < width; j++) {
+#ifdef _OPENMP
+ threadnum = omp_get_thread_num();
+#endif
+
//if (i == 125 && j == 280) {
LightMap *pixel = &lightmap_ptr[i * width + j];
@@ -1879,7 +1903,7 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
pixel->light = _compute_pixel_light_at_pos(pixel->pos, pixel->normal) * energy;
} break;
case BAKE_MODE_RAY_TRACE: {
- pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal) * energy;
+ pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal, &rng_states_p[threadnum]) * energy;
} break;
// pixel->light = Vector3(1, 1, 1);
//}
diff --git a/scene/3d/voxel_light_baker.h b/scene/3d/voxel_light_baker.h
index d6ba414a46..7db31f8a67 100644
--- a/scene/3d/voxel_light_baker.h
+++ b/scene/3d/voxel_light_baker.h
@@ -148,7 +148,7 @@ private:
_FORCE_INLINE_ void _sample_baked_octree_filtered_and_anisotropic(const Vector3 &p_posf, const Vector3 &p_direction, float p_level, Vector3 &r_color, float &r_alpha);
_FORCE_INLINE_ Vector3 _voxel_cone_trace(const Vector3 &p_pos, const Vector3 &p_normal, float p_aperture);
_FORCE_INLINE_ Vector3 _compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
- _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
+ _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal, uint32_t *rng_state);
public:
void begin_bake(int p_subdiv, const AABB &p_bounds);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ae855e803c..c156b0df31 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2371,7 +2371,17 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
p_control->_modal_set_prev_focus_owner(0);
if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus)) {
- gui.mouse_focus->notification(Control::NOTIFICATION_MOUSE_EXIT);
+ Ref<InputEventMouseButton> mb;
+ mb.instance();
+ mb->set_position(gui.mouse_focus->get_local_mouse_position());
+ mb->set_global_position(gui.mouse_focus->get_local_mouse_position());
+ mb->set_button_index(gui.mouse_focus_button);
+ mb->set_pressed(false);
+ gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
+
+ //if (gui.mouse_over == gui.mouse_focus) {
+ // gui.mouse_focus->notification(Control::NOTIFICATION_MOUSE_EXIT);
+ //}
gui.mouse_focus = NULL;
}