diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-05-28 21:46:48 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-05-28 21:48:05 -0300 |
commit | bb20f230ad307a2a5f18c03bece3793d29ae208a (patch) | |
tree | b217d7c10054e23b0f456acee41bc208dc12bfdf /scene | |
parent | 06fc9637966dafe8e06e1d4f823bf9e8b3475c97 (diff) |
-Added .hdr format support
-Added default environment editor setting
-Added environment created by default in new projects
-Removed default light and ambient from spatial editor, to make the editor more PBR compliant
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/line_2d.cpp | 4 | ||||
-rw-r--r-- | scene/2d/line_2d.h | 6 | ||||
-rw-r--r-- | scene/2d/line_builder.h | 2 | ||||
-rw-r--r-- | scene/2d/particles_2d.cpp | 6 | ||||
-rw-r--r-- | scene/2d/particles_2d.h | 6 | ||||
-rw-r--r-- | scene/gui/color_ramp_edit.cpp | 18 | ||||
-rw-r--r-- | scene/gui/color_ramp_edit.h | 6 | ||||
-rw-r--r-- | scene/main/scene_main_loop.cpp | 60 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 3 | ||||
-rw-r--r-- | scene/resources/color_ramp.cpp | 56 | ||||
-rw-r--r-- | scene/resources/color_ramp.h | 10 | ||||
-rw-r--r-- | scene/resources/sky_box.cpp | 391 | ||||
-rw-r--r-- | scene/resources/sky_box.h | 112 | ||||
-rw-r--r-- | scene/resources/world.cpp | 17 | ||||
-rw-r--r-- | scene/resources/world.h | 5 |
15 files changed, 631 insertions, 71 deletions
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index c782968ea0..80969d11b3 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -99,7 +99,7 @@ Color Line2D::get_default_color() const { return _default_color; } -void Line2D::set_gradient(const Ref<ColorRamp> &gradient) { +void Line2D::set_gradient(const Ref<Gradient> &gradient) { // Cleanup previous connection if any if (_gradient.is_valid()) { @@ -116,7 +116,7 @@ void Line2D::set_gradient(const Ref<ColorRamp> &gradient) { update(); } -Ref<ColorRamp> Line2D::get_gradient() const { +Ref<Gradient> Line2D::get_gradient() const { return _gradient; } diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index fee1cad942..e8ca5e6e7c 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -57,8 +57,8 @@ public: void set_default_color(Color color); Color get_default_color() const; - void set_gradient(const Ref<ColorRamp> &gradient); - Ref<ColorRamp> get_gradient() const; + void set_gradient(const Ref<Gradient> &gradient); + Ref<Gradient> get_gradient() const; void set_texture(const Ref<Texture> &texture); Ref<Texture> get_texture() const; @@ -97,7 +97,7 @@ private: LineCapMode _end_cap_mode; float _width; Color _default_color; - Ref<ColorRamp> _gradient; + Ref<Gradient> _gradient; Ref<Texture> _texture; LineTextureMode _texture_mode; float _sharp_limit; diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index eed9cac0aa..0e1a2aaf50 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -62,7 +62,7 @@ public: LineCapMode end_cap_mode; float width; Color default_color; - ColorRamp *gradient; + Gradient *gradient; LineTextureMode texture_mode; float sharp_limit; int round_precision; diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index b91d9b835c..951861256e 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -774,12 +774,12 @@ Color Particles2D::get_color() const { return default_color; } -void Particles2D::set_color_ramp(const Ref<ColorRamp> &p_color_ramp) { +void Particles2D::set_color_ramp(const Ref<Gradient> &p_color_ramp) { color_ramp = p_color_ramp; } -Ref<ColorRamp> Particles2D::get_color_ramp() const { +Ref<Gradient> Particles2D::get_color_ramp() const { return color_ramp; } @@ -810,7 +810,7 @@ void Particles2D::set_color_phases(int p_phases) { //Create color ramp if we have 2 or more phases. //Otherwise first phase phase will be assigned to default color. if (p_phases > 1 && color_ramp.is_null()) { - color_ramp = Ref<ColorRamp>(memnew(ColorRamp())); + color_ramp = Ref<Gradient>(memnew(Gradient())); } if (color_ramp.is_valid()) { color_ramp->get_points().resize(p_phases); diff --git a/scene/2d/particles_2d.h b/scene/2d/particles_2d.h index 4b87a26195..5769fdd251 100644 --- a/scene/2d/particles_2d.h +++ b/scene/2d/particles_2d.h @@ -169,7 +169,7 @@ private: //If no color ramp is set then default color is used. Created as simple alternative to color_ramp. Color default_color; - Ref<ColorRamp> color_ramp; + Ref<Gradient> color_ramp; void _process_particles(float p_delta); friend class ParticleAttractor2D; @@ -241,8 +241,8 @@ public: void set_color(const Color &p_color); Color get_color() const; - void set_color_ramp(const Ref<ColorRamp> &p_texture); - Ref<ColorRamp> get_color_ramp() const; + void set_color_ramp(const Ref<Gradient> &p_texture); + Ref<Gradient> get_color_ramp() const; void set_emissor_offset(const Point2 &p_offset); Point2 get_emissor_offset() const; diff --git a/scene/gui/color_ramp_edit.cpp b/scene/gui/color_ramp_edit.cpp index 9270b97e02..8c47f8559a 100644 --- a/scene/gui/color_ramp_edit.cpp +++ b/scene/gui/color_ramp_edit.cpp @@ -114,7 +114,7 @@ void ColorRampEdit::_gui_input(const Ref<InputEvent> &p_event) { if (grabbed != -1) { int total_w = get_size().width - get_size().height - 3; - ColorRamp::Point newPoint = points[grabbed]; + Gradient::Point newPoint = points[grabbed]; newPoint.offset = CLAMP(x / float(total_w), 0, 1); points.push_back(newPoint); @@ -152,11 +152,11 @@ void ColorRampEdit::_gui_input(const Ref<InputEvent> &p_event) { } //insert - ColorRamp::Point newPoint; + Gradient::Point newPoint; newPoint.offset = CLAMP(x / float(total_w), 0, 1); - ColorRamp::Point prev; - ColorRamp::Point next; + Gradient::Point prev; + Gradient::Point next; int pos = -1; for (int i = 0; i < points.size(); i++) { @@ -293,7 +293,7 @@ void ColorRampEdit::_notification(int p_what) { _draw_checker(0, 0, total_w, h); //Draw color ramp - ColorRamp::Point prev; + Gradient::Point prev; prev.offset = 0; if (points.size() == 0) prev.color = Color(0, 0, 0); //Draw black rectangle if we have no points @@ -302,7 +302,7 @@ void ColorRampEdit::_notification(int p_what) { for (int i = -1; i < points.size(); i++) { - ColorRamp::Point next; + Gradient::Point next; //If there is no next point if (i + 1 == points.size()) { if (points.size() == 0) @@ -410,7 +410,7 @@ void ColorRampEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> ERR_FAIL_COND(p_offsets.size() != p_colors.size()); points.clear(); for (int i = 0; i < p_offsets.size(); i++) { - ColorRamp::Point p; + Gradient::Point p; p.offset = p_offsets[i]; p.color = p_colors[i]; points.push_back(p); @@ -434,14 +434,14 @@ Vector<Color> ColorRampEdit::get_colors() const { return ret; } -void ColorRampEdit::set_points(Vector<ColorRamp::Point> &p_points) { +void ColorRampEdit::set_points(Vector<Gradient::Point> &p_points) { if (points.size() != p_points.size()) grabbed = -1; points.clear(); points = p_points; } -Vector<ColorRamp::Point> &ColorRampEdit::get_points() { +Vector<Gradient::Point> &ColorRampEdit::get_points() { return points; } diff --git a/scene/gui/color_ramp_edit.h b/scene/gui/color_ramp_edit.h index ede8954040..0fe447c43a 100644 --- a/scene/gui/color_ramp_edit.h +++ b/scene/gui/color_ramp_edit.h @@ -48,7 +48,7 @@ class ColorRampEdit : public Control { bool grabbing; int grabbed; - Vector<ColorRamp::Point> points; + Vector<Gradient::Point> points; void _draw_checker(int x, int y, int w, int h); void _color_changed(const Color &p_color); @@ -64,8 +64,8 @@ public: void set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors); Vector<float> get_offsets() const; Vector<Color> get_colors() const; - void set_points(Vector<ColorRamp::Point> &p_points); - Vector<ColorRamp::Point> &get_points(); + void set_points(Vector<Gradient::Point> &p_points); + Vector<Gradient::Point> &get_points(); virtual Size2 get_minimum_size() const; ColorRampEdit(); diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index b55a925f55..96a3519840 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -37,6 +37,7 @@ #include "print_string.h" #include <stdio.h> //#include "servers/spatial_sound_2d_server.h" + #include "io/marshalls.h" #include "io/resource_loader.h" #include "scene/resources/material.h" @@ -609,6 +610,30 @@ bool SceneTree::idle(float p_time) { _call_idle_callbacks(); +#ifdef TOOLS_ENABLED + + if (is_editor_hint()) { + //simple hack to reload fallback environment if it changed from editor + String env_path = GlobalConfig::get_singleton()->get("rendering/viewport/default_environment"); + env_path = env_path.strip_edges(); //user may have added a space or two + String cpath; + Ref<Environment> fallback = get_root()->get_world()->get_fallback_environment(); + if (fallback.is_valid()) { + cpath = fallback->get_path(); + } + if (cpath != env_path) { + + if (env_path != String()) { + fallback = ResourceLoader::load(env_path); + } else { + fallback.unref(); + } + get_root()->get_world()->set_fallback_environment(fallback); + } + } + +#endif + return _quit; } @@ -2301,7 +2326,9 @@ SceneTree::SceneTree() { root = memnew(Viewport); root->set_name("root"); - root->set_world(Ref<World>(memnew(World))); + if (!root->get_world().is_valid()) + root->set_world(Ref<World>(memnew(World))); + //root->set_world_2d( Ref<World2D>( memnew( World2D ))); root->set_as_audio_listener(true); root->set_as_audio_listener_2d(true); @@ -2317,6 +2344,37 @@ SceneTree::SceneTree() { VS::get_singleton()->scenario_set_reflection_atlas_size(root->get_world()->get_scenario(), ref_atlas_size, ref_atlas_subdiv); + { //load default fallback environment + //get possible extensions + List<String> exts; + ResourceLoader::get_recognized_extensions_for_type("Environment", &exts); + String ext_hint; + for (List<String>::Element *E = exts.front(); E; E = E->next()) { + if (ext_hint != String()) + ext_hint += ","; + ext_hint += "*." + E->get(); + } + //get path + String env_path = GLOBAL_DEF("rendering/viewport/default_environment", ""); + //setup property + GlobalConfig::get_singleton()->set_custom_property_info("rendering/viewport/default_environment", PropertyInfo(Variant::STRING, "rendering/viewport/default_environment", PROPERTY_HINT_FILE, ext_hint)); + env_path = env_path.strip_edges(); + if (env_path != String()) { + Ref<Environment> env = ResourceLoader::load(env_path); + if (env.is_valid()) { + root->get_world()->set_fallback_environment(env); + } else { + if (is_editor_hint()) { + //file was erased, clear the field. + GlobalConfig::get_singleton()->set("rendering/viewport/default_environment", ""); + } else { + //file was erased, notify user. + ERR_PRINTS(RTR("Default Environment as specified in Project Setings (Rendering -> Viewport -> Default Environment) could not be loaded.")); + } + } + } + } + stretch_mode = STRETCH_MODE_DISABLED; stretch_aspect = STRETCH_ASPECT_IGNORE; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 4c359f73ab..0a3f64eacd 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -563,6 +563,7 @@ void register_scene_types() { ClassDB::register_virtual_class<Texture>(); ClassDB::register_virtual_class<Sky>(); ClassDB::register_class<PanoramaSky>(); + ClassDB::register_class<ProceduralSky>(); ClassDB::register_class<StreamTexture>(); ClassDB::register_class<ImageTexture>(); ClassDB::register_class<AtlasTexture>(); @@ -584,7 +585,7 @@ void register_scene_types() { ClassDB::register_class<PolygonPathFinder>(); ClassDB::register_class<BitMap>(); - ClassDB::register_class<ColorRamp>(); + ClassDB::register_class<Gradient>(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/color_ramp.cpp b/scene/resources/color_ramp.cpp index 3c58a76998..3cf8845189 100644 --- a/scene/resources/color_ramp.cpp +++ b/scene/resources/color_ramp.cpp @@ -36,7 +36,7 @@ #define COLOR_RAMP_SET_OFFSETS "set_offsets" #define COLOR_RAMP_SET_COLORS "set_colors" -ColorRamp::ColorRamp() { +Gradient::Gradient() { //Set initial color ramp transition from black to white points.resize(2); points[0].color = Color(0, 0, 0, 1); @@ -46,35 +46,35 @@ ColorRamp::ColorRamp() { is_sorted = true; } -ColorRamp::~ColorRamp() { +Gradient::~Gradient() { } -void ColorRamp::_bind_methods() { +void Gradient::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &ColorRamp::add_point); - ClassDB::bind_method(D_METHOD("remove_point", "offset", "color"), &ColorRamp::remove_point); + ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &Gradient::add_point); + ClassDB::bind_method(D_METHOD("remove_point", "offset", "color"), &Gradient::remove_point); - ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &ColorRamp::set_offset); - ClassDB::bind_method(D_METHOD("get_offset", "point"), &ColorRamp::get_offset); + ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &Gradient::set_offset); + ClassDB::bind_method(D_METHOD("get_offset", "point"), &Gradient::get_offset); - ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &ColorRamp::set_color); - ClassDB::bind_method(D_METHOD("get_color", "point"), &ColorRamp::get_color); + ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &Gradient::set_color); + ClassDB::bind_method(D_METHOD("get_color", "point"), &Gradient::get_color); - ClassDB::bind_method(D_METHOD("interpolate", "offset"), &ColorRamp::get_color_at_offset); + ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Gradient::get_color_at_offset); - ClassDB::bind_method(D_METHOD("get_point_count"), &ColorRamp::get_points_count); + ClassDB::bind_method(D_METHOD("get_point_count"), &Gradient::get_points_count); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS, "offsets"), &ColorRamp::set_offsets); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS), &ColorRamp::get_offsets); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS, "offsets"), &Gradient::set_offsets); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS), &Gradient::get_offsets); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &ColorRamp::set_colors); - ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &ColorRamp::get_colors); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &Gradient::set_colors); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &Gradient::get_colors); ADD_PROPERTY(PropertyInfo(Variant::REAL, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); ADD_PROPERTY(PropertyInfo(Variant::REAL, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); } -Vector<float> ColorRamp::get_offsets() const { +Vector<float> Gradient::get_offsets() const { Vector<float> offsets; offsets.resize(points.size()); for (int i = 0; i < points.size(); i++) { @@ -83,7 +83,7 @@ Vector<float> ColorRamp::get_offsets() const { return offsets; } -Vector<Color> ColorRamp::get_colors() const { +Vector<Color> Gradient::get_colors() const { Vector<Color> colors; colors.resize(points.size()); for (int i = 0; i < points.size(); i++) { @@ -92,7 +92,7 @@ Vector<Color> ColorRamp::get_colors() const { return colors; } -void ColorRamp::set_offsets(const Vector<float> &p_offsets) { +void Gradient::set_offsets(const Vector<float> &p_offsets) { points.resize(p_offsets.size()); for (int i = 0; i < points.size(); i++) { points[i].offset = p_offsets[i]; @@ -101,7 +101,7 @@ void ColorRamp::set_offsets(const Vector<float> &p_offsets) { emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::set_colors(const Vector<Color> &p_colors) { +void Gradient::set_colors(const Vector<Color> &p_colors) { if (points.size() < p_colors.size()) is_sorted = false; points.resize(p_colors.size()); @@ -111,11 +111,11 @@ void ColorRamp::set_colors(const Vector<Color> &p_colors) { emit_signal(CoreStringNames::get_singleton()->changed); } -Vector<ColorRamp::Point> &ColorRamp::get_points() { +Vector<Gradient::Point> &Gradient::get_points() { return points; } -void ColorRamp::add_point(float p_offset, const Color &p_color) { +void Gradient::add_point(float p_offset, const Color &p_color) { Point p; p.offset = p_offset; @@ -126,7 +126,7 @@ void ColorRamp::add_point(float p_offset, const Color &p_color) { emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::remove_point(int p_index) { +void Gradient::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, points.size()); ERR_FAIL_COND(points.size() <= 2); @@ -134,13 +134,13 @@ void ColorRamp::remove_point(int p_index) { emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::set_points(Vector<ColorRamp::Point> &p_points) { +void Gradient::set_points(Vector<Gradient::Point> &p_points) { points = p_points; is_sorted = false; emit_signal(CoreStringNames::get_singleton()->changed); } -void ColorRamp::set_offset(int pos, const float offset) { +void Gradient::set_offset(int pos, const float offset) { if (points.size() <= pos) points.resize(pos + 1); points[pos].offset = offset; @@ -148,13 +148,13 @@ void ColorRamp::set_offset(int pos, const float offset) { emit_signal(CoreStringNames::get_singleton()->changed); } -float ColorRamp::get_offset(int pos) const { +float Gradient::get_offset(int pos) const { if (points.size() > pos) return points[pos].offset; return 0; //TODO: Maybe throw some error instead? } -void ColorRamp::set_color(int pos, const Color &color) { +void Gradient::set_color(int pos, const Color &color) { if (points.size() <= pos) { points.resize(pos + 1); is_sorted = false; @@ -163,12 +163,12 @@ void ColorRamp::set_color(int pos, const Color &color) { emit_signal(CoreStringNames::get_singleton()->changed); } -Color ColorRamp::get_color(int pos) const { +Color Gradient::get_color(int pos) const { if (points.size() > pos) return points[pos].color; return Color(0, 0, 0, 1); //TODO: Maybe throw some error instead? } -int ColorRamp::get_points_count() const { +int Gradient::get_points_count() const { return points.size(); } diff --git a/scene/resources/color_ramp.h b/scene/resources/color_ramp.h index e231e9fc52..d7ec20b324 100644 --- a/scene/resources/color_ramp.h +++ b/scene/resources/color_ramp.h @@ -32,9 +32,9 @@ #include "resource.h" -class ColorRamp : public Resource { - GDCLASS(ColorRamp, Resource); - OBJ_SAVE_TYPE(ColorRamp); +class Gradient : public Resource { + GDCLASS(Gradient, Resource); + OBJ_SAVE_TYPE(Gradient); public: struct Point { @@ -54,8 +54,8 @@ protected: static void _bind_methods(); public: - ColorRamp(); - virtual ~ColorRamp(); + Gradient(); + virtual ~Gradient(); void add_point(float p_offset, const Color &p_color); void remove_point(int p_index); diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp index 59ade4a729..61aaaf8fb4 100644 --- a/scene/resources/sky_box.cpp +++ b/scene/resources/sky_box.cpp @@ -112,3 +112,394 @@ PanoramaSky::~PanoramaSky() { VS::get_singleton()->free(sky); } +////////////////////////////////// + +void ProceduralSky::_radiance_changed() { + + if (update_queued) + return; //do nothing yet + + static const int size[RADIANCE_SIZE_MAX] = { + 256, 512, 1024, 2048 + }; + VS::get_singleton()->sky_set_texture(sky, texture, size[get_radiance_size()]); +} + +void ProceduralSky::_update_sky() { + + update_queued = false; + + PoolVector<uint8_t> imgdata; + + static const int size[TEXTURE_SIZE_MAX] = { + 1024, 2048, 4096 + }; + + int w = size[texture_size]; + int h = w / 2; + + imgdata.resize(w * h * 4); //RGBE + + { + PoolVector<uint8_t>::Write dataw = imgdata.write(); + + uint32_t *ptr = (uint32_t *)dataw.ptr(); + + Color sky_top_linear = sky_top_color.to_linear(); + Color sky_horizon_linear = sky_horizon_color.to_linear(); + + Color ground_bottom_linear = ground_bottom_color.to_linear(); + Color ground_horizon_linear = ground_horizon_color.to_linear(); + + //Color sun_linear = sun_color.to_linear(); + + Vector3 sun(0, 0, -1); + + sun = Basis(Vector3(1, 0, 0), Math::deg2rad(sun_latitude)).xform(sun); + sun = Basis(Vector3(0, 1, 0), Math::deg2rad(sun_longitude)).xform(sun); + + sun.normalize(); + + for (int i = 0; i < w; i++) { + + float u = float(i) / (w - 1); + float phi = u * 2.0 * Math_PI; + + for (int j = 0; j < h; j++) { + + float v = float(j) / (h - 1); + float theta = v * Math_PI; + + Vector3 normal( + Math::sin(phi) * Math::sin(theta) * -1.0, + Math::cos(theta), + Math::cos(phi) * Math::sin(theta) * -1.0); + + normal.normalize(); + + float v_angle = Math::acos(normal.y); + + Color color; + + if (normal.y < 0) { + //ground + + float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5); + color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve)); + } else { + float c = v_angle / (Math_PI * 0.5); + color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve)); + + float sun_angle = Math::rad2deg(Math::acos(sun.dot(normal))); + + if (sun_angle < sun_angle_min) { + color = color.blend(sun_color); + } else if (sun_angle < sun_angle_max) { + + float c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min); + c2 = Math::ease(c2, sun_curve); + + color = color.blend(sun_color).linear_interpolate(color, c2); + } + } + + ptr[j * w + i] = color.to_rgbe9995(); + } + } + } + + Ref<Image> image; + 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(); +} + +void ProceduralSky::set_sky_top_color(const Color &p_sky_top) { + + sky_top_color = p_sky_top; + _queue_update(); +} + +Color ProceduralSky::get_sky_top_color() const { + + return sky_top_color; +} + +void ProceduralSky::set_sky_horizon_color(const Color &p_sky_horizon) { + + sky_horizon_color = p_sky_horizon; + _queue_update(); +} +Color ProceduralSky::get_sky_horizon_color() const { + + return sky_horizon_color; +} + +void ProceduralSky::set_sky_curve(float p_curve) { + + sky_curve = p_curve; + _queue_update(); +} +float ProceduralSky::get_sky_curve() const { + + return sky_curve; +} + +void ProceduralSky::set_sky_energy(float p_energy) { + + sky_energy = p_energy; + _queue_update(); +} +float ProceduralSky::get_sky_energy() const { + + return sky_energy; +} + +void ProceduralSky::set_ground_bottom_color(const Color &p_ground_bottom) { + + ground_bottom_color = p_ground_bottom; + _queue_update(); +} +Color ProceduralSky::get_ground_bottom_color() const { + + return ground_bottom_color; +} + +void ProceduralSky::set_ground_horizon_color(const Color &p_ground_horizon) { + + ground_horizon_color = p_ground_horizon; + _queue_update(); +} +Color ProceduralSky::get_ground_horizon_color() const { + + return ground_horizon_color; +} + +void ProceduralSky::set_ground_curve(float p_curve) { + + ground_curve = p_curve; + _queue_update(); +} +float ProceduralSky::get_ground_curve() const { + + return ground_curve; +} + +void ProceduralSky::set_ground_energy(float p_energy) { + + ground_energy = p_energy; + _queue_update(); +} +float ProceduralSky::get_ground_energy() const { + + return ground_energy; +} + +void ProceduralSky::set_sun_color(const Color &p_sun) { + + sun_color = p_sun; + _queue_update(); +} +Color ProceduralSky::get_sun_color() const { + + return sun_color; +} + +void ProceduralSky::set_sun_latitude(float p_angle) { + + sun_latitude = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_latitude() const { + + return sun_latitude; +} + +void ProceduralSky::set_sun_longitude(float p_angle) { + + sun_longitude = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_longitude() const { + + return sun_longitude; +} + +void ProceduralSky::set_sun_angle_min(float p_angle) { + + sun_angle_min = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_angle_min() const { + + return sun_angle_min; +} + +void ProceduralSky::set_sun_angle_max(float p_angle) { + + sun_angle_max = p_angle; + _queue_update(); +} +float ProceduralSky::get_sun_angle_max() const { + + return sun_angle_max; +} + +void ProceduralSky::set_sun_curve(float p_curve) { + + sun_curve = p_curve; + _queue_update(); +} +float ProceduralSky::get_sun_curve() const { + + return sun_curve; +} + +void ProceduralSky::set_sun_energy(float p_energy) { + + sun_energy = p_energy; + _queue_update(); +} +float ProceduralSky::get_sun_energy() const { + + return sun_energy; +} + +void ProceduralSky::set_texture_size(TextureSize p_size) { + ERR_FAIL_INDEX(p_size, TEXTURE_SIZE_MAX); + + texture_size = p_size; + _queue_update(); +} +ProceduralSky::TextureSize ProceduralSky::get_texture_size() const { + return texture_size; +} + +RID ProceduralSky::get_rid() const { + return sky; +} + +void ProceduralSky::_queue_update() { + + if (update_queued) + return; + + update_queued = true; + call_deferred("_update_sky"); +} + +void ProceduralSky::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_update_sky"), &ProceduralSky::_update_sky); + + ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSky::set_sky_top_color); + ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSky::get_sky_top_color); + + ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSky::set_sky_horizon_color); + ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSky::get_sky_horizon_color); + + ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSky::set_sky_curve); + ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSky::get_sky_curve); + + ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSky::set_sky_energy); + ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSky::get_sky_energy); + + ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSky::set_ground_bottom_color); + ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSky::get_ground_bottom_color); + + ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSky::set_ground_horizon_color); + ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSky::get_ground_horizon_color); + + ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSky::set_ground_curve); + ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSky::get_ground_curve); + + ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSky::set_ground_energy); + ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSky::get_ground_energy); + + ClassDB::bind_method(D_METHOD("set_sun_color", "color"), &ProceduralSky::set_sun_color); + ClassDB::bind_method(D_METHOD("get_sun_color"), &ProceduralSky::get_sun_color); + + ClassDB::bind_method(D_METHOD("set_sun_latitude", "degrees"), &ProceduralSky::set_sun_latitude); + ClassDB::bind_method(D_METHOD("get_sun_latitude"), &ProceduralSky::get_sun_latitude); + + ClassDB::bind_method(D_METHOD("set_sun_longitude", "degrees"), &ProceduralSky::set_sun_longitude); + ClassDB::bind_method(D_METHOD("get_sun_longitude"), &ProceduralSky::get_sun_longitude); + + ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSky::set_sun_angle_min); + ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSky::get_sun_angle_min); + + ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSky::set_sun_angle_max); + ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSky::get_sun_angle_max); + + ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSky::set_sun_curve); + ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSky::get_sun_curve); + + ClassDB::bind_method(D_METHOD("set_sun_energy", "energy"), &ProceduralSky::set_sun_energy); + ClassDB::bind_method(D_METHOD("get_sun_energy"), &ProceduralSky::get_sun_energy); + + 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); + + 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"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy"); + + ADD_GROUP("Ground", "ground_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color"), "set_ground_bottom_color", "get_ground_bottom_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color"), "set_ground_horizon_color", "get_ground_horizon_color"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy"); + + ADD_GROUP("Sun", "sun_"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sun_color"), "set_sun_color", "get_sun_color"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_latitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_latitude", "get_sun_latitude"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_longitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_longitude", "get_sun_longitude"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy"); + + ADD_GROUP("Texture", "texture_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "1024,2048,4096"), "set_texture_size", "get_texture_size"); +} + +ProceduralSky::ProceduralSky() { + + sky = VS::get_singleton()->sky_create(); + texture = VS::get_singleton()->texture_create(); + + update_queued = false; + + sky_top_color = Color::hex(0x4d67e8ff); + sky_horizon_color = Color::hex(0x8ed2e8ff); + sky_curve = 0.25; + sky_energy = 1; + + ground_bottom_color = Color::hex(0x322719ff); + ground_horizon_color = Color::hex(0x543610ff); + ground_curve = 0.25; + ground_energy = 1; + + sun_color = Color(1, 1, 1); + sun_latitude = 35; + sun_longitude = 0; + sun_angle_min = 1; + sun_angle_max = 100; + sun_curve = 0.05; + sun_energy = 16; + + texture_size = TEXTURE_SIZE_1024; + + _queue_update(); +} + +ProceduralSky::~ProceduralSky() { + + VS::get_singleton()->free(sky); + VS::get_singleton()->free(texture); +} diff --git a/scene/resources/sky_box.h b/scene/resources/sky_box.h index afbfb3019e..7b707af3a6 100644 --- a/scene/resources/sky_box.h +++ b/scene/resources/sky_box.h @@ -62,17 +62,6 @@ VARIANT_ENUM_CAST(Sky::RadianceSize) class PanoramaSky : public Sky { GDCLASS(PanoramaSky, Sky); -public: - enum ImagePath { - IMAGE_PATH_NEGATIVE_X, - IMAGE_PATH_POSITIVE_X, - IMAGE_PATH_NEGATIVE_Y, - IMAGE_PATH_POSITIVE_Y, - IMAGE_PATH_NEGATIVE_Z, - IMAGE_PATH_POSITIVE_Z, - IMAGE_PATH_MAX - }; - private: RID sky; Ref<Texture> panorama; @@ -91,6 +80,105 @@ public: ~PanoramaSky(); }; -VARIANT_ENUM_CAST(PanoramaSky::ImagePath) +class ProceduralSky : public Sky { + GDCLASS(ProceduralSky, Sky); + +public: + enum TextureSize { + TEXTURE_SIZE_1024, + TEXTURE_SIZE_2048, + TEXTURE_SIZE_4096, + TEXTURE_SIZE_MAX + }; + +private: + Color sky_top_color; + Color sky_horizon_color; + float sky_curve; + float sky_energy; + + Color ground_bottom_color; + Color ground_horizon_color; + float ground_curve; + float ground_energy; + + Color sun_color; + float sun_latitude; + float sun_longitude; + float sun_angle_min; + float sun_angle_max; + float sun_curve; + float sun_energy; + + TextureSize texture_size; + + RID sky; + RID texture; + + bool update_queued; + +protected: + static void _bind_methods(); + virtual void _radiance_changed(); + + void _update_sky(); + void _queue_update(); + +public: + void set_sky_top_color(const Color &p_sky_top); + Color get_sky_top_color() const; + + void set_sky_horizon_color(const Color &p_sky_horizon); + Color get_sky_horizon_color() const; + + void set_sky_curve(float p_curve); + float get_sky_curve() const; + + void set_sky_energy(float p_energy); + float get_sky_energy() const; + + void set_ground_bottom_color(const Color &p_ground_bottom); + Color get_ground_bottom_color() const; + + void set_ground_horizon_color(const Color &p_ground_horizon); + Color get_ground_horizon_color() const; + + void set_ground_curve(float p_curve); + float get_ground_curve() const; + + void set_ground_energy(float p_energy); + float get_ground_energy() const; + + void set_sun_color(const Color &p_sun); + Color get_sun_color() const; + + void set_sun_latitude(float p_angle); + float get_sun_latitude() const; + + void set_sun_longitude(float p_angle); + float get_sun_longitude() const; + + void set_sun_angle_min(float p_angle); + float get_sun_angle_min() const; + + void set_sun_angle_max(float p_angle); + float get_sun_angle_max() const; + + void set_sun_curve(float p_curve); + float get_sun_curve() const; + + void set_sun_energy(float p_energy); + float get_sun_energy() const; + + void set_texture_size(TextureSize p_size); + TextureSize get_texture_size() const; + + virtual RID get_rid() const; + + ProceduralSky(); + ~ProceduralSky(); +}; + +VARIANT_ENUM_CAST(ProceduralSky::TextureSize) #endif // Sky_H diff --git a/scene/resources/world.cpp b/scene/resources/world.cpp index eab7cf6098..24551e9135 100644 --- a/scene/resources/world.cpp +++ b/scene/resources/world.cpp @@ -280,6 +280,20 @@ Ref<Environment> World::get_environment() const { return environment; } +void World::set_fallback_environment(const Ref<Environment> &p_environment) { + + fallback_environment = p_environment; + if (fallback_environment.is_valid()) + VS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); + else + VS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); +} + +Ref<Environment> World::get_fallback_environment() const { + + return fallback_environment; +} + PhysicsDirectSpaceState *World::get_direct_space_state() { return PhysicsServer::get_singleton()->space_get_direct_state(space); @@ -291,8 +305,11 @@ void World::_bind_methods() { ClassDB::bind_method(D_METHOD("get_scenario"), &World::get_scenario); ClassDB::bind_method(D_METHOD("set_environment", "env:Environment"), &World::set_environment); ClassDB::bind_method(D_METHOD("get_environment:Environment"), &World::get_environment); + ClassDB::bind_method(D_METHOD("set_fallback_environment", "env:Environment"), &World::set_fallback_environment); + ClassDB::bind_method(D_METHOD("get_fallback_environment:Environment"), &World::get_fallback_environment); ClassDB::bind_method(D_METHOD("get_direct_space_state:PhysicsDirectSpaceState"), &World::get_direct_space_state); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_environment", "get_environment"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_environment", PROPERTY_HINT_RESOURCE_TYPE, "Environment"), "set_fallback_environment", "get_fallback_environment"); } World::World() { diff --git a/scene/resources/world.h b/scene/resources/world.h index f2c85f31f6..96857a577a 100644 --- a/scene/resources/world.h +++ b/scene/resources/world.h @@ -48,6 +48,7 @@ private: RID scenario; SpatialIndexer *indexer; Ref<Environment> environment; + Ref<Environment> fallback_environment; protected: static void _bind_methods(); @@ -68,9 +69,13 @@ protected: public: RID get_space() const; RID get_scenario() const; + void set_environment(const Ref<Environment> &p_environment); Ref<Environment> get_environment() const; + void set_fallback_environment(const Ref<Environment> &p_environment); + Ref<Environment> get_fallback_environment() const; + PhysicsDirectSpaceState *get_direct_space_state(); World(); |