diff options
author | clayjohn <claynjohn@gmail.com> | 2020-03-19 17:32:19 -0700 |
---|---|---|
committer | clayjohn <claynjohn@gmail.com> | 2020-03-21 20:43:44 -0700 |
commit | 61a74739ca2d201e7e057d85aa99ae68f0500c33 (patch) | |
tree | 73f170a76bb138f01d2df825798d6c4109b81cc8 /scene/resources | |
parent | c3fee7ba6cdefd285255b9e1198bc1fdf585b1ac (diff) |
Working sky shader implementation
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/environment.cpp | 31 | ||||
-rw-r--r-- | scene/resources/environment.h | 5 | ||||
-rw-r--r-- | scene/resources/sky.cpp | 509 | ||||
-rw-r--r-- | scene/resources/sky.h | 130 | ||||
-rw-r--r-- | scene/resources/sky_material.cpp | 619 | ||||
-rw-r--r-- | scene/resources/sky_material.h | 213 |
6 files changed, 687 insertions, 820 deletions
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index b5a182ed5a..d407dd3722 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -56,17 +56,6 @@ 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; @@ -151,11 +140,6 @@ 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; @@ -322,13 +306,6 @@ 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; @@ -357,7 +334,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_INTERNAL; + property.usage = PROPERTY_USAGE_NOEDITOR; } } @@ -862,7 +839,6 @@ 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); @@ -877,7 +853,6 @@ 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); @@ -896,14 +871,10 @@ 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 9ee0cc312c..f9fe26f792 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -34,7 +34,6 @@ #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 { @@ -93,8 +92,6 @@ 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; @@ -183,7 +180,6 @@ 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); @@ -200,7 +196,6 @@ 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/sky.cpp b/scene/resources/sky.cpp index 54648e8af7..1185b693b7 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -56,6 +56,18 @@ Sky::ProcessMode Sky::get_process_mode() const { return mode; } +void Sky::set_material(const Ref<Material> &p_material) { + sky_material = p_material; + RID material_rid; + if (sky_material.is_valid()) + material_rid = sky_material->get_rid(); + VS::get_singleton()->sky_set_material(sky, material_rid); +} + +Ref<Material> Sky::get_material() const { + return sky_material; +} + RID Sky::get_rid() const { return sky; @@ -69,6 +81,10 @@ void Sky::_bind_methods() { ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Sky::set_process_mode); ClassDB::bind_method(D_METHOD("get_process_mode"), &Sky::get_process_mode); + ClassDB::bind_method(D_METHOD("set_material", "material"), &Sky::set_material); + ClassDB::bind_method(D_METHOD("get_material"), &Sky::get_material); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,PanoramaSkyMaterial,ProceduralSkyMaterial,PhysicalSkyMaterial"), "set_material", "get_material"); ADD_PROPERTY(PropertyInfo(Variant::INT, "radiance_size", PROPERTY_HINT_ENUM, "32,64,128,256,512,1024,2048"), "set_radiance_size", "get_radiance_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "HighQuality,RealTime"), "set_process_mode", "get_process_mode"); @@ -87,500 +103,11 @@ void Sky::_bind_methods() { Sky::Sky() { mode = PROCESS_MODE_QUALITY; - radiance_size = RADIANCE_SIZE_128; + radiance_size = RADIANCE_SIZE_256; sky = VS::get_singleton()->sky_create(); } Sky::~Sky() { VS::get_singleton()->free(sky); -} - -///////////////////////////////////////// - -void PanoramaSky::set_panorama(const Ref<Texture2D> &p_panorama) { - - panorama = p_panorama; - - RID rid = p_panorama.is_valid() ? p_panorama->get_rid() : RID(); - VS::get_singleton()->sky_set_texture(get_rid(), rid); -} - -Ref<Texture2D> PanoramaSky::get_panorama() const { - - return panorama; -} - -void PanoramaSky::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSky::set_panorama); - ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSky::get_panorama); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama"); -} - -PanoramaSky::PanoramaSky() { -} - -PanoramaSky::~PanoramaSky() { -} -////////////////////////////////// - -Ref<Image> ProceduralSky::_generate_sky() { - - update_queued = false; - - Vector<uint8_t> imgdata; - - static const int size[TEXTURE_SIZE_MAX] = { - 256, 512, 1024, 2048, 4096 - }; - - int w = size[texture_size]; - int h = w / 2; - - imgdata.resize(w * h * 4); //RGBE - - { - uint8_t *dataw = imgdata.ptrw(); - - uint32_t *ptr = (uint32_t *)dataw; - - 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_linear.r = sun_color.r * sun_energy; - sun_linear.g = sun_color.g * sun_energy; - sun_linear.b = sun_color.b * sun_energy; - - 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(CLAMP(normal.y, -1.0, 1.0)); - - 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)); - color.r *= ground_energy; - color.g *= ground_energy; - color.b *= ground_energy; - } 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)); - color.r *= sky_energy; - color.g *= sky_energy; - color.b *= sky_energy; - - float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0))); - - if (sun_angle < sun_angle_min) { - color = color.blend(sun_linear); - } 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_linear).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); - - return image; -} - -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; -} - -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(); - if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(image); - VS::get_singleton()->texture_replace(texture, new_texture); - } else { - texture = VS::get_singleton()->texture_2d_create(image); - } - VS::get_singleton()->sky_set_texture(get_rid(), texture); - } -} - -void ProceduralSky::_queue_update() { - - if (update_queued) - return; - - update_queued = true; - call_deferred("_update_sky"); -} - -void ProceduralSky::_thread_done(const Ref<Image> &p_image) { - - if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(p_image); - VS::get_singleton()->texture_replace(texture, new_texture); - } else { - texture = VS::get_singleton()->texture_2d_create(p_image); - } - - VS::get_singleton()->sky_set_texture(get_rid(), texture); - - 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); - - 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); - - 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"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "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::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "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::FLOAT, "sun_latitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_latitude", "get_sun_latitude"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_longitude", PROPERTY_HINT_RANGE, "-180,180,0.01"), "set_sun_longitude", "get_sun_longitude"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sun_energy", "get_sun_energy"); - - ADD_GROUP("Texture2D", "texture_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_texture_size", "get_texture_size"); - - BIND_ENUM_CONSTANT(TEXTURE_SIZE_256); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_512); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_1024); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_2048); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_4096); - BIND_ENUM_CONSTANT(TEXTURE_SIZE_MAX); -} - -ProceduralSky::ProceduralSky(bool p_desaturate) { - - update_queued = false; - sky_top_color = Color::hex(0xa5d6f1ff); - sky_horizon_color = Color::hex(0xd6eafaff); - sky_curve = 0.09; - sky_energy = 1; - - ground_bottom_color = Color::hex(0x282f36ff); - ground_horizon_color = Color::hex(0x6c655fff); - ground_curve = 0.02; - ground_energy = 1; - - if (p_desaturate) { - sky_top_color.set_hsv(sky_top_color.get_h(), 0, sky_top_color.get_v()); - sky_horizon_color.set_hsv(sky_horizon_color.get_h(), 0, sky_horizon_color.get_v()); - ground_bottom_color.set_hsv(ground_bottom_color.get_h(), 0, ground_bottom_color.get_v()); - ground_horizon_color.set_hsv(ground_horizon_color.get_h(), 0, ground_horizon_color.get_v()); - } - 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 = 1; - - 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; - } - if (texture.is_valid()) { - VS::get_singleton()->free(texture); - } -} +}
\ No newline at end of file diff --git a/scene/resources/sky.h b/scene/resources/sky.h index 09ebbd88a0..37f0a589f9 100644 --- a/scene/resources/sky.h +++ b/scene/resources/sky.h @@ -32,6 +32,7 @@ #define SKY_H #include "core/os/thread.h" +#include "scene/resources/material.h" #include "scene/resources/texture.h" class Sky : public Resource { @@ -58,6 +59,7 @@ private: RID sky; ProcessMode mode; RadianceSize radiance_size; + Ref<Material> sky_material; protected: static void _bind_methods(); @@ -69,6 +71,9 @@ public: void set_process_mode(ProcessMode p_mode); ProcessMode get_process_mode() const; + void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; + virtual RID get_rid() const; Sky(); @@ -78,129 +83,4 @@ public: VARIANT_ENUM_CAST(Sky::RadianceSize) VARIANT_ENUM_CAST(Sky::ProcessMode) -class PanoramaSky : public Sky { - GDCLASS(PanoramaSky, Sky); - -private: - Ref<Texture2D> panorama; - -protected: - static void _bind_methods(); - -public: - void set_panorama(const Ref<Texture2D> &p_panorama); - Ref<Texture2D> get_panorama() const; - - PanoramaSky(); - ~PanoramaSky(); -}; - -class ProceduralSky : public Sky { - GDCLASS(ProceduralSky, Sky); - -public: - enum TextureSize { - TEXTURE_SIZE_256, - TEXTURE_SIZE_512, - TEXTURE_SIZE_1024, - TEXTURE_SIZE_2048, - TEXTURE_SIZE_4096, - TEXTURE_SIZE_MAX - }; - -private: - Thread *sky_thread; - 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 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(); - - Ref<Image> _generate_sky(); - 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; - - ProceduralSky(bool p_desaturate = false); - ~ProceduralSky(); -}; - -VARIANT_ENUM_CAST(ProceduralSky::TextureSize) - #endif // SKY_H diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index 8c2b339015..5d8ceacbf2 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -30,162 +30,597 @@ #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 ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { -void SkyMaterial::init_shaders() { + sky_top_color = p_sky_top; + VS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); +} -#ifndef NO_THREADS - material_mutex = Mutex::create(); -#endif +Color ProceduralSkyMaterial::get_sky_top_color() const { - dirty_materials = memnew(SelfList<SkyMaterial>::List); + return sky_top_color; +} - shader_names = memnew(ShaderNames); +void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { - shader_names->placeholder = "placeholder"; + sky_horizon_color = p_sky_horizon; + VS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear()); } +Color ProceduralSkyMaterial::get_sky_horizon_color() const { -void SkyMaterial::finish_shaders() { + return sky_horizon_color; +} -#ifndef NO_THREADS - memdelete(material_mutex); -#endif +void ProceduralSkyMaterial::set_sky_curve(float p_curve) { - memdelete(dirty_materials); - dirty_materials = NULL; + sky_curve = p_curve; + VS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve); +} +float ProceduralSkyMaterial::get_sky_curve() const { - memdelete(shader_names); + return sky_curve; } -void SkyMaterial::_update_shader() { +void ProceduralSkyMaterial::set_sky_energy(float p_energy) { - dirty_materials->remove(&element); + sky_energy = p_energy; + VS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy); +} +float ProceduralSkyMaterial::get_sky_energy() const { + + return sky_energy; +} - MaterialKey mk = _compute_key(); - if (mk.key == current_key.key) - return; //no update required in the end +void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { - 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); - } - } + ground_bottom_color = p_ground_bottom; + VS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear()); +} +Color ProceduralSkyMaterial::get_ground_bottom_color() const { - current_key = mk; + return ground_bottom_color; +} - if (shader_map.has(mk)) { +void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); - shader_map[mk].users++; - return; - } + ground_horizon_color = p_ground_horizon; + VS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear()); +} +Color ProceduralSkyMaterial::get_ground_horizon_color() const { - //must create a shader! + return ground_horizon_color; +} - String code = "shader_type sky;\n"; +void ProceduralSkyMaterial::set_ground_curve(float p_curve) { - ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); - shader_data.users = 1; + ground_curve = p_curve; + VS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve); +} +float ProceduralSkyMaterial::get_ground_curve() const { - VS::get_singleton()->shader_set_code(shader_data.shader, code); + return ground_curve; +} - shader_map[mk] = shader_data; +void ProceduralSkyMaterial::set_ground_energy(float p_energy) { - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + ground_energy = p_energy; + VS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy); } +float ProceduralSkyMaterial::get_ground_energy() const { -void SkyMaterial::flush_changes() { + return ground_energy; +} - if (material_mutex) - material_mutex->lock(); +void ProceduralSkyMaterial::set_sun_angle_min(float p_angle) { - while (dirty_materials->first()) { + sun_angle_min = p_angle; + VS::get_singleton()->material_set_param(_get_material(), "sun_angle_min", Math::deg2rad(sun_angle_min)); +} +float ProceduralSkyMaterial::get_sun_angle_min() const { - dirty_materials->first()->self()->_update_shader(); - } + return sun_angle_min; +} - if (material_mutex) - material_mutex->unlock(); +void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { + + sun_angle_max = p_angle; + VS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); +} +float ProceduralSkyMaterial::get_sun_angle_max() const { + + return sun_angle_max; } -void SkyMaterial::_queue_shader_change() { +void ProceduralSkyMaterial::set_sun_curve(float p_curve) { - if (material_mutex) - material_mutex->lock(); + sun_curve = p_curve; + VS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve); +} +float ProceduralSkyMaterial::get_sun_curve() const { - if (!element.in_list()) { - dirty_materials->add(&element); - } + return sun_curve; +} - if (material_mutex) - material_mutex->unlock(); +bool ProceduralSkyMaterial::_can_do_next_pass() const { + return false; } -bool SkyMaterial::_is_shader_dirty() const { +Shader::Mode ProceduralSkyMaterial::get_shader_mode() const { + + return Shader::MODE_SKY; +} + +RID ProceduralSkyMaterial::get_shader_rid() const { + + return shader; +} + +void ProceduralSkyMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color); + ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color); + + ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSkyMaterial::set_sky_horizon_color); + ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSkyMaterial::get_sky_horizon_color); + + ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve); + ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve); - bool dirty = false; + ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy); + ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy); - if (material_mutex) - material_mutex->lock(); + ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color); + ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color); - dirty = element.in_list(); + ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSkyMaterial::set_ground_horizon_color); + ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSkyMaterial::get_ground_horizon_color); - if (material_mutex) - material_mutex->unlock(); + ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve); + ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve); - return dirty; + ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSkyMaterial::set_ground_energy); + ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSkyMaterial::get_ground_energy); + + ClassDB::bind_method(D_METHOD("set_sun_angle_min", "degrees"), &ProceduralSkyMaterial::set_sun_angle_min); + ClassDB::bind_method(D_METHOD("get_sun_angle_min"), &ProceduralSkyMaterial::get_sun_angle_min); + + ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max); + ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max); + + ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSkyMaterial::set_sun_curve); + ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSkyMaterial::get_sun_curve); + + 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::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "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::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy"); + + ADD_GROUP("Sun", "sun_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_min", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_min", "get_sun_angle_min"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve"); } +ProceduralSkyMaterial::ProceduralSkyMaterial() { + + String code = "shader_type sky;\n\n"; + + code += "uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);\n"; + code += "uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0);\n"; + code += "uniform float sky_curve : hint_range(0, 1) = 0.09;\n"; + code += "uniform float sky_energy = 1.0;\n\n"; + code += "uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0);\n"; + code += "uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0);\n"; + code += "uniform float ground_curve : hint_range(0, 1) = 0.02;\n"; + code += "uniform float ground_energy = 1.0;\n\n"; + code += "uniform float sun_angle_min = 0.01;\n"; + code += "uniform float sun_angle_max = 1.0;\n"; + code += "uniform float sun_curve : hint_range(0, 1) = 0.05;\n\n"; + code += "const float PI = 3.1415926535897932384626433833;\n\n"; + code += "void fragment() {\n"; + code += "\tfloat v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));\n"; + code += "\tfloat c = (1.0 - v_angle / (PI * 0.5));\n"; + code += "\tvec3 sky = mix(sky_horizon_color.rgb, sky_top_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / sky_curve), 0.0, 1.0));\n"; + code += "\tsky *= sky_energy;\n"; + code += "\tif (LIGHT0_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < sun_angle_min) {\n"; + code += "\t\t\tsky = LIGHT0_COLOR * LIGHT0_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n"; + code += "\t\t\tsky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tif (LIGHT1_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < sun_angle_min) {\n"; + code += "\t\t\tsky = LIGHT1_COLOR * LIGHT1_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n"; + code += "\t\t\tsky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tif (LIGHT2_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < sun_angle_min) {\n"; + code += "\t\t\tsky = LIGHT2_COLOR * LIGHT2_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n"; + code += "\t\t\tsky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tif (LIGHT3_ENABLED) {\n"; + code += "\t\tfloat sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));\n"; + code += "\t\tif (sun_angle < sun_angle_min) {\n"; + code += "\t\t\tsky = LIGHT3_COLOR * LIGHT3_ENERGY;\n"; + code += "\t\t} else if (sun_angle < sun_angle_max) {\n"; + code += "\t\t\tfloat c2 = (sun_angle - sun_angle_min) / (sun_angle_max - sun_angle_min);\n"; + code += "\t\t\tsky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));\n"; + code += "\t\t}\n"; + code += "\t}\n"; + code += "\tc = (v_angle - (PI * 0.5)) / (PI * 0.5);\n"; + code += "\tvec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));\n"; + code += "\tground *= ground_energy;\n"; + code += "\tCOLOR = mix(ground, sky, step(0.0, EYEDIR.y));\n"; + code += "}\n"; + + shader = VS::get_singleton()->shader_create(); + + VS::get_singleton()->shader_set_code(shader, code); + + VS::get_singleton()->material_set_shader(_get_material(), shader); + + 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); + set_sky_energy(1.0); + + set_ground_bottom_color(Color(0.12, 0.12, 0.13)); + set_ground_horizon_color(Color(0.37, 0.33, 0.31)); + set_ground_curve(0.02); + set_ground_energy(1.0); + + set_sun_angle_min(1.0); + set_sun_angle_max(100.0); + set_sun_curve(0.05); +} -RID SkyMaterial::get_shader_rid() const { +ProceduralSkyMaterial::~ProceduralSkyMaterial() { +} - ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); - return shader_map[current_key].shader; +///////////////////////////////////////// +/* PanoramaSkyMaterial */ + +void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) { + + panorama = p_panorama; + VS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama); } -void SkyMaterial::_validate_property(PropertyInfo &property) const { +Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const { + + return panorama; +} +bool PanoramaSkyMaterial::_can_do_next_pass() const { + return false; } -Shader::Mode SkyMaterial::get_shader_mode() const { +Shader::Mode PanoramaSkyMaterial::get_shader_mode() const { return Shader::MODE_SKY; } -void SkyMaterial::_bind_methods() { +RID PanoramaSkyMaterial::get_shader_rid() const { + + return shader; +} + +void PanoramaSkyMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama); + ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama"); +} + +PanoramaSkyMaterial::PanoramaSkyMaterial() { + String code = "shader_type sky;\n\n"; + + code += "uniform sampler2D source_panorama : filter_linear;\n"; + code += "void fragment() {\n"; + code += "\tCOLOR = texture(source_panorama, SKY_COORDS).rgb;\n"; + code += "}"; + + shader = VS::get_singleton()->shader_create(); + + VS::get_singleton()->shader_set_code(shader, code); + + VS::get_singleton()->material_set_shader(_get_material(), shader); +} + +PanoramaSkyMaterial::~PanoramaSkyMaterial() { + VS::get_singleton()->free(shader); + VS::get_singleton()->material_set_shader(_get_material(), RID()); +} +////////////////////////////////// +/* PhysicalSkyMaterial */ + +void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) { + + rayleigh = p_rayleigh; + VS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh); +} +float PhysicalSkyMaterial::get_rayleigh_coefficient() const { + + return rayleigh; +} + +void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) { + + rayleigh_color = p_rayleigh_color; + VS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color); +} +Color PhysicalSkyMaterial::get_rayleigh_color() const { + + return rayleigh_color; +} + +void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) { + + mie = p_mie; + VS::get_singleton()->material_set_param(_get_material(), "mie", mie); +} +float PhysicalSkyMaterial::get_mie_coefficient() const { + + return mie; +} + +void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) { + mie_eccentricity = p_eccentricity; + VS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity); } +float PhysicalSkyMaterial::get_mie_eccentricity() const { -SkyMaterial::SkyMaterial() : - element(this) { + return mie_eccentricity; +} +void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) { - _queue_shader_change(); + mie_color = p_mie_color; + VS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color); +} +Color PhysicalSkyMaterial::get_mie_color() const { + return mie_color; } -SkyMaterial::~SkyMaterial() { +void PhysicalSkyMaterial::set_turbidity(float p_turbidity) { - if (material_mutex) - material_mutex->lock(); + turbidity = p_turbidity; + VS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity); +} +float PhysicalSkyMaterial::get_turbidity() const { - 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); - } + return turbidity; +} + +void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) { + + sun_disk_scale = p_sun_disk_scale; + VS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale); +} +float PhysicalSkyMaterial::get_sun_disk_scale() const { + + return sun_disk_scale; +} + +void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) { + + ground_color = p_ground_color; + VS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color); +} +Color PhysicalSkyMaterial::get_ground_color() const { + + return ground_color; +} + +void PhysicalSkyMaterial::set_exposure(float p_exposure) { + + exposure = p_exposure; + VS::get_singleton()->material_set_param(_get_material(), "exposure", exposure); +} +float PhysicalSkyMaterial::get_exposure() const { + + return exposure; +} - VS::get_singleton()->material_set_shader(_get_material(), RID()); - } +void PhysicalSkyMaterial::set_dither_strength(float p_dither_strength) { + + dither_strength = p_dither_strength; + VS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength); +} +float PhysicalSkyMaterial::get_dither_strength() const { + + return dither_strength; +} + +bool PhysicalSkyMaterial::_can_do_next_pass() const { + return false; +} + +Shader::Mode PhysicalSkyMaterial::get_shader_mode() const { + + return Shader::MODE_SKY; +} + +RID PhysicalSkyMaterial::get_shader_rid() const { + + return 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); + + ClassDB::bind_method(D_METHOD("set_rayleigh_color", "color"), &PhysicalSkyMaterial::set_rayleigh_color); + ClassDB::bind_method(D_METHOD("get_rayleigh_color"), &PhysicalSkyMaterial::get_rayleigh_color); + + ClassDB::bind_method(D_METHOD("set_mie_coefficient", "mie"), &PhysicalSkyMaterial::set_mie_coefficient); + ClassDB::bind_method(D_METHOD("get_mie_coefficient"), &PhysicalSkyMaterial::get_mie_coefficient); + + ClassDB::bind_method(D_METHOD("set_mie_eccentricity", "eccentricity"), &PhysicalSkyMaterial::set_mie_eccentricity); + ClassDB::bind_method(D_METHOD("get_mie_eccentricity"), &PhysicalSkyMaterial::get_mie_eccentricity); + + ClassDB::bind_method(D_METHOD("set_mie_color", "color"), &PhysicalSkyMaterial::set_mie_color); + ClassDB::bind_method(D_METHOD("get_mie_color"), &PhysicalSkyMaterial::get_mie_color); + + ClassDB::bind_method(D_METHOD("set_turbidity", "turbidity"), &PhysicalSkyMaterial::set_turbidity); + ClassDB::bind_method(D_METHOD("get_turbidity"), &PhysicalSkyMaterial::get_turbidity); + + ClassDB::bind_method(D_METHOD("set_sun_disk_scale", "scale"), &PhysicalSkyMaterial::set_sun_disk_scale); + ClassDB::bind_method(D_METHOD("get_sun_disk_scale"), &PhysicalSkyMaterial::get_sun_disk_scale); + + ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color); + ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color); + + ClassDB::bind_method(D_METHOD("set_exposure", "exposure"), &PhysicalSkyMaterial::set_exposure); + ClassDB::bind_method(D_METHOD("get_exposure"), &PhysicalSkyMaterial::get_exposure); + + ClassDB::bind_method(D_METHOD("set_dither_strength", "strength"), &PhysicalSkyMaterial::set_dither_strength); + ClassDB::bind_method(D_METHOD("get_dither_strength"), &PhysicalSkyMaterial::get_dither_strength); + + ADD_GROUP("Rayleigh", "rayleigh_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_rayleigh_coefficient", "get_rayleigh_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color"), "set_rayleigh_color", "get_rayleigh_color"); + + ADD_GROUP("Mie", "mie_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_coefficient", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_mie_coefficient", "get_mie_coefficient"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_eccentricity", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_mie_eccentricity", "get_mie_eccentricity"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "mie_color"), "set_mie_color", "get_mie_color"); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color"), "set_ground_color", "get_ground_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dither_strength", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_dither_strength", "get_dither_strength"); +} + +PhysicalSkyMaterial::PhysicalSkyMaterial() { + String code = "shader_type sky;\n\n"; + + code += "uniform float rayleigh : hint_range(0, 64) = 2.0;\n"; + code += "uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0);\n"; + code += "uniform float mie : hint_range(0, 1) = 0.005;\n"; + code += "uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;\n"; + code += "uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0);\n\n"; + + code += "uniform float turbidity : hint_range(0, 1000) = 10.0;\n"; + code += "uniform float sun_disk_scale : hint_range(0, 360) = 1.0;\n"; + code += "uniform vec4 ground_color : hint_color = vec4(1.0);\n"; + code += "uniform float exposure : hint_range(0, 128) = 0.1;\n"; + code += "uniform float dither_strength : hint_range(0, 10) = 1.0;\n\n"; + + code += "const float PI = 3.141592653589793238462643383279502884197169;\n"; + code += "const vec3 UP = vec3( 0.0, 1.0, 0.0 );\n\n"; + + code += "// Sun constants\n"; + code += "const float SOL_SIZE = 0.00872663806;\n"; + code += "const float SUN_ENERGY = 1000.0;\n\n"; + + code += "// optical length at zenith for molecules\n"; + code += "const float rayleigh_zenith_size = 8.4e3;\n"; + code += "const float mie_zenith_size = 1.25e3;\n\n"; + + code += "float henyey_greenstein(float cos_theta, float g) {\n"; + code += "\tconst float k = 0.0795774715459;\n"; + code += "\treturn k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));\n"; + code += "}\n\n"; + + code += "// From: https://www.shadertoy.com/view/4sfGzS credit to iq\n"; + code += "float hash(vec3 p) {\n"; + code += "\tp = fract( p * 0.3183099 + 0.1 );\n"; + code += "\tp *= 17.0;\n"; + code += "\treturn fract(p.x * p.y * p.z * (p.x + p.y + p.z));\n"; + code += "}\n\n"; + + code += "void fragment() {\n"; + code += "\tfloat zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );\n"; + code += "\tfloat sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;\n"; + code += "\tfloat sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);\n\n"; + + code += "\t// rayleigh coefficients\n"; + code += "\tfloat rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );\n"; + code += "\tvec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;\n"; + code += "\t// mie coefficients from Preetham\n"; + code += "\tvec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;\n\n"; + + code += "\t// optical length\n"; + code += "\tfloat zenith = acos(max(0.0, dot(UP, EYEDIR)));\n"; + code += "\tfloat optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));\n"; + code += "\tfloat rayleigh_scatter = rayleigh_zenith_size * optical_mass;\n"; + code += "\tfloat mie_scatter = mie_zenith_size * optical_mass;\n\n"; + + code += "\t// light extinction based on thickness of atmosphere\n"; + code += "\tvec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));\n\n"; + + code += "\t// in scattering\n"; + code += "\tfloat cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));\n\n"; + + code += "\tfloat rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));\n"; + code += "\tvec3 betaRTheta = rayleigh_beta * rayleigh_phase;\n\n"; + + code += "\tfloat mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);\n"; + code += "\tvec3 betaMTheta = mie_beta * mie_phase;\n\n"; + + code += "\tvec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));\n"; + code += "\t// Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js\n"; + code += "\tLin *= mix(vec3(1.0), pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * extinction, vec3(0.5)), clamp(pow(1.0 - zenith_angle, 5.0), 0.0, 1.0));\n\n"; + + code += "\t// Hack in the ground color\n"; + code += "\tLin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));\n\n"; + + code += "\t// Solar disk and out-scattering\n"; + code += "\tfloat sunAngularDiameterCos = cos(SOL_SIZE * sun_disk_scale);\n"; + code += "\tfloat sunAngularDiameterCos2 = cos(SOL_SIZE * sun_disk_scale*0.5);\n"; + code += "\tfloat sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);\n"; + code += "\tvec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;\n"; + code += "\t// Note: Add nightime here: L0 += night_sky * extinction\n\n"; + + code += "\tvec3 color = (Lin + L0) * 0.04;\n"; + code += "\tCOLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));\n"; + code += "\tCOLOR *= exposure;\n"; + code += "\t// Make optional, eliminates banding\n"; + code += "\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.008 * dither_strength;\n"; + code += "}\n"; + + shader = VS::get_singleton()->shader_create(); + + VS::get_singleton()->shader_set_code(shader, code); + + VS::get_singleton()->material_set_shader(_get_material(), shader); + + set_rayleigh_coefficient(2.0); + set_rayleigh_color(Color(0.056, 0.14, 0.3)); + set_mie_coefficient(0.005); + set_mie_eccentricity(0.8); + set_mie_color(Color(0.36, 0.56, 0.82)); + set_turbidity(10.0); + set_sun_disk_scale(1.0); + set_ground_color(Color(1.0, 1.0, 1.0)); + set_exposure(0.1); + set_dither_strength(1.0); +} - if (material_mutex) - material_mutex->unlock(); +PhysicalSkyMaterial::~PhysicalSkyMaterial() { + VS::get_singleton()->free(shader); + VS::get_singleton()->material_set_shader(_get_material(), RID()); } diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h index 5c8cddb10e..2d0a62e0f6 100644 --- a/scene/resources/sky_material.h +++ b/scene/resources/sky_material.h @@ -34,98 +34,157 @@ #ifndef SKY_MATERIAL_H #define SKY_MATERIAL_H -class SkyMaterial : public Material { +class ProceduralSkyMaterial : public Material { - GDCLASS(SkyMaterial, Material); + GDCLASS(ProceduralSkyMaterial, Material); + +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; + + float sun_angle_min; + float sun_angle_max; + float sun_curve; + + RID shader; + +protected: + static void _bind_methods(); + virtual bool _can_do_next_pass() const; 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_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; + + virtual Shader::Mode get_shader_mode() const; + RID get_shader_rid() const; + + ProceduralSkyMaterial(); + ~ProceduralSkyMaterial(); +}; + +////////////////////////////////////////////////////// +/* PanoramaSkyMaterial */ + +class PanoramaSkyMaterial : public Material { + GDCLASS(PanoramaSkyMaterial, Material); 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; + Ref<Texture2D> panorama; + RID shader; protected: static void _bind_methods(); - virtual void _validate_property(PropertyInfo &property) const; + virtual bool _can_do_next_pass() const; public: - static void init_shaders(); - static void finish_shaders(); - static void flush_changes(); + void set_panorama(const Ref<Texture2D> &p_panorama); + Ref<Texture2D> get_panorama() const; + virtual Shader::Mode get_shader_mode() const; RID get_shader_rid() const; + PanoramaSkyMaterial(); + ~PanoramaSkyMaterial(); +}; + +////////////////////////////////////////////////////// +/* PanoramaSkyMaterial */ + +class PhysicalSkyMaterial : public Material { + GDCLASS(PhysicalSkyMaterial, Material); + +private: + RID shader; + + float rayleigh; + Color rayleigh_color; + float mie; + float mie_eccentricity; + Color mie_color; + float turbidity; + float sun_disk_scale; + Color ground_color; + float exposure; + float dither_strength; + +protected: + static void _bind_methods(); + virtual bool _can_do_next_pass() const; + +public: + void set_rayleigh_coefficient(float p_rayleigh); + float get_rayleigh_coefficient() const; + + void set_rayleigh_color(Color p_rayleigh_color); + Color get_rayleigh_color() const; + + void set_turbidity(float p_turbidity); + float get_turbidity() const; + + void set_mie_coefficient(float p_mie); + float get_mie_coefficient() const; + + void set_mie_eccentricity(float p_eccentricity); + float get_mie_eccentricity() const; + + void set_mie_color(Color p_mie_color); + Color get_mie_color() const; + + void set_sun_disk_scale(float p_sun_disk_scale); + float get_sun_disk_scale() const; + + void set_ground_color(Color p_ground_color); + Color get_ground_color() const; + + void set_exposure(float p_exposure); + float get_exposure() const; + + void set_dither_strength(float p_dither_strength); + float get_dither_strength() const; + virtual Shader::Mode get_shader_mode() const; + RID get_shader_rid() const; - SkyMaterial(); - ~SkyMaterial(); + PhysicalSkyMaterial(); + ~PhysicalSkyMaterial(); }; #endif /* !SKY_MATERIAL_H */ |