浏览代码

Merge pull request #50695 from reduz/fix-sky-initialization

Rémi Verschelde 4 年之前
父节点
当前提交
286e9b8533
共有 3 个文件被更改,包括 111 次插入19 次删除
  1. 4 0
      scene/register_scene_types.cpp
  2. 85 16
      scene/resources/sky_material.cpp
  3. 22 3
      scene/resources/sky_material.h

+ 4 - 0
scene/register_scene_types.cpp

@@ -1085,6 +1085,10 @@ void unregister_scene_types() {
 	BaseMaterial3D::finish_shaders();
 #endif // _3D_DISABLED
 
+	PhysicalSkyMaterial::cleanup_shader();
+	PanoramaSkyMaterial::cleanup_shader();
+	ProceduralSkyMaterial::cleanup_shader();
+
 	ParticlesMaterial::finish_shaders();
 	CanvasItemMaterial::finish_shaders();
 	ColorPicker::finish_shaders();

+ 85 - 16
scene/resources/sky_material.cpp

@@ -30,6 +30,9 @@
 
 #include "sky_material.h"
 
+Mutex ProceduralSkyMaterial::shader_mutex;
+RID ProceduralSkyMaterial::shader;
+
 void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {
 	sky_top_color = p_sky_top;
 	RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear());
@@ -128,7 +131,17 @@ Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {
 	return Shader::MODE_SKY;
 }
 
+RID ProceduralSkyMaterial::get_rid() const {
+	_update_shader();
+	if (!shader_set) {
+		RS::get_singleton()->material_set_shader(_get_material(), shader);
+		shader_set = true;
+	}
+	return _get_material();
+}
+
 RID ProceduralSkyMaterial::get_shader_rid() const {
+	_update_shader();
 	return shader;
 }
 
@@ -180,10 +193,18 @@ void ProceduralSkyMaterial::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
 }
 
-ProceduralSkyMaterial::ProceduralSkyMaterial() {
-	shader = RS::get_singleton()->shader_create();
+void ProceduralSkyMaterial::cleanup_shader() {
+	if (shader.is_valid()) {
+		RS::get_singleton()->free(shader);
+	}
+}
 
-	RS::get_singleton()->shader_set_code(shader, R"(
+void ProceduralSkyMaterial::_update_shader() {
+	shader_mutex.lock();
+	if (shader.is_null()) {
+		shader = RS::get_singleton()->shader_create();
+
+		RS::get_singleton()->shader_set_code(shader, R"(
 shader_type sky;
 
 uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);
@@ -250,9 +271,11 @@ void sky() {
 	COLOR = mix(ground, sky, step(0.0, EYEDIR.y));
 }
 )");
+	}
+	shader_mutex.unlock();
+}
 
-	RS::get_singleton()->material_set_shader(_get_material(), shader);
-
+ProceduralSkyMaterial::ProceduralSkyMaterial() {
 	set_sky_top_color(Color(0.35, 0.46, 0.71));
 	set_sky_horizon_color(Color(0.55, 0.69, 0.81));
 	set_sky_curve(0.09);
@@ -268,7 +291,6 @@ void sky() {
 }
 
 ProceduralSkyMaterial::~ProceduralSkyMaterial() {
-	RS::get_singleton()->free(shader);
 	RS::get_singleton()->material_set_shader(_get_material(), RID());
 }
 
@@ -293,7 +315,17 @@ Shader::Mode PanoramaSkyMaterial::get_shader_mode() const {
 	return Shader::MODE_SKY;
 }
 
+RID PanoramaSkyMaterial::get_rid() const {
+	_update_shader();
+	if (!shader_set) {
+		RS::get_singleton()->material_set_shader(_get_material(), shader);
+		shader_set = true;
+	}
+	return _get_material();
+}
+
 RID PanoramaSkyMaterial::get_shader_rid() const {
+	_update_shader();
 	return shader;
 }
 
@@ -304,10 +336,21 @@ void PanoramaSkyMaterial::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
 }
 
-PanoramaSkyMaterial::PanoramaSkyMaterial() {
-	shader = RS::get_singleton()->shader_create();
+Mutex PanoramaSkyMaterial::shader_mutex;
+RID PanoramaSkyMaterial::shader;
 
-	RS::get_singleton()->shader_set_code(shader, R"(
+void PanoramaSkyMaterial::cleanup_shader() {
+	if (shader.is_valid()) {
+		RS::get_singleton()->free(shader);
+	}
+}
+
+void PanoramaSkyMaterial::_update_shader() {
+	shader_mutex.lock();
+	if (shader.is_null()) {
+		shader = RS::get_singleton()->shader_create();
+
+		RS::get_singleton()->shader_set_code(shader, R"(
 shader_type sky;
 
 uniform sampler2D source_panorama : filter_linear;
@@ -316,12 +359,15 @@ void sky() {
 	COLOR = texture(source_panorama, SKY_COORDS).rgb;
 }
 )");
+	}
 
-	RS::get_singleton()->material_set_shader(_get_material(), shader);
+	shader_mutex.unlock();
+}
+
+PanoramaSkyMaterial::PanoramaSkyMaterial() {
 }
 
 PanoramaSkyMaterial::~PanoramaSkyMaterial() {
-	RS::get_singleton()->free(shader);
 	RS::get_singleton()->material_set_shader(_get_material(), RID());
 }
 
@@ -436,10 +482,23 @@ Shader::Mode PhysicalSkyMaterial::get_shader_mode() const {
 	return Shader::MODE_SKY;
 }
 
+RID PhysicalSkyMaterial::get_rid() const {
+	_update_shader();
+	if (!shader_set) {
+		RS::get_singleton()->material_set_shader(_get_material(), shader);
+		shader_set = true;
+	}
+	return _get_material();
+}
+
 RID PhysicalSkyMaterial::get_shader_rid() const {
+	_update_shader();
 	return shader;
 }
 
+Mutex PhysicalSkyMaterial::shader_mutex;
+RID PhysicalSkyMaterial::shader;
+
 void PhysicalSkyMaterial::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient);
 	ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient);
@@ -491,10 +550,18 @@ void PhysicalSkyMaterial::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
 }
 
-PhysicalSkyMaterial::PhysicalSkyMaterial() {
-	shader = RS::get_singleton()->shader_create();
+void PhysicalSkyMaterial::cleanup_shader() {
+	if (shader.is_valid()) {
+		RS::get_singleton()->free(shader);
+	}
+}
 
-	RS::get_singleton()->shader_set_code(shader, R"(
+void PhysicalSkyMaterial::_update_shader() {
+	shader_mutex.lock();
+	if (shader.is_null()) {
+		shader = RS::get_singleton()->shader_create();
+
+		RS::get_singleton()->shader_set_code(shader, R"(
 shader_type sky;
 
 uniform float rayleigh : hint_range(0, 64) = 2.0;
@@ -588,9 +655,12 @@ void sky() {
 	}
 }
 )");
+	}
 
-	RS::get_singleton()->material_set_shader(_get_material(), shader);
+	shader_mutex.unlock();
+}
 
+PhysicalSkyMaterial::PhysicalSkyMaterial() {
 	set_rayleigh_coefficient(2.0);
 	set_rayleigh_color(Color(0.056, 0.14, 0.3));
 	set_mie_coefficient(0.005);
@@ -604,5 +674,4 @@ void sky() {
 }
 
 PhysicalSkyMaterial::~PhysicalSkyMaterial() {
-	RS::get_singleton()->free(shader);
 }

+ 22 - 3
scene/resources/sky_material.h

@@ -51,7 +51,10 @@ private:
 	float sun_angle_max;
 	float sun_curve;
 
-	RID shader;
+	static Mutex shader_mutex;
+	static RID shader;
+	static void _update_shader();
+	mutable bool shader_set = false;
 
 protected:
 	static void _bind_methods();
@@ -90,6 +93,9 @@ public:
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual RID get_shader_rid() const override;
+	virtual RID get_rid() const override;
+
+	static void cleanup_shader();
 
 	ProceduralSkyMaterial();
 	~ProceduralSkyMaterial();
@@ -103,7 +109,11 @@ class PanoramaSkyMaterial : public Material {
 
 private:
 	Ref<Texture2D> panorama;
-	RID shader;
+
+	static Mutex shader_mutex;
+	static RID shader;
+	static void _update_shader();
+	mutable bool shader_set = false;
 
 protected:
 	static void _bind_methods();
@@ -115,6 +125,9 @@ public:
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual RID get_shader_rid() const override;
+	virtual RID get_rid() const override;
+
+	static void cleanup_shader();
 
 	PanoramaSkyMaterial();
 	~PanoramaSkyMaterial();
@@ -127,7 +140,8 @@ class PhysicalSkyMaterial : public Material {
 	GDCLASS(PhysicalSkyMaterial, Material);
 
 private:
-	RID shader;
+	static Mutex shader_mutex;
+	static RID shader;
 
 	float rayleigh;
 	Color rayleigh_color;
@@ -140,6 +154,8 @@ private:
 	float exposure;
 	float dither_strength;
 	Ref<Texture2D> night_sky;
+	static void _update_shader();
+	mutable bool shader_set = false;
 
 protected:
 	static void _bind_methods();
@@ -182,6 +198,9 @@ public:
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual RID get_shader_rid() const override;
 
+	static void cleanup_shader();
+	virtual RID get_rid() const override;
+
 	PhysicalSkyMaterial();
 	~PhysicalSkyMaterial();
 };