Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/noise/tests/test_noise_texture_3d.h
10278 views
1
/**************************************************************************/
2
/* test_noise_texture_3d.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_3d.h"
34
35
#include "tests/test_macros.h"
36
37
namespace TestNoiseTexture3D {
38
39
class NoiseTexture3DTester : public RefCounted {
40
GDCLASS(NoiseTexture3DTester, RefCounted);
41
42
const NoiseTexture3D *const texture;
43
44
public:
45
NoiseTexture3DTester(const NoiseTexture3D *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 Vector<Ref<Image>> noise_data = texture->get_data();
65
66
for (int i = 0; i < noise_data.size(); i++) {
67
const Ref<Image> noise_image = noise_data[i];
68
69
CHECK(noise_image.is_valid());
70
CHECK(noise_image->get_width() == texture->get_width());
71
CHECK(noise_image->get_height() == texture->get_height());
72
73
CHECK(noise_image->get_format() == Image::FORMAT_RGBA8);
74
CHECK(!noise_image->has_mipmaps());
75
76
Color avg_color = compute_average_color(noise_image);
77
78
// Check that the noise texture is modulated correctly by the color ramp (Gradient).
79
CHECK_FALSE_MESSAGE((avg_color.r + avg_color.g + avg_color.b) == doctest::Approx(0.0), "The noise texture should not be all black");
80
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");
81
CHECK_MESSAGE(avg_color.g == doctest::Approx(0.0), "The noise texture should not have any green when modulated correctly by the color ramp");
82
}
83
}
84
85
void check_seamless_texture_grayscale() {
86
const Vector<Ref<Image>> noise_data = texture->get_data();
87
88
for (int i = 0; i < noise_data.size(); i++) {
89
const Ref<Image> noise_image = noise_data[i];
90
91
CHECK(noise_image.is_valid());
92
CHECK(noise_image->get_width() == texture->get_width());
93
CHECK(noise_image->get_height() == texture->get_height());
94
95
CHECK(noise_image->get_format() == Image::FORMAT_L8);
96
97
Color avg_color = compute_average_color(noise_image);
98
99
// Since it's a grayscale image and every channel except the alpha channel has the
100
// same values (conversion happens in Image::get_pixel) we only need to test one channel.
101
CHECK(avg_color.r == doctest::Approx(0.5).epsilon(0.05));
102
}
103
}
104
105
void check_seamless_texture_rgba() {
106
const Vector<Ref<Image>> noise_data = texture->get_data();
107
108
for (int i = 0; i < noise_data.size(); i++) {
109
const Ref<Image> noise_image = noise_data[i];
110
111
CHECK(noise_image.is_valid());
112
CHECK(noise_image->get_width() == texture->get_width());
113
CHECK(noise_image->get_height() == texture->get_height());
114
115
CHECK(noise_image->get_format() == Image::FORMAT_RGBA8);
116
117
// Check that the noise texture is modulated correctly by the color ramp (Gradient).
118
Color avg_color = compute_average_color(noise_image);
119
120
// We use a default (black to white) gradient, so the average of the red, green and blue channels should be the same.
121
CHECK(avg_color.r == doctest::Approx(0.5).epsilon(0.05));
122
CHECK(avg_color.g == doctest::Approx(0.5).epsilon(0.05));
123
CHECK(avg_color.b == doctest::Approx(0.5).epsilon(0.05));
124
}
125
}
126
};
127
128
TEST_CASE("[NoiseTexture][SceneTree] Getter and setter") {
129
Ref<NoiseTexture3D> noise_texture = memnew(NoiseTexture3D);
130
131
Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
132
noise_texture->set_noise(noise);
133
CHECK(noise_texture->get_noise() == noise);
134
noise_texture->set_noise(nullptr);
135
CHECK(noise_texture->get_noise().is_null());
136
137
noise_texture->set_width(8);
138
noise_texture->set_height(4);
139
noise_texture->set_depth(2);
140
CHECK(noise_texture->get_width() == 8);
141
CHECK(noise_texture->get_height() == 4);
142
CHECK(noise_texture->get_depth() == 2);
143
144
ERR_PRINT_OFF;
145
noise_texture->set_width(-1);
146
noise_texture->set_height(-1);
147
noise_texture->set_depth(-1);
148
ERR_PRINT_ON;
149
CHECK(noise_texture->get_width() == 8);
150
CHECK(noise_texture->get_height() == 4);
151
CHECK(noise_texture->get_depth() == 2);
152
153
noise_texture->set_invert(true);
154
CHECK(noise_texture->get_invert() == true);
155
noise_texture->set_invert(false);
156
CHECK(noise_texture->get_invert() == false);
157
158
noise_texture->set_seamless(true);
159
CHECK(noise_texture->get_seamless() == true);
160
noise_texture->set_seamless(false);
161
CHECK(noise_texture->get_seamless() == false);
162
163
noise_texture->set_seamless_blend_skirt(0.45);
164
CHECK(noise_texture->get_seamless_blend_skirt() == doctest::Approx(0.45));
165
166
ERR_PRINT_OFF;
167
noise_texture->set_seamless_blend_skirt(-1.0);
168
noise_texture->set_seamless_blend_skirt(2.0);
169
CHECK(noise_texture->get_seamless_blend_skirt() == doctest::Approx(0.45));
170
ERR_PRINT_ON;
171
172
Ref<Gradient> gradient = memnew(Gradient);
173
noise_texture->set_color_ramp(gradient);
174
CHECK(noise_texture->get_color_ramp() == gradient);
175
noise_texture->set_color_ramp(nullptr);
176
CHECK(noise_texture->get_color_ramp().is_null());
177
}
178
179
TEST_CASE("[NoiseTexture3D][SceneTree] Generating a basic noise texture with mipmaps and color ramp modulation") {
180
Ref<NoiseTexture3D> noise_texture = memnew(NoiseTexture3D);
181
182
Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
183
noise_texture->set_noise(noise);
184
185
Ref<Gradient> gradient = memnew(Gradient);
186
Vector<float> offsets = { 0.0, 1.0 };
187
Vector<Color> colors = { Color(1, 0, 0), Color(0, 0, 1) };
188
gradient->set_offsets(offsets);
189
gradient->set_colors(colors);
190
191
noise_texture->set_color_ramp(gradient);
192
noise_texture->set_width(16);
193
noise_texture->set_height(16);
194
noise_texture->set_depth(16);
195
196
Ref<NoiseTexture3DTester> tester = memnew(NoiseTexture3DTester(noise_texture.ptr()));
197
noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTexture3DTester::check_mip_and_color_ramp));
198
MessageQueue::get_singleton()->flush();
199
}
200
201
TEST_CASE("[NoiseTexture3D][SceneTree] Generating a seamless noise texture") {
202
Ref<NoiseTexture3D> noise_texture = memnew(NoiseTexture3D);
203
204
Ref<FastNoiseLite> noise = memnew(FastNoiseLite);
205
noise->set_frequency(0.5);
206
noise_texture->set_noise(noise);
207
noise_texture->set_width(16);
208
noise_texture->set_height(16);
209
noise_texture->set_depth(16);
210
noise_texture->set_seamless(true);
211
212
Ref<NoiseTexture3DTester> tester = memnew(NoiseTexture3DTester(noise_texture.ptr()));
213
214
SUBCASE("Grayscale(L8) 16x16x16, with seamless blend skirt of 0.05") {
215
noise_texture->set_seamless_blend_skirt(0.05);
216
noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTexture3DTester::check_seamless_texture_grayscale));
217
MessageQueue::get_singleton()->flush();
218
}
219
220
SUBCASE("16x16x16 modulated with default (transparent)black and white gradient (RGBA8), with seamless blend skirt of 1.0") {
221
Ref<Gradient> gradient = memnew(Gradient);
222
223
Vector<float> offsets = { 0.0, 1.0 };
224
Vector<Color> colors = { Color(0, 0, 0, 0), Color(1, 1, 1, 1) };
225
gradient->set_offsets(offsets);
226
gradient->set_colors(colors);
227
228
noise_texture->set_color_ramp(gradient);
229
noise_texture->set_seamless_blend_skirt(1.0);
230
noise_texture->connect_changed(callable_mp(tester.ptr(), &NoiseTexture3DTester::check_seamless_texture_rgba));
231
MessageQueue::get_singleton()->flush();
232
}
233
}
234
235
} //namespace TestNoiseTexture3D
236
237