fog_material.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /**************************************************************************/
  2. /* fog_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 "fog_material.h"
  31. #include "core/version.h"
  32. Mutex FogMaterial::shader_mutex;
  33. RID FogMaterial::shader;
  34. void FogMaterial::set_density(float p_density) {
  35. density = p_density;
  36. RS::get_singleton()->material_set_param(_get_material(), "density", density);
  37. }
  38. float FogMaterial::get_density() const {
  39. return density;
  40. }
  41. void FogMaterial::set_albedo(Color p_albedo) {
  42. albedo = p_albedo;
  43. RS::get_singleton()->material_set_param(_get_material(), "albedo", albedo);
  44. }
  45. Color FogMaterial::get_albedo() const {
  46. return albedo;
  47. }
  48. void FogMaterial::set_emission(Color p_emission) {
  49. emission = p_emission;
  50. RS::get_singleton()->material_set_param(_get_material(), "emission", emission);
  51. }
  52. Color FogMaterial::get_emission() const {
  53. return emission;
  54. }
  55. void FogMaterial::set_height_falloff(float p_falloff) {
  56. height_falloff = MAX(p_falloff, 0.0f);
  57. RS::get_singleton()->material_set_param(_get_material(), "height_falloff", height_falloff);
  58. }
  59. float FogMaterial::get_height_falloff() const {
  60. return height_falloff;
  61. }
  62. void FogMaterial::set_edge_fade(float p_edge_fade) {
  63. edge_fade = MAX(p_edge_fade, 0.0f);
  64. RS::get_singleton()->material_set_param(_get_material(), "edge_fade", edge_fade);
  65. }
  66. float FogMaterial::get_edge_fade() const {
  67. return edge_fade;
  68. }
  69. void FogMaterial::set_density_texture(const Ref<Texture3D> &p_texture) {
  70. density_texture = p_texture;
  71. Variant tex_rid = p_texture.is_valid() ? Variant(p_texture->get_rid()) : Variant();
  72. RS::get_singleton()->material_set_param(_get_material(), "density_texture", tex_rid);
  73. }
  74. Ref<Texture3D> FogMaterial::get_density_texture() const {
  75. return density_texture;
  76. }
  77. Shader::Mode FogMaterial::get_shader_mode() const {
  78. return Shader::MODE_FOG;
  79. }
  80. RID FogMaterial::get_shader_rid() const {
  81. _update_shader();
  82. return shader;
  83. }
  84. RID FogMaterial::get_rid() const {
  85. _update_shader();
  86. if (!shader_set) {
  87. RS::get_singleton()->material_set_shader(_get_material(), shader);
  88. shader_set = true;
  89. }
  90. return _get_material();
  91. }
  92. void FogMaterial::_bind_methods() {
  93. ClassDB::bind_method(D_METHOD("set_density", "density"), &FogMaterial::set_density);
  94. ClassDB::bind_method(D_METHOD("get_density"), &FogMaterial::get_density);
  95. ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &FogMaterial::set_albedo);
  96. ClassDB::bind_method(D_METHOD("get_albedo"), &FogMaterial::get_albedo);
  97. ClassDB::bind_method(D_METHOD("set_emission", "emission"), &FogMaterial::set_emission);
  98. ClassDB::bind_method(D_METHOD("get_emission"), &FogMaterial::get_emission);
  99. ClassDB::bind_method(D_METHOD("set_height_falloff", "height_falloff"), &FogMaterial::set_height_falloff);
  100. ClassDB::bind_method(D_METHOD("get_height_falloff"), &FogMaterial::get_height_falloff);
  101. ClassDB::bind_method(D_METHOD("set_edge_fade", "edge_fade"), &FogMaterial::set_edge_fade);
  102. ClassDB::bind_method(D_METHOD("get_edge_fade"), &FogMaterial::get_edge_fade);
  103. ClassDB::bind_method(D_METHOD("set_density_texture", "density_texture"), &FogMaterial::set_density_texture);
  104. ClassDB::bind_method(D_METHOD("get_density_texture"), &FogMaterial::get_density_texture);
  105. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "density", PROPERTY_HINT_RANGE, "-8.0,8.0,0.0001,or_greater,or_less"), "set_density", "get_density");
  106. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo", PROPERTY_HINT_COLOR_NO_ALPHA), "set_albedo", "get_albedo");
  107. ADD_PROPERTY(PropertyInfo(Variant::COLOR, "emission", PROPERTY_HINT_COLOR_NO_ALPHA), "set_emission", "get_emission");
  108. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height_falloff", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_height_falloff", "get_height_falloff");
  109. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "edge_fade", PROPERTY_HINT_EXP_EASING), "set_edge_fade", "get_edge_fade");
  110. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "density_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_density_texture", "get_density_texture");
  111. }
  112. void FogMaterial::cleanup_shader() {
  113. if (shader.is_valid()) {
  114. ERR_FAIL_NULL(RenderingServer::get_singleton());
  115. RS::get_singleton()->free(shader);
  116. }
  117. }
  118. void FogMaterial::_update_shader() {
  119. MutexLock shader_lock(shader_mutex);
  120. if (shader.is_null()) {
  121. shader = RS::get_singleton()->shader_create();
  122. // Add a comment to describe the shader origin (useful when converting to ShaderMaterial).
  123. RS::get_singleton()->shader_set_code(shader, R"(
  124. // NOTE: Shader automatically converted from )" VERSION_NAME " " VERSION_FULL_CONFIG R"('s FogMaterial.
  125. shader_type fog;
  126. uniform float density : hint_range(0, 1, 0.0001) = 1.0;
  127. uniform vec4 albedo : source_color = vec4(1.0);
  128. uniform vec4 emission : source_color = vec4(0, 0, 0, 1);
  129. uniform float height_falloff = 0.0;
  130. uniform float edge_fade = 0.1;
  131. uniform sampler3D density_texture: hint_default_white;
  132. void fog() {
  133. DENSITY = density * clamp(exp2(-height_falloff * (WORLD_POSITION.y - OBJECT_POSITION.y)), 0.0, 1.0);
  134. DENSITY *= texture(density_texture, UVW).r;
  135. DENSITY *= pow(clamp(-2.0 * SDF / min(min(SIZE.x, SIZE.y), SIZE.z), 0.0, 1.0), edge_fade);
  136. ALBEDO = albedo.rgb;
  137. EMISSION = emission.rgb;
  138. }
  139. )");
  140. }
  141. }
  142. FogMaterial::FogMaterial() {
  143. _set_material(RS::get_singleton()->material_create());
  144. set_density(1.0);
  145. set_albedo(Color(1, 1, 1, 1));
  146. set_emission(Color(0, 0, 0, 1));
  147. set_height_falloff(0.0);
  148. set_edge_fade(0.1);
  149. }
  150. FogMaterial::~FogMaterial() {
  151. RS::get_singleton()->material_set_shader(_get_material(), RID());
  152. }