test_noise_texture_2d.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /**************************************************************************/
  2. /* test_noise_texture_2d.h */
  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. #ifndef TEST_NOISE_TEXTURE_2D_H
  31. #define TEST_NOISE_TEXTURE_2D_H
  32. #include "../noise_texture_2d.h"
  33. #include "tests/test_macros.h"
  34. namespace TestNoiseTexture2D {
  35. class NoiseTextureTester : public RefCounted {
  36. GDCLASS(NoiseTextureTester, RefCounted);
  37. const NoiseTexture2D *const texture;
  38. public:
  39. NoiseTextureTester(const NoiseTexture2D *const p_texture) :
  40. texture{ p_texture } {}
  41. Color compute_average_color(const Ref<Image> &p_noise_image) {
  42. Color r_avg_color{};
  43. for (int i = 0; i < p_noise_image->get_width(); ++i) {
  44. for (int j = 0; j < p_noise_image->get_height(); ++j) {
  45. const Color pixel = p_noise_image->get_pixel(i, j);
  46. r_avg_color += pixel;
  47. }
  48. }
  49. int pixel_count = p_noise_image->get_width() * p_noise_image->get_height();
  50. r_avg_color /= pixel_count;
  51. return r_avg_color;
  52. }
  53. void check_mip_and_color_ramp() {
  54. const Ref<Image> noise_image = texture->get_image();
  55. CHECK(noise_image.is_valid());
  56. CHECK(noise_image->get_width() == texture->get_width());
  57. CHECK(noise_image->get_height() == texture->get_height());
  58. CHECK(noise_image->get_format() == Image::FORMAT_RGBA8);
  59. CHECK(noise_image->has_mipmaps());
  60. Color avg_color = compute_average_color(noise_image);
  61. // Check that the noise texture is modulated correctly by the color ramp (Gradient).
  62. CHECK_FALSE_MESSAGE((avg_color.r + avg_color.g + avg_color.b) == doctest::Approx(0.0), "The noise texture should not be all black");
  63. CHECK_FALSE_MESSAGE((avg_color.r + avg_color.g + avg_color.b) == doctest::Approx(noise_image->get_width() * noise_image->get_height() * 3.0), "The noise texture should not be all white");
  64. CHECK_MESSAGE(avg_color.g == doctest::Approx(0.0), "The noise texture should not have any green when modulated correctly by the color ramp");
  65. }
  66. void check_normal_map() {
  67. const Ref<Image> noise_image = texture->get_image();
  68. CHECK(noise_image.is_valid());
  69. CHECK(noise_image->get_width() == texture->get_width());
  70. CHECK(noise_image->get_height() == texture->get_height());
  71. CHECK(noise_image->get_format() == Image::FORMAT_RGBA8);
  72. CHECK_FALSE(noise_image->has_mipmaps());
  73. Color avg_color = compute_average_color(noise_image);
  74. // Check for the characteristic color distribution (for tangent space) of a normal map.
  75. CHECK(avg_color.r == doctest::Approx(0.5).epsilon(0.05));
  76. CHECK(avg_color.g == doctest::Approx(0.5).epsilon(0.05));
  77. CHECK(avg_color.b == doctest::Approx(1.0).epsilon(0.05));
  78. }
  79. void check_seamless_texture_grayscale() {
  80. const Ref<Image> noise_image = texture->get_image();
  81. CHECK(noise_image.is_valid());
  82. CHECK(noise_image->get_width() == texture->get_width());
  83. CHECK(noise_image->get_height() == texture->get_height());
  84. CHECK(noise_image->get_format() == Image::FORMAT_L8);
  85. Color avg_color = compute_average_color(noise_image);
  86. // Since it's a grayscale image and every channel except the alpha channel has the
  87. // same values (conversion happens in Image::get_pixel) we only need to test one channel.
  88. CHECK(avg_color.r == doctest::Approx(0.5).epsilon(0.05));
  89. }
  90. void check_seamless_texture_rgba() {
  91. const Ref<Image> noise_image = texture->get_image();
  92. CHECK(noise_image.is_valid());
  93. CHECK(noise_image->get_width() == texture->get_width());
  94. CHECK(noise_image->get_height() == texture->get_height());
  95. CHECK(noise_image->get_format() == Image::FORMAT_RGBA8);
  96. // Check that the noise texture is modulated correctly by the color ramp (Gradient).
  97. Color avg_color = compute_average_color(noise_image);
  98. // We use a default (black to white) gradient, so the average of the red, green and blue channels should be the same.
  99. CHECK(avg_color.r == doctest::Approx(0.5).epsilon(0.05));
  100. CHECK(avg_color.g == doctest::Approx(0.5).epsilon(0.05));
  101. CHECK(avg_color.b == doctest::Approx(0.5).epsilon(0.05));
  102. }
  103. };
  104. TEST_CASE("[NoiseTexture][SceneTree] Getter and setter") {
  105. Ref<NoiseTexture2D> noise_texture = memnew(NoiseTexture2D);
  106. Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
  107. noise_texture->set_noise(noise);
  108. CHECK(noise_texture->get_noise() == noise);
  109. noise_texture->set_noise(nullptr);
  110. CHECK(noise_texture->get_noise().is_null());
  111. noise_texture->set_width(8);
  112. noise_texture->set_height(4);
  113. CHECK(noise_texture->get_width() == 8);
  114. CHECK(noise_texture->get_height() == 4);
  115. ERR_PRINT_OFF;
  116. noise_texture->set_width(-1);
  117. noise_texture->set_height(-1);
  118. ERR_PRINT_ON;
  119. CHECK(noise_texture->get_width() == 8);
  120. CHECK(noise_texture->get_height() == 4);
  121. noise_texture->set_invert(true);
  122. CHECK(noise_texture->get_invert() == true);
  123. noise_texture->set_invert(false);
  124. CHECK(noise_texture->get_invert() == false);
  125. noise_texture->set_in_3d_space(true);
  126. CHECK(noise_texture->is_in_3d_space() == true);
  127. noise_texture->set_in_3d_space(false);
  128. CHECK(noise_texture->is_in_3d_space() == false);
  129. noise_texture->set_generate_mipmaps(true);
  130. CHECK(noise_texture->is_generating_mipmaps() == true);
  131. noise_texture->set_generate_mipmaps(false);
  132. CHECK(noise_texture->is_generating_mipmaps() == false);
  133. noise_texture->set_seamless(true);
  134. CHECK(noise_texture->get_seamless() == true);
  135. noise_texture->set_seamless(false);
  136. CHECK(noise_texture->get_seamless() == false);
  137. noise_texture->set_seamless_blend_skirt(0.45);
  138. CHECK(noise_texture->get_seamless_blend_skirt() == doctest::Approx(0.45));
  139. ERR_PRINT_OFF;
  140. noise_texture->set_seamless_blend_skirt(-1.0);
  141. noise_texture->set_seamless_blend_skirt(2.0);
  142. CHECK(noise_texture->get_seamless_blend_skirt() == doctest::Approx(0.45));
  143. ERR_PRINT_ON;
  144. noise_texture->set_as_normal_map(true);
  145. CHECK(noise_texture->is_normal_map() == true);
  146. noise_texture->set_as_normal_map(false);
  147. CHECK(noise_texture->is_normal_map() == false);
  148. noise_texture->set_bump_strength(0.168);
  149. CHECK(noise_texture->get_bump_strength() == doctest::Approx(0.168));
  150. Ref<Gradient> gradient = memnew(Gradient);
  151. noise_texture->set_color_ramp(gradient);
  152. CHECK(noise_texture->get_color_ramp() == gradient);
  153. noise_texture->set_color_ramp(nullptr);
  154. CHECK(noise_texture->get_color_ramp().is_null());
  155. }
  156. TEST_CASE("[NoiseTexture2D][SceneTree] Generating a basic noise texture with mipmaps and color ramp modulation") {
  157. Ref<NoiseTexture2D> noise_texture = memnew(NoiseTexture2D);
  158. Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
  159. noise_texture->set_noise(noise);
  160. Ref<Gradient> gradient = memnew(Gradient);
  161. Vector<float> offsets = { 0.0, 1.0 };
  162. Vector<Color> colors = { Color(1, 0, 0), Color(0, 0, 1) };
  163. gradient->set_offsets(offsets);
  164. gradient->set_colors(colors);
  165. noise_texture->set_color_ramp(gradient);
  166. noise_texture->set_width(16);
  167. noise_texture->set_height(16);
  168. noise_texture->set_generate_mipmaps(true);
  169. Ref<NoiseTextureTester> tester = memnew(NoiseTextureTester(noise_texture.ptr()));
  170. noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTextureTester::check_mip_and_color_ramp));
  171. MessageQueue::get_singleton()->flush();
  172. }
  173. TEST_CASE("[NoiseTexture2D][SceneTree] Generating a normal map without mipmaps") {
  174. Ref<NoiseTexture2D> noise_texture = memnew(NoiseTexture2D);
  175. Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
  176. noise->set_frequency(0.5);
  177. noise_texture->set_noise(noise);
  178. noise_texture->set_width(16);
  179. noise_texture->set_height(16);
  180. noise_texture->set_as_normal_map(true);
  181. noise_texture->set_bump_strength(0.5);
  182. noise_texture->set_generate_mipmaps(false);
  183. Ref<NoiseTextureTester> tester = memnew(NoiseTextureTester(noise_texture.ptr()));
  184. noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTextureTester::check_normal_map));
  185. MessageQueue::get_singleton()->flush();
  186. }
  187. TEST_CASE("[NoiseTexture2D][SceneTree] Generating a seamless noise texture") {
  188. Ref<NoiseTexture2D> noise_texture = memnew(NoiseTexture2D);
  189. Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
  190. noise->set_frequency(0.5);
  191. noise_texture->set_noise(noise);
  192. noise_texture->set_width(16);
  193. noise_texture->set_height(16);
  194. noise_texture->set_seamless(true);
  195. Ref<NoiseTextureTester> tester = memnew(NoiseTextureTester(noise_texture.ptr()));
  196. SUBCASE("Grayscale(L8) 16x16, with seamless blend skirt of 0.05") {
  197. noise_texture->set_seamless_blend_skirt(0.05);
  198. noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTextureTester::check_seamless_texture_grayscale));
  199. MessageQueue::get_singleton()->flush();
  200. }
  201. SUBCASE("16x16 modulated with default (transparent)black and white gradient (RGBA8), with seamless blend skirt of 1.0") {
  202. Ref<Gradient> gradient = memnew(Gradient);
  203. Vector<float> offsets = { 0.0, 1.0 };
  204. Vector<Color> colors = { Color(0, 0, 0, 0), Color(1, 1, 1, 1) };
  205. gradient->set_offsets(offsets);
  206. gradient->set_colors(colors);
  207. noise_texture->set_color_ramp(gradient);
  208. noise_texture->set_seamless_blend_skirt(1.0);
  209. noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTextureTester::check_seamless_texture_rgba));
  210. MessageQueue::get_singleton()->flush();
  211. }
  212. }
  213. } //namespace TestNoiseTexture2D
  214. #endif // TEST_NOISE_TEXTURE_2D_H