Browse Source

ProceduralSky now regenerates in a thread (the second time, first does not), closes #9138

Juan Linietsky 8 năm trước cách đây
mục cha
commit
3f8efdef49
2 tập tin đã thay đổi với 69 bổ sung5 xóa
  1. 59 4
      scene/resources/sky_box.cpp
  2. 10 1
      scene/resources/sky_box.h

+ 59 - 4
scene/resources/sky_box.cpp

@@ -128,7 +128,7 @@ void ProceduralSky::_radiance_changed() {
 	VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]);
 }
 
-void ProceduralSky::_update_sky() {
+Ref<Image> ProceduralSky::_generate_sky() {
 
 	update_queued = false;
 
@@ -215,9 +215,7 @@ void ProceduralSky::_update_sky() {
 	image.instance();
 	image->create(w, h, false, Image::FORMAT_RGBE9995, imgdata);
 
-	VS::get_singleton()->texture_allocate(texture, w, h, Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
-	VS::get_singleton()->texture_set_data(texture, image);
-	_radiance_changed();
+	return image;
 }
 
 void ProceduralSky::set_sky_top_color(const Color &p_sky_top) {
@@ -385,6 +383,33 @@ RID ProceduralSky::get_rid() const {
 	return sky;
 }
 
+void ProceduralSky::_update_sky() {
+
+	bool use_thread = true;
+	if (first_time) {
+		use_thread = false;
+		first_time = false;
+	}
+#ifdef NO_THREADS
+	use_thread = false;
+#endif
+	if (use_thread) {
+
+		if (!sky_thread) {
+			sky_thread = Thread::create(_thread_function, this);
+			regen_queued = false;
+		} else {
+			regen_queued = true;
+		}
+
+	} else {
+		Ref<Image> image = _generate_sky();
+		VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
+		VS::get_singleton()->texture_set_data(texture, image);
+		_radiance_changed();
+	}
+}
+
 void ProceduralSky::_queue_update() {
 
 	if (update_queued)
@@ -394,6 +419,26 @@ void ProceduralSky::_queue_update() {
 	call_deferred("_update_sky");
 }
 
+void ProceduralSky::_thread_done(const Ref<Image> &image) {
+
+	VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
+	VS::get_singleton()->texture_set_data(texture, image);
+	_radiance_changed();
+	Thread::wait_to_finish(sky_thread);
+	memdelete(sky_thread);
+	sky_thread = NULL;
+	if (regen_queued) {
+		sky_thread = Thread::create(_thread_function, this);
+		regen_queued = false;
+	}
+}
+
+void ProceduralSky::_thread_function(void *p_ud) {
+
+	ProceduralSky *psky = (ProceduralSky *)p_ud;
+	psky->call_deferred("_thread_done", psky->_generate_sky());
+}
+
 void ProceduralSky::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("_update_sky"), &ProceduralSky::_update_sky);
@@ -446,6 +491,8 @@ void ProceduralSky::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_texture_size", "size"), &ProceduralSky::set_texture_size);
 	ClassDB::bind_method(D_METHOD("get_texture_size"), &ProceduralSky::get_texture_size);
 
+	ClassDB::bind_method(D_METHOD("_thread_done", "image"), &ProceduralSky::_thread_done);
+
 	ADD_GROUP("Sky", "sky_");
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color"), "set_sky_top_color", "get_sky_top_color");
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color"), "set_sky_horizon_color", "get_sky_horizon_color");
@@ -503,12 +550,20 @@ ProceduralSky::ProceduralSky() {
 	sun_energy = 16;
 
 	texture_size = TEXTURE_SIZE_1024;
+	sky_thread = NULL;
+	regen_queued = false;
+	first_time = true;
 
 	_queue_update();
 }
 
 ProceduralSky::~ProceduralSky() {
 
+	if (sky_thread) {
+		Thread::wait_to_finish(sky_thread);
+		memdelete(sky_thread);
+		sky_thread = NULL;
+	}
 	VS::get_singleton()->free(sky);
 	VS::get_singleton()->free(texture);
 }

+ 10 - 1
scene/resources/sky_box.h

@@ -30,8 +30,8 @@
 #ifndef Sky_H
 #define Sky_H
 
+#include "os/thread.h"
 #include "scene/resources/texture.h"
-
 class Sky : public Resource {
 	GDCLASS(Sky, Resource);
 
@@ -97,6 +97,7 @@ public:
 	};
 
 private:
+	Thread *sky_thread;
 	Color sky_top_color;
 	Color sky_horizon_color;
 	float sky_curve;
@@ -121,12 +122,20 @@ private:
 	RID texture;
 
 	bool update_queued;
+	bool regen_queued;
+
+	bool first_time;
+
+	void _thread_done(const Ref<Image> &p_image);
+	static void _thread_function(void *p_ud);
 
 protected:
 	static void _bind_methods();
 	virtual void _radiance_changed();
 
+	Ref<Image> _generate_sky();
 	void _update_sky();
+
 	void _queue_update();
 
 public: