| 1 | /**************************************************************************/ |
| 2 | /* sky_material.cpp */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #include "sky_material.h" |
| 32 | |
| 33 | #include "core/config/project_settings.h" |
| 34 | #include "core/version.h" |
| 35 | |
| 36 | Mutex ProceduralSkyMaterial::shader_mutex; |
| 37 | RID ProceduralSkyMaterial::shader_cache[2]; |
| 38 | |
| 39 | void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { |
| 40 | sky_top_color = p_sky_top; |
| 41 | RS::get_singleton()->material_set_param(_get_material(), "sky_top_color" , sky_top_color); |
| 42 | } |
| 43 | |
| 44 | Color ProceduralSkyMaterial::get_sky_top_color() const { |
| 45 | return sky_top_color; |
| 46 | } |
| 47 | |
| 48 | void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { |
| 49 | sky_horizon_color = p_sky_horizon; |
| 50 | RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color" , sky_horizon_color); |
| 51 | } |
| 52 | |
| 53 | Color ProceduralSkyMaterial::get_sky_horizon_color() const { |
| 54 | return sky_horizon_color; |
| 55 | } |
| 56 | |
| 57 | void ProceduralSkyMaterial::set_sky_curve(float p_curve) { |
| 58 | sky_curve = p_curve; |
| 59 | RS::get_singleton()->material_set_param(_get_material(), "sky_curve" , sky_curve); |
| 60 | } |
| 61 | |
| 62 | float ProceduralSkyMaterial::get_sky_curve() const { |
| 63 | return sky_curve; |
| 64 | } |
| 65 | |
| 66 | void ProceduralSkyMaterial::set_sky_energy_multiplier(float p_multiplier) { |
| 67 | sky_energy_multiplier = p_multiplier; |
| 68 | RS::get_singleton()->material_set_param(_get_material(), "sky_energy" , sky_energy_multiplier); |
| 69 | } |
| 70 | |
| 71 | float ProceduralSkyMaterial::get_sky_energy_multiplier() const { |
| 72 | return sky_energy_multiplier; |
| 73 | } |
| 74 | |
| 75 | void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) { |
| 76 | sky_cover = p_sky_cover; |
| 77 | if (p_sky_cover.is_valid()) { |
| 78 | RS::get_singleton()->material_set_param(_get_material(), "sky_cover" , p_sky_cover->get_rid()); |
| 79 | } else { |
| 80 | RS::get_singleton()->material_set_param(_get_material(), "sky_cover" , Variant()); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const { |
| 85 | return sky_cover; |
| 86 | } |
| 87 | |
| 88 | void ProceduralSkyMaterial::set_sky_cover_modulate(const Color &p_sky_cover_modulate) { |
| 89 | sky_cover_modulate = p_sky_cover_modulate; |
| 90 | RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate" , sky_cover_modulate); |
| 91 | } |
| 92 | |
| 93 | Color ProceduralSkyMaterial::get_sky_cover_modulate() const { |
| 94 | return sky_cover_modulate; |
| 95 | } |
| 96 | |
| 97 | void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { |
| 98 | ground_bottom_color = p_ground_bottom; |
| 99 | RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color" , ground_bottom_color); |
| 100 | } |
| 101 | |
| 102 | Color ProceduralSkyMaterial::get_ground_bottom_color() const { |
| 103 | return ground_bottom_color; |
| 104 | } |
| 105 | |
| 106 | void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { |
| 107 | ground_horizon_color = p_ground_horizon; |
| 108 | RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color" , ground_horizon_color); |
| 109 | } |
| 110 | |
| 111 | Color ProceduralSkyMaterial::get_ground_horizon_color() const { |
| 112 | return ground_horizon_color; |
| 113 | } |
| 114 | |
| 115 | void ProceduralSkyMaterial::set_ground_curve(float p_curve) { |
| 116 | ground_curve = p_curve; |
| 117 | RS::get_singleton()->material_set_param(_get_material(), "ground_curve" , ground_curve); |
| 118 | } |
| 119 | |
| 120 | float ProceduralSkyMaterial::get_ground_curve() const { |
| 121 | return ground_curve; |
| 122 | } |
| 123 | |
| 124 | void ProceduralSkyMaterial::set_ground_energy_multiplier(float p_multiplier) { |
| 125 | ground_energy_multiplier = p_multiplier; |
| 126 | RS::get_singleton()->material_set_param(_get_material(), "ground_energy" , ground_energy_multiplier); |
| 127 | } |
| 128 | |
| 129 | float ProceduralSkyMaterial::get_ground_energy_multiplier() const { |
| 130 | return ground_energy_multiplier; |
| 131 | } |
| 132 | |
| 133 | void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { |
| 134 | sun_angle_max = p_angle; |
| 135 | RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max" , Math::deg_to_rad(sun_angle_max)); |
| 136 | } |
| 137 | |
| 138 | float ProceduralSkyMaterial::get_sun_angle_max() const { |
| 139 | return sun_angle_max; |
| 140 | } |
| 141 | |
| 142 | void ProceduralSkyMaterial::set_sun_curve(float p_curve) { |
| 143 | sun_curve = p_curve; |
| 144 | RS::get_singleton()->material_set_param(_get_material(), "sun_curve" , sun_curve); |
| 145 | } |
| 146 | |
| 147 | float ProceduralSkyMaterial::get_sun_curve() const { |
| 148 | return sun_curve; |
| 149 | } |
| 150 | |
| 151 | void ProceduralSkyMaterial::set_use_debanding(bool p_use_debanding) { |
| 152 | use_debanding = p_use_debanding; |
| 153 | _update_shader(); |
| 154 | // Only set if shader already compiled |
| 155 | if (shader_set) { |
| 156 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | bool ProceduralSkyMaterial::get_use_debanding() const { |
| 161 | return use_debanding; |
| 162 | } |
| 163 | |
| 164 | Shader::Mode ProceduralSkyMaterial::get_shader_mode() const { |
| 165 | return Shader::MODE_SKY; |
| 166 | } |
| 167 | |
| 168 | RID ProceduralSkyMaterial::get_rid() const { |
| 169 | _update_shader(); |
| 170 | if (!shader_set) { |
| 171 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]); |
| 172 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); |
| 173 | shader_set = true; |
| 174 | } |
| 175 | return _get_material(); |
| 176 | } |
| 177 | |
| 178 | RID ProceduralSkyMaterial::get_shader_rid() const { |
| 179 | _update_shader(); |
| 180 | return shader_cache[int(use_debanding)]; |
| 181 | } |
| 182 | |
| 183 | void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const { |
| 184 | if ((p_property.name == "sky_luminance" || p_property.name == "ground_luminance" ) && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units" )) { |
| 185 | p_property.usage = PROPERTY_USAGE_NO_EDITOR; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | void ProceduralSkyMaterial::_bind_methods() { |
| 190 | ClassDB::bind_method(D_METHOD("set_sky_top_color" , "color" ), &ProceduralSkyMaterial::set_sky_top_color); |
| 191 | ClassDB::bind_method(D_METHOD("get_sky_top_color" ), &ProceduralSkyMaterial::get_sky_top_color); |
| 192 | |
| 193 | ClassDB::bind_method(D_METHOD("set_sky_horizon_color" , "color" ), &ProceduralSkyMaterial::set_sky_horizon_color); |
| 194 | ClassDB::bind_method(D_METHOD("get_sky_horizon_color" ), &ProceduralSkyMaterial::get_sky_horizon_color); |
| 195 | |
| 196 | ClassDB::bind_method(D_METHOD("set_sky_curve" , "curve" ), &ProceduralSkyMaterial::set_sky_curve); |
| 197 | ClassDB::bind_method(D_METHOD("get_sky_curve" ), &ProceduralSkyMaterial::get_sky_curve); |
| 198 | |
| 199 | ClassDB::bind_method(D_METHOD("set_sky_energy_multiplier" , "multiplier" ), &ProceduralSkyMaterial::set_sky_energy_multiplier); |
| 200 | ClassDB::bind_method(D_METHOD("get_sky_energy_multiplier" ), &ProceduralSkyMaterial::get_sky_energy_multiplier); |
| 201 | |
| 202 | ClassDB::bind_method(D_METHOD("set_sky_cover" , "sky_cover" ), &ProceduralSkyMaterial::set_sky_cover); |
| 203 | ClassDB::bind_method(D_METHOD("get_sky_cover" ), &ProceduralSkyMaterial::get_sky_cover); |
| 204 | |
| 205 | ClassDB::bind_method(D_METHOD("set_sky_cover_modulate" , "color" ), &ProceduralSkyMaterial::set_sky_cover_modulate); |
| 206 | ClassDB::bind_method(D_METHOD("get_sky_cover_modulate" ), &ProceduralSkyMaterial::get_sky_cover_modulate); |
| 207 | |
| 208 | ClassDB::bind_method(D_METHOD("set_ground_bottom_color" , "color" ), &ProceduralSkyMaterial::set_ground_bottom_color); |
| 209 | ClassDB::bind_method(D_METHOD("get_ground_bottom_color" ), &ProceduralSkyMaterial::get_ground_bottom_color); |
| 210 | |
| 211 | ClassDB::bind_method(D_METHOD("set_ground_horizon_color" , "color" ), &ProceduralSkyMaterial::set_ground_horizon_color); |
| 212 | ClassDB::bind_method(D_METHOD("get_ground_horizon_color" ), &ProceduralSkyMaterial::get_ground_horizon_color); |
| 213 | |
| 214 | ClassDB::bind_method(D_METHOD("set_ground_curve" , "curve" ), &ProceduralSkyMaterial::set_ground_curve); |
| 215 | ClassDB::bind_method(D_METHOD("get_ground_curve" ), &ProceduralSkyMaterial::get_ground_curve); |
| 216 | |
| 217 | ClassDB::bind_method(D_METHOD("set_ground_energy_multiplier" , "energy" ), &ProceduralSkyMaterial::set_ground_energy_multiplier); |
| 218 | ClassDB::bind_method(D_METHOD("get_ground_energy_multiplier" ), &ProceduralSkyMaterial::get_ground_energy_multiplier); |
| 219 | |
| 220 | ClassDB::bind_method(D_METHOD("set_sun_angle_max" , "degrees" ), &ProceduralSkyMaterial::set_sun_angle_max); |
| 221 | ClassDB::bind_method(D_METHOD("get_sun_angle_max" ), &ProceduralSkyMaterial::get_sun_angle_max); |
| 222 | |
| 223 | ClassDB::bind_method(D_METHOD("set_sun_curve" , "curve" ), &ProceduralSkyMaterial::set_sun_curve); |
| 224 | ClassDB::bind_method(D_METHOD("get_sun_curve" ), &ProceduralSkyMaterial::get_sun_curve); |
| 225 | |
| 226 | ClassDB::bind_method(D_METHOD("set_use_debanding" , "use_debanding" ), &ProceduralSkyMaterial::set_use_debanding); |
| 227 | ClassDB::bind_method(D_METHOD("get_use_debanding" ), &ProceduralSkyMaterial::get_use_debanding); |
| 228 | |
| 229 | ADD_GROUP("Sky" , "sky_" ); |
| 230 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_top_color" , "get_sky_top_color" ); |
| 231 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color" , "get_sky_horizon_color" ); |
| 232 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve" , PROPERTY_HINT_EXP_EASING), "set_sky_curve" , "get_sky_curve" ); |
| 233 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy_multiplier" , PROPERTY_HINT_RANGE, "0,64,0.01" ), "set_sky_energy_multiplier" , "get_sky_energy_multiplier" ); |
| 234 | ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover" , PROPERTY_HINT_RESOURCE_TYPE, "Texture2D" ), "set_sky_cover" , "get_sky_cover" ); |
| 235 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate" ), "set_sky_cover_modulate" , "get_sky_cover_modulate" ); |
| 236 | |
| 237 | ADD_GROUP("Ground" , "ground_" ); |
| 238 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color" , "get_ground_bottom_color" ); |
| 239 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_horizon_color" , "get_ground_horizon_color" ); |
| 240 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve" , PROPERTY_HINT_EXP_EASING), "set_ground_curve" , "get_ground_curve" ); |
| 241 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy_multiplier" , PROPERTY_HINT_RANGE, "0,64,0.01" ), "set_ground_energy_multiplier" , "get_ground_energy_multiplier" ); |
| 242 | |
| 243 | ADD_GROUP("Sun" , "sun_" ); |
| 244 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max" , PROPERTY_HINT_RANGE, "0,360,0.01,degrees" ), "set_sun_angle_max" , "get_sun_angle_max" ); |
| 245 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve" , PROPERTY_HINT_EXP_EASING), "set_sun_curve" , "get_sun_curve" ); |
| 246 | |
| 247 | ADD_GROUP("" , "" ); |
| 248 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding" ), "set_use_debanding" , "get_use_debanding" ); |
| 249 | } |
| 250 | |
| 251 | void ProceduralSkyMaterial::cleanup_shader() { |
| 252 | if (shader_cache[0].is_valid()) { |
| 253 | RS::get_singleton()->free(shader_cache[0]); |
| 254 | RS::get_singleton()->free(shader_cache[1]); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | void ProceduralSkyMaterial::_update_shader() { |
| 259 | shader_mutex.lock(); |
| 260 | if (shader_cache[0].is_null()) { |
| 261 | for (int i = 0; i < 2; i++) { |
| 262 | shader_cache[i] = RS::get_singleton()->shader_create(); |
| 263 | |
| 264 | // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). |
| 265 | RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"( |
| 266 | // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s ProceduralSkyMaterial. |
| 267 | |
| 268 | shader_type sky; |
| 269 | %s |
| 270 | |
| 271 | uniform vec4 sky_top_color : source_color = vec4(0.385, 0.454, 0.55, 1.0); |
| 272 | uniform vec4 sky_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0); |
| 273 | uniform float sky_curve : hint_range(0, 1) = 0.15; |
| 274 | uniform float sky_energy = 1.0; // In Lux. |
| 275 | uniform sampler2D sky_cover : filter_linear, source_color, hint_default_black; |
| 276 | uniform vec4 sky_cover_modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0); |
| 277 | uniform vec4 ground_bottom_color : source_color = vec4(0.2, 0.169, 0.133, 1.0); |
| 278 | uniform vec4 ground_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0); |
| 279 | uniform float ground_curve : hint_range(0, 1) = 0.02; |
| 280 | uniform float ground_energy = 1.0; |
| 281 | uniform float sun_angle_max = 30.0; |
| 282 | uniform float sun_curve : hint_range(0, 1) = 0.15; |
| 283 | |
| 284 | void sky() { |
| 285 | float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0)); |
| 286 | float c = (1.0 - v_angle / (PI * 0.5)); |
| 287 | vec3 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)); |
| 288 | sky *= sky_energy; |
| 289 | |
| 290 | if (LIGHT0_ENABLED) { |
| 291 | float sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR)); |
| 292 | if (sun_angle < LIGHT0_SIZE) { |
| 293 | sky = LIGHT0_COLOR * LIGHT0_ENERGY; |
| 294 | } else if (sun_angle < sun_angle_max) { |
| 295 | float c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE); |
| 296 | sky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | if (LIGHT1_ENABLED) { |
| 301 | float sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR)); |
| 302 | if (sun_angle < LIGHT1_SIZE) { |
| 303 | sky = LIGHT1_COLOR * LIGHT1_ENERGY; |
| 304 | } else if (sun_angle < sun_angle_max) { |
| 305 | float c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE); |
| 306 | sky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | if (LIGHT2_ENABLED) { |
| 311 | float sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR)); |
| 312 | if (sun_angle < LIGHT2_SIZE) { |
| 313 | sky = LIGHT2_COLOR * LIGHT2_ENERGY; |
| 314 | } else if (sun_angle < sun_angle_max) { |
| 315 | float c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE); |
| 316 | sky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | if (LIGHT3_ENABLED) { |
| 321 | float sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR)); |
| 322 | if (sun_angle < LIGHT3_SIZE) { |
| 323 | sky = LIGHT3_COLOR * LIGHT3_ENERGY; |
| 324 | } else if (sun_angle < sun_angle_max) { |
| 325 | float c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE); |
| 326 | sky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0)); |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS); |
| 331 | sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a * sky_energy; |
| 332 | |
| 333 | c = (v_angle - (PI * 0.5)) / (PI * 0.5); |
| 334 | vec3 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)); |
| 335 | ground *= ground_energy; |
| 336 | |
| 337 | COLOR = mix(ground, sky, step(0.0, EYEDIR.y)); |
| 338 | } |
| 339 | )" , |
| 340 | i ? "render_mode use_debanding;" : "" )); |
| 341 | } |
| 342 | } |
| 343 | shader_mutex.unlock(); |
| 344 | } |
| 345 | |
| 346 | ProceduralSkyMaterial::ProceduralSkyMaterial() { |
| 347 | set_sky_top_color(Color(0.385, 0.454, 0.55)); |
| 348 | set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708)); |
| 349 | set_sky_curve(0.15); |
| 350 | set_sky_energy_multiplier(1.0); |
| 351 | set_sky_cover_modulate(Color(1, 1, 1)); |
| 352 | |
| 353 | set_ground_bottom_color(Color(0.2, 0.169, 0.133)); |
| 354 | set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708)); |
| 355 | set_ground_curve(0.02); |
| 356 | set_ground_energy_multiplier(1.0); |
| 357 | |
| 358 | set_sun_angle_max(30.0); |
| 359 | set_sun_curve(0.15); |
| 360 | set_use_debanding(true); |
| 361 | } |
| 362 | |
| 363 | ProceduralSkyMaterial::~ProceduralSkyMaterial() { |
| 364 | } |
| 365 | |
| 366 | ///////////////////////////////////////// |
| 367 | /* PanoramaSkyMaterial */ |
| 368 | |
| 369 | void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) { |
| 370 | panorama = p_panorama; |
| 371 | if (p_panorama.is_valid()) { |
| 372 | RS::get_singleton()->material_set_param(_get_material(), "source_panorama" , p_panorama->get_rid()); |
| 373 | } else { |
| 374 | RS::get_singleton()->material_set_param(_get_material(), "source_panorama" , Variant()); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const { |
| 379 | return panorama; |
| 380 | } |
| 381 | |
| 382 | void PanoramaSkyMaterial::set_filtering_enabled(bool p_enabled) { |
| 383 | filter = p_enabled; |
| 384 | notify_property_list_changed(); |
| 385 | _update_shader(); |
| 386 | // Only set if shader already compiled |
| 387 | if (shader_set) { |
| 388 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(filter)]); |
| 389 | } |
| 390 | } |
| 391 | |
| 392 | bool PanoramaSkyMaterial::is_filtering_enabled() const { |
| 393 | return filter; |
| 394 | } |
| 395 | |
| 396 | Shader::Mode PanoramaSkyMaterial::get_shader_mode() const { |
| 397 | return Shader::MODE_SKY; |
| 398 | } |
| 399 | |
| 400 | RID PanoramaSkyMaterial::get_rid() const { |
| 401 | _update_shader(); |
| 402 | // Don't compile shaders until first use, then compile both |
| 403 | if (!shader_set) { |
| 404 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(filter)]); |
| 405 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(filter)]); |
| 406 | shader_set = true; |
| 407 | } |
| 408 | return _get_material(); |
| 409 | } |
| 410 | |
| 411 | RID PanoramaSkyMaterial::get_shader_rid() const { |
| 412 | _update_shader(); |
| 413 | return shader_cache[int(filter)]; |
| 414 | } |
| 415 | |
| 416 | void PanoramaSkyMaterial::_bind_methods() { |
| 417 | ClassDB::bind_method(D_METHOD("set_panorama" , "texture" ), &PanoramaSkyMaterial::set_panorama); |
| 418 | ClassDB::bind_method(D_METHOD("get_panorama" ), &PanoramaSkyMaterial::get_panorama); |
| 419 | |
| 420 | ClassDB::bind_method(D_METHOD("set_filtering_enabled" , "enabled" ), &PanoramaSkyMaterial::set_filtering_enabled); |
| 421 | ClassDB::bind_method(D_METHOD("is_filtering_enabled" ), &PanoramaSkyMaterial::is_filtering_enabled); |
| 422 | |
| 423 | ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama" , PROPERTY_HINT_RESOURCE_TYPE, "Texture2D" ), "set_panorama" , "get_panorama" ); |
| 424 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter" ), "set_filtering_enabled" , "is_filtering_enabled" ); |
| 425 | } |
| 426 | |
| 427 | Mutex PanoramaSkyMaterial::shader_mutex; |
| 428 | RID PanoramaSkyMaterial::shader_cache[2]; |
| 429 | |
| 430 | void PanoramaSkyMaterial::cleanup_shader() { |
| 431 | if (shader_cache[0].is_valid()) { |
| 432 | RS::get_singleton()->free(shader_cache[0]); |
| 433 | RS::get_singleton()->free(shader_cache[1]); |
| 434 | } |
| 435 | } |
| 436 | |
| 437 | void PanoramaSkyMaterial::_update_shader() { |
| 438 | shader_mutex.lock(); |
| 439 | if (shader_cache[0].is_null()) { |
| 440 | for (int i = 0; i < 2; i++) { |
| 441 | shader_cache[i] = RS::get_singleton()->shader_create(); |
| 442 | |
| 443 | // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). |
| 444 | RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"( |
| 445 | // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PanoramaSkyMaterial. |
| 446 | |
| 447 | shader_type sky; |
| 448 | |
| 449 | uniform sampler2D source_panorama : %s, source_color, hint_default_black; |
| 450 | |
| 451 | void sky() { |
| 452 | COLOR = texture(source_panorama, SKY_COORDS).rgb; |
| 453 | } |
| 454 | )" , |
| 455 | i ? "filter_linear" : "filter_nearest" )); |
| 456 | } |
| 457 | } |
| 458 | |
| 459 | shader_mutex.unlock(); |
| 460 | } |
| 461 | |
| 462 | PanoramaSkyMaterial::PanoramaSkyMaterial() { |
| 463 | } |
| 464 | |
| 465 | PanoramaSkyMaterial::~PanoramaSkyMaterial() { |
| 466 | } |
| 467 | |
| 468 | ////////////////////////////////// |
| 469 | /* PhysicalSkyMaterial */ |
| 470 | |
| 471 | void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) { |
| 472 | rayleigh = p_rayleigh; |
| 473 | RS::get_singleton()->material_set_param(_get_material(), "rayleigh" , rayleigh); |
| 474 | } |
| 475 | |
| 476 | float PhysicalSkyMaterial::get_rayleigh_coefficient() const { |
| 477 | return rayleigh; |
| 478 | } |
| 479 | |
| 480 | void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) { |
| 481 | rayleigh_color = p_rayleigh_color; |
| 482 | RS::get_singleton()->material_set_param(_get_material(), "rayleigh_color" , rayleigh_color); |
| 483 | } |
| 484 | |
| 485 | Color PhysicalSkyMaterial::get_rayleigh_color() const { |
| 486 | return rayleigh_color; |
| 487 | } |
| 488 | |
| 489 | void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) { |
| 490 | mie = p_mie; |
| 491 | RS::get_singleton()->material_set_param(_get_material(), "mie" , mie); |
| 492 | } |
| 493 | |
| 494 | float PhysicalSkyMaterial::get_mie_coefficient() const { |
| 495 | return mie; |
| 496 | } |
| 497 | |
| 498 | void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) { |
| 499 | mie_eccentricity = p_eccentricity; |
| 500 | RS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity" , mie_eccentricity); |
| 501 | } |
| 502 | |
| 503 | float PhysicalSkyMaterial::get_mie_eccentricity() const { |
| 504 | return mie_eccentricity; |
| 505 | } |
| 506 | |
| 507 | void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) { |
| 508 | mie_color = p_mie_color; |
| 509 | RS::get_singleton()->material_set_param(_get_material(), "mie_color" , mie_color); |
| 510 | } |
| 511 | |
| 512 | Color PhysicalSkyMaterial::get_mie_color() const { |
| 513 | return mie_color; |
| 514 | } |
| 515 | |
| 516 | void PhysicalSkyMaterial::set_turbidity(float p_turbidity) { |
| 517 | turbidity = p_turbidity; |
| 518 | RS::get_singleton()->material_set_param(_get_material(), "turbidity" , turbidity); |
| 519 | } |
| 520 | |
| 521 | float PhysicalSkyMaterial::get_turbidity() const { |
| 522 | return turbidity; |
| 523 | } |
| 524 | |
| 525 | void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) { |
| 526 | sun_disk_scale = p_sun_disk_scale; |
| 527 | RS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale" , sun_disk_scale); |
| 528 | } |
| 529 | |
| 530 | float PhysicalSkyMaterial::get_sun_disk_scale() const { |
| 531 | return sun_disk_scale; |
| 532 | } |
| 533 | |
| 534 | void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) { |
| 535 | ground_color = p_ground_color; |
| 536 | RS::get_singleton()->material_set_param(_get_material(), "ground_color" , ground_color); |
| 537 | } |
| 538 | |
| 539 | Color PhysicalSkyMaterial::get_ground_color() const { |
| 540 | return ground_color; |
| 541 | } |
| 542 | |
| 543 | void PhysicalSkyMaterial::set_energy_multiplier(float p_multiplier) { |
| 544 | energy_multiplier = p_multiplier; |
| 545 | RS::get_singleton()->material_set_param(_get_material(), "exposure" , energy_multiplier); |
| 546 | } |
| 547 | |
| 548 | float PhysicalSkyMaterial::get_energy_multiplier() const { |
| 549 | return energy_multiplier; |
| 550 | } |
| 551 | |
| 552 | void PhysicalSkyMaterial::set_use_debanding(bool p_use_debanding) { |
| 553 | use_debanding = p_use_debanding; |
| 554 | _update_shader(); |
| 555 | // Only set if shader already compiled |
| 556 | if (shader_set) { |
| 557 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); |
| 558 | } |
| 559 | } |
| 560 | |
| 561 | bool PhysicalSkyMaterial::get_use_debanding() const { |
| 562 | return use_debanding; |
| 563 | } |
| 564 | |
| 565 | void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) { |
| 566 | night_sky = p_night_sky; |
| 567 | if (p_night_sky.is_valid()) { |
| 568 | RS::get_singleton()->material_set_param(_get_material(), "night_sky" , p_night_sky->get_rid()); |
| 569 | } else { |
| 570 | RS::get_singleton()->material_set_param(_get_material(), "night_sky" , Variant()); |
| 571 | } |
| 572 | } |
| 573 | |
| 574 | Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const { |
| 575 | return night_sky; |
| 576 | } |
| 577 | |
| 578 | Shader::Mode PhysicalSkyMaterial::get_shader_mode() const { |
| 579 | return Shader::MODE_SKY; |
| 580 | } |
| 581 | |
| 582 | RID PhysicalSkyMaterial::get_rid() const { |
| 583 | _update_shader(); |
| 584 | if (!shader_set) { |
| 585 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]); |
| 586 | RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]); |
| 587 | shader_set = true; |
| 588 | } |
| 589 | return _get_material(); |
| 590 | } |
| 591 | |
| 592 | RID PhysicalSkyMaterial::get_shader_rid() const { |
| 593 | _update_shader(); |
| 594 | return shader_cache[int(use_debanding)]; |
| 595 | } |
| 596 | |
| 597 | void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const { |
| 598 | if (p_property.name == "exposure_value" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units" )) { |
| 599 | p_property.usage = PROPERTY_USAGE_NO_EDITOR; |
| 600 | } |
| 601 | } |
| 602 | |
| 603 | Mutex PhysicalSkyMaterial::shader_mutex; |
| 604 | RID PhysicalSkyMaterial::shader_cache[2]; |
| 605 | |
| 606 | void PhysicalSkyMaterial::_bind_methods() { |
| 607 | ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient" , "rayleigh" ), &PhysicalSkyMaterial::set_rayleigh_coefficient); |
| 608 | ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient" ), &PhysicalSkyMaterial::get_rayleigh_coefficient); |
| 609 | |
| 610 | ClassDB::bind_method(D_METHOD("set_rayleigh_color" , "color" ), &PhysicalSkyMaterial::set_rayleigh_color); |
| 611 | ClassDB::bind_method(D_METHOD("get_rayleigh_color" ), &PhysicalSkyMaterial::get_rayleigh_color); |
| 612 | |
| 613 | ClassDB::bind_method(D_METHOD("set_mie_coefficient" , "mie" ), &PhysicalSkyMaterial::set_mie_coefficient); |
| 614 | ClassDB::bind_method(D_METHOD("get_mie_coefficient" ), &PhysicalSkyMaterial::get_mie_coefficient); |
| 615 | |
| 616 | ClassDB::bind_method(D_METHOD("set_mie_eccentricity" , "eccentricity" ), &PhysicalSkyMaterial::set_mie_eccentricity); |
| 617 | ClassDB::bind_method(D_METHOD("get_mie_eccentricity" ), &PhysicalSkyMaterial::get_mie_eccentricity); |
| 618 | |
| 619 | ClassDB::bind_method(D_METHOD("set_mie_color" , "color" ), &PhysicalSkyMaterial::set_mie_color); |
| 620 | ClassDB::bind_method(D_METHOD("get_mie_color" ), &PhysicalSkyMaterial::get_mie_color); |
| 621 | |
| 622 | ClassDB::bind_method(D_METHOD("set_turbidity" , "turbidity" ), &PhysicalSkyMaterial::set_turbidity); |
| 623 | ClassDB::bind_method(D_METHOD("get_turbidity" ), &PhysicalSkyMaterial::get_turbidity); |
| 624 | |
| 625 | ClassDB::bind_method(D_METHOD("set_sun_disk_scale" , "scale" ), &PhysicalSkyMaterial::set_sun_disk_scale); |
| 626 | ClassDB::bind_method(D_METHOD("get_sun_disk_scale" ), &PhysicalSkyMaterial::get_sun_disk_scale); |
| 627 | |
| 628 | ClassDB::bind_method(D_METHOD("set_ground_color" , "color" ), &PhysicalSkyMaterial::set_ground_color); |
| 629 | ClassDB::bind_method(D_METHOD("get_ground_color" ), &PhysicalSkyMaterial::get_ground_color); |
| 630 | |
| 631 | ClassDB::bind_method(D_METHOD("set_energy_multiplier" , "multiplier" ), &PhysicalSkyMaterial::set_energy_multiplier); |
| 632 | ClassDB::bind_method(D_METHOD("get_energy_multiplier" ), &PhysicalSkyMaterial::get_energy_multiplier); |
| 633 | |
| 634 | ClassDB::bind_method(D_METHOD("set_use_debanding" , "use_debanding" ), &PhysicalSkyMaterial::set_use_debanding); |
| 635 | ClassDB::bind_method(D_METHOD("get_use_debanding" ), &PhysicalSkyMaterial::get_use_debanding); |
| 636 | |
| 637 | ClassDB::bind_method(D_METHOD("set_night_sky" , "night_sky" ), &PhysicalSkyMaterial::set_night_sky); |
| 638 | ClassDB::bind_method(D_METHOD("get_night_sky" ), &PhysicalSkyMaterial::get_night_sky); |
| 639 | |
| 640 | ADD_GROUP("Rayleigh" , "rayleigh_" ); |
| 641 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient" , PROPERTY_HINT_RANGE, "0,64,0.01" ), "set_rayleigh_coefficient" , "get_rayleigh_coefficient" ); |
| 642 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_rayleigh_color" , "get_rayleigh_color" ); |
| 643 | |
| 644 | ADD_GROUP("Mie" , "mie_" ); |
| 645 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_coefficient" , PROPERTY_HINT_RANGE, "0,1,0.001" ), "set_mie_coefficient" , "get_mie_coefficient" ); |
| 646 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_eccentricity" , PROPERTY_HINT_RANGE, "-1,1,0.01" ), "set_mie_eccentricity" , "get_mie_eccentricity" ); |
| 647 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "mie_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_mie_color" , "get_mie_color" ); |
| 648 | |
| 649 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity" , PROPERTY_HINT_RANGE, "0,1000,0.01" ), "set_turbidity" , "get_turbidity" ); |
| 650 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale" , PROPERTY_HINT_RANGE, "0,360,0.01" ), "set_sun_disk_scale" , "get_sun_disk_scale" ); |
| 651 | ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color" , PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_color" , "get_ground_color" ); |
| 652 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy_multiplier" , PROPERTY_HINT_RANGE, "0,128,0.01" ), "set_energy_multiplier" , "get_energy_multiplier" ); |
| 653 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding" ), "set_use_debanding" , "get_use_debanding" ); |
| 654 | ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky" , PROPERTY_HINT_RESOURCE_TYPE, "Texture2D" ), "set_night_sky" , "get_night_sky" ); |
| 655 | } |
| 656 | |
| 657 | void PhysicalSkyMaterial::cleanup_shader() { |
| 658 | if (shader_cache[0].is_valid()) { |
| 659 | RS::get_singleton()->free(shader_cache[0]); |
| 660 | RS::get_singleton()->free(shader_cache[1]); |
| 661 | } |
| 662 | } |
| 663 | |
| 664 | void PhysicalSkyMaterial::_update_shader() { |
| 665 | shader_mutex.lock(); |
| 666 | if (shader_cache[0].is_null()) { |
| 667 | for (int i = 0; i < 2; i++) { |
| 668 | shader_cache[i] = RS::get_singleton()->shader_create(); |
| 669 | |
| 670 | // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). |
| 671 | RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"( |
| 672 | // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PhysicalSkyMaterial. |
| 673 | |
| 674 | shader_type sky; |
| 675 | %s |
| 676 | |
| 677 | uniform float rayleigh : hint_range(0, 64) = 2.0; |
| 678 | uniform vec4 rayleigh_color : source_color = vec4(0.3, 0.405, 0.6, 1.0); |
| 679 | uniform float mie : hint_range(0, 1) = 0.005; |
| 680 | uniform float mie_eccentricity : hint_range(-1, 1) = 0.8; |
| 681 | uniform vec4 mie_color : source_color = vec4(0.69, 0.729, 0.812, 1.0); |
| 682 | |
| 683 | uniform float turbidity : hint_range(0, 1000) = 10.0; |
| 684 | uniform float sun_disk_scale : hint_range(0, 360) = 1.0; |
| 685 | uniform vec4 ground_color : source_color = vec4(0.1, 0.07, 0.034, 1.0); |
| 686 | uniform float exposure : hint_range(0, 128) = 1.0; |
| 687 | |
| 688 | uniform sampler2D night_sky : filter_linear, source_color, hint_default_black; |
| 689 | |
| 690 | const vec3 UP = vec3( 0.0, 1.0, 0.0 ); |
| 691 | |
| 692 | // Optical length at zenith for molecules. |
| 693 | const float rayleigh_zenith_size = 8.4e3; |
| 694 | const float mie_zenith_size = 1.25e3; |
| 695 | |
| 696 | float henyey_greenstein(float cos_theta, float g) { |
| 697 | const float k = 0.0795774715459; |
| 698 | return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5)); |
| 699 | } |
| 700 | |
| 701 | void sky() { |
| 702 | if (LIGHT0_ENABLED) { |
| 703 | float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 ); |
| 704 | float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * LIGHT0_ENERGY; |
| 705 | float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0); |
| 706 | |
| 707 | // Rayleigh coefficients. |
| 708 | float rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) ); |
| 709 | vec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001; |
| 710 | // mie coefficients from Preetham |
| 711 | vec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434; |
| 712 | |
| 713 | // Optical length. |
| 714 | float zenith = acos(max(0.0, dot(UP, EYEDIR))); |
| 715 | float optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253)); |
| 716 | float rayleigh_scatter = rayleigh_zenith_size * optical_mass; |
| 717 | float mie_scatter = mie_zenith_size * optical_mass; |
| 718 | |
| 719 | // Light extinction based on thickness of atmosphere. |
| 720 | vec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter)); |
| 721 | |
| 722 | // In scattering. |
| 723 | float cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION)); |
| 724 | |
| 725 | float rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0)); |
| 726 | vec3 betaRTheta = rayleigh_beta * rayleigh_phase; |
| 727 | |
| 728 | float mie_phase = henyey_greenstein(cos_theta, mie_eccentricity); |
| 729 | vec3 betaMTheta = mie_beta * mie_phase; |
| 730 | |
| 731 | vec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5)); |
| 732 | // Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js |
| 733 | Lin *= 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)); |
| 734 | |
| 735 | // Hack in the ground color. |
| 736 | Lin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR))); |
| 737 | |
| 738 | // Solar disk and out-scattering. |
| 739 | float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale); |
| 740 | float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5); |
| 741 | float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta); |
| 742 | vec3 L0 = (sun_energy * extinction) * sundisk * LIGHT0_COLOR; |
| 743 | L0 += texture(night_sky, SKY_COORDS).xyz * extinction; |
| 744 | |
| 745 | vec3 color = Lin + L0; |
| 746 | COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade)))); |
| 747 | COLOR *= exposure; |
| 748 | } else { |
| 749 | // There is no sun, so display night_sky and nothing else. |
| 750 | COLOR = texture(night_sky, SKY_COORDS).xyz; |
| 751 | COLOR *= exposure; |
| 752 | } |
| 753 | } |
| 754 | )" , |
| 755 | i ? "render_mode use_debanding;" : "" )); |
| 756 | } |
| 757 | } |
| 758 | |
| 759 | shader_mutex.unlock(); |
| 760 | } |
| 761 | |
| 762 | PhysicalSkyMaterial::PhysicalSkyMaterial() { |
| 763 | set_rayleigh_coefficient(2.0); |
| 764 | set_rayleigh_color(Color(0.3, 0.405, 0.6)); |
| 765 | set_mie_coefficient(0.005); |
| 766 | set_mie_eccentricity(0.8); |
| 767 | set_mie_color(Color(0.69, 0.729, 0.812)); |
| 768 | set_turbidity(10.0); |
| 769 | set_sun_disk_scale(1.0); |
| 770 | set_ground_color(Color(0.1, 0.07, 0.034)); |
| 771 | set_energy_multiplier(1.0); |
| 772 | set_use_debanding(true); |
| 773 | } |
| 774 | |
| 775 | PhysicalSkyMaterial::~PhysicalSkyMaterial() { |
| 776 | } |
| 777 | |