mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 11:32:13 +00:00
[Noise/NoiseTexture2D] Allow disabling normalization
This commit is contained in:
parent
d01ac9c736
commit
d44eb95e93
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -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 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));
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
if (p_invert) {
|
||||
value = 255 - value;
|
||||
}
|
||||
if (p_invert) {
|
||||
ivalue = 255 - ivalue;
|
||||
}
|
||||
|
||||
wd8[x] = value;
|
||||
wd8[x] = ivalue;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user