sky_material.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. /*************************************************************************/
  2. /* sky_material.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
  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/version.h"
  32. Mutex ProceduralSkyMaterial::shader_mutex;
  33. RID ProceduralSkyMaterial::shader;
  34. void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {
  35. sky_top_color = p_sky_top;
  36. RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear());
  37. }
  38. Color ProceduralSkyMaterial::get_sky_top_color() const {
  39. return sky_top_color;
  40. }
  41. void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) {
  42. sky_horizon_color = p_sky_horizon;
  43. RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear());
  44. }
  45. Color ProceduralSkyMaterial::get_sky_horizon_color() const {
  46. return sky_horizon_color;
  47. }
  48. void ProceduralSkyMaterial::set_sky_curve(float p_curve) {
  49. sky_curve = p_curve;
  50. RS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve);
  51. }
  52. float ProceduralSkyMaterial::get_sky_curve() const {
  53. return sky_curve;
  54. }
  55. void ProceduralSkyMaterial::set_sky_energy(float p_energy) {
  56. sky_energy = p_energy;
  57. RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy);
  58. }
  59. float ProceduralSkyMaterial::get_sky_energy() const {
  60. return sky_energy;
  61. }
  62. void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) {
  63. ground_bottom_color = p_ground_bottom;
  64. RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear());
  65. }
  66. Color ProceduralSkyMaterial::get_ground_bottom_color() const {
  67. return ground_bottom_color;
  68. }
  69. void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) {
  70. ground_horizon_color = p_ground_horizon;
  71. RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear());
  72. }
  73. Color ProceduralSkyMaterial::get_ground_horizon_color() const {
  74. return ground_horizon_color;
  75. }
  76. void ProceduralSkyMaterial::set_ground_curve(float p_curve) {
  77. ground_curve = p_curve;
  78. RS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve);
  79. }
  80. float ProceduralSkyMaterial::get_ground_curve() const {
  81. return ground_curve;
  82. }
  83. void ProceduralSkyMaterial::set_ground_energy(float p_energy) {
  84. ground_energy = p_energy;
  85. RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy);
  86. }
  87. float ProceduralSkyMaterial::get_ground_energy() const {
  88. return ground_energy;
  89. }
  90. void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) {
  91. sun_angle_max = p_angle;
  92. RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max));
  93. }
  94. float ProceduralSkyMaterial::get_sun_angle_max() const {
  95. return sun_angle_max;
  96. }
  97. void ProceduralSkyMaterial::set_sun_curve(float p_curve) {
  98. sun_curve = p_curve;
  99. RS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve);
  100. }
  101. float ProceduralSkyMaterial::get_sun_curve() const {
  102. return sun_curve;
  103. }
  104. Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {
  105. return Shader::MODE_SKY;
  106. }
  107. RID ProceduralSkyMaterial::get_rid() const {
  108. _update_shader();
  109. if (!shader_set) {
  110. RS::get_singleton()->material_set_shader(_get_material(), shader);
  111. shader_set = true;
  112. }
  113. return _get_material();
  114. }
  115. RID ProceduralSkyMaterial::get_shader_rid() const {
  116. _update_shader();
  117. return shader;
  118. }
  119. void ProceduralSkyMaterial::_bind_methods() {
  120. ClassDB::bind_method(D_METHOD("set_sky_top_color", "color"), &ProceduralSkyMaterial::set_sky_top_color);
  121. ClassDB::bind_method(D_METHOD("get_sky_top_color"), &ProceduralSkyMaterial::get_sky_top_color);
  122. ClassDB::bind_method(D_METHOD("set_sky_horizon_color", "color"), &ProceduralSkyMaterial::set_sky_horizon_color);
  123. ClassDB::bind_method(D_METHOD("get_sky_horizon_color"), &ProceduralSkyMaterial::get_sky_horizon_color);
  124. ClassDB::bind_method(D_METHOD("set_sky_curve", "curve"), &ProceduralSkyMaterial::set_sky_curve);
  125. ClassDB::bind_method(D_METHOD("get_sky_curve"), &ProceduralSkyMaterial::get_sky_curve);
  126. ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy);
  127. ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy);
  128. ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color);
  129. ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color);
  130. ClassDB::bind_method(D_METHOD("set_ground_horizon_color", "color"), &ProceduralSkyMaterial::set_ground_horizon_color);
  131. ClassDB::bind_method(D_METHOD("get_ground_horizon_color"), &ProceduralSkyMaterial::get_ground_horizon_color);
  132. ClassDB::bind_method(D_METHOD("set_ground_curve", "curve"), &ProceduralSkyMaterial::set_ground_curve);
  133. ClassDB::bind_method(D_METHOD("get_ground_curve"), &ProceduralSkyMaterial::get_ground_curve);
  134. ClassDB::bind_method(D_METHOD("set_ground_energy", "energy"), &ProceduralSkyMaterial::set_ground_energy);
  135. ClassDB::bind_method(D_METHOD("get_ground_energy"), &ProceduralSkyMaterial::get_ground_energy);
  136. ClassDB::bind_method(D_METHOD("set_sun_angle_max", "degrees"), &ProceduralSkyMaterial::set_sun_angle_max);
  137. ClassDB::bind_method(D_METHOD("get_sun_angle_max"), &ProceduralSkyMaterial::get_sun_angle_max);
  138. ClassDB::bind_method(D_METHOD("set_sun_curve", "curve"), &ProceduralSkyMaterial::set_sun_curve);
  139. ClassDB::bind_method(D_METHOD("get_sun_curve"), &ProceduralSkyMaterial::get_sun_curve);
  140. ADD_GROUP("Sky", "sky_");
  141. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_top_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_top_color", "get_sky_top_color");
  142. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color");
  143. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
  144. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
  145. ADD_GROUP("Ground", "ground_");
  146. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color");
  147. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_horizon_color", "get_ground_horizon_color");
  148. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_curve", PROPERTY_HINT_EXP_EASING), "set_ground_curve", "get_ground_curve");
  149. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ground_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_ground_energy", "get_ground_energy");
  150. ADD_GROUP("Sun", "sun_");
  151. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_angle_max", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_angle_max", "get_sun_angle_max");
  152. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
  153. }
  154. void ProceduralSkyMaterial::cleanup_shader() {
  155. if (shader.is_valid()) {
  156. RS::get_singleton()->free(shader);
  157. }
  158. }
  159. void ProceduralSkyMaterial::_update_shader() {
  160. shader_mutex.lock();
  161. if (shader.is_null()) {
  162. shader = RS::get_singleton()->shader_create();
  163. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  164. RS::get_singleton()->shader_set_code(shader, R"(
  165. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s ProceduralSkyMaterial.
  166. shader_type sky;
  167. uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);
  168. uniform vec4 sky_horizon_color : hint_color = vec4(0.55, 0.69, 0.81, 1.0);
  169. uniform float sky_curve : hint_range(0, 1) = 0.09;
  170. uniform float sky_energy = 1.0;
  171. uniform vec4 ground_bottom_color : hint_color = vec4(0.12, 0.12, 0.13, 1.0);
  172. uniform vec4 ground_horizon_color : hint_color = vec4(0.37, 0.33, 0.31, 1.0);
  173. uniform float ground_curve : hint_range(0, 1) = 0.02;
  174. uniform float ground_energy = 1.0;
  175. uniform float sun_angle_max = 1.74;
  176. uniform float sun_curve : hint_range(0, 1) = 0.05;
  177. void sky() {
  178. float v_angle = acos(clamp(EYEDIR.y, -1.0, 1.0));
  179. float c = (1.0 - v_angle / (PI * 0.5));
  180. 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));
  181. sky *= sky_energy;
  182. if (LIGHT0_ENABLED) {
  183. float sun_angle = acos(dot(LIGHT0_DIRECTION, EYEDIR));
  184. if (sun_angle < LIGHT0_SIZE) {
  185. sky = LIGHT0_COLOR * LIGHT0_ENERGY;
  186. } else if (sun_angle < sun_angle_max) {
  187. float c2 = (sun_angle - LIGHT0_SIZE) / (sun_angle_max - LIGHT0_SIZE);
  188. sky = mix(LIGHT0_COLOR * LIGHT0_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  189. }
  190. }
  191. if (LIGHT1_ENABLED) {
  192. float sun_angle = acos(dot(LIGHT1_DIRECTION, EYEDIR));
  193. if (sun_angle < LIGHT1_SIZE) {
  194. sky = LIGHT1_COLOR * LIGHT1_ENERGY;
  195. } else if (sun_angle < sun_angle_max) {
  196. float c2 = (sun_angle - LIGHT1_SIZE) / (sun_angle_max - LIGHT1_SIZE);
  197. sky = mix(LIGHT1_COLOR * LIGHT1_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  198. }
  199. }
  200. if (LIGHT2_ENABLED) {
  201. float sun_angle = acos(dot(LIGHT2_DIRECTION, EYEDIR));
  202. if (sun_angle < LIGHT2_SIZE) {
  203. sky = LIGHT2_COLOR * LIGHT2_ENERGY;
  204. } else if (sun_angle < sun_angle_max) {
  205. float c2 = (sun_angle - LIGHT2_SIZE) / (sun_angle_max - LIGHT2_SIZE);
  206. sky = mix(LIGHT2_COLOR * LIGHT2_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  207. }
  208. }
  209. if (LIGHT3_ENABLED) {
  210. float sun_angle = acos(dot(LIGHT3_DIRECTION, EYEDIR));
  211. if (sun_angle < LIGHT3_SIZE) {
  212. sky = LIGHT3_COLOR * LIGHT3_ENERGY;
  213. } else if (sun_angle < sun_angle_max) {
  214. float c2 = (sun_angle - LIGHT3_SIZE) / (sun_angle_max - LIGHT3_SIZE);
  215. sky = mix(LIGHT3_COLOR * LIGHT3_ENERGY, sky, clamp(1.0 - pow(1.0 - c2, 1.0 / sun_curve), 0.0, 1.0));
  216. }
  217. }
  218. c = (v_angle - (PI * 0.5)) / (PI * 0.5);
  219. 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));
  220. ground *= ground_energy;
  221. COLOR = mix(ground, sky, step(0.0, EYEDIR.y));
  222. }
  223. )");
  224. }
  225. shader_mutex.unlock();
  226. }
  227. ProceduralSkyMaterial::ProceduralSkyMaterial() {
  228. set_sky_top_color(Color(0.35, 0.46, 0.71));
  229. set_sky_horizon_color(Color(0.55, 0.69, 0.81));
  230. set_sky_curve(0.09);
  231. set_sky_energy(1.0);
  232. set_ground_bottom_color(Color(0.12, 0.12, 0.13));
  233. set_ground_horizon_color(Color(0.37, 0.33, 0.31));
  234. set_ground_curve(0.02);
  235. set_ground_energy(1.0);
  236. set_sun_angle_max(100.0);
  237. set_sun_curve(0.05);
  238. }
  239. ProceduralSkyMaterial::~ProceduralSkyMaterial() {
  240. }
  241. /////////////////////////////////////////
  242. /* PanoramaSkyMaterial */
  243. void PanoramaSkyMaterial::set_panorama(const Ref<Texture2D> &p_panorama) {
  244. panorama = p_panorama;
  245. RID tex_rid = p_panorama.is_valid() ? p_panorama->get_rid() : RID();
  246. RS::get_singleton()->material_set_param(_get_material(), "source_panorama", tex_rid);
  247. }
  248. Ref<Texture2D> PanoramaSkyMaterial::get_panorama() const {
  249. return panorama;
  250. }
  251. Shader::Mode PanoramaSkyMaterial::get_shader_mode() const {
  252. return Shader::MODE_SKY;
  253. }
  254. RID PanoramaSkyMaterial::get_rid() const {
  255. _update_shader();
  256. if (!shader_set) {
  257. RS::get_singleton()->material_set_shader(_get_material(), shader);
  258. shader_set = true;
  259. }
  260. return _get_material();
  261. }
  262. RID PanoramaSkyMaterial::get_shader_rid() const {
  263. _update_shader();
  264. return shader;
  265. }
  266. void PanoramaSkyMaterial::_bind_methods() {
  267. ClassDB::bind_method(D_METHOD("set_panorama", "texture"), &PanoramaSkyMaterial::set_panorama);
  268. ClassDB::bind_method(D_METHOD("get_panorama"), &PanoramaSkyMaterial::get_panorama);
  269. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
  270. }
  271. Mutex PanoramaSkyMaterial::shader_mutex;
  272. RID PanoramaSkyMaterial::shader;
  273. void PanoramaSkyMaterial::cleanup_shader() {
  274. if (shader.is_valid()) {
  275. RS::get_singleton()->free(shader);
  276. }
  277. }
  278. void PanoramaSkyMaterial::_update_shader() {
  279. shader_mutex.lock();
  280. if (shader.is_null()) {
  281. shader = RS::get_singleton()->shader_create();
  282. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  283. RS::get_singleton()->shader_set_code(shader, R"(
  284. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PanoramaSkyMaterial.
  285. shader_type sky;
  286. uniform sampler2D source_panorama : filter_linear, hint_albedo;
  287. void sky() {
  288. COLOR = texture(source_panorama, SKY_COORDS).rgb;
  289. }
  290. )");
  291. }
  292. shader_mutex.unlock();
  293. }
  294. PanoramaSkyMaterial::PanoramaSkyMaterial() {
  295. }
  296. PanoramaSkyMaterial::~PanoramaSkyMaterial() {
  297. }
  298. //////////////////////////////////
  299. /* PhysicalSkyMaterial */
  300. void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) {
  301. rayleigh = p_rayleigh;
  302. RS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh);
  303. }
  304. float PhysicalSkyMaterial::get_rayleigh_coefficient() const {
  305. return rayleigh;
  306. }
  307. void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) {
  308. rayleigh_color = p_rayleigh_color;
  309. RS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color);
  310. }
  311. Color PhysicalSkyMaterial::get_rayleigh_color() const {
  312. return rayleigh_color;
  313. }
  314. void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) {
  315. mie = p_mie;
  316. RS::get_singleton()->material_set_param(_get_material(), "mie", mie);
  317. }
  318. float PhysicalSkyMaterial::get_mie_coefficient() const {
  319. return mie;
  320. }
  321. void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) {
  322. mie_eccentricity = p_eccentricity;
  323. RS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity);
  324. }
  325. float PhysicalSkyMaterial::get_mie_eccentricity() const {
  326. return mie_eccentricity;
  327. }
  328. void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) {
  329. mie_color = p_mie_color;
  330. RS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color);
  331. }
  332. Color PhysicalSkyMaterial::get_mie_color() const {
  333. return mie_color;
  334. }
  335. void PhysicalSkyMaterial::set_turbidity(float p_turbidity) {
  336. turbidity = p_turbidity;
  337. RS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity);
  338. }
  339. float PhysicalSkyMaterial::get_turbidity() const {
  340. return turbidity;
  341. }
  342. void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) {
  343. sun_disk_scale = p_sun_disk_scale;
  344. RS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale);
  345. }
  346. float PhysicalSkyMaterial::get_sun_disk_scale() const {
  347. return sun_disk_scale;
  348. }
  349. void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) {
  350. ground_color = p_ground_color;
  351. RS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color);
  352. }
  353. Color PhysicalSkyMaterial::get_ground_color() const {
  354. return ground_color;
  355. }
  356. void PhysicalSkyMaterial::set_exposure(float p_exposure) {
  357. exposure = p_exposure;
  358. RS::get_singleton()->material_set_param(_get_material(), "exposure", exposure);
  359. }
  360. float PhysicalSkyMaterial::get_exposure() const {
  361. return exposure;
  362. }
  363. void PhysicalSkyMaterial::set_dither_strength(float p_dither_strength) {
  364. dither_strength = p_dither_strength;
  365. RS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength);
  366. }
  367. float PhysicalSkyMaterial::get_dither_strength() const {
  368. return dither_strength;
  369. }
  370. void PhysicalSkyMaterial::set_night_sky(const Ref<Texture2D> &p_night_sky) {
  371. night_sky = p_night_sky;
  372. RID tex_rid = p_night_sky.is_valid() ? p_night_sky->get_rid() : RID();
  373. RS::get_singleton()->material_set_param(_get_material(), "night_sky", tex_rid);
  374. }
  375. Ref<Texture2D> PhysicalSkyMaterial::get_night_sky() const {
  376. return night_sky;
  377. }
  378. Shader::Mode PhysicalSkyMaterial::get_shader_mode() const {
  379. return Shader::MODE_SKY;
  380. }
  381. RID PhysicalSkyMaterial::get_rid() const {
  382. _update_shader();
  383. if (!shader_set) {
  384. RS::get_singleton()->material_set_shader(_get_material(), shader);
  385. shader_set = true;
  386. }
  387. return _get_material();
  388. }
  389. RID PhysicalSkyMaterial::get_shader_rid() const {
  390. _update_shader();
  391. return shader;
  392. }
  393. Mutex PhysicalSkyMaterial::shader_mutex;
  394. RID PhysicalSkyMaterial::shader;
  395. void PhysicalSkyMaterial::_bind_methods() {
  396. ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient);
  397. ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient);
  398. ClassDB::bind_method(D_METHOD("set_rayleigh_color", "color"), &PhysicalSkyMaterial::set_rayleigh_color);
  399. ClassDB::bind_method(D_METHOD("get_rayleigh_color"), &PhysicalSkyMaterial::get_rayleigh_color);
  400. ClassDB::bind_method(D_METHOD("set_mie_coefficient", "mie"), &PhysicalSkyMaterial::set_mie_coefficient);
  401. ClassDB::bind_method(D_METHOD("get_mie_coefficient"), &PhysicalSkyMaterial::get_mie_coefficient);
  402. ClassDB::bind_method(D_METHOD("set_mie_eccentricity", "eccentricity"), &PhysicalSkyMaterial::set_mie_eccentricity);
  403. ClassDB::bind_method(D_METHOD("get_mie_eccentricity"), &PhysicalSkyMaterial::get_mie_eccentricity);
  404. ClassDB::bind_method(D_METHOD("set_mie_color", "color"), &PhysicalSkyMaterial::set_mie_color);
  405. ClassDB::bind_method(D_METHOD("get_mie_color"), &PhysicalSkyMaterial::get_mie_color);
  406. ClassDB::bind_method(D_METHOD("set_turbidity", "turbidity"), &PhysicalSkyMaterial::set_turbidity);
  407. ClassDB::bind_method(D_METHOD("get_turbidity"), &PhysicalSkyMaterial::get_turbidity);
  408. ClassDB::bind_method(D_METHOD("set_sun_disk_scale", "scale"), &PhysicalSkyMaterial::set_sun_disk_scale);
  409. ClassDB::bind_method(D_METHOD("get_sun_disk_scale"), &PhysicalSkyMaterial::get_sun_disk_scale);
  410. ClassDB::bind_method(D_METHOD("set_ground_color", "color"), &PhysicalSkyMaterial::set_ground_color);
  411. ClassDB::bind_method(D_METHOD("get_ground_color"), &PhysicalSkyMaterial::get_ground_color);
  412. ClassDB::bind_method(D_METHOD("set_exposure", "exposure"), &PhysicalSkyMaterial::set_exposure);
  413. ClassDB::bind_method(D_METHOD("get_exposure"), &PhysicalSkyMaterial::get_exposure);
  414. ClassDB::bind_method(D_METHOD("set_dither_strength", "strength"), &PhysicalSkyMaterial::set_dither_strength);
  415. ClassDB::bind_method(D_METHOD("get_dither_strength"), &PhysicalSkyMaterial::get_dither_strength);
  416. ClassDB::bind_method(D_METHOD("set_night_sky", "night_sky"), &PhysicalSkyMaterial::set_night_sky);
  417. ClassDB::bind_method(D_METHOD("get_night_sky"), &PhysicalSkyMaterial::get_night_sky);
  418. ADD_GROUP("Rayleigh", "rayleigh_");
  419. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rayleigh_coefficient", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_rayleigh_coefficient", "get_rayleigh_coefficient");
  420. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "rayleigh_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_rayleigh_color", "get_rayleigh_color");
  421. ADD_GROUP("Mie", "mie_");
  422. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_coefficient", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_mie_coefficient", "get_mie_coefficient");
  423. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mie_eccentricity", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_mie_eccentricity", "get_mie_eccentricity");
  424. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "mie_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_mie_color", "get_mie_color");
  425. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "turbidity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_turbidity", "get_turbidity");
  426. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_disk_scale", PROPERTY_HINT_RANGE, "0,360,0.01"), "set_sun_disk_scale", "get_sun_disk_scale");
  427. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_color", "get_ground_color");
  428. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure", PROPERTY_HINT_RANGE, "0,128,0.01"), "set_exposure", "get_exposure");
  429. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dither_strength", PROPERTY_HINT_RANGE, "0,10,0.01"), "set_dither_strength", "get_dither_strength");
  430. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
  431. }
  432. void PhysicalSkyMaterial::cleanup_shader() {
  433. if (shader.is_valid()) {
  434. RS::get_singleton()->free(shader);
  435. }
  436. }
  437. void PhysicalSkyMaterial::_update_shader() {
  438. shader_mutex.lock();
  439. if (shader.is_null()) {
  440. shader = RS::get_singleton()->shader_create();
  441. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  442. RS::get_singleton()->shader_set_code(shader, R"(
  443. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s PhysicalSkyMaterial.
  444. shader_type sky;
  445. uniform float rayleigh : hint_range(0, 64) = 2.0;
  446. uniform vec4 rayleigh_color : hint_color = vec4(0.056, 0.14, 0.3, 1.0);
  447. uniform float mie : hint_range(0, 1) = 0.005;
  448. uniform float mie_eccentricity : hint_range(-1, 1) = 0.8;
  449. uniform vec4 mie_color : hint_color = vec4(0.36, 0.56, 0.82, 1.0);
  450. uniform float turbidity : hint_range(0, 1000) = 10.0;
  451. uniform float sun_disk_scale : hint_range(0, 360) = 1.0;
  452. uniform vec4 ground_color : hint_color = vec4(1.0);
  453. uniform float exposure : hint_range(0, 128) = 0.1;
  454. uniform float dither_strength : hint_range(0, 10) = 1.0;
  455. uniform sampler2D night_sky : hint_black_albedo;
  456. const vec3 UP = vec3( 0.0, 1.0, 0.0 );
  457. // Sun constants
  458. const float SUN_ENERGY = 1000.0;
  459. // Optical length at zenith for molecules.
  460. const float rayleigh_zenith_size = 8.4e3;
  461. const float mie_zenith_size = 1.25e3;
  462. float henyey_greenstein(float cos_theta, float g) {
  463. const float k = 0.0795774715459;
  464. return k * (1.0 - g * g) / (pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5));
  465. }
  466. // From: https://www.shadertoy.com/view/4sfGzS credit to iq
  467. float hash(vec3 p) {
  468. p = fract( p * 0.3183099 + 0.1 );
  469. p *= 17.0;
  470. return fract(p.x * p.y * p.z * (p.x + p.y + p.z));
  471. }
  472. void sky() {
  473. if (LIGHT0_ENABLED) {
  474. float zenith_angle = clamp( dot(UP, normalize(LIGHT0_DIRECTION)), -1.0, 1.0 );
  475. float sun_energy = max(0.0, 1.0 - exp(-((PI * 0.5) - acos(zenith_angle)))) * SUN_ENERGY * LIGHT0_ENERGY;
  476. float sun_fade = 1.0 - clamp(1.0 - exp(LIGHT0_DIRECTION.y), 0.0, 1.0);
  477. // Rayleigh coefficients.
  478. float rayleigh_coefficient = rayleigh - ( 1.0 * ( 1.0 - sun_fade ) );
  479. vec3 rayleigh_beta = rayleigh_coefficient * rayleigh_color.rgb * 0.0001;
  480. // mie coefficients from Preetham
  481. vec3 mie_beta = turbidity * mie * mie_color.rgb * 0.000434;
  482. // Optical length.
  483. float zenith = acos(max(0.0, dot(UP, EYEDIR)));
  484. float optical_mass = 1.0 / (cos(zenith) + 0.15 * pow(93.885 - degrees(zenith), -1.253));
  485. float rayleigh_scatter = rayleigh_zenith_size * optical_mass;
  486. float mie_scatter = mie_zenith_size * optical_mass;
  487. // Light extinction based on thickness of atmosphere.
  488. vec3 extinction = exp(-(rayleigh_beta * rayleigh_scatter + mie_beta * mie_scatter));
  489. // In scattering.
  490. float cos_theta = dot(EYEDIR, normalize(LIGHT0_DIRECTION));
  491. float rayleigh_phase = (3.0 / (16.0 * PI)) * (1.0 + pow(cos_theta * 0.5 + 0.5, 2.0));
  492. vec3 betaRTheta = rayleigh_beta * rayleigh_phase;
  493. float mie_phase = henyey_greenstein(cos_theta, mie_eccentricity);
  494. vec3 betaMTheta = mie_beta * mie_phase;
  495. vec3 Lin = pow(sun_energy * ((betaRTheta + betaMTheta) / (rayleigh_beta + mie_beta)) * (1.0 - extinction), vec3(1.5));
  496. // Hack from https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Sky.js
  497. 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));
  498. // Hack in the ground color.
  499. Lin *= mix(ground_color.rgb, vec3(1.0), smoothstep(-0.1, 0.1, dot(UP, EYEDIR)));
  500. // Solar disk and out-scattering.
  501. float sunAngularDiameterCos = cos(LIGHT0_SIZE * sun_disk_scale);
  502. float sunAngularDiameterCos2 = cos(LIGHT0_SIZE * sun_disk_scale*0.5);
  503. float sundisk = smoothstep(sunAngularDiameterCos, sunAngularDiameterCos2, cos_theta);
  504. vec3 L0 = (sun_energy * 1900.0 * extinction) * sundisk * LIGHT0_COLOR;
  505. L0 += texture(night_sky, SKY_COORDS).xyz * extinction;
  506. vec3 color = (Lin + L0) * 0.04;
  507. COLOR = pow(color, vec3(1.0 / (1.2 + (1.2 * sun_fade))));
  508. COLOR *= exposure;
  509. // Make optional, eliminates banding.
  510. COLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.016 * dither_strength;
  511. } else {
  512. // There is no sun, so display night_sky and nothing else.
  513. COLOR = texture(night_sky, SKY_COORDS).xyz * 0.04;
  514. COLOR *= exposure;
  515. }
  516. }
  517. )");
  518. }
  519. shader_mutex.unlock();
  520. }
  521. PhysicalSkyMaterial::PhysicalSkyMaterial() {
  522. set_rayleigh_coefficient(2.0);
  523. set_rayleigh_color(Color(0.056, 0.14, 0.3));
  524. set_mie_coefficient(0.005);
  525. set_mie_eccentricity(0.8);
  526. set_mie_color(Color(0.36, 0.56, 0.82));
  527. set_turbidity(10.0);
  528. set_sun_disk_scale(1.0);
  529. set_ground_color(Color(1.0, 1.0, 1.0));
  530. set_exposure(0.1);
  531. set_dither_strength(1.0);
  532. }
  533. PhysicalSkyMaterial::~PhysicalSkyMaterial() {
  534. }