Merge pull request #48805 from radishes/noise-image-offset

Add support for generating noise images with an offset
This commit is contained in:
Rémi Verschelde 2021-05-20 21:00:38 +02:00 committed by GitHub
commit 78d85de13b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 31 additions and 6 deletions

View File

@ -31,6 +31,9 @@
<member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise"> <member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise">
The [OpenSimplexNoise] instance used to generate the noise. The [OpenSimplexNoise] instance used to generate the noise.
</member> </member>
<member name="noise_offset" type="Vector2" setter="set_noise_offset" getter="get_noise_offset" default="Vector2( 0, 0 )">
An offset used to specify the noise space coordinate of the top left corner of the generated noise. This value is ignored if [member seamless] is enabled.
</member>
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false"> <member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate. Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate.
[b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise. [b]Note:[/b] Seamless noise has a lower contrast compared to non-seamless noise. This is due to the way noise uses higher dimensions for generating seamless noise.

View File

@ -31,8 +31,10 @@
</argument> </argument>
<argument index="1" name="height" type="int"> <argument index="1" name="height" type="int">
</argument> </argument>
<argument index="2" name="noise_offset" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description> <description>
Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters. Generate a noise image in [constant Image.FORMAT_L8] format with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters. If [code]noise_offset[/code] is specified, then the offset value is used as the coordinates of the top-left corner of the generated noise.
</description> </description>
</method> </method>
<method name="get_noise_1d" qualifiers="const"> <method name="get_noise_1d" qualifiers="const">

View File

@ -52,6 +52,9 @@ void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise);
ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise);
ClassDB::bind_method(D_METHOD("set_noise_offset", "noise_offset"), &NoiseTexture::set_noise_offset);
ClassDB::bind_method(D_METHOD("get_noise_offset"), &NoiseTexture::get_noise_offset);
ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless); ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless);
ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless); ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless);
@ -71,6 +74,7 @@ void NoiseTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normal_map"), "set_as_normal_map", "is_normal_map"); 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::FLOAT, "bump_strength", PROPERTY_HINT_RANGE, "0,32,0.1,or_greater"), "set_bump_strength", "get_bump_strength");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "OpenSimplexNoise"), "set_noise", "get_noise");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "noise_offset"), "set_noise_offset", "get_noise_offset");
} }
void NoiseTexture::_validate_property(PropertyInfo &property) const { void NoiseTexture::_validate_property(PropertyInfo &property) const {
@ -130,7 +134,7 @@ Ref<Image> NoiseTexture::_generate_texture() {
if (seamless) { if (seamless) {
image = ref_noise->get_seamless_image(size.x); image = ref_noise->get_seamless_image(size.x);
} else { } else {
image = ref_noise->get_image(size.x, size.y); image = ref_noise->get_image(size.x, size.y, noise_offset);
} }
if (as_normal_map) { if (as_normal_map) {
@ -198,6 +202,14 @@ void NoiseTexture::set_height(int p_height) {
_queue_update(); _queue_update();
} }
void NoiseTexture::set_noise_offset(Vector2 p_noise_offset) {
if (noise_offset == p_noise_offset) {
return;
}
noise_offset = p_noise_offset;
_queue_update();
}
void NoiseTexture::set_seamless(bool p_seamless) { void NoiseTexture::set_seamless(bool p_seamless) {
if (p_seamless == seamless) { if (p_seamless == seamless) {
return; return;
@ -245,6 +257,10 @@ int NoiseTexture::get_height() const {
return size.y; return size.y;
} }
Vector2 NoiseTexture::get_noise_offset() const {
return noise_offset;
}
RID NoiseTexture::get_rid() const { RID NoiseTexture::get_rid() const {
if (!texture.is_valid()) { if (!texture.is_valid()) {
texture = RS::get_singleton()->texture_2d_placeholder_create(); texture = RS::get_singleton()->texture_2d_placeholder_create();

View File

@ -56,6 +56,7 @@ private:
Ref<OpenSimplexNoise> noise; Ref<OpenSimplexNoise> noise;
Vector2i size = Vector2i(512, 512); Vector2i size = Vector2i(512, 512);
Vector2 noise_offset;
bool seamless = false; bool seamless = false;
bool as_normal_map = false; bool as_normal_map = false;
float bump_strength = 8.0; float bump_strength = 8.0;
@ -79,6 +80,9 @@ public:
void set_width(int p_width); void set_width(int p_width);
void set_height(int p_height); void set_height(int p_height);
void set_noise_offset(Vector2 p_noise_offset);
Vector2 get_noise_offset() const;
void set_seamless(bool p_seamless); void set_seamless(bool p_seamless);
bool get_seamless(); bool get_seamless();

View File

@ -96,7 +96,7 @@ void OpenSimplexNoise::set_lacunarity(float p_lacunarity) {
emit_changed(); emit_changed();
} }
Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const { Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height, const Vector2 &p_noise_offset) const {
Vector<uint8_t> data; Vector<uint8_t> data;
data.resize(p_width * p_height); data.resize(p_width * p_height);
@ -104,7 +104,7 @@ Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) const {
for (int i = 0; i < p_height; i++) { for (int i = 0; i < p_height; i++) {
for (int j = 0; j < p_width; j++) { for (int j = 0; j < p_width; j++) {
float v = get_noise_2d(j, i); float v = get_noise_2d(float(j) + p_noise_offset.x, float(i) + p_noise_offset.y);
v = v * 0.5 + 0.5; // Normalize [0..1] v = v * 0.5 + 0.5; // Normalize [0..1]
wd8[(i * p_width + j)] = uint8_t(CLAMP(v * 255.0, 0, 255)); wd8[(i * p_width + j)] = uint8_t(CLAMP(v * 255.0, 0, 255));
} }
@ -161,7 +161,7 @@ void OpenSimplexNoise::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &OpenSimplexNoise::set_lacunarity); ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &OpenSimplexNoise::set_lacunarity);
ClassDB::bind_method(D_METHOD("get_lacunarity"), &OpenSimplexNoise::get_lacunarity); ClassDB::bind_method(D_METHOD("get_lacunarity"), &OpenSimplexNoise::get_lacunarity);
ClassDB::bind_method(D_METHOD("get_image", "width", "height"), &OpenSimplexNoise::get_image); ClassDB::bind_method(D_METHOD("get_image", "width", "height", "noise_offset"), &OpenSimplexNoise::get_image, DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &OpenSimplexNoise::get_seamless_image); ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &OpenSimplexNoise::get_seamless_image);
ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &OpenSimplexNoise::get_noise_1d); ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &OpenSimplexNoise::get_noise_1d);

View File

@ -75,7 +75,7 @@ public:
void set_lacunarity(float p_lacunarity); void set_lacunarity(float p_lacunarity);
float get_lacunarity() const { return lacunarity; } float get_lacunarity() const { return lacunarity; }
Ref<Image> get_image(int p_width, int p_height) const; Ref<Image> get_image(int p_width, int p_height, const Vector2 &p_noise_offset = Vector2()) const;
Ref<Image> get_seamless_image(int p_size) const; Ref<Image> get_seamless_image(int p_size) const;
float get_noise_1d(float x) const; float get_noise_1d(float x) const;