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