sky_material.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  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. #include "sky_material.h"
  31. #include "core/config/project_settings.h"
  32. #include "core/version.h"
  33. Mutex ProceduralSkyMaterial::shader_mutex;
  34. RID ProceduralSkyMaterial::shader_cache[2];
  35. void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {
  36. sky_top_color = p_sky_top;
  37. RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color);
  38. }
  39. Color ProceduralSkyMaterial::get_sky_top_color() const {
  40. return sky_top_color;
  41. }
  42. void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) {
  43. sky_horizon_color = p_sky_horizon;
  44. RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color);
  45. }
  46. Color ProceduralSkyMaterial::get_sky_horizon_color() const {
  47. return sky_horizon_color;
  48. }
  49. void ProceduralSkyMaterial::set_sky_curve(float p_curve) {
  50. sky_curve = p_curve;
  51. RS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve);
  52. }
  53. float ProceduralSkyMaterial::get_sky_curve() const {
  54. return sky_curve;
  55. }
  56. void ProceduralSkyMaterial::set_sky_energy_multiplier(float p_multiplier) {
  57. sky_energy_multiplier = p_multiplier;
  58. RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy_multiplier);
  59. }
  60. float ProceduralSkyMaterial::get_sky_energy_multiplier() const {
  61. return sky_energy_multiplier;
  62. }
  63. void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) {
  64. sky_cover = p_sky_cover;
  65. if (p_sky_cover.is_valid()) {
  66. RS::get_singleton()->material_set_param(_get_material(), "sky_cover", p_sky_cover->get_rid());
  67. } else {
  68. RS::get_singleton()->material_set_param(_get_material(), "sky_cover", Variant());
  69. }
  70. }
  71. Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const {
  72. return sky_cover;
  73. }
  74. void ProceduralSkyMaterial::set_sky_cover_modulate(const Color &p_sky_cover_modulate) {
  75. sky_cover_modulate = p_sky_cover_modulate;
  76. RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate", sky_cover_modulate);
  77. }
  78. Color ProceduralSkyMaterial::get_sky_cover_modulate() const {
  79. return sky_cover_modulate;
  80. }
  81. void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) {
  82. ground_bottom_color = p_ground_bottom;
  83. RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color);
  84. }
  85. Color ProceduralSkyMaterial::get_ground_bottom_color() const {
  86. return ground_bottom_color;
  87. }
  88. void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) {
  89. ground_horizon_color = p_ground_horizon;
  90. RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color);
  91. }
  92. Color ProceduralSkyMaterial::get_ground_horizon_color() const {
  93. return ground_horizon_color;
  94. }
  95. void ProceduralSkyMaterial::set_ground_curve(float p_curve) {
  96. ground_curve = p_curve;
  97. RS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve);
  98. }
  99. float ProceduralSkyMaterial::get_ground_curve() const {
  100. return ground_curve;
  101. }
  102. void ProceduralSkyMaterial::set_ground_energy_multiplier(float p_multiplier) {
  103. ground_energy_multiplier = p_multiplier;
  104. RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy_multiplier);
  105. }
  106. float ProceduralSkyMaterial::get_ground_energy_multiplier() const {
  107. return ground_energy_multiplier;
  108. }
  109. void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) {
  110. sun_angle_max = p_angle;
  111. RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg_to_rad(sun_angle_max));
  112. }
  113. float ProceduralSkyMaterial::get_sun_angle_max() const {
  114. return sun_angle_max;
  115. }
  116. void ProceduralSkyMaterial::set_sun_curve(float p_curve) {
  117. sun_curve = p_curve;
  118. RS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve);
  119. }
  120. float ProceduralSkyMaterial::get_sun_curve() const {
  121. return sun_curve;
  122. }
  123. void ProceduralSkyMaterial::set_use_debanding(bool p_use_debanding) {
  124. use_debanding = p_use_debanding;
  125. _update_shader();
  126. // Only set if shader already compiled
  127. if (shader_set) {
  128. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]);
  129. }
  130. }
  131. bool ProceduralSkyMaterial::get_use_debanding() const {
  132. return use_debanding;
  133. }
  134. void ProceduralSkyMaterial::set_energy_multiplier(float p_multiplier) {
  135. global_energy_multiplier = p_multiplier;
  136. RS::get_singleton()->material_set_param(_get_material(), "exposure", global_energy_multiplier);
  137. }
  138. float ProceduralSkyMaterial::get_energy_multiplier() const {
  139. return global_energy_multiplier;
  140. }
  141. Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {
  142. return Shader::MODE_SKY;
  143. }
  144. RID ProceduralSkyMaterial::get_rid() const {
  145. _update_shader();
  146. if (!shader_set) {
  147. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]);
  148. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]);
  149. shader_set = true;
  150. }
  151. return _get_material();
  152. }
  153. RID ProceduralSkyMaterial::get_shader_rid() const {
  154. _update_shader();
  155. return shader_cache[int(use_debanding)];
  156. }
  157. void ProceduralSkyMaterial::_validate_property(PropertyInfo &p_property) const {
  158. if ((p_property.name == "sky_luminance" || p_property.name == "ground_luminance") && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
  159. p_property.usage = PROPERTY_USAGE_NO_EDITOR;
  160. }
  161. }
  162. void ProceduralSkyMaterial::_bind_methods() {
  163. ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color);
  164. ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color);
  165. ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSkyMaterial::set_sky_horizon_color);
  166. ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSkyMaterial::get_sky_horizon_color);
  167. ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve);
  168. ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve);
  169. ClassDB::bind_method(D_METHOD("set_sky_energy_multiplier", "multiplier"), &ProceduralSkyMaterial::set_sky_energy_multiplier);
  170. ClassDB::bind_method(D_METHOD("get_sky_energy_multiplier"), &ProceduralSkyMaterial::get_sky_energy_multiplier);
  171. ClassDB::bind_method(D_METHOD("set_sky_cover", "sky_cover"), &ProceduralSkyMaterial::set_sky_cover);
  172. ClassDB::bind_method(D_METHOD("get_sky_cover"), &ProceduralSkyMaterial::get_sky_cover);
  173. ClassDB::bind_method(D_METHOD("set_sky_cover_modulate", "color"), &ProceduralSkyMaterial::set_sky_cover_modulate);
  174. ClassDB::bind_method(D_METHOD("get_sky_cover_modulate"), &ProceduralSkyMaterial::get_sky_cover_modulate);
  175. ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color);
  176. ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color);
  177. ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSkyMaterial::set_ground_horizon_color);
  178. ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSkyMaterial::get_ground_horizon_color);
  179. ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve);
  180. ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve);
  181. ClassDB::bind_method(D_METHOD("set_ground_energy_multiplier", "energy"), &ProceduralSkyMaterial::set_ground_energy_multiplier);
  182. ClassDB::bind_method(D_METHOD("get_ground_energy_multiplier"), &ProceduralSkyMaterial::get_ground_energy_multiplier);
  183. ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max);
  184. ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max);
  185. ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSkyMaterial::set_sun_curve);
  186. ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSkyMaterial::get_sun_curve);
  187. ClassDB::bind_method(D_METHOD("set_use_debanding", "use_debanding"), &ProceduralSkyMaterial::set_use_debanding);
  188. ClassDB::bind_method(D_METHOD("get_use_debanding"), &ProceduralSkyMaterial::get_use_debanding);
  189. ClassDB::bind_method(D_METHOD("set_energy_multiplier", "multiplier"), &ProceduralSkyMaterial::set_energy_multiplier);
  190. ClassDB::bind_method(D_METHOD("get_energy_multiplier"), &ProceduralSkyMaterial::get_energy_multiplier);
  191. ADD_GROUP("Sky", "sky_");
  192. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_top_color", "get_sky_top_color");
  193. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color");
  194. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
  195. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy_multiplier", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy_multiplier", "get_sky_energy_multiplier");
  196. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_sky_cover", "get_sky_cover");
  197. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate"), "set_sky_cover_modulate", "get_sky_cover_modulate");
  198. ADD_GROUP("Ground", "ground_");
  199. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color");
  200. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_horizon_color", "get_ground_horizon_color");
  201. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
  202. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy_multiplier", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy_multiplier", "get_ground_energy_multiplier");
  203. ADD_GROUP("Sun", "sun_");
  204. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01,degrees"), "set_sun_angle_max", "get_sun_angle_max");
  205. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
  206. ADD_GROUP("", "");
  207. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "get_use_debanding");
  208. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy_multiplier", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_energy_multiplier", "get_energy_multiplier");
  209. }
  210. void ProceduralSkyMaterial::cleanup_shader() {
  211. if (shader_cache[0].is_valid()) {
  212. RS::get_singleton()->free(shader_cache[0]);
  213. RS::get_singleton()->free(shader_cache[1]);
  214. }
  215. }
  216. void ProceduralSkyMaterial::_update_shader() {
  217. MutexLock shader_lock(shader_mutex);
  218. if (shader_cache[0].is_null()) {
  219. for (int i = 0; i < 2; i++) {
  220. shader_cache[i] = RS::get_singleton()->shader_create();
  221. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  222. RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"(
  223. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s ProceduralSkyMaterial.
  224. shader_type sky;
  225. %s
  226. uniform vec4 sky_top_color : source_color = vec4(0.385, 0.454, 0.55, 1.0);
  227. uniform vec4 sky_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0);
  228. uniform float sky_curve : hint_range(0, 1) = 0.15;
  229. uniform float sky_energy = 1.0; // In Lux.
  230. uniform sampler2D sky_cover : filter_linear, source_color, hint_default_black;
  231. uniform vec4 sky_cover_modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0);
  232. uniform vec4 ground_bottom_color : source_color = vec4(0.2, 0.169, 0.133, 1.0);
  233. uniform vec4 ground_horizon_color : source_color = vec4(0.646, 0.656, 0.67, 1.0);
  234. uniform float ground_curve : hint_range(0, 1) = 0.02;
  235. uniform float ground_energy = 1.0;
  236. uniform float sun_angle_max = 30.0;
  237. uniform float sun_curve : hint_range(0, 1) = 0.15;
  238. uniform float exposure : hint_range(0, 128) = 1.0;
  239. void sky() {
  240. float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));
  241. float c = (1.0 - v_angle / (PI * 0.5));
  242. 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));
  243. sky *= sky_energy;
  244. if (LIGHT0_ENABLED) {
  245. float sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));
  246. if (sun_angle < LIGHT0_SIZE) {
  247. sky = LIGHT0_COLOR * LIGHT0_ENERGY;
  248. } else if (sun_angle < sun_angle_max) {
  249. float c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE);
  250. sky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  251. }
  252. }
  253. if (LIGHT1_ENABLED) {
  254. float sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));
  255. if (sun_angle < LIGHT1_SIZE) {
  256. sky = LIGHT1_COLOR * LIGHT1_ENERGY;
  257. } else if (sun_angle < sun_angle_max) {
  258. float c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE);
  259. sky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  260. }
  261. }
  262. if (LIGHT2_ENABLED) {
  263. float sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));
  264. if (sun_angle < LIGHT2_SIZE) {
  265. sky = LIGHT2_COLOR * LIGHT2_ENERGY;
  266. } else if (sun_angle < sun_angle_max) {
  267. float c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE);
  268. sky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  269. }
  270. }
  271. if (LIGHT3_ENABLED) {
  272. float sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));
  273. if (sun_angle < LIGHT3_SIZE) {
  274. sky = LIGHT3_COLOR * LIGHT3_ENERGY;
  275. } else if (sun_angle < sun_angle_max) {
  276. float c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE);
  277. sky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  278. }
  279. }
  280. vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS);
  281. sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a * sky_energy;
  282. c = (v_angle - (PI * 0.5)) / (PI * 0.5);
  283. 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));
  284. ground *= ground_energy;
  285. COLOR = mix(ground, sky, step(0.0, EYEDIR.y)) * exposure;
  286. }
  287. )",
  288. i ? "render_mode use_debanding;" : ""));
  289. }
  290. }
  291. }
  292. ProceduralSkyMaterial::ProceduralSkyMaterial() {
  293. _set_material(RS::get_singleton()->material_create());
  294. set_sky_top_color(Color(0.385, 0.454, 0.55));
  295. set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708));
  296. set_sky_curve(0.15);
  297. set_sky_energy_multiplier(1.0);
  298. set_sky_cover_modulate(Color(1, 1, 1));
  299. set_ground_bottom_color(Color(0.2, 0.169, 0.133));
  300. set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708));
  301. set_ground_curve(0.02);
  302. set_ground_energy_multiplier(1.0);
  303. set_sun_angle_max(30.0);
  304. set_sun_curve(0.15);
  305. set_use_debanding(true);
  306. set_energy_multiplier(1.0);
  307. }
  308. ProceduralSkyMaterial::~ProceduralSkyMaterial() {
  309. }
  310. /////////////////////////////////////////
  311. /* PanoramaSkyMaterial */
  312. void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) {
  313. panorama = p_panorama;
  314. if (p_panorama.is_valid()) {
  315. RS::get_singleton()->material_set_param(_get_material(), "source_panorama", p_panorama->get_rid());
  316. } else {
  317. RS::get_singleton()->material_set_param(_get_material(), "source_panorama", Variant());
  318. }
  319. }
  320. Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const {
  321. return panorama;
  322. }
  323. void PanoramaSkyMaterial::set_filtering_enabled(bool p_enabled) {
  324. filter = p_enabled;
  325. notify_property_list_changed();
  326. _update_shader();
  327. // Only set if shader already compiled
  328. if (shader_set) {
  329. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(filter)]);
  330. }
  331. }
  332. bool PanoramaSkyMaterial::is_filtering_enabled() const {
  333. return filter;
  334. }
  335. void PanoramaSkyMaterial::set_energy_multiplier(float p_multiplier) {
  336. energy_multiplier = p_multiplier;
  337. RS::get_singleton()->material_set_param(_get_material(), "exposure", energy_multiplier);
  338. }
  339. float PanoramaSkyMaterial::get_energy_multiplier() const {
  340. return energy_multiplier;
  341. }
  342. Shader::Mode PanoramaSkyMaterial::get_shader_mode() const {
  343. return Shader::MODE_SKY;
  344. }
  345. RID PanoramaSkyMaterial::get_rid() const {
  346. _update_shader();
  347. // Don't compile shaders until first use, then compile both
  348. if (!shader_set) {
  349. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(filter)]);
  350. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(filter)]);
  351. shader_set = true;
  352. }
  353. return _get_material();
  354. }
  355. RID PanoramaSkyMaterial::get_shader_rid() const {
  356. _update_shader();
  357. return shader_cache[int(filter)];
  358. }
  359. void PanoramaSkyMaterial::_bind_methods() {
  360. ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama);
  361. ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama);
  362. ClassDB::bind_method(D_METHOD("set_filtering_enabled", "enabled"), &PanoramaSkyMaterial::set_filtering_enabled);
  363. ClassDB::bind_method(D_METHOD("is_filtering_enabled"), &PanoramaSkyMaterial::is_filtering_enabled);
  364. ClassDB::bind_method(D_METHOD("set_energy_multiplier", "multiplier"), &PanoramaSkyMaterial::set_energy_multiplier);
  365. ClassDB::bind_method(D_METHOD("get_energy_multiplier"), &PanoramaSkyMaterial::get_energy_multiplier);
  366. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
  367. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter"), "set_filtering_enabled", "is_filtering_enabled");
  368. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy_multiplier", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_energy_multiplier", "get_energy_multiplier");
  369. }
  370. Mutex PanoramaSkyMaterial::shader_mutex;
  371. RID PanoramaSkyMaterial::shader_cache[2];
  372. void PanoramaSkyMaterial::cleanup_shader() {
  373. if (shader_cache[0].is_valid()) {
  374. RS::get_singleton()->free(shader_cache[0]);
  375. RS::get_singleton()->free(shader_cache[1]);
  376. }
  377. }
  378. void PanoramaSkyMaterial::_update_shader() {
  379. MutexLock shader_lock(shader_mutex);
  380. if (shader_cache[0].is_null()) {
  381. for (int i = 0; i < 2; i++) {
  382. shader_cache[i] = RS::get_singleton()->shader_create();
  383. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  384. RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"(
  385. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PanoramaSkyMaterial.
  386. shader_type sky;
  387. uniform sampler2D source_panorama : %s, source_color, hint_default_black;
  388. uniform float exposure : hint_range(0, 128) = 1.0;
  389. void sky() {
  390. COLOR = texture(source_panorama, SKY_COORDS).rgb * exposure;
  391. }
  392. )",
  393. i ? "filter_linear" : "filter_nearest"));
  394. }
  395. }
  396. }
  397. PanoramaSkyMaterial::PanoramaSkyMaterial() {
  398. _set_material(RS::get_singleton()->material_create());
  399. set_energy_multiplier(1.0);
  400. }
  401. PanoramaSkyMaterial::~PanoramaSkyMaterial() {
  402. }
  403. //////////////////////////////////
  404. /* PhysicalSkyMaterial */
  405. void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) {
  406. rayleigh = p_rayleigh;
  407. RS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh);
  408. }
  409. float PhysicalSkyMaterial::get_rayleigh_coefficient() const {
  410. return rayleigh;
  411. }
  412. void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) {
  413. rayleigh_color = p_rayleigh_color;
  414. RS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color);
  415. }
  416. Color PhysicalSkyMaterial::get_rayleigh_color() const {
  417. return rayleigh_color;
  418. }
  419. void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) {
  420. mie = p_mie;
  421. RS::get_singleton()->material_set_param(_get_material(), "mie", mie);
  422. }
  423. float PhysicalSkyMaterial::get_mie_coefficient() const {
  424. return mie;
  425. }
  426. void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) {
  427. mie_eccentricity = p_eccentricity;
  428. RS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity);
  429. }
  430. float PhysicalSkyMaterial::get_mie_eccentricity() const {
  431. return mie_eccentricity;
  432. }
  433. void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) {
  434. mie_color = p_mie_color;
  435. RS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color);
  436. }
  437. Color PhysicalSkyMaterial::get_mie_color() const {
  438. return mie_color;
  439. }
  440. void PhysicalSkyMaterial::set_turbidity(float p_turbidity) {
  441. turbidity = p_turbidity;
  442. RS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity);
  443. }
  444. float PhysicalSkyMaterial::get_turbidity() const {
  445. return turbidity;
  446. }
  447. void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) {
  448. sun_disk_scale = p_sun_disk_scale;
  449. RS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale);
  450. }
  451. float PhysicalSkyMaterial::get_sun_disk_scale() const {
  452. return sun_disk_scale;
  453. }
  454. void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) {
  455. ground_color = p_ground_color;
  456. RS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color);
  457. }
  458. Color PhysicalSkyMaterial::get_ground_color() const {
  459. return ground_color;
  460. }
  461. void PhysicalSkyMaterial::set_energy_multiplier(float p_multiplier) {
  462. energy_multiplier = p_multiplier;
  463. RS::get_singleton()->material_set_param(_get_material(), "exposure", energy_multiplier);
  464. }
  465. float PhysicalSkyMaterial::get_energy_multiplier() const {
  466. return energy_multiplier;
  467. }
  468. void PhysicalSkyMaterial::set_use_debanding(bool p_use_debanding) {
  469. use_debanding = p_use_debanding;
  470. _update_shader();
  471. // Only set if shader already compiled
  472. if (shader_set) {
  473. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]);
  474. }
  475. }
  476. bool PhysicalSkyMaterial::get_use_debanding() const {
  477. return use_debanding;
  478. }
  479. void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) {
  480. night_sky = p_night_sky;
  481. if (p_night_sky.is_valid()) {
  482. RS::get_singleton()->material_set_param(_get_material(), "night_sky", p_night_sky->get_rid());
  483. } else {
  484. RS::get_singleton()->material_set_param(_get_material(), "night_sky", Variant());
  485. }
  486. }
  487. Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const {
  488. return night_sky;
  489. }
  490. Shader::Mode PhysicalSkyMaterial::get_shader_mode() const {
  491. return Shader::MODE_SKY;
  492. }
  493. RID PhysicalSkyMaterial::get_rid() const {
  494. _update_shader();
  495. if (!shader_set) {
  496. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[1 - int(use_debanding)]);
  497. RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(use_debanding)]);
  498. shader_set = true;
  499. }
  500. return _get_material();
  501. }
  502. RID PhysicalSkyMaterial::get_shader_rid() const {
  503. _update_shader();
  504. return shader_cache[int(use_debanding)];
  505. }
  506. void PhysicalSkyMaterial::_validate_property(PropertyInfo &p_property) const {
  507. if (p_property.name == "exposure_value" && !GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) {
  508. p_property.usage = PROPERTY_USAGE_NO_EDITOR;
  509. }
  510. }
  511. Mutex PhysicalSkyMaterial::shader_mutex;
  512. RID PhysicalSkyMaterial::shader_cache[2];
  513. void PhysicalSkyMaterial::_bind_methods() {
  514. ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient);
  515. ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient);
  516. ClassDB::bind_method(D_METHOD("set_rayleigh_color", "color"), &PhysicalSkyMaterial::set_rayleigh_color);
  517. ClassDB::bind_method(D_METHOD("get_rayleigh_color"), &PhysicalSkyMaterial::get_rayleigh_color);
  518. ClassDB::bind_method(D_METHOD("set_mie_coefficient", "mie"), &PhysicalSkyMaterial::set_mie_coefficient);
  519. ClassDB::bind_method(D_METHOD("get_mie_coefficient"), &PhysicalSkyMaterial::get_mie_coefficient);
  520. ClassDB::bind_method(D_METHOD("set_mie_eccentricity", "eccentricity"), &PhysicalSkyMaterial::set_mie_eccentricity);
  521. ClassDB::bind_method(D_METHOD("get_mie_eccentricity"), &PhysicalSkyMaterial::get_mie_eccentricity);
  522. ClassDB::bind_method(D_METHOD("set_mie_color", "color"), &PhysicalSkyMaterial::set_mie_color);
  523. ClassDB::bind_method(D_METHOD("get_mie_color"), &PhysicalSkyMaterial::get_mie_color);
  524. ClassDB::bind_method(D_METHOD("set_turbidity", "turbidity"), &PhysicalSkyMaterial::set_turbidity);
  525. ClassDB::bind_method(D_METHOD("get_turbidity"), &PhysicalSkyMaterial::get_turbidity);
  526. ClassDB::bind_method(D_METHOD("set_sun_disk_scale", "scale"), &PhysicalSkyMaterial::set_sun_disk_scale);
  527. ClassDB::bind_method(D_METHOD("get_sun_disk_scale"), &PhysicalSkyMaterial::get_sun_disk_scale);
  528. ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color);
  529. ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color);
  530. ClassDB::bind_method(D_METHOD("set_energy_multiplier", "multiplier"), &PhysicalSkyMaterial::set_energy_multiplier);
  531. ClassDB::bind_method(D_METHOD("get_energy_multiplier"), &PhysicalSkyMaterial::get_energy_multiplier);
  532. ClassDB::bind_method(D_METHOD("set_use_debanding", "use_debanding"), &PhysicalSkyMaterial::set_use_debanding);
  533. ClassDB::bind_method(D_METHOD("get_use_debanding"), &PhysicalSkyMaterial::get_use_debanding);
  534. ClassDB::bind_method(D_METHOD("set_night_sky", "night_sky"), &PhysicalSkyMaterial::set_night_sky);
  535. ClassDB::bind_method(D_METHOD("get_night_sky"), &PhysicalSkyMaterial::get_night_sky);
  536. ADD_GROUP("Rayleigh", "rayleigh_");
  537. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_rayleigh_coefficient", "get_rayleigh_coefficient");
  538. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_rayleigh_color", "get_rayleigh_color");
  539. ADD_GROUP("Mie", "mie_");
  540. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_coefficient", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_mie_coefficient", "get_mie_coefficient");
  541. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_eccentricity", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_mie_eccentricity", "get_mie_eccentricity");
  542. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "mie_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_mie_color", "get_mie_color");
  543. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity");
  544. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale");
  545. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_color", "get_ground_color");
  546. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy_multiplier", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_energy_multiplier", "get_energy_multiplier");
  547. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "get_use_debanding");
  548. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
  549. }
  550. void PhysicalSkyMaterial::cleanup_shader() {
  551. if (shader_cache[0].is_valid()) {
  552. RS::get_singleton()->free(shader_cache[0]);
  553. RS::get_singleton()->free(shader_cache[1]);
  554. }
  555. }
  556. void PhysicalSkyMaterial::_update_shader() {
  557. MutexLock shader_lock(shader_mutex);
  558. if (shader_cache[0].is_null()) {
  559. for (int i = 0; i < 2; i++) {
  560. shader_cache[i] = RS::get_singleton()->shader_create();
  561. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  562. RS::get_singleton()->shader_set_code(shader_cache[i], vformat(R"(
  563. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PhysicalSkyMaterial.
  564. shader_type sky;
  565. %s
  566. uniform float rayleigh : hint_range(0, 64) = 2.0;
  567. uniform vec4 rayleigh_color : source_color = vec4(0.3, 0.405, 0.6, 1.0);
  568. uniform float mie : hint_range(0, 1) = 0.005;
  569. uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;
  570. uniform vec4 mie_color : source_color = vec4(0.69, 0.729, 0.812, 1.0);
  571. uniform float turbidity : hint_range(0, 1000) = 10.0;
  572. uniform float sun_disk_scale : hint_range(0, 360) = 1.0;
  573. uniform vec4 ground_color : source_color = vec4(0.1, 0.07, 0.034, 1.0);
  574. uniform float exposure : hint_range(0, 128) = 1.0;
  575. uniform sampler2D night_sky : filter_linear, source_color, hint_default_black;
  576. const vec3 UP = vec3( 0.0, 1.0, 0.0 );
  577. // Optical length at zenith for molecules.
  578. const float rayleigh_zenith_size = 8.4e3;
  579. const float mie_zenith_size = 1.25e3;
  580. float henyey_greenstein(float cos_theta, float g) {
  581. const float k = 0.0795774715459;
  582. return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
  583. }
  584. void sky() {
  585. if (LIGHT0_ENABLED) {
  586. float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
  587. float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * LIGHT0_ENERGY;
  588. float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);
  589. // Rayleigh coefficients.
  590. float rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );
  591. vec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;
  592. // mie coefficients from Preetham
  593. vec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;
  594. // Optical length.
  595. float zenith = acos(max(0.0, dot(UP, EYEDIR)));
  596. float optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));
  597. float rayleigh_scatter = rayleigh_zenith_size * optical_mass;
  598. float mie_scatter = mie_zenith_size * optical_mass;
  599. // Light extinction based on thickness of atmosphere.
  600. vec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));
  601. // In scattering.
  602. float cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));
  603. float rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));
  604. vec3 betaRTheta = rayleigh_beta * rayleigh_phase;
  605. float mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);
  606. vec3 betaMTheta = mie_beta * mie_phase;
  607. vec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));
  608. // Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js
  609. 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));
  610. // Hack in the ground color.
  611. Lin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));
  612. // Solar disk and out-scattering.
  613. float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);
  614. float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);
  615. float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
  616. vec3 L0 = (sun_energy * extinction) * sundisk * LIGHT0_COLOR;
  617. L0 += texture(night_sky, SKY_COORDS).xyz * extinction;
  618. vec3 color = Lin + L0;
  619. COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
  620. COLOR *= exposure;
  621. } else {
  622. // There is no sun, so display night_sky and nothing else.
  623. COLOR = texture(night_sky, SKY_COORDS).xyz;
  624. COLOR *= exposure;
  625. }
  626. }
  627. )",
  628. i ? "render_mode use_debanding;" : ""));
  629. }
  630. }
  631. }
  632. PhysicalSkyMaterial::PhysicalSkyMaterial() {
  633. _set_material(RS::get_singleton()->material_create());
  634. set_rayleigh_coefficient(2.0);
  635. set_rayleigh_color(Color(0.3, 0.405, 0.6));
  636. set_mie_coefficient(0.005);
  637. set_mie_eccentricity(0.8);
  638. set_mie_color(Color(0.69, 0.729, 0.812));
  639. set_turbidity(10.0);
  640. set_sun_disk_scale(1.0);
  641. set_ground_color(Color(0.1, 0.07, 0.034));
  642. set_energy_multiplier(1.0);
  643. set_use_debanding(true);
  644. }
  645. PhysicalSkyMaterial::~PhysicalSkyMaterial() {
  646. }