summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Brucker <hendrik.brucker@mail.de>2023-01-29 14:56:10 +0100
committerHendrik Brucker <hendrik.brucker@mail.de>2023-01-29 14:59:10 +0100
commitd44eb95e93d239e79477ad1fd882dbbe0cdebb92 (patch)
tree57272b0fcedd1ddca9ee2bc7a9fb44e1802262d1
parentd01ac9c73686fdf86f083f4d3ee1301bb54d855f (diff)
[Noise/NoiseTexture2D] Allow disabling normalization
-rw-r--r--modules/noise/doc_classes/Noise.xml4
-rw-r--r--modules/noise/doc_classes/NoiseTexture2D.xml4
-rw-r--r--modules/noise/noise.cpp77
-rw-r--r--modules/noise/noise.h4
-rw-r--r--modules/noise/noise_texture_2d.cpp20
-rw-r--r--modules/noise/noise_texture_2d.h4
6 files changed, 76 insertions, 37 deletions
diff --git a/modules/noise/doc_classes/Noise.xml b/modules/noise/doc_classes/Noise.xml
index 735ca388de..78d7d6a15b 100644
--- a/modules/noise/doc_classes/Noise.xml
+++ b/modules/noise/doc_classes/Noise.xml
@@ -17,8 +17,10 @@
<param index="1" name="height" type="int" />
<param index="2" name="invert" type="bool" default="false" />
<param index="3" name="in_3d_space" type="bool" default="false" />
+ <param index="4" name="normalize" type="bool" default="true" />
<description>
Returns a 2D [Image] noise image.
+ Note: With [param normalize] set to [code]false[/code] the default implementation expects the noise generator to return values in the range [code]-1.0[/code] to [code]1.0[/code].
</description>
</method>
<method name="get_noise_1d" qualifiers="const">
@@ -66,8 +68,10 @@
<param index="2" name="invert" type="bool" default="false" />
<param index="3" name="in_3d_space" type="bool" default="false" />
<param index="4" name="skirt" type="float" default="0.1" />
+ <param index="5" name="normalize" type="bool" default="true" />
<description>
Returns a seamless 2D [Image] noise image.
+ Note: With [param normalize] set to [code]false[/code] the default implementation expects the noise generator to return values in the range [code]-1.0[/code] to [code]1.0[/code].
</description>
</method>
</methods>
diff --git a/modules/noise/doc_classes/NoiseTexture2D.xml b/modules/noise/doc_classes/NoiseTexture2D.xml
index 0a800a143b..0f10a3f32f 100644
--- a/modules/noise/doc_classes/NoiseTexture2D.xml
+++ b/modules/noise/doc_classes/NoiseTexture2D.xml
@@ -44,6 +44,10 @@
<member name="noise" type="Noise" setter="set_noise" getter="get_noise">
The instance of the [Noise] object.
</member>
+ <member name="normalize" type="bool" setter="set_normalize" getter="is_normalized" default="true">
+ If [code]true[/code], the noise image coming from the noise generator is normalized to the range [code]0.0[/code] to [code]1.0[/code].
+ Turning normalization off can affect the contrast and allows you to generate non repeating tileable noise textures.
+ </member>
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
If [code]true[/code], a seamless texture is requested from the [Noise] resource.
diff --git a/modules/noise/noise.cpp b/modules/noise/noise.cpp
index 5a901cb6e1..e95788b863 100644
--- a/modules/noise/noise.cpp
+++ b/modules/noise/noise.cpp
@@ -32,7 +32,7 @@
#include <float.h>
-Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space, real_t p_blend_skirt) const {
+Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space, real_t p_blend_skirt, bool p_normalize) const {
ERR_FAIL_COND_V(p_width <= 0 || p_height <= 0, Ref<Image>());
int skirt_width = MAX(1, p_width * p_blend_skirt);
@@ -40,7 +40,7 @@ Ref<Image> Noise::get_seamless_image(int p_width, int p_height, bool p_invert, b
int src_width = p_width + skirt_width;
int src_height = p_height + skirt_height;
- Ref<Image> src = get_image(src_width, src_height, p_invert, p_in_3d_space);
+ Ref<Image> src = get_image(src_width, src_height, p_invert, p_in_3d_space, p_normalize);
bool grayscale = (src->get_format() == Image::FORMAT_L8);
if (grayscale) {
return _generate_seamless_image<uint8_t>(src, p_width, p_height, p_invert, p_blend_skirt);
@@ -58,7 +58,7 @@ uint8_t Noise::_alpha_blend<uint8_t>(uint8_t p_bg, uint8_t p_fg, int p_alpha) co
return (uint8_t)((alpha * p_fg + inv_alpha * p_bg) >> 8);
}
-Ref<Image> Noise::get_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space) const {
+Ref<Image> Noise::get_image(int p_width, int p_height, bool p_invert, bool p_in_3d_space, bool p_normalize) const {
ERR_FAIL_COND_V(p_width <= 0 || p_height <= 0, Ref<Image>());
Vector<uint8_t> data;
@@ -66,38 +66,49 @@ Ref<Image> Noise::get_image(int p_width, int p_height, bool p_invert, bool p_in_
uint8_t *wd8 = data.ptrw();
- // Get all values and identify min/max values.
- Vector<real_t> values;
- values.resize(p_width * p_height);
- real_t min_val = FLT_MAX;
- real_t max_val = -FLT_MAX;
-
- for (int y = 0, i = 0; y < p_height; y++) {
- for (int x = 0; x < p_width; x++, i++) {
- values.set(i, p_in_3d_space ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y));
- if (values[i] > max_val) {
- max_val = values[i];
- }
- if (values[i] < min_val) {
- min_val = values[i];
+ if (p_normalize) {
+ // Get all values and identify min/max values.
+ Vector<real_t> values;
+ values.resize(p_width * p_height);
+ real_t min_val = FLT_MAX;
+ real_t max_val = -FLT_MAX;
+ for (int y = 0, i = 0; y < p_height; y++) {
+ for (int x = 0; x < p_width; x++, i++) {
+ values.set(i, p_in_3d_space ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y));
+ if (values[i] > max_val) {
+ max_val = values[i];
+ }
+ if (values[i] < min_val) {
+ min_val = values[i];
+ }
}
}
- }
-
- // Normalize values and write to texture.
- uint8_t value;
- for (int i = 0, x = 0; i < p_height; i++) {
- for (int j = 0; j < p_width; j++, x++) {
- if (max_val == min_val) {
- value = 0;
- } else {
- value = uint8_t(CLAMP((values[x] - min_val) / (max_val - min_val) * 255.f, 0, 255));
+ // Normalize values and write to texture.
+ uint8_t ivalue;
+ for (int i = 0, x = 0; i < p_height; i++) {
+ for (int j = 0; j < p_width; j++, x++) {
+ if (max_val == min_val) {
+ ivalue = 0;
+ } else {
+ ivalue = static_cast<uint8_t>(CLAMP((values[x] - min_val) / (max_val - min_val) * 255.f, 0, 255));
+ }
+
+ if (p_invert) {
+ ivalue = 255 - ivalue;
+ }
+
+ wd8[x] = ivalue;
}
- if (p_invert) {
- value = 255 - value;
+ }
+ } else {
+ // Without normalization, the expected range of the noise function is [-1, 1].
+ uint8_t ivalue;
+ for (int y = 0, i = 0; y < p_height; y++) {
+ for (int x = 0; x < p_width; x++, i++) {
+ float value = (p_in_3d_space ? get_noise_3d(x, y, 0.0) : get_noise_2d(x, y));
+ ivalue = static_cast<uint8_t>(CLAMP(value * 127.5f + 127.5f, 0.0f, 255.0f));
+ wd8[i] = p_invert ? (255 - ivalue) : ivalue;
}
-
- wd8[x] = value;
}
}
@@ -113,6 +124,6 @@ void Noise::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_noise_3dv", "v"), &Noise::get_noise_3dv);
// Textures.
- ClassDB::bind_method(D_METHOD("get_image", "width", "height", "invert", "in_3d_space"), &Noise::get_image, DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_seamless_image", "width", "height", "invert", "in_3d_space", "skirt"), &Noise::get_seamless_image, DEFVAL(false), DEFVAL(false), DEFVAL(0.1));
+ ClassDB::bind_method(D_METHOD("get_image", "width", "height", "invert", "in_3d_space", "normalize"), &Noise::get_image, DEFVAL(false), DEFVAL(false), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_seamless_image", "width", "height", "invert", "in_3d_space", "skirt", "normalize"), &Noise::get_seamless_image, DEFVAL(false), DEFVAL(false), DEFVAL(0.1), DEFVAL(true));
}
diff --git a/modules/noise/noise.h b/modules/noise/noise.h
index 8f8ecf29a5..f7e615c2aa 100644
--- a/modules/noise/noise.h
+++ b/modules/noise/noise.h
@@ -233,8 +233,8 @@ public:
virtual real_t get_noise_3dv(Vector3 p_v) const = 0;
virtual real_t get_noise_3d(real_t p_x, real_t p_y, real_t p_z) const = 0;
- virtual Ref<Image> get_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false) const;
- virtual Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false, real_t p_blend_skirt = 0.1) const;
+ virtual Ref<Image> get_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false, bool p_normalize = true) const;
+ virtual Ref<Image> get_seamless_image(int p_width, int p_height, bool p_invert = false, bool p_in_3d_space = false, real_t p_blend_skirt = 0.1, bool p_normalize = true) const;
};
#endif // NOISE_H
diff --git a/modules/noise/noise_texture_2d.cpp b/modules/noise/noise_texture_2d.cpp
index 0eedb286bd..0d5e778875 100644
--- a/modules/noise/noise_texture_2d.cpp
+++ b/modules/noise/noise_texture_2d.cpp
@@ -76,6 +76,9 @@ void NoiseTexture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture2D::set_bump_strength);
ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture2D::get_bump_strength);
+ ClassDB::bind_method(D_METHOD("set_normalize", "normalize"), &NoiseTexture2D::set_normalize);
+ ClassDB::bind_method(D_METHOD("is_normalized"), &NoiseTexture2D::is_normalized);
+
ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture2D::set_color_ramp);
ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture2D::get_color_ramp);
@@ -91,6 +94,7 @@ void NoiseTexture2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "seamless_blend_skirt", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_seamless_blend_skirt", "get_seamless_blend_skirt");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normal_map"), "set_as_normal_map", "is_normal_map");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalize"), "set_normalize", "is_normalized");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "Gradient"), "set_color_ramp", "get_color_ramp");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "Noise"), "set_noise", "get_noise");
}
@@ -156,9 +160,9 @@ Ref<Image> NoiseTexture2D::_generate_texture() {
Ref<Image> new_image;
if (seamless) {
- new_image = ref_noise->get_seamless_image(size.x, size.y, invert, in_3d_space, seamless_blend_skirt);
+ new_image = ref_noise->get_seamless_image(size.x, size.y, invert, in_3d_space, seamless_blend_skirt, normalize);
} else {
- new_image = ref_noise->get_image(size.x, size.y, invert, in_3d_space);
+ new_image = ref_noise->get_image(size.x, size.y, invert, in_3d_space, normalize);
}
if (color_ramp.is_valid()) {
new_image = _modulate_with_gradient(new_image, color_ramp);
@@ -349,6 +353,18 @@ void NoiseTexture2D::set_color_ramp(const Ref<Gradient> &p_gradient) {
_queue_update();
}
+void NoiseTexture2D::set_normalize(bool p_normalize) {
+ if (normalize == p_normalize) {
+ return;
+ }
+ normalize = p_normalize;
+ _queue_update();
+}
+
+bool NoiseTexture2D::is_normalized() const {
+ return normalize;
+}
+
Ref<Gradient> NoiseTexture2D::get_color_ramp() const {
return color_ramp;
}
diff --git a/modules/noise/noise_texture_2d.h b/modules/noise/noise_texture_2d.h
index cda14df6c2..f53670b690 100644
--- a/modules/noise/noise_texture_2d.h
+++ b/modules/noise/noise_texture_2d.h
@@ -59,6 +59,7 @@ private:
real_t seamless_blend_skirt = 0.1;
bool as_normal_map = false;
float bump_strength = 8.0;
+ bool normalize = true;
Ref<Gradient> color_ramp;
Ref<Noise> noise;
@@ -105,6 +106,9 @@ public:
void set_bump_strength(float p_bump_strength);
float get_bump_strength();
+ void set_normalize(bool p_normalize);
+ bool is_normalized() const;
+
void set_color_ramp(const Ref<Gradient> &p_gradient);
Ref<Gradient> get_color_ramp() const;