Merge pull request #55551 from brennengreen/panorama-sky-filtering

Add filtering property to PanoramaSkyMaterial and switch from static shader to shader cache
This commit is contained in:
Rémi Verschelde 2022-01-16 01:30:44 +01:00 committed by GitHub
commit 1cff9a2e49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 15 deletions

View File

@ -11,6 +11,9 @@
<tutorials> <tutorials>
</tutorials> </tutorials>
<members> <members>
<member name="filter" type="bool" setter="set_filtering_enabled" getter="is_filtering_enabled" default="true">
A boolean value to determine if the background texture should be filtered or not.
</member>
<member name="panorama" type="Texture2D" setter="set_panorama" getter="get_panorama"> <member name="panorama" type="Texture2D" setter="set_panorama" getter="get_panorama">
[Texture2D] to be applied to the [PanoramaSkyMaterial]. [Texture2D] to be applied to the [PanoramaSkyMaterial].
</member> </member>

View File

@ -308,14 +308,30 @@ Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const {
return panorama; return panorama;
} }
void PanoramaSkyMaterial::set_filtering_enabled(bool p_enabled) {
filter = p_enabled;
notify_property_list_changed();
_update_shader();
// Only set if shader already compiled
if (shader_set) {
RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(filter)]);
}
}
bool PanoramaSkyMaterial::is_filtering_enabled() const {
return filter;
}
Shader::Mode PanoramaSkyMaterial::get_shader_mode() const { Shader::Mode PanoramaSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY; return Shader::MODE_SKY;
} }
RID PanoramaSkyMaterial::get_rid() const { RID PanoramaSkyMaterial::get_rid() const {
_update_shader(); _update_shader();
// Don't compile shaders until first use, then compile both
if (!shader_set) { if (!shader_set) {
RS::get_singleton()->material_set_shader(_get_material(), shader); RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(filter)]);
RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(filter)]);
shader_set = true; shader_set = true;
} }
return _get_material(); return _get_material();
@ -323,42 +339,47 @@ RID PanoramaSkyMaterial::get_rid() const {
RID PanoramaSkyMaterial::get_shader_rid() const { RID PanoramaSkyMaterial::get_shader_rid() const {
_update_shader(); _update_shader();
return shader; return shader_cache[int(filter)];
} }
void PanoramaSkyMaterial::_bind_methods() { void PanoramaSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama); ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama);
ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama); ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama);
ClassDB::bind_method(D_METHOD("set_filtering_enabled", "enabled"), &PanoramaSkyMaterial::set_filtering_enabled);
ClassDB::bind_method(D_METHOD("is_filtering_enabled"), &PanoramaSkyMaterial::is_filtering_enabled);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter"), "set_filtering_enabled", "is_filtering_enabled");
} }
Mutex PanoramaSkyMaterial::shader_mutex; Mutex PanoramaSkyMaterial::shader_mutex;
RID PanoramaSkyMaterial::shader; RID PanoramaSkyMaterial::shader_cache[2];
void PanoramaSkyMaterial::cleanup_shader() { void PanoramaSkyMaterial::cleanup_shader() {
if (shader.is_valid()) { if (shader_cache[0].is_valid()) {
RS::get_singleton()->free(shader); RS::get_singleton()->free(shader_cache[0]);
RS::get_singleton()->free(shader_cache[1]);
} }
} }
void PanoramaSkyMaterial::_update_shader() { void PanoramaSkyMaterial::_update_shader() {
shader_mutex.lock(); shader_mutex.lock();
if (shader.is_null()) { if (shader_cache[0].is_null()) {
shader = RS::get_singleton()->shader_create(); for (int i = 0; i < 2; i++) {
shader_cache[i] = RS::get_singleton()->shader_create();
// Add a comment to describe the shader origin (useful when converting to ShaderMaterial). // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
RS::get_singleton()->shader_set_code(shader, R"( RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"(
// NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PanoramaSkyMaterial. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PanoramaSkyMaterial.
shader_type sky; shader_type sky;
uniform sampler2D source_panorama : %s, hint_albedo;
uniform sampler2D source_panorama : filter_linear, hint_albedo;
void sky() { void sky() {
COLOR = texture(source_panorama, SKY_COORDS).rgb; COLOR = texture(source_panorama, SKY_COORDS).rgb;
} }
)"); )",
i ? "filter_linear" : "filter_nearest"));
}
} }
shader_mutex.unlock(); shader_mutex.unlock();

View File

@ -110,10 +110,12 @@ private:
Ref<Texture2D> panorama; Ref<Texture2D> panorama;
static Mutex shader_mutex; static Mutex shader_mutex;
static RID shader; static RID shader_cache[2];
static void _update_shader(); static void _update_shader();
mutable bool shader_set = false; mutable bool shader_set = false;
bool filter = true;
protected: protected:
static void _bind_methods(); static void _bind_methods();
@ -121,6 +123,9 @@ public:
void set_panorama(const Ref<Texture2D> &p_panorama); void set_panorama(const Ref<Texture2D> &p_panorama);
Ref<Texture2D> get_panorama() const; Ref<Texture2D> get_panorama() const;
void set_filtering_enabled(bool p_enabled);
bool is_filtering_enabled() const;
virtual Shader::Mode get_shader_mode() const override; virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override; virtual RID get_shader_rid() const override;
virtual RID get_rid() const override; virtual RID get_rid() const override;