diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/register_scene_types.cpp | 4 | ||||
-rw-r--r-- | scene/resources/environment.cpp | 31 | ||||
-rw-r--r-- | scene/resources/environment.h | 5 | ||||
-rw-r--r-- | scene/resources/shader.cpp | 3 | ||||
-rw-r--r-- | scene/resources/shader.h | 1 | ||||
-rw-r--r-- | scene/resources/sky_material.cpp | 191 | ||||
-rw-r--r-- | scene/resources/sky_material.h | 131 |
7 files changed, 365 insertions, 1 deletions
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index dd00565929..c152bb7e97 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -158,6 +158,7 @@ #include "scene/resources/resource_format_text.h" #include "scene/resources/segment_shape_2d.h" #include "scene/resources/sky.h" +#include "scene/resources/sky_material.h" #include "scene/resources/sphere_shape.h" #include "scene/resources/surface_tool.h" #include "scene/resources/text_file.h" @@ -609,6 +610,9 @@ void register_scene_types() { SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); ParticlesMaterial::init_shaders(); + ClassDB::register_class<SkyMaterial>(); + SkyMaterial::init_shaders(); + ClassDB::register_virtual_class<Mesh>(); ClassDB::register_class<ArrayMesh>(); ClassDB::register_class<MultiMesh>(); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index d407dd3722..b5a182ed5a 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -56,6 +56,17 @@ void Environment::set_sky(const Ref<Sky> &p_sky) { VS::get_singleton()->environment_set_sky(environment, sb_rid); } +void Environment::set_bg_material(const Ref<Material> &p_material) { + + bg_material = p_material; + + RID mb_rid; + if (bg_material.is_valid()) + mb_rid = bg_material->get_rid(); + + VS::get_singleton()->environment_set_bg_material(environment, mb_rid); +} + void Environment::set_sky_custom_fov(float p_scale) { bg_sky_custom_fov = p_scale; @@ -140,6 +151,11 @@ Vector3 Environment::get_sky_rotation() const { return sky_rotation; } +Ref<Material> Environment::get_bg_material() const { + + return bg_material; +} + Color Environment::get_bg_color() const { return bg_color; @@ -306,6 +322,13 @@ Ref<Texture2D> Environment::get_adjustment_color_correction() const { void Environment::_validate_property(PropertyInfo &property) const { + if (property.name == "background_material") { + if (bg_mode != BG_SKY) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } + + // TODO: We are retiring sky in favour of a background material that implements the sky. These properties will become part of the sky material if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") { if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; @@ -334,7 +357,7 @@ void Environment::_validate_property(PropertyInfo &property) const { if (property.name == "background_camera_feed_id") { if (bg_mode != BG_CAMERA_FEED) { - property.usage = PROPERTY_USAGE_NOEDITOR; + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -839,6 +862,7 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov); ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); + ClassDB::bind_method(D_METHOD("set_bg_material", "material"), &Environment::set_bg_material); ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); @@ -853,6 +877,7 @@ void Environment::_bind_methods() { ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky); ClassDB::bind_method(D_METHOD("get_sky_custom_fov"), &Environment::get_sky_custom_fov); ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation); + ClassDB::bind_method(D_METHOD("get_bg_material"), &Environment::get_bg_material); ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color); ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy); ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer); @@ -871,10 +896,14 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SkyMaterial"), "set_bg_material", "get_bg_material"); + + // TODO: We are retiring sky in favour of a background material that implements the sky. These properties will become part of the sky material ADD_GROUP("Sky", "sky_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "sky_rotation"), "set_sky_rotation", "get_sky_rotation"); + ADD_GROUP("Ambient Light", "ambient_light_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Color,Sky"), "set_ambient_source", "get_ambient_source"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); diff --git a/scene/resources/environment.h b/scene/resources/environment.h index f9fe26f792..9ee0cc312c 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -34,6 +34,7 @@ #include "core/resource.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" +#include "scene/resources/material.h" #include "servers/visual_server.h" class Environment : public Resource { @@ -92,6 +93,8 @@ private: BGMode bg_mode; Ref<Sky> bg_sky; + //@TODO for now introducing material but once it works we'll be replacing the current sky classes with material classes + Ref<Material> bg_material; float bg_sky_custom_fov; Vector3 sky_rotation; Color bg_color; @@ -180,6 +183,7 @@ public: void set_sky(const Ref<Sky> &p_sky); void set_sky_custom_fov(float p_scale); void set_sky_rotation(const Vector3 &p_rotation); + void set_bg_material(const Ref<Material> &p_material); void set_bg_color(const Color &p_color); void set_bg_energy(float p_energy); void set_canvas_max_layer(int p_max_layer); @@ -196,6 +200,7 @@ public: Ref<Sky> get_sky() const; float get_sky_custom_fov() const; Vector3 get_sky_rotation() const; + Ref<Material> get_bg_material() const; Color get_bg_color() const; float get_bg_energy() const; int get_canvas_max_layer() const; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index e61a1e6880..47f6d673ae 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -48,6 +48,8 @@ void Shader::set_code(const String &p_code) { mode = MODE_CANVAS_ITEM; } else if (type == "particles") { mode = MODE_PARTICLES; + } else if (type == "sky") { + mode = MODE_SKY; } else { mode = MODE_SPATIAL; } @@ -158,6 +160,7 @@ void Shader::_bind_methods() { BIND_ENUM_CONSTANT(MODE_SPATIAL); BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM); BIND_ENUM_CONSTANT(MODE_PARTICLES); + BIND_ENUM_CONSTANT(MODE_SKY); } Shader::Shader() { diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 84908852da..5804fe8fef 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -47,6 +47,7 @@ public: MODE_SPATIAL, MODE_CANVAS_ITEM, MODE_PARTICLES, + MODE_SKY, MODE_MAX }; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp new file mode 100644 index 0000000000..8c2b339015 --- /dev/null +++ b/scene/resources/sky_material.cpp @@ -0,0 +1,191 @@ +/*************************************************************************/ +/* sky_material.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "sky_material.h" + +Mutex *SkyMaterial::material_mutex = NULL; +SelfList<SkyMaterial>::List *SkyMaterial::dirty_materials = NULL; +Map<SkyMaterial::MaterialKey, SkyMaterial::ShaderData> SkyMaterial::shader_map; +SkyMaterial::ShaderNames *SkyMaterial::shader_names = NULL; + +void SkyMaterial::init_shaders() { + +#ifndef NO_THREADS + material_mutex = Mutex::create(); +#endif + + dirty_materials = memnew(SelfList<SkyMaterial>::List); + + shader_names = memnew(ShaderNames); + + shader_names->placeholder = "placeholder"; +} + +void SkyMaterial::finish_shaders() { + +#ifndef NO_THREADS + memdelete(material_mutex); +#endif + + memdelete(dirty_materials); + dirty_materials = NULL; + + memdelete(shader_names); +} + +void SkyMaterial::_update_shader() { + + dirty_materials->remove(&element); + + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) + return; //no update required in the end + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } + + current_key = mk; + + if (shader_map.has(mk)) { + + VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; + } + + //must create a shader! + + String code = "shader_type sky;\n"; + + ShaderData shader_data; + shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.users = 1; + + VS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); +} + +void SkyMaterial::flush_changes() { + + if (material_mutex) + material_mutex->lock(); + + while (dirty_materials->first()) { + + dirty_materials->first()->self()->_update_shader(); + } + + if (material_mutex) + material_mutex->unlock(); +} + +void SkyMaterial::_queue_shader_change() { + + if (material_mutex) + material_mutex->lock(); + + if (!element.in_list()) { + dirty_materials->add(&element); + } + + if (material_mutex) + material_mutex->unlock(); +} + +bool SkyMaterial::_is_shader_dirty() const { + + bool dirty = false; + + if (material_mutex) + material_mutex->lock(); + + dirty = element.in_list(); + + if (material_mutex) + material_mutex->unlock(); + + return dirty; +} + + +RID SkyMaterial::get_shader_rid() const { + + ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); + return shader_map[current_key].shader; +} + +void SkyMaterial::_validate_property(PropertyInfo &property) const { + +} + +Shader::Mode SkyMaterial::get_shader_mode() const { + + return Shader::MODE_SKY; +} + +void SkyMaterial::_bind_methods() { + +} + +SkyMaterial::SkyMaterial() : + element(this) { + + + _queue_shader_change(); +} + +SkyMaterial::~SkyMaterial() { + + if (material_mutex) + material_mutex->lock(); + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + + VS::get_singleton()->material_set_shader(_get_material(), RID()); + } + + if (material_mutex) + material_mutex->unlock(); +} diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h new file mode 100644 index 0000000000..5c8cddb10e --- /dev/null +++ b/scene/resources/sky_material.h @@ -0,0 +1,131 @@ +/*************************************************************************/ +/* sky_material.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/rid.h" +#include "scene/resources/material.h" + +#ifndef SKY_MATERIAL_H +#define SKY_MATERIAL_H + +class SkyMaterial : public Material { + + GDCLASS(SkyMaterial, Material); + +public: + +private: + union MaterialKey { + + struct { + uint32_t texture_mask : 16; + uint32_t texture_color : 1; + uint32_t flags : 4; + uint32_t emission_shape : 2; + uint32_t trail_size_texture : 1; + uint32_t trail_color_texture : 1; + uint32_t invalid_key : 1; + uint32_t has_emission_color : 1; + }; + + uint32_t key; + + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; + + struct ShaderData { + RID shader; + int users; + }; + + static Map<MaterialKey, ShaderData> shader_map; + + MaterialKey current_key; + + _FORCE_INLINE_ MaterialKey _compute_key() const { + + MaterialKey mk; + mk.key = 0; + /* + for (int i = 0; i < PARAM_MAX; i++) { + if (tex_parameters[i].is_valid()) { + mk.texture_mask |= (1 << i); + } + } + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + mk.flags |= (1 << i); + } + } + + mk.texture_color = color_ramp.is_valid() ? 1 : 0; + mk.emission_shape = emission_shape; + mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; + mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; + mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); + */ + + return mk; + } + + static Mutex *material_mutex; + static SelfList<SkyMaterial>::List *dirty_materials; + + struct ShaderNames { + StringName placeholder; + }; + + static ShaderNames *shader_names; + + SelfList<SkyMaterial> element; + + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + +protected: + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; + +public: + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); + + RID get_shader_rid() const; + + virtual Shader::Mode get_shader_mode() const; + + SkyMaterial(); + ~SkyMaterial(); +}; + +#endif /* !SKY_MATERIAL_H */ |