Merge pull request #21569 from JFonS/add_noise_textures

Add SimplexNoise and NoiseTexture as new resources
This commit is contained in:
Rémi Verschelde 2018-09-14 16:57:26 +02:00 committed by GitHub
commit 2aad7f1376
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 3450 additions and 2 deletions

View file

@ -0,0 +1,4 @@
#!/usr/bin/env python
Import('env')
env.add_source_files(env.modules_sources, ["register_types.cpp", "simplex_noise.cpp", "noise_texture.cpp", "#thirdparty/misc/open-simplex-noise.c"])

View file

@ -0,0 +1,14 @@
def can_build(env, platform):
return True
def configure(env):
pass
def get_doc_classes():
return [
"NoiseTexture",
"SimplexNoise"
]
def get_doc_path():
return "doc_classes"

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="NoiseTexture" inherits="Texture" category="Core" version="3.1">
<brief_description>
[SimplexNoise] filled texture.
</brief_description>
<description>
Uses a [SimplexNoise] to fill the texture data. You can specify the texture size but keep in mind that larger textures will take longer to generate and seamless noise only works with square sized textures.
NoiseTexture can also generate normalmap textures.
</description>
<tutorials>
</tutorials>
<demos>
</demos>
<methods>
<method name="set_height">
<return type="void">
</return>
<argument index="0" name="height" type="int">
</argument>
<description>
Set texture height.
</description>
</method>
<method name="set_width">
<return type="void">
</return>
<argument index="0" name="width" type="int">
</argument>
<description>
Set texture width.
</description>
</method>
</methods>
<members>
<member name="as_normalmap" type="bool" setter="set_as_normalmap" getter="is_normalmap">
If true, the resulting texture contains a normal map created from the original noise interpreted as a bump map.
</member>
<member name="noise" type="SimplexNoise" setter="set_noise" getter="get_noise">
The [SimplexNoise] instance used to generate the noise.
</member>
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless">
Whether the texture can be tiled without visible seams or not. Seamless textures take longer to generate.
</member>
<member name="size" type="Vector2" setter="set_size" getter="get_size">
Size of the generated texture.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SimplexNoise" inherits="Resource" category="Core" version="3.1">
<brief_description>
Noise generator based on Open Simplex.
</brief_description>
<description>
This resource allows you to configure and sample a fractal noise space.
Here is a brief usage example that configures a SimplexNoise and gets samples at various positions and dimensions:
[codeblock]
var noise = SimplexNoise.new()
# Configure
noise.seed = randi()
noise.octaves = 4
noise.period = 20.0
noise.persistance = 0.8
#Sample
print("Values:")
print(noise.get_noise_2d(1.0,1.0))
print(noise.get_noise_3d(0.5,3.0,15.0))
print(noise.get_noise_3d(0.5,1.9,4.7,0.0))
[/codeblock]
</description>
<tutorials>
</tutorials>
<demos>
</demos>
<methods>
<method name="get_image">
<return type="Image">
</return>
<argument index="0" name="width" type="int">
</argument>
<argument index="1" name="height" type="int">
</argument>
<description>
Generate a noise image with the requested [code]width[/code] and [code]height[/code], based on the current noise parameters.
</description>
</method>
<method name="get_noise_2d">
<return type="float">
</return>
<argument index="0" name="x" type="float">
</argument>
<argument index="1" name="y" type="float">
</argument>
<description>
2D noise value [-1,1] at position [code]x[/code],[code]y[/code].
</description>
</method>
<method name="get_noise_2dv">
<return type="float">
</return>
<argument index="0" name="pos" type="Vector2">
</argument>
<description>
2D noise value [-1,1] at position [code]pos.x[/code],[code]pos.y[/code].
</description>
</method>
<method name="get_noise_3d">
<return type="float">
</return>
<argument index="0" name="x" type="float">
</argument>
<argument index="1" name="y" type="float">
</argument>
<argument index="2" name="z" type="float">
</argument>
<description>
3D noise value [-1,1] at position [code]x[/code],[code]y[/code],[code]z[/code].
</description>
</method>
<method name="get_noise_3dv">
<return type="float">
</return>
<argument index="0" name="pos" type="Vector3">
</argument>
<description>
3D noise value [-1,1] at position [code]pos.x[/code],[code]pos.y[/code],[code]pos.z[/code].
</description>
</method>
<method name="get_noise_4d">
<return type="float">
</return>
<argument index="0" name="x" type="float">
</argument>
<argument index="1" name="y" type="float">
</argument>
<argument index="2" name="z" type="float">
</argument>
<argument index="3" name="w" type="float">
</argument>
<description>
4D noise value [-1,1] at position [code]x[/code],[code]y[/code],[code]z[/code],[code]w[/code].
</description>
</method>
<method name="get_seamless_image">
<return type="Image">
</return>
<argument index="0" name="size" type="int">
</argument>
<description>
Generate a tileable noise image, based on the current noise parameters.
Generated seamless images are always square ([code]size[/code]x[code]size[/code]).
</description>
</method>
</methods>
<members>
<member name="lacunarity" type="float" setter="set_lacunarity" getter="get_lacunarity">
Difference in period between [member octaves].
</member>
<member name="octaves" type="int" setter="set_octaves" getter="get_octaves">
Number of Simplex Noise layers that are sampled to get the fractal noise.
</member>
<member name="period" type="float" setter="set_period" getter="get_period">
Period of the base octave.
A lower period results in a higher frequancy noise (more value changes across the same distance).
</member>
<member name="persistance" type="float" setter="set_persistance" getter="get_persistance">
Contribuiton factor of the different octaves.
A [code]persistance[/code] value of 1 means all the octaves have the same contribution, a value of 0.5 means each octave contributes half as much as the previous one.
</member>
<member name="seed" type="int" setter="set_seed" getter="get_seed">
Seed used to generate random values, different seeds will generate different noise maps.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -0,0 +1,244 @@
/*************************************************************************/
/* noise_texture.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "noise_texture.h"
#include "core/core_string_names.h"
NoiseTexture::NoiseTexture() {
update_queued = false;
noise_thread = NULL;
regen_queued = false;
first_time = true;
size = Vector2i(512, 512);
seamless = false;
as_normalmap = false;
flags = FLAGS_DEFAULT;
noise = Ref<SimplexNoise>();
texture = VS::get_singleton()->texture_create();
_queue_update();
}
NoiseTexture::~NoiseTexture() {
VS::get_singleton()->free(texture);
}
void NoiseTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width);
ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height);
ClassDB::bind_method(D_METHOD("set_size", "size"), &NoiseTexture::set_size);
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("set_seamless", "seamless"), &NoiseTexture::set_seamless);
ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless);
ClassDB::bind_method(D_METHOD("set_as_normalmap", "as_normalmap"), &NoiseTexture::set_as_normalmap);
ClassDB::bind_method(D_METHOD("is_normalmap"), &NoiseTexture::is_normalmap);
ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture);
ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture);
ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "seamless"), "set_seamless", "get_seamless");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "as_normalmap"), "set_as_normalmap", "is_normalmap");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "SimplexNoise"), "set_noise", "get_noise");
}
void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) {
data = p_image;
if (data.is_valid()) {
VS::get_singleton()->texture_allocate(texture, size.x, size.y, 0, Image::FORMAT_RGBA8, VS::TEXTURE_TYPE_2D, flags);
VS::get_singleton()->texture_set_data(texture, p_image);
}
emit_changed();
}
void NoiseTexture::_thread_done(const Ref<Image> &p_image) {
_set_texture_data(p_image);
Thread::wait_to_finish(noise_thread);
memdelete(noise_thread);
noise_thread = NULL;
if (regen_queued) {
noise_thread = Thread::create(_thread_function, this);
regen_queued = false;
}
}
void NoiseTexture::_thread_function(void *p_ud) {
NoiseTexture *tex = (NoiseTexture *)p_ud;
tex->call_deferred("_thread_done", tex->_generate_texture());
}
void NoiseTexture::_queue_update() {
if (update_queued)
return;
update_queued = true;
call_deferred("_update_texture");
}
Ref<Image> NoiseTexture::_generate_texture() {
update_queued = false;
if (noise.is_null()) return Ref<Image>();
Ref<Image> image;
if (seamless) {
image = noise->get_seamless_image(size.x);
} else {
image = noise->get_image(size.x, size.y);
}
if (as_normalmap) {
image->bumpmap_to_normalmap();
}
return image;
}
void NoiseTexture::_update_texture() {
bool use_thread = true;
if (first_time) {
use_thread = false;
first_time = false;
}
#ifdef NO_THREADS
use_thread = false;
#endif
if (use_thread) {
if (!noise_thread) {
noise_thread = Thread::create(_thread_function, this);
regen_queued = false;
} else {
regen_queued = true;
}
} else {
Ref<Image> image = _generate_texture();
_set_texture_data(image);
}
}
void NoiseTexture::set_noise(Ref<SimplexNoise> p_noise) {
if (p_noise == noise)
return;
if (noise.is_valid()) {
noise->disconnect(CoreStringNames::get_singleton()->changed, this, "_update_texture");
}
noise = p_noise;
if (noise.is_valid()) {
noise->connect(CoreStringNames::get_singleton()->changed, this, "_update_texture");
}
_queue_update();
}
Ref<SimplexNoise> NoiseTexture::get_noise() {
return noise;
}
void NoiseTexture::set_width(int p_width) {
if (p_width == size.x) return;
size.x = p_width;
_queue_update();
}
void NoiseTexture::set_height(int p_height) {
if (p_height == size.y) return;
size.y = p_height;
_queue_update();
}
void NoiseTexture::set_seamless(bool p_seamless) {
if (p_seamless == seamless) return;
seamless = p_seamless;
_queue_update();
}
bool NoiseTexture::get_seamless() {
return seamless;
}
void NoiseTexture::set_as_normalmap(bool p_as_normalmap) {
if (p_as_normalmap == as_normalmap) return;
as_normalmap = p_as_normalmap;
_queue_update();
}
bool NoiseTexture::is_normalmap() {
return as_normalmap;
}
void NoiseTexture::set_size(Vector2 p_size) {
if (p_size == size) return;
size = p_size;
_queue_update();
}
Vector2 NoiseTexture::get_size() {
return size;
}
int NoiseTexture::get_width() const {
return size.x;
}
int NoiseTexture::get_height() const {
return size.y;
}
void NoiseTexture::set_flags(uint32_t p_flags) {
flags = p_flags;
VS::get_singleton()->texture_set_flags(texture, flags);
}
uint32_t NoiseTexture::get_flags() const {
return flags;
}
Ref<Image> NoiseTexture::get_data() const {
return data;
}

View file

@ -0,0 +1,104 @@
/*************************************************************************/
/* noise_texture.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef NOISE_TEXTURE_H
#define NOISE_TEXTURE_H
#include "simplex_noise.h"
#include "core/image.h"
#include "core/reference.h"
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/property_editor.h"
class NoiseTexture : public Texture {
GDCLASS(NoiseTexture, Texture)
private:
Ref<Image> data;
Thread *noise_thread;
bool first_time;
bool update_queued;
bool regen_queued;
RID texture;
uint32_t flags;
Ref<SimplexNoise> noise;
Vector2i size;
bool seamless;
bool as_normalmap;
void _thread_done(const Ref<Image> &p_image);
static void _thread_function(void *p_ud);
void _queue_update();
Ref<Image> _generate_texture();
void _update_texture();
void _set_texture_data(const Ref<Image> &p_image);
protected:
static void _bind_methods();
public:
void set_noise(Ref<SimplexNoise> p_noise);
Ref<SimplexNoise> get_noise();
void set_width(int p_width);
void set_height(int p_hieght);
void set_seamless(bool p_seamless);
bool get_seamless();
void set_as_normalmap(bool p_seamless);
bool is_normalmap();
void set_size(Vector2 p_size);
Vector2 get_size();
int get_width() const;
int get_height() const;
virtual void set_flags(uint32_t p_flags);
virtual uint32_t get_flags() const;
virtual RID get_rid() const { return texture; }
virtual bool has_alpha() const { return false; }
virtual Ref<Image> get_data() const;
NoiseTexture();
virtual ~NoiseTexture();
};
#endif // NOISE_TEXTURE_H

View file

@ -0,0 +1,42 @@
/*************************************************************************/
/* register_types.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_types.h"
#include "noise_texture.h"
#include "simplex_noise.h"
void register_opensimplex_types() {
ClassDB::register_class<SimplexNoise>();
ClassDB::register_class<NoiseTexture>();
}
void unregister_opensimplex_types() {
}

View file

@ -0,0 +1,32 @@
/*************************************************************************/
/* register_types.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
void register_opensimplex_types();
void unregister_opensimplex_types();

View file

@ -0,0 +1,257 @@
/*************************************************************************/
/* simplex_noise.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "simplex_noise.h"
#include "core/core_string_names.h"
SimplexNoise::SimplexNoise() {
seed = 0;
persistance = 0.5;
octaves = 3;
period = 64;
lacunarity = 2.0;
_init_seeds();
}
SimplexNoise::~SimplexNoise() {
}
void SimplexNoise::_init_seeds() {
for (int i = 0; i < 6; ++i) {
open_simplex_noise(seed + i * 2, &(contexts[i]));
}
}
void SimplexNoise::set_seed(int p_seed) {
if (seed == p_seed)
return;
seed = p_seed;
_init_seeds();
emit_changed();
}
int SimplexNoise::get_seed() {
return seed;
}
void SimplexNoise::set_octaves(int p_octaves) {
if (p_octaves == octaves) return;
octaves = CLAMP(p_octaves, 1, 6);
emit_changed();
}
void SimplexNoise::set_period(float p_period) {
if (p_period == period) return;
period = p_period;
emit_changed();
}
void SimplexNoise::set_persistance(float p_persistance) {
if (p_persistance == persistance) return;
persistance = p_persistance;
emit_changed();
}
void SimplexNoise::set_lacunarity(float p_lacunarity) {
if (p_lacunarity == lacunarity) return;
lacunarity = p_lacunarity;
emit_changed();
}
Ref<Image> SimplexNoise::get_image(int p_width, int p_height) {
PoolVector<uint8_t> data;
data.resize(p_width * p_height * 4);
PoolVector<uint8_t>::Write wd8 = data.write();
for (int i = 0; i < p_height; i++) {
for (int j = 0; j < p_width; j++) {
float v = get_noise_2d(i, j);
v = v * 0.5 + 0.5; // Normalize [0..1]
uint8_t value = uint8_t(CLAMP(v * 255.0, 0, 255));
wd8[(i * p_width + j) * 4 + 0] = value;
wd8[(i * p_width + j) * 4 + 1] = value;
wd8[(i * p_width + j) * 4 + 2] = value;
wd8[(i * p_width + j) * 4 + 3] = 255;
}
}
Ref<Image> image = memnew(Image(p_width, p_height, false, Image::FORMAT_RGBA8, data));
return image;
}
Ref<Image> SimplexNoise::get_seamless_image(int p_size) {
PoolVector<uint8_t> data;
data.resize(p_size * p_size * 4);
PoolVector<uint8_t>::Write wd8 = data.write();
for (int i = 0; i < p_size; i++) {
for (int j = 0; j < p_size; j++) {
float ii = (float)i / (float)p_size;
float jj = (float)j / (float)p_size;
ii *= 2.0 * Math_PI;
jj *= 2.0 * Math_PI;
float radius = p_size / (2.0 * Math_PI);
float x = radius * Math::sin(jj);
float y = radius * Math::cos(jj);
float z = radius * Math::sin(ii);
float w = radius * Math::cos(ii);
float v = get_noise_4d(x, y, z, w);
v = v * 0.5 + 0.5; // Normalize [0..1]
uint8_t value = uint8_t(CLAMP(v * 255.0, 0, 255));
wd8[(i * p_size + j) * 4 + 0] = value;
wd8[(i * p_size + j) * 4 + 1] = value;
wd8[(i * p_size + j) * 4 + 2] = value;
wd8[(i * p_size + j) * 4 + 3] = 255;
}
}
Ref<Image> image = memnew(Image(p_size, p_size, false, Image::FORMAT_RGBA8, data));
return image;
}
void SimplexNoise::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_seed"), &SimplexNoise::get_seed);
ClassDB::bind_method(D_METHOD("set_seed", "seed"), &SimplexNoise::set_seed);
ClassDB::bind_method(D_METHOD("set_octaves", "octave_count"), &SimplexNoise::set_octaves);
ClassDB::bind_method(D_METHOD("get_octaves"), &SimplexNoise::get_octaves);
ClassDB::bind_method(D_METHOD("set_period", "period"), &SimplexNoise::set_period);
ClassDB::bind_method(D_METHOD("get_period"), &SimplexNoise::get_period);
ClassDB::bind_method(D_METHOD("set_persistance", "persistance"), &SimplexNoise::set_persistance);
ClassDB::bind_method(D_METHOD("get_persistance"), &SimplexNoise::get_persistance);
ClassDB::bind_method(D_METHOD("set_lacunarity", "lacunarity"), &SimplexNoise::set_lacunarity);
ClassDB::bind_method(D_METHOD("get_lacunarity"), &SimplexNoise::get_lacunarity);
ClassDB::bind_method(D_METHOD("get_image", "width", "height"), &SimplexNoise::get_image);
ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &SimplexNoise::get_seamless_image);
ClassDB::bind_method(D_METHOD("get_noise_2d", "x", "y"), &SimplexNoise::get_noise_2d);
ClassDB::bind_method(D_METHOD("get_noise_3d", "x", "y", "z"), &SimplexNoise::get_noise_3d);
ClassDB::bind_method(D_METHOD("get_noise_4d", "x", "y", "z", "w"), &SimplexNoise::get_noise_4d);
ClassDB::bind_method(D_METHOD("get_noise_2dv", "pos"), &SimplexNoise::get_noise_2dv);
ClassDB::bind_method(D_METHOD("get_noise_3dv", "pos"), &SimplexNoise::get_noise_3dv);
ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "octaves", PROPERTY_HINT_RANGE, "1,6,1"), "set_octaves", "get_octaves");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "period", PROPERTY_HINT_RANGE, "0.1,256.0,0.1"), "set_period", "get_period");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "persistance", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_persistance", "get_persistance");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "lacunarity", PROPERTY_HINT_RANGE, "0.1,4.0,0.01"), "set_lacunarity", "get_lacunarity");
}
float SimplexNoise::get_noise_2d(float x, float y) {
x /= period;
y /= period;
float amp = 1.0;
float max = 1.0;
float sum = _get_octave_noise_2d(0, x, y);
unsigned int i = 0;
while (++i < octaves) {
x *= lacunarity;
y *= lacunarity;
amp *= persistance;
max += amp;
sum += _get_octave_noise_2d(i, x, y) * amp;
}
return sum / max;
}
float SimplexNoise::get_noise_3d(float x, float y, float z) {
x /= period;
y /= period;
z /= period;
float amp = 1.0;
float max = 1.0;
float sum = _get_octave_noise_3d(0, x, y, z);
unsigned int i = 0;
while (++i < octaves) {
x *= lacunarity;
y *= lacunarity;
z *= lacunarity;
amp *= persistance;
max += amp;
sum += _get_octave_noise_3d(i, x, y, z) * amp;
}
return sum / max;
}
float SimplexNoise::get_noise_4d(float x, float y, float z, float w) {
x /= period;
y /= period;
z /= period;
w /= period;
float amp = 1.0;
float max = 1.0;
float sum = _get_octave_noise_4d(0, x, y, z, w);
unsigned int i = 0;
while (++i < octaves) {
x *= lacunarity;
y *= lacunarity;
z *= lacunarity;
w *= lacunarity;
amp *= persistance;
max += amp;
sum += _get_octave_noise_4d(i, x, y, z, w) * amp;
}
return sum / max;
}

View file

@ -0,0 +1,93 @@
/*************************************************************************/
/* simplex_noise.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef SIMPLEX_NOISE_H
#define SIMPLEX_NOISE_H
#include "core/image.h"
#include "core/reference.h"
#include "scene/resources/texture.h"
#include "thirdparty/misc/open-simplex-noise.h"
class SimplexNoise : public Resource {
GDCLASS(SimplexNoise, Resource)
OBJ_SAVE_TYPE(SimplexNoise);
osn_context contexts[6];
int seed;
float persistance; // Controls details, value in [0,1]. Higher increases grain, lower increases smoothness.
int octaves; // Number of noise layers
float period; // Distance above which we start to see similarities. The higher, the longer "hills" will be on a terrain.
float lacunarity; // Controls period change across octaves. 2 is usually a good value to address all detail levels.
public:
SimplexNoise();
~SimplexNoise();
void _init_seeds();
void set_seed(int seed);
int get_seed();
void set_octaves(int p_octaves);
int get_octaves() const { return octaves; }
void set_period(float p_period);
float get_period() const { return period; }
void set_persistance(float p_persistance);
float get_persistance() const { return persistance; }
void set_lacunarity(float p_lacunarity);
float get_lacunarity() const { return lacunarity; }
Ref<Image> get_image(int p_width, int p_height);
Ref<Image> get_seamless_image(int p_size);
float get_noise_2d(float x, float y);
float get_noise_3d(float x, float y, float z);
float get_noise_4d(float x, float y, float z, float w);
_FORCE_INLINE_ float _get_octave_noise_2d(int octave, float x, float y) { return open_simplex_noise2(&(contexts[octave]), x, y); }
_FORCE_INLINE_ float _get_octave_noise_3d(int octave, float x, float y, float z) { return open_simplex_noise3(&(contexts[octave]), x, y, z); }
_FORCE_INLINE_ float _get_octave_noise_4d(int octave, float x, float y, float z, float w) { return open_simplex_noise4(&(contexts[octave]), x, y, z, w); }
// Convenience
_FORCE_INLINE_ float get_noise_2dv(Vector2 v) { return get_noise_2d(v.x, v.y); }
_FORCE_INLINE_ float get_noise_3dv(Vector3 v) { return get_noise_3d(v.x, v.y, v.z); }
protected:
static void _bind_methods();
};
#endif // OPENSIMPLEX_NOISE_H

View file

@ -1633,16 +1633,17 @@ void GradientTexture::_queue_update() {
if (update_pending)
return;
update_pending = true;
call_deferred("_update");
}
void GradientTexture::_update() {
update_pending = false;
if (gradient.is_null())
return;
update_pending = false;
PoolVector<uint8_t> data;
data.resize(width * 4);
{

View file

@ -356,6 +356,11 @@ Collection of single-file libraries used in Godot components.
* Upstream: https://github.com/ivanfratric/polypartition (`src/polypartition.cpp`)
* Version: TBD, class was renamed
* License: MIT
- `open-simplex-noise.{c,h}`
* Upstream: https://github.com/smcameron/open-simplex-noise-in-c
* Version: git (0d555e7, 2015)
* License: Unlicense
### modules

View file

@ -0,0 +1,25 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>

View file

@ -0,0 +1,133 @@
diff -u orig/open-simplex-noise.c misc/open-simplex-noise.c
--- orig/open-simplex-noise.c 2018-09-14 11:11:40.049810000 +0200
+++ misc/open-simplex-noise.c 2018-09-14 11:09:39.726457000 +0200
@@ -13,6 +13,11 @@
* of any particular randomization library, so results
* will be the same when ported to other languages.
*/
+
+// -- GODOT start --
+// Modified to work without allocating memory, also removed some unused function.
+// -- GODOT end --
+
#include <math.h>
#include <stdlib.h>
#include <stdint.h>
@@ -34,11 +39,12 @@
#define DEFAULT_SEED (0LL)
-struct osn_context {
+// -- GODOT start --
+/*struct osn_context {
int16_t *perm;
int16_t *permGradIndex3D;
-};
-
+};*/
+// -- GODOT end --
#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
/*
@@ -126,7 +132,9 @@
int xi = (int) x;
return x < xi ? xi - 1 : xi;
}
-
+
+// -- GODOT start --
+/*
static int allocate_perm(struct osn_context *ctx, int nperm, int ngrad)
{
if (ctx->perm)
@@ -154,18 +162,21 @@
memcpy(ctx->perm, p, sizeof(*ctx->perm) * nelements);
for (i = 0; i < 256; i++) {
- /* Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array. */
+ // Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array.
ctx->permGradIndex3D[i] = (int16_t)((ctx->perm[i] % (ARRAYSIZE(gradients3D) / 3)) * 3);
}
return 0;
}
+*/
+// -- GODOT end --
/*
* Initializes using a permutation array generated from a 64-bit seed.
* Generates a proper permutation (i.e. doesn't merely perform N successive pair
* swaps on a base array). Uses a simple 64-bit LCG.
*/
-int open_simplex_noise(int64_t seed, struct osn_context **ctx)
+// -- GODOT start --
+int open_simplex_noise(int64_t seed, struct osn_context *ctx)
{
int rc;
int16_t source[256];
@@ -174,20 +185,9 @@
int16_t *permGradIndex3D;
int r;
- *ctx = (struct osn_context *) malloc(sizeof(**ctx));
- if (!(*ctx))
- return -ENOMEM;
- (*ctx)->perm = NULL;
- (*ctx)->permGradIndex3D = NULL;
-
- rc = allocate_perm(*ctx, 256, 256);
- if (rc) {
- free(*ctx);
- return rc;
- }
-
- perm = (*ctx)->perm;
- permGradIndex3D = (*ctx)->permGradIndex3D;
+ perm = ctx->perm;
+ permGradIndex3D = ctx->permGradIndex3D;
+// -- GODOT end --
for (i = 0; i < 256; i++)
source[i] = (int16_t) i;
@@ -206,6 +206,8 @@
return 0;
}
+// -- GODOT start --
+/*
void open_simplex_noise_free(struct osn_context *ctx)
{
if (!ctx)
@@ -220,6 +222,8 @@
}
free(ctx);
}
+*/
+// -- GODOT end --
/* 2D OpenSimplex (Simplectic) Noise. */
double open_simplex_noise2(struct osn_context *ctx, double x, double y)
diff -u orig/open-simplex-noise.h misc/open-simplex-noise.h
--- orig/open-simplex-noise.h 2018-09-14 11:11:19.659807000 +0200
+++ misc/open-simplex-noise.h 2018-09-14 11:10:05.006460000 +0200
@@ -35,11 +35,18 @@
extern "C" {
#endif
-struct osn_context;
+// -- GODOT start --
+// Modified to work without allocating memory, also removed some unused function.
-int open_simplex_noise(int64_t seed, struct osn_context **ctx);
+struct osn_context {
+ int16_t perm[256];
+ int16_t permGradIndex3D[256];
+};
+
+int open_simplex_noise(int64_t seed, struct osn_context *ctx);
+//int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements);
+// -- GODOT end --
void open_simplex_noise_free(struct osn_context *ctx);
-int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements);
double open_simplex_noise2(struct osn_context *ctx, double x, double y);
double open_simplex_noise3(struct osn_context *ctx, double x, double y, double z);
double open_simplex_noise4(struct osn_context *ctx, double x, double y, double z, double w);

2254
thirdparty/misc/open-simplex-noise.c vendored Normal file

File diff suppressed because it is too large Load diff

58
thirdparty/misc/open-simplex-noise.h vendored Normal file
View file

@ -0,0 +1,58 @@
#ifndef OPEN_SIMPLEX_NOISE_H__
#define OPEN_SIMPLEX_NOISE_H__
/*
* OpenSimplex (Simplectic) Noise in C.
* Ported to C from Kurt Spencer's java implementation by Stephen M. Cameron
*
* v1.1 (October 6, 2014)
* - Ported to C
*
* v1.1 (October 5, 2014)
* - Added 2D and 4D implementations.
* - Proper gradient sets for all dimensions, from a
* dimensionally-generalizable scheme with an actual
* rhyme and reason behind it.
* - Removed default permutation array in favor of
* default seed.
* - Changed seed-based constructor to be independent
* of any particular randomization library, so results
* will be the same when ported to other languages.
*/
#if ((__GNUC_STDC_INLINE__) || (__STDC_VERSION__ >= 199901L))
#include <stdint.h>
#define INLINE inline
#elif (defined (_MSC_VER) || defined (__GNUC_GNU_INLINE__))
#include <stdint.h>
#define INLINE __inline
#else
/* ANSI C doesn't have inline or stdint.h. */
#define INLINE
#endif
#ifdef __cplusplus
extern "C" {
#endif
// -- GODOT start --
// Modified to work without allocating memory, also removed some unused function.
struct osn_context {
int16_t perm[256];
int16_t permGradIndex3D[256];
};
int open_simplex_noise(int64_t seed, struct osn_context *ctx);
//int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements);
// -- GODOT end --
void open_simplex_noise_free(struct osn_context *ctx);
double open_simplex_noise2(struct osn_context *ctx, double x, double y);
double open_simplex_noise3(struct osn_context *ctx, double x, double y, double z);
double open_simplex_noise4(struct osn_context *ctx, double x, double y, double z, double w);
#ifdef __cplusplus
}
#endif
#endif