├── cmake └── Config.cmake.in ├── src ├── FastSIMD │ ├── FastSIMD_Level_NEON.cpp │ ├── FastSIMD_Level_SSE2.cpp │ ├── FastSIMD_Level_SSE3.cpp │ ├── FastSIMD_Level_SSE41.cpp │ ├── FastSIMD_Level_SSE42.cpp │ ├── FastSIMD_Level_SSSE3.cpp │ ├── FastSIMD_Level_Scalar.cpp │ ├── FastSIMD_BuildList.inl │ ├── Example │ │ ├── Example.h │ │ └── Example.inl │ ├── FastSIMD_Level_AVX2.cpp │ ├── FastSIMD_Level_AVX512.cpp │ ├── Internal │ │ ├── SourceBuilder.inl │ │ └── VecTools.h │ └── FastSIMD.cpp ├── CMakeLists.txt └── FastNoise │ └── Base64.h ├── include ├── FastSIMD │ ├── InlInclude.h │ ├── FastSIMD_Export.h │ ├── SIMDTypeList.h │ ├── FastSIMD_Config.h │ └── FastSIMD.h └── FastNoise │ ├── FastNoise_Export.h │ ├── Generators │ ├── Perlin.h │ ├── Value.h │ ├── Simplex.h │ ├── DomainWarpFractal.h │ ├── DomainWarp.h │ ├── BasicGenerators.inl │ ├── DomainWarpFractal.inl │ ├── Fractal.inl │ ├── Fractal.h │ ├── Cellular.h │ ├── Value.inl │ ├── BasicGenerators.h │ ├── Blends.inl │ ├── Perlin.inl │ ├── Blends.h │ ├── Modifiers.inl │ └── DomainWarp.inl │ ├── FastNoise_Config.h │ ├── FastNoise.h │ ├── FastNoise_BuildList.inl │ ├── FastNoise_C.h │ ├── SmartNode.h │ └── Metadata.h ├── NoiseTool ├── resources.conf ├── DemoNodeTrees.inl ├── WindowsHiDPI.manifest ├── ImGuiExtra.h ├── VertexLight.vert ├── VertexLight.frag ├── NoiseToolApp.h ├── MultiThreadQueues.h ├── NoiseTexture.h ├── CMakeLists.txt ├── FastNoiseNodeEditor.h └── MeshNoisePreview.h ├── .gitignore ├── .github ├── FUNDING.yml └── workflows │ ├── benchmark.yml │ ├── release.yml │ └── main.yml ├── LICENSE ├── .clang-format ├── tests ├── FastNoiseCpp11Include.cpp ├── CMakeLists.txt └── FastNoiseBenchmark.cpp ├── CMakePresets.json ├── README.md └── CMakeLists.txt /cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | @PACKAGE_INIT@ 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake") 6 | check_required_components("@PROJECT_NAME@") 7 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_NEON.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_NEON 4 | #include "Internal/NEON.h" 5 | #define FS_SIMD_CLASS FastSIMD::NEON 6 | #include "Internal/SourceBuilder.inl" 7 | #endif -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_SSE2.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_SSE2 4 | #include "Internal/SSE.h" 5 | #define FS_SIMD_CLASS FastSIMD::SSE2 6 | #include "Internal/SourceBuilder.inl" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_SSE3.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_SSE3 4 | #include "Internal/SSE.h" 5 | #define FS_SIMD_CLASS FastSIMD::SSE3 6 | #include "Internal/SourceBuilder.inl" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_SSE41.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_SSE41 4 | #include "Internal/SSE.h" 5 | #define FS_SIMD_CLASS FastSIMD::SSE41 6 | #include "Internal/SourceBuilder.inl" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_SSE42.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_SSE42 4 | #include "Internal/SSE.h" 5 | #define FS_SIMD_CLASS FastSIMD::SSE42 6 | #include "Internal/SourceBuilder.inl" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_SSSE3.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_SSSE3 4 | #include "Internal/SSE.h" 5 | #define FS_SIMD_CLASS FastSIMD::SSSE3 6 | #include "Internal/SourceBuilder.inl" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_Scalar.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_SCALAR 4 | #include "Internal/Scalar.h" 5 | #define FS_SIMD_CLASS FastSIMD::Scalar 6 | #include "Internal/SourceBuilder.inl" 7 | #endif -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_BuildList.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FASTSIMD_BUILD_CLASS 4 | #error Do not include this file 5 | #endif 6 | 7 | //#include "Example/Example.inl" 8 | //FASTSIMD_BUILD_CLASS( Example ) 9 | 10 | #include "FastNoise/FastNoise_BuildList.inl" -------------------------------------------------------------------------------- /include/FastSIMD/InlInclude.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FunctionList.h" 3 | 4 | template 5 | class FS_T; 6 | 7 | #define FASTSIMD_DECLARE_FS_TYPES \ 8 | using float32v = typename FS::float32v;\ 9 | using int32v = typename FS::int32v;\ 10 | using mask32v = typename FS::mask32v 11 | -------------------------------------------------------------------------------- /NoiseTool/resources.conf: -------------------------------------------------------------------------------- 1 | group=NoiseTool 2 | 3 | [file] 4 | filename=${NoiseTool_RESOURCES_DIR}/VertexLight.frag 5 | alias=VertexLight.frag 6 | 7 | [file] 8 | filename=${NoiseTool_RESOURCES_DIR}/VertexLight.vert 9 | alias=VertexLight.vert 10 | 11 | [file] 12 | filename=${imgui_SOURCE_DIR}/misc/fonts/DroidSans.ttf 13 | alias=Font.ttf 14 | -------------------------------------------------------------------------------- /include/FastSIMD/FastSIMD_Export.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if !defined( FASTNOISE_STATIC_LIB ) && ( defined( _WIN32 ) || defined( __CYGWIN__ ) ) 4 | #ifdef FASTNOISE_EXPORT // CHANGE ME 5 | #define FASTSIMD_API __declspec( dllexport ) 6 | #else 7 | #define FASTSIMD_API __declspec( dllimport ) 8 | #endif 9 | #else 10 | #define FASTSIMD_API 11 | #endif -------------------------------------------------------------------------------- /include/FastNoise/FastNoise_Export.h: -------------------------------------------------------------------------------- 1 | #ifndef FASTNOISE_EXPORT_H 2 | #define FASTNOISE_EXPORT_H 3 | 4 | #if !defined( FASTNOISE_STATIC_LIB ) && ( defined( _WIN32 ) || defined( __CYGWIN__ ) ) 5 | #ifdef FASTNOISE_EXPORT 6 | #define FASTNOISE_API __declspec( dllexport ) 7 | #else 8 | #define FASTNOISE_API __declspec( dllimport ) 9 | #endif 10 | #else 11 | #define FASTNOISE_API 12 | #endif 13 | 14 | #endif -------------------------------------------------------------------------------- /NoiseTool/DemoNodeTrees.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | inline const char* gDemoNodeTrees[][2] = 4 | { 5 | { "Simple Terrain", "EQACAAAAAAAgQBAAAAAAQBkAEwDD9Sg/DQAEAAAAAAAgQAkAAGZmJj8AAAAAPwEEAAAAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM3MTD4AMzMzPwAAAAA/" }, 6 | { "Cellular Caves", "EwCamZk+GgABEQACAAAAAADgQBAAAACIQR8AFgABAAAACwADAAAAAgAAAAMAAAAEAAAAAAAAAD8BFAD//wAAAAAAAD8AAAAAPwAAAAA/AAAAAD8BFwAAAIC/AACAPz0KF0BSuB5AEwAAAKBABgAAj8J1PACamZk+AAAAAAAA4XoUPw==" }, 7 | }; 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | /.vs* 34 | /out 35 | /build 36 | /enc_temp_folder 37 | /cpm-cache 38 | -------------------------------------------------------------------------------- /src/FastSIMD/Example/Example.h: -------------------------------------------------------------------------------- 1 | #include "FS_Class.inl" 2 | #ifdef FASTSIMD_INCLUDE_CHECK 3 | #include __FILE__ 4 | #endif 5 | #include "FS_Class.inl" 6 | #pragma once 7 | 8 | FASTSIMD_CLASS_DECLARATION( Example ) 9 | { 10 | FASTSIMD_CLASS_SETUP( FastSIMD::Level_AVX2 | FastSIMD::Level_SSE41 | FastSIMD::Level_SSE2 | FastSIMD::Level_Scalar ); 11 | 12 | public: 13 | 14 | FS_EXTERNAL_FUNC( void DoStuff( int* data ) ); 15 | 16 | FS_EXTERNAL_FUNC( void DoArray( int* data0, int* data1, int size ) ); 17 | }; 18 | -------------------------------------------------------------------------------- /NoiseTool/WindowsHiDPI.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true/pm 6 | 7 | 8 | permonitorv2,permonitor 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Perlin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | namespace FastNoise 5 | { 6 | class Perlin : public virtual Generator 7 | { 8 | public: 9 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 10 | const Metadata& GetMetadata() const override; 11 | }; 12 | 13 | #ifdef FASTNOISE_METADATA 14 | template<> 15 | struct MetadataT : MetadataT 16 | { 17 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 18 | 19 | MetadataT() 20 | { 21 | groups.push_back( "Coherent Noise" ); 22 | } 23 | }; 24 | #endif 25 | } 26 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Value.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | namespace FastNoise 5 | { 6 | class Value : public virtual Generator 7 | { 8 | public: 9 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 10 | const Metadata& GetMetadata() const override; 11 | }; 12 | 13 | #ifdef FASTNOISE_METADATA 14 | template<> 15 | struct MetadataT : MetadataT 16 | { 17 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 18 | 19 | MetadataT() 20 | { 21 | groups.push_back( "Coherent Noise" ); 22 | } 23 | }; 24 | #endif 25 | } 26 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: Auburn 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_AVX2.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_AVX2 4 | 5 | // To compile AVX2 support enable AVX(2) code generation compiler flags for this file 6 | #ifndef __AVX__ 7 | #ifdef _MSC_VER 8 | #error To compile AVX set C++ code generation to use /arch:AVX on FastSIMD_Level_AVX2.cpp, or change "#define FASTSIMD_COMPILE_AVX2" in FastSIMD_Config.h 9 | #else 10 | #error To compile AVX add build command "-march=core-avx" on FastSIMD_Level_AVX2.cpp, or change "#define FASTSIMD_COMPILE_AVX2" in FastSIMD_Config.h 11 | #endif 12 | #endif 13 | 14 | #include "Internal/AVX.h" 15 | #define FS_SIMD_CLASS FastSIMD::AVX2 16 | #include "Internal/SourceBuilder.inl" 17 | #endif -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD_Level_AVX512.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #if FASTSIMD_COMPILE_AVX512 4 | 5 | // To compile AVX512 support enable AVX512 code generation compiler flags for this file 6 | #ifndef __AVX512DQ__ 7 | #ifdef _MSC_VER 8 | #error To compile AVX512 set C++ code generation to use /arch:AVX512 on FastSIMD_Level_AVX512.cpp, or change "#define FASTSIMD_COMPILE_AVX512" in FastSIMD_Config.h 9 | #else 10 | #error To compile AVX512 add build command "-mavx512f -mavx512dq" on FastSIMD_Level_AVX512.cpp, or change "#define FASTSIMD_COMPILE_AVX512" in FastSIMD_Config.h 11 | #endif 12 | #endif 13 | 14 | #include "Internal/AVX512.h" 15 | #define FS_SIMD_CLASS FastSIMD::AVX512 16 | #include "Internal/SourceBuilder.inl" 17 | #endif -------------------------------------------------------------------------------- /src/FastSIMD/Internal/SourceBuilder.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FastSIMD/FastSIMD.h" 3 | 4 | template 5 | class FS_T; 6 | 7 | template 8 | CLASS* FastSIMD::ClassFactory( FastSIMD::MemoryAllocator allocator ) 9 | { 10 | if constexpr( ( CLASS::Supported_SIMD_Levels & LEVEL & FastSIMD::COMPILED_SIMD_LEVELS ) != 0 ) 11 | { 12 | static_assert( std::is_base_of_v> ); 13 | 14 | if( allocator ) 15 | { 16 | void* alloc = allocator( sizeof( FS_T ), alignof( FS_T ) ); 17 | 18 | return new( alloc ) FS_T; 19 | } 20 | 21 | return new FS_T; 22 | } 23 | return nullptr; 24 | } 25 | 26 | #define FASTSIMD_BUILD_CLASS( CLASS ) \ 27 | template FASTSIMD_API CLASS* FastSIMD::ClassFactory( FastSIMD::MemoryAllocator ); 28 | 29 | #include "../FastSIMD_BuildList.inl" 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jordan Peck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /include/FastSIMD/SIMDTypeList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FastSIMD.h" 4 | 5 | namespace FastSIMD 6 | { 7 | template 8 | struct SIMDTypeContainer 9 | { 10 | static constexpr eLevel MinimumCompiled = Level_Null; 11 | 12 | template 13 | static constexpr eLevel GetNextCompiledAfter = Level_Null; 14 | }; 15 | 16 | template 17 | struct SIMDTypeContainer 18 | { 19 | static constexpr eLevel MinimumCompiled = (HEAD & COMPILED_SIMD_LEVELS) != 0 ? HEAD : SIMDTypeContainer::MinimumCompiled; 20 | 21 | template 22 | static constexpr eLevel GetNextCompiledAfter = (L == HEAD) ? SIMDTypeContainer::MinimumCompiled : SIMDTypeContainer::template GetNextCompiledAfter; 23 | }; 24 | 25 | using SIMDTypeList = SIMDTypeContainer< 26 | Level_Scalar, 27 | Level_SSE, 28 | Level_SSE2, 29 | Level_SSE3, 30 | Level_SSSE3, 31 | Level_SSE41, 32 | Level_SSE42, 33 | Level_AVX, 34 | Level_AVX2, 35 | Level_AVX512, 36 | Level_NEON>; 37 | } -------------------------------------------------------------------------------- /include/FastNoise/FastNoise_Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "FastNoise_Export.h" 4 | 5 | #define FASTNOISE_CALC_MIN_MAX true 6 | #define FASTNOISE_USE_SHARED_PTR false 7 | 8 | #if FASTNOISE_USE_SHARED_PTR 9 | #include 10 | #endif 11 | 12 | namespace FastNoise 13 | { 14 | const FastSIMD::Level_BitFlags SUPPORTED_SIMD_LEVELS = 15 | FastSIMD::Level_Scalar | 16 | FastSIMD::Level_SSE2 | 17 | FastSIMD::Level_SSE41 | 18 | FastSIMD::Level_AVX2 | 19 | FastSIMD::Level_AVX512 ; 20 | 21 | class Generator; 22 | struct Metadata; 23 | 24 | template 25 | struct MetadataT; 26 | 27 | #if FASTNOISE_USE_SHARED_PTR 28 | template 29 | using SmartNode = std::shared_ptr; 30 | #else 31 | template 32 | class SmartNode; 33 | #endif 34 | 35 | template 36 | using SmartNodeArg = const SmartNode&; 37 | 38 | template 39 | SmartNode New( FastSIMD::eLevel maxSimdLevel = FastSIMD::Level_Null ); 40 | } // namespace FastNoise 41 | 42 | #if !FASTNOISE_USE_SHARED_PTR 43 | #include "SmartNode.h" 44 | #endif -------------------------------------------------------------------------------- /include/FastNoise/Generators/Simplex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | namespace FastNoise 5 | { 6 | class Simplex : public virtual Generator 7 | { 8 | public: 9 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 10 | const Metadata& GetMetadata() const override; 11 | }; 12 | 13 | #ifdef FASTNOISE_METADATA 14 | template<> 15 | struct MetadataT : MetadataT 16 | { 17 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 18 | 19 | MetadataT() 20 | { 21 | groups.push_back( "Coherent Noise" ); 22 | } 23 | }; 24 | #endif 25 | 26 | class OpenSimplex2 : public virtual Generator 27 | { 28 | public: 29 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 30 | const Metadata& GetMetadata() const override; 31 | }; 32 | 33 | #ifdef FASTNOISE_METADATA 34 | template<> 35 | struct MetadataT : MetadataT 36 | { 37 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 38 | 39 | MetadataT() 40 | { 41 | groups.push_back( "Coherent Noise" ); 42 | } 43 | }; 44 | #endif 45 | } 46 | -------------------------------------------------------------------------------- /include/FastSIMD/FastSIMD_Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include "FastSIMD_Export.h" 6 | 7 | #if defined(__arm__) || defined(__aarch64__) 8 | #define FASTSIMD_x86 false 9 | #define FASTSIMD_ARM true 10 | #else 11 | #define FASTSIMD_x86 true 12 | #define FASTSIMD_ARM false 13 | #endif 14 | 15 | #define FASTSIMD_64BIT (INTPTR_MAX == INT64_MAX) 16 | 17 | #define FASTSIMD_COMPILE_SCALAR (!(FASTSIMD_x86 && FASTSIMD_64BIT)) // Don't compile for x86 64bit since CPU is guaranteed SSE2 support 18 | 19 | #define FASTSIMD_COMPILE_SSE (FASTSIMD_x86 & false) // Not supported 20 | #define FASTSIMD_COMPILE_SSE2 (FASTSIMD_x86 & true ) 21 | #define FASTSIMD_COMPILE_SSE3 (FASTSIMD_x86 & true ) 22 | #define FASTSIMD_COMPILE_SSSE3 (FASTSIMD_x86 & true ) 23 | #define FASTSIMD_COMPILE_SSE41 (FASTSIMD_x86 & true ) 24 | #define FASTSIMD_COMPILE_SSE42 (FASTSIMD_x86 & true ) 25 | #define FASTSIMD_COMPILE_AVX (FASTSIMD_x86 & false) // Not supported 26 | #define FASTSIMD_COMPILE_AVX2 (FASTSIMD_x86 & true ) 27 | #define FASTSIMD_COMPILE_AVX512 (FASTSIMD_x86 & true ) 28 | 29 | #define FASTSIMD_COMPILE_NEON (FASTSIMD_ARM & true ) 30 | 31 | #define FASTSIMD_USE_FMA true 32 | #define FASTSIMD_CONFIG_GENERATE_CONSTANTS false 33 | 34 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Microsoft 4 | AccessModifierOffset: -4 5 | AlignOperands: false 6 | AlignTrailingComments: false 7 | AlwaysBreakTemplateDeclarations: Yes 8 | BraceWrapping: 9 | AfterCaseLabel: true 10 | AfterClass: true 11 | AfterControlStatement: true 12 | AfterEnum: true 13 | AfterFunction: true 14 | AfterNamespace: true 15 | AfterStruct: true 16 | AfterUnion: true 17 | AfterExternBlock: false 18 | BeforeCatch: true 19 | BeforeElse: true 20 | SplitEmptyFunction: true 21 | SplitEmptyRecord: true 22 | SplitEmptyNamespace: true 23 | BreakConstructorInitializers: AfterColon 24 | ColumnLimit: 0 25 | Cpp11BracedListStyle: false 26 | IncludeCategories: 27 | - Regex: '^<.*' 28 | Priority: 1 29 | - Regex: '^".*' 30 | Priority: 2 31 | - Regex: '.*' 32 | Priority: 3 33 | IncludeIsMainRegex: '([-_](test|unittest))?$' 34 | MaxEmptyLinesToKeep: 2 35 | NamespaceIndentation: All 36 | PointerAlignment: Left 37 | SpaceAfterTemplateKeyword: 'false' 38 | SpaceBeforeCpp11BracedList: 'true' 39 | SpaceBeforeParens: Never 40 | SpaceBeforeRangeBasedForLoopColon: 'false' 41 | SpaceInEmptyParentheses: 'false' 42 | SpacesInCStyleCastParentheses: 'false' 43 | SpacesInContainerLiterals: 'false' 44 | SpacesInParentheses: 'true' 45 | SpacesInSquareBrackets: 'false' 46 | UseTab: Never 47 | ... 48 | -------------------------------------------------------------------------------- /NoiseTool/ImGuiExtra.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace ImGuiExtra 7 | { 8 | inline void MarkSettingsDirty() 9 | { 10 | if( ImGui::GetCurrentContext() && ImGui::GetCurrentContext()->SettingsDirtyTimer <= 0.0f ) 11 | { 12 | ImGui::GetCurrentContext()->SettingsDirtyTimer = ImGui::GetIO().IniSavingRate; 13 | } 14 | } 15 | 16 | inline void AddOrReplaceSettingsHandler( ImGuiSettingsHandler& settings ) 17 | { 18 | if( auto* existing = ImGui::FindSettingsHandler( settings.TypeName ) ) 19 | { 20 | *existing = settings; 21 | } 22 | else 23 | { 24 | ImGui::GetCurrentContext()->SettingsHandlers.push_back( settings ); 25 | } 26 | } 27 | 28 | inline bool ScrollCombo( int* comboIndex, int comboCount ) 29 | { 30 | if( ImGui::IsItemHovered() ) 31 | { 32 | ImGui::SetItemUsingMouseWheel(); 33 | 34 | if( ImGui::GetIO().MouseWheel < 0 && *comboIndex < comboCount - 1 ) 35 | { 36 | (*comboIndex)++; 37 | return true; 38 | } 39 | 40 | if( ImGui::GetIO().MouseWheel > 0 && *comboIndex > 0 ) 41 | { 42 | (*comboIndex)--; 43 | return true; 44 | } 45 | } 46 | return false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/DomainWarpFractal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Fractal.h" 3 | #include "DomainWarp.h" 4 | 5 | namespace FastNoise 6 | { 7 | class DomainWarpFractalProgressive : public virtual Fractal 8 | { 9 | public: 10 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 11 | const Metadata& GetMetadata() const override; 12 | }; 13 | 14 | #ifdef FASTNOISE_METADATA 15 | template<> 16 | struct MetadataT : MetadataT> 17 | { 18 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 19 | 20 | MetadataT() : MetadataT>( "Domain Warp Source" ) 21 | { 22 | groups.push_back( "Domain Warp" ); 23 | } 24 | }; 25 | #endif 26 | 27 | class DomainWarpFractalIndependant : public virtual Fractal 28 | { 29 | public: 30 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 31 | const Metadata& GetMetadata() const override; 32 | }; 33 | 34 | #ifdef FASTNOISE_METADATA 35 | template<> 36 | struct MetadataT : MetadataT> 37 | { 38 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 39 | 40 | MetadataT() : MetadataT>( "Domain Warp Source" ) 41 | { 42 | groups.push_back( "Domain Warp" ); 43 | } 44 | }; 45 | #endif 46 | } 47 | -------------------------------------------------------------------------------- /tests/FastNoiseCpp11Include.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int main() 7 | { 8 | auto node = FastNoise::New(); 9 | 10 | std::cout << node->GetSIMDLevel() << std::endl; 11 | 12 | node->SetSource( FastNoise::New() ); 13 | node->SetGain( FastNoise::New() ); 14 | 15 | const int size = 4; 16 | 17 | float noise[size * size]; 18 | 19 | node->GenUniformGrid2D( noise, 0, 0, size, size, 0.02f, 1337 ); 20 | 21 | for( int i = 0; i < sizeof(noise) / sizeof(float); i++ ) 22 | { 23 | std::cout << noise[i] << ", "; 24 | } 25 | 26 | std::cout << std::endl; 27 | 28 | // SmartNode down cast example 29 | #if !FASTNOISE_USE_SHARED_PTR 30 | { 31 | // New Checkerboard node stored in base SmartNode type 32 | FastNoise::SmartNode<> base = FastNoise::New(); 33 | 34 | // Compile error 35 | // base->SetSize( 8.0f ); 36 | 37 | // Down cast to known type 38 | auto checkerboard = FastNoise::SmartNode::DynamicCast( base ); 39 | 40 | // Ok 41 | checkerboard->SetSize( 8.0f ); 42 | 43 | // Down cast to wrong type will return nullptr 44 | auto simplex = FastNoise::SmartNode::DynamicCast( base ); 45 | 46 | std::cout << ( simplex ? "valid" : "nullptr" ) << std::endl; 47 | } 48 | #endif 49 | } -------------------------------------------------------------------------------- /include/FastNoise/Generators/DomainWarp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | namespace FastNoise 5 | { 6 | class DomainWarp : public virtual Generator 7 | { 8 | public: 9 | void SetSource( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mSource, gen ); } 10 | void SetWarpAmplitude( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mWarpAmplitude, gen ); } 11 | void SetWarpAmplitude( float value ) { mWarpAmplitude = value; } 12 | void SetWarpFrequency( float value ) { mWarpFrequency = value; } 13 | 14 | protected: 15 | GeneratorSource mSource; 16 | HybridSource mWarpAmplitude = 1.0f; 17 | float mWarpFrequency = 0.5f; 18 | }; 19 | 20 | #ifdef FASTNOISE_METADATA 21 | template<> 22 | struct MetadataT : MetadataT 23 | { 24 | MetadataT() 25 | { 26 | groups.push_back( "Domain Warp" ); 27 | this->AddGeneratorSource( "Source", &DomainWarp::SetSource ); 28 | this->AddHybridSource( "Warp Amplitude", 1.0f, &DomainWarp::SetWarpAmplitude, &DomainWarp::SetWarpAmplitude ); 29 | this->AddVariable( "Warp Frequency", 0.5f, &DomainWarp::SetWarpFrequency ); 30 | } 31 | }; 32 | #endif 33 | 34 | class DomainWarpGradient : public virtual DomainWarp 35 | { 36 | public: 37 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 38 | const Metadata& GetMetadata() const override; 39 | }; 40 | 41 | #ifdef FASTNOISE_METADATA 42 | template<> 43 | struct MetadataT : MetadataT 44 | { 45 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 46 | }; 47 | #endif 48 | } 49 | -------------------------------------------------------------------------------- /NoiseTool/VertexLight.vert: -------------------------------------------------------------------------------- 1 | #if (!defined(GL_ES) && __VERSION__ >= 130) || (defined(GL_ES) && __VERSION__ >= 300) 2 | #define NEW_GLSL 3 | #endif 4 | 5 | #if !defined(GL_ES) && defined(GL_ARB_explicit_attrib_location) && !defined(DISABLE_GL_ARB_explicit_attrib_location) 6 | #extension GL_ARB_explicit_attrib_location: enable 7 | #define EXPLICIT_ATTRIB_LOCATION 8 | #endif 9 | 10 | #if !defined(GL_ES) && defined(GL_ARB_shading_language_420pack) && !defined(DISABLE_GL_ARB_shading_language_420pack) 11 | #extension GL_ARB_shading_language_420pack: enable 12 | #define RUNTIME_CONST 13 | #define EXPLICIT_TEXTURE_LAYER 14 | #endif 15 | 16 | #if !defined(GL_ES) && defined(GL_ARB_explicit_uniform_location) && !defined(DISABLE_GL_ARB_explicit_uniform_location) 17 | #extension GL_ARB_explicit_uniform_location: enable 18 | #define EXPLICIT_UNIFORM_LOCATION 19 | #endif 20 | 21 | #if defined(GL_ES) && __VERSION__ >= 300 22 | #define EXPLICIT_ATTRIB_LOCATION 23 | /* EXPLICIT_TEXTURE_LAYER, EXPLICIT_UNIFORM_LOCATION and RUNTIME_CONST is not 24 | available in OpenGL ES */ 25 | #endif 26 | 27 | /* Precision qualifiers are not supported in GLSL 1.20 */ 28 | #if !defined(GL_ES) && __VERSION__ == 120 29 | #define highp 30 | #define mediump 31 | #define lowp 32 | #endif 33 | 34 | #ifndef NEW_GLSL 35 | #define in attribute 36 | #define out varying 37 | #endif 38 | 39 | /* Uniform buffers */ 40 | 41 | #ifdef EXPLICIT_UNIFORM_LOCATION 42 | layout(location = 0) 43 | #endif 44 | 45 | uniform highp mat4 transformationProjectionMatrix 46 | #ifndef GL_ES 47 | = mat4(1.0) 48 | #endif 49 | ; 50 | 51 | /* Inputs */ 52 | 53 | #ifdef EXPLICIT_ATTRIB_LOCATION 54 | layout(location = 0) 55 | #endif 56 | in highp vec4 positionLight; 57 | 58 | /* Outputs */ 59 | 60 | out highp float interpolatedLight; 61 | 62 | void main() 63 | { 64 | gl_Position = transformationProjectionMatrix * vec4(positionLight.xyz, 1.0); 65 | 66 | interpolatedLight = positionLight.w; 67 | } 68 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CPMAddPackage( 2 | NAME benchmark 3 | GITHUB_REPOSITORY google/benchmark 4 | VERSION 1.5.5 5 | EXCLUDE_FROM_ALL YES 6 | OPTIONS 7 | "BENCHMARK_ENABLE_TESTING OFF" 8 | ) 9 | 10 | if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY AND NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY AND NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY) 11 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/bin CACHE PATH "" FORCE) 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib CACHE PATH "" FORCE) 13 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$/lib CACHE PATH "" FORCE) 14 | endif() 15 | 16 | # Ensure FastNoise.dll is built into the same dir as executables 17 | set_target_properties(FastNoise 18 | PROPERTIES 19 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} 20 | LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} 21 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 22 | ) 23 | 24 | add_executable(FastNoiseBenchmark 25 | "FastNoiseBenchmark.cpp" 26 | ) 27 | 28 | target_link_libraries(FastNoiseBenchmark 29 | FastNoise 30 | benchmark::benchmark 31 | ) 32 | 33 | 34 | add_executable(FastNoiseCpp11Test 35 | "FastNoiseCpp11Include.cpp" 36 | ) 37 | 38 | set_target_properties(FastNoiseCpp11Test PROPERTIES CXX_STANDARD 11) 39 | 40 | target_link_libraries(FastNoiseCpp11Test 41 | FastNoise 42 | ) 43 | 44 | add_executable(FastSIMDTest 45 | "SIMDUnitTest.cpp" 46 | ) 47 | 48 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 49 | set_source_files_properties("SIMDUnitTest.cpp" PROPERTIES COMPILE_FLAGS "/arch:AVX512") 50 | 51 | elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") 52 | set_source_files_properties("SIMDUnitTest.cpp" PROPERTIES COMPILE_FLAGS "-mavx512f -mavx512dq -mavx2 -mfma -msse4.2") 53 | endif() 54 | 55 | target_link_libraries(FastSIMDTest 56 | FastNoise 57 | ) 58 | 59 | add_dependencies(FastSIMDTest 60 | FastNoise 61 | ) -------------------------------------------------------------------------------- /NoiseTool/VertexLight.frag: -------------------------------------------------------------------------------- 1 | #if (!defined(GL_ES) && __VERSION__ >= 130) || (defined(GL_ES) && __VERSION__ >= 300) 2 | #define NEW_GLSL 3 | #endif 4 | 5 | #if !defined(GL_ES) && defined(GL_ARB_explicit_attrib_location) && !defined(DISABLE_GL_ARB_explicit_attrib_location) 6 | #extension GL_ARB_explicit_attrib_location: enable 7 | #define EXPLICIT_ATTRIB_LOCATION 8 | #endif 9 | 10 | #if !defined(GL_ES) && defined(GL_ARB_shading_language_420pack) && !defined(DISABLE_GL_ARB_shading_language_420pack) 11 | #extension GL_ARB_shading_language_420pack: enable 12 | #define RUNTIME_CONST 13 | #define EXPLICIT_TEXTURE_LAYER 14 | #endif 15 | 16 | #if !defined(GL_ES) && defined(GL_ARB_explicit_uniform_location) && !defined(DISABLE_GL_ARB_explicit_uniform_location) 17 | #extension GL_ARB_explicit_uniform_location: enable 18 | #define EXPLICIT_UNIFORM_LOCATION 19 | #endif 20 | 21 | #if defined(GL_ES) && __VERSION__ >= 300 22 | #define EXPLICIT_ATTRIB_LOCATION 23 | /* EXPLICIT_TEXTURE_LAYER, EXPLICIT_UNIFORM_LOCATION and RUNTIME_CONST is not 24 | available in OpenGL ES */ 25 | #endif 26 | 27 | /* Precision qualifiers are not supported in GLSL 1.20 */ 28 | #if !defined(GL_ES) && __VERSION__ == 120 29 | #define highp 30 | #define mediump 31 | #define lowp 32 | #endif 33 | 34 | #ifndef NEW_GLSL 35 | #define in varying 36 | #define fragmentColor gl_FragColor 37 | #endif 38 | 39 | /* Uniform Buffers */ 40 | 41 | #ifdef EXPLICIT_UNIFORM_LOCATION 42 | layout(location = 1) 43 | #endif 44 | 45 | uniform highp vec4 colorTint 46 | #ifndef GL_ES 47 | = vec4(1.0) 48 | #endif 49 | ; 50 | 51 | /* Inputs */ 52 | 53 | in highp float interpolatedLight; 54 | 55 | /* Outputs */ 56 | 57 | #ifdef NEW_GLSL 58 | #ifdef EXPLICIT_ATTRIB_LOCATION 59 | layout(location = 0) 60 | #endif 61 | out highp vec4 fragmentColor; 62 | #endif 63 | 64 | void main() 65 | { 66 | highp float light; 67 | 68 | if(gl_FrontFacing) 69 | { 70 | light = interpolatedLight; 71 | } 72 | else 73 | { 74 | light = (1.0 - interpolatedLight) * 0.08; 75 | } 76 | 77 | fragmentColor = colorTint * light; 78 | } 79 | -------------------------------------------------------------------------------- /include/FastSIMD/FastSIMD.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FastSIMD_Config.h" 3 | 4 | namespace FastSIMD 5 | { 6 | typedef uint32_t Level_BitFlags; 7 | 8 | enum eLevel : Level_BitFlags 9 | { 10 | Level_Null = 0, // Uninitilised 11 | Level_Scalar = 1 << 0, // 80386 instruction set (Not SIMD) 12 | Level_SSE = 1 << 1, // SSE (XMM) supported by CPU (not testing for O.S. support) 13 | Level_SSE2 = 1 << 2, // SSE2 14 | Level_SSE3 = 1 << 3, // SSE3 15 | Level_SSSE3 = 1 << 4, // Supplementary SSE3 (SSSE3) 16 | Level_SSE41 = 1 << 5, // SSE4.1 17 | Level_SSE42 = 1 << 6, // SSE4.2 18 | Level_AVX = 1 << 7, // AVX supported by CPU and operating system 19 | Level_AVX2 = 1 << 8, // AVX2 20 | Level_AVX512 = 1 << 9, // AVX512, AVX512DQ supported by CPU and operating system 21 | 22 | Level_NEON = 1 << 16, // ARM NEON 23 | }; 24 | 25 | const Level_BitFlags COMPILED_SIMD_LEVELS = 26 | (FASTSIMD_COMPILE_SCALAR ? Level_Scalar : 0) | 27 | (FASTSIMD_COMPILE_SSE ? Level_SSE : 0) | 28 | (FASTSIMD_COMPILE_SSE2 ? Level_SSE2 : 0) | 29 | (FASTSIMD_COMPILE_SSE3 ? Level_SSE3 : 0) | 30 | (FASTSIMD_COMPILE_SSSE3 ? Level_SSSE3 : 0) | 31 | (FASTSIMD_COMPILE_SSE41 ? Level_SSE41 : 0) | 32 | (FASTSIMD_COMPILE_SSE42 ? Level_SSE42 : 0) | 33 | (FASTSIMD_COMPILE_AVX ? Level_AVX : 0) | 34 | (FASTSIMD_COMPILE_AVX2 ? Level_AVX2 : 0) | 35 | (FASTSIMD_COMPILE_AVX512 ? Level_AVX512 : 0) | 36 | (FASTSIMD_COMPILE_NEON ? Level_NEON : 0) ; 37 | 38 | typedef void* (*MemoryAllocator)( size_t size, size_t align ); 39 | 40 | FASTSIMD_API eLevel CPUMaxSIMDLevel(); 41 | 42 | template 43 | T* New( eLevel maxSIMDLevel = Level_Null, MemoryAllocator allocator = nullptr ); 44 | 45 | template 46 | T* ClassFactory( MemoryAllocator allocator = nullptr ); 47 | 48 | #define FASTSIMD_LEVEL_SUPPORT( ... ) \ 49 | static const FastSIMD::Level_BitFlags Supported_SIMD_Levels = __VA_ARGS__ 50 | 51 | } 52 | -------------------------------------------------------------------------------- /NoiseTool/NoiseToolApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "FastNoiseNodeEditor.h" 12 | 13 | namespace Magnum 14 | { 15 | class NoiseToolApp : public Platform::Application 16 | { 17 | public: 18 | explicit NoiseToolApp( const Arguments& arguments ); 19 | ~NoiseToolApp(); 20 | 21 | private: 22 | void drawEvent() override; 23 | void viewportEvent( ViewportEvent& event ) override; 24 | 25 | void keyPressEvent( KeyEvent& event ) override; 26 | void keyReleaseEvent( KeyEvent& event ) override; 27 | void mousePressEvent( MouseEvent& event ) override; 28 | void mouseReleaseEvent( MouseEvent& event ) override; 29 | void mouseMoveEvent( MouseMoveEvent& event ) override; 30 | void mouseScrollEvent( MouseScrollEvent& event ) override; 31 | void textInputEvent( TextInputEvent& event ) override; 32 | 33 | void UpdatePespectiveProjection(); 34 | void HandleKeyEvent( KeyEvent::Key key, bool value ); 35 | 36 | SceneGraph::Object mCameraObject; 37 | SceneGraph::Camera3D mCamera{ mCameraObject }; 38 | Vector2 mLookAngle{ 0 }; 39 | Timeline mFrameTime; 40 | 41 | Color3 mClearColor{ 0.122f }; 42 | bool mBackFaceCulling = false; 43 | int mMaxSIMDLevel = 0; 44 | std::vector mLevelNames; 45 | std::vector mLevelEnums; 46 | 47 | ImGuiIntegration::Context mImGuiIntegrationContext; 48 | ImGuiContext* mImGuiContext; 49 | FastNoiseNodeEditor mNodeEditor; 50 | 51 | enum Key 52 | { 53 | Key_W, Key_A, Key_S, Key_D, Key_Q, Key_E, 54 | Key_Left, Key_Right, Key_Up, Key_Down, Key_PgUp, Key_PgDn, 55 | Key_LShift, Key_RShift, 56 | Key_Count 57 | }; 58 | 59 | std::array mKeyDown = {}; 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /include/FastNoise/FastNoise.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FastNoise_Config.h" 3 | 4 | // Node class definitions 5 | #include "Generators/BasicGenerators.h" 6 | #include "Generators/Value.h" 7 | #include "Generators/Perlin.h" 8 | #include "Generators/Simplex.h" 9 | #include "Generators/Cellular.h" 10 | #include "Generators/Fractal.h" 11 | #include "Generators/DomainWarp.h" 12 | #include "Generators/DomainWarpFractal.h" 13 | #include "Generators/Modifiers.h" 14 | #include "Generators/Blends.h" 15 | 16 | namespace FastNoise 17 | { 18 | /// 19 | /// Create new instance of a FastNoise node 20 | /// 21 | /// 22 | /// auto node = FastNoise::New(); 23 | /// 24 | /// Node class to create 25 | /// Max SIMD level, Null = Auto 26 | /// SmartNode is guaranteed not nullptr 27 | template 28 | SmartNode New( FastSIMD::eLevel maxSimdLevel /*= FastSIMD::Level_Null*/ ) 29 | { 30 | static_assert( std::is_base_of::value, "This function should only be used for FastNoise node classes, for example FastNoise::Simplex" ); 31 | static_assert( std::is_member_function_pointer::value, "Cannot create abstract node class, use a derived class, for example: Fractal -> FractalFBm" ); 32 | 33 | #if FASTNOISE_USE_SHARED_PTR 34 | return SmartNode( FastSIMD::New( maxSimdLevel ) ); 35 | #else 36 | return SmartNode( FastSIMD::New( maxSimdLevel, &SmartNodeManager::Allocate ) ); 37 | #endif 38 | } 39 | 40 | /// 41 | /// Create a tree of FastNoise nodes from an encoded string 42 | /// 43 | /// 44 | /// FastNoise::SmartNode<> rootNode = FastNoise::NewFromEncodedNodeTree( "DQAFAAAAAAAAQAgAAAAAAD8AAAAAAA==" ); 45 | /// 46 | /// Can be generated using the NoiseTool 47 | /// Max SIMD level, Null = Auto 48 | /// Root node of the tree, nullptr for invalid strings 49 | FASTNOISE_API SmartNode<> NewFromEncodedNodeTree( const char* encodedNodeTreeString, FastSIMD::eLevel maxSimdLevel = FastSIMD::Level_Null ); 50 | } 51 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "configurePresets": [ 4 | { 5 | "name": "noisetool", 6 | "displayName": "NoiseTool", 7 | "generator": "Ninja Multi-Config", 8 | "binaryDir": "${sourceDir}/out/build/${presetName}", 9 | "installDir": "${sourceDir}/out/install/${presetName}", 10 | "cacheVariables": { 11 | "CPM_SOURCE_CACHE": { 12 | "value": "${sourceDir}/out/cpm-cache", 13 | "type": "PATH" 14 | }, 15 | "BUILD_SHARED_LIBS": { 16 | "value": "True", 17 | "type": "BOOL" 18 | } 19 | } 20 | }, 21 | { 22 | "name": "minimal", 23 | "displayName": "Minimal", 24 | "inherits": "noisetool", 25 | "cacheVariables": { 26 | "FASTNOISE2_NOISETOOL": { 27 | "value": "False", 28 | "type": "BOOL" 29 | }, 30 | "FASTNOISE2_TESTS": { 31 | "value": "False", 32 | "type": "BOOL" 33 | } 34 | } 35 | }, 36 | { 37 | "name": "all", 38 | "displayName": "All", 39 | "inherits": "noisetool", 40 | "cacheVariables": { 41 | "FASTNOISE2_NOISETOOL": { 42 | "value": "True", 43 | "type": "BOOL" 44 | }, 45 | "FASTNOISE2_TESTS": { 46 | "value": "True", 47 | "type": "BOOL" 48 | } 49 | } 50 | } 51 | ], 52 | "buildPresets": [ 53 | { 54 | "name": "noisetool-debug", 55 | "displayName": "NoiseTool Debug", 56 | "configurePreset": "noisetool" 57 | }, 58 | { 59 | "name": "noisetool-release", 60 | "displayName": "NoiseTool Release", 61 | "configurePreset": "noisetool", 62 | "configuration": "Release" 63 | }, 64 | { 65 | "name": "minimal-debug", 66 | "displayName": "Minimal Debug", 67 | "configurePreset": "minimal" 68 | }, 69 | { 70 | "name": "minimal-release", 71 | "displayName": "Minimal Release", 72 | "configurePreset": "minimal", 73 | "configuration": "Release" 74 | }, 75 | { 76 | "name": "all-debug", 77 | "displayName": "All Debug", 78 | "configurePreset": "all", 79 | "configuration": "Debug" 80 | }, 81 | { 82 | "name": "all-release", 83 | "displayName": "All Release", 84 | "configurePreset": "all", 85 | "configuration": "Release" 86 | } 87 | ] 88 | } -------------------------------------------------------------------------------- /NoiseTool/MultiThreadQueues.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | template 7 | class GenerateQueue 8 | { 9 | public: 10 | void KillThreads() 11 | { 12 | std::unique_lock lock( mMutex ); 13 | mKillThreads = true; 14 | mCond.notify_all(); 15 | } 16 | 17 | bool ShouldKillThread() 18 | { 19 | return mKillThreads; 20 | } 21 | 22 | void Clear() 23 | { 24 | std::unique_lock lock( mMutex ); 25 | mQueue = {}; 26 | } 27 | 28 | size_t Count() 29 | { 30 | std::unique_lock lock( mMutex ); 31 | return mQueue.size(); 32 | } 33 | 34 | T Pop() 35 | { 36 | std::unique_lock lock( mMutex ); 37 | while( mQueue.empty() || mKillThreads ) 38 | { 39 | if( mKillThreads ) 40 | { 41 | return {}; 42 | } 43 | 44 | mCond.wait( lock ); 45 | } 46 | auto item = mQueue.front(); 47 | mQueue.pop(); 48 | return item; 49 | } 50 | 51 | size_t Push( const T& item ) 52 | { 53 | std::unique_lock lock( mMutex ); 54 | mQueue.push( item ); 55 | size_t size = mQueue.size(); 56 | lock.unlock(); 57 | mCond.notify_one(); 58 | return size; 59 | } 60 | 61 | private: 62 | std::queue mQueue; 63 | std::mutex mMutex; 64 | std::condition_variable mCond; 65 | bool mKillThreads = false; 66 | }; 67 | 68 | template 69 | class CompleteQueue 70 | { 71 | public: 72 | void SetVersion( uint32_t v ) 73 | { 74 | std::unique_lock lock( mMutex ); 75 | mVersion = v; 76 | } 77 | 78 | uint32_t IncVersion() 79 | { 80 | std::unique_lock lock( mMutex ); 81 | return ++mVersion; 82 | } 83 | 84 | size_t Count() 85 | { 86 | std::unique_lock lock( mMutex ); 87 | return mQueue.size(); 88 | } 89 | 90 | bool Pop( T& out ) 91 | { 92 | std::unique_lock lock( mMutex ); 93 | if( mQueue.empty() ) 94 | { 95 | return false; 96 | } 97 | out = mQueue.front(); 98 | mQueue.pop(); 99 | return true; 100 | } 101 | 102 | bool Push( const T& item, uint32_t version = 0 ) 103 | { 104 | std::unique_lock lock( mMutex ); 105 | if( version == mVersion ) 106 | { 107 | mQueue.push( item ); 108 | return true; 109 | } 110 | return false; 111 | } 112 | 113 | private: 114 | uint32_t mVersion = 0; 115 | std::queue mQueue; 116 | std::mutex mMutex; 117 | }; 118 | -------------------------------------------------------------------------------- /.github/workflows/benchmark.yml: -------------------------------------------------------------------------------- 1 | name: Trigger Benchmark 2 | on: 3 | workflow_dispatch: 4 | 5 | push: 6 | branches: 7 | - 'master' 8 | paths-ignore: 9 | - 'NoiseTool/**' 10 | - '.github/**' 11 | - '*.md' 12 | 13 | jobs: 14 | benchmark-matrix: 15 | name: ${{ matrix.name }} 16 | runs-on: ${{ matrix.os }} 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | include: 21 | - os: windows-latest 22 | name: win64-msvc 23 | cmake_options: -A x64 24 | - os: windows-latest 25 | name: win64-clangcl 26 | cmake_options: -A x64 -T ClangCL 27 | - os: ubuntu-22.04 28 | name: linux64-gcc 29 | cmake_options: -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 30 | - os: ubuntu-22.04 31 | name: linux64-clang 32 | cmake_options: -DCMAKE_C_COMPILER=clang-14 -DCMAKE_CXX_COMPILER=clang++-14 33 | 34 | steps: 35 | - name: 'Checkout' 36 | uses: actions/checkout@v2 37 | 38 | - name: 'CMake Configure' 39 | run: cmake -S ${{ github.workspace }} -B ${{ github.workspace }}/build -DCMAKE_BUILD_TYPE=Release -DFASTNOISE2_NOISETOOL=OFF -DFASTNOISE2_TESTS=ON ${{ matrix.cmake_options }} 40 | 41 | - name: 'CMake Build' 42 | run: cmake --build ${{ github.workspace }}/build --config Release --target FastNoiseBenchmark --parallel 4 43 | 44 | - name: 'Upload artifact' 45 | uses: actions/upload-artifact@v2 46 | with: 47 | name: ${{ matrix.name }}-benchmark-bin 48 | path: ${{ github.workspace }}/build/Release/bin/ 49 | if-no-files-found: error 50 | 51 | - id: get-commit-msg 52 | run: echo "::set-output name=msg::$(git log --format=%B -n 1 ${{ github.sha }})" 53 | 54 | - id: message-format-1 55 | uses: ashley-taylor/regex-property-action@1.2 56 | with: 57 | value: ${{ steps.get-commit-msg.outputs.msg }} 58 | regex: "^\\s*|[^a-zA-Z0-9_&\\(\\) -]" 59 | replacement: "" 60 | 61 | - id: message-format 62 | uses: ashley-taylor/regex-property-action@1.2 63 | with: 64 | value: ${{ steps.message-format-1.outputs.value }} 65 | regex: "(?<=.{50}).*" 66 | replacement: "" 67 | 68 | - name: Repository Dispatch 69 | uses: peter-evans/repository-dispatch@v1 70 | with: 71 | token: ${{ secrets.REPO_ACCESS_TOKEN }} 72 | repository: Auburn/FastNoise2Benchmarking 73 | event-type: benchmark 74 | client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "runid": "${{ github.run_id }}", "name": "${{ matrix.name }}", "msg": "${{ steps.message-format.outputs.value }}"}' 75 | 76 | benchmarkbin-complete: 77 | runs-on: ubuntu-latest 78 | needs: benchmark-matrix 79 | steps: 80 | - run: echo benchmarkbin-complete 81 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | repository_dispatch: 8 | types: [check-release] 9 | 10 | jobs: 11 | check-release: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: 'Checkout' 15 | uses: actions/checkout@v2 16 | with: 17 | ref: master 18 | fetch-depth: 0 19 | 20 | - name: 'Ensure no parallel instances' 21 | uses: softprops/turnstyle@v1 22 | with: 23 | abort-after-seconds: 180 24 | poll-interval-seconds: 10 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | 28 | - name: 'Check new CMake version' 29 | id: cmake-ver 30 | run: | 31 | for commit in $(git rev-list master) 32 | do 33 | git checkout --quiet $commit 34 | cmake_ver=v$(grep -oEi 'project\s*\(\s*FastNoise2.*VERSION\s+([[:digit:]\.]+)\s*\)' CMakeLists.txt | grep -oEi '[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+') 35 | 36 | if echo "$cmake_ver" | grep '^v0\.'; then 37 | cmake_ver="${cmake_ver}-alpha" 38 | fi 39 | 40 | if git show-ref --tags $cmake_ver --quiet; then 41 | echo "$cmake_ver exists" 42 | if echo $cmake_ver | grep -oEi '[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+'; then 43 | echo "::set-output name=new-tag::$prev_cmake_ver" 44 | echo "::set-output name=tag-commit::$prev_commit" 45 | fi 46 | break 47 | else 48 | echo "$cmake_ver not found" 49 | prev_commit=$commit 50 | prev_cmake_ver=$cmake_ver 51 | fi 52 | done 53 | 54 | - name: 'Create tag' 55 | if: ${{ steps.cmake-ver.outputs.new-tag != '' }} 56 | uses: actions/github-script@v3 57 | with: 58 | github-token: ${{ secrets.REPO_ACCESS_TOKEN }} 59 | script: | 60 | github.git.createRef({ 61 | owner: context.repo.owner, 62 | repo: context.repo.repo, 63 | ref: "refs/tags/${{ steps.cmake-ver.outputs.new-tag }}", 64 | sha: "${{ steps.cmake-ver.outputs.tag-commit }}" 65 | }) 66 | 67 | - name: 'Create release' 68 | if: ${{ steps.cmake-ver.outputs.new-tag != '' }} 69 | uses: fregante/release-with-changelog@v3 70 | with: 71 | token: ${{ secrets.REPO_ACCESS_TOKEN }} 72 | exclude: '^Update\s\S+\.(md|yml)$' 73 | tag: ${{ steps.cmake-ver.outputs.new-tag }} 74 | draft: true 75 | template: | 76 | ### Changelog 77 | 78 | {commits} 79 | 80 | {range} 81 | 82 | - name: 'Repeat workflow' 83 | if: ${{ steps.cmake-ver.outputs.new-tag != '' }} 84 | uses: peter-evans/repository-dispatch@v1 85 | with: 86 | token: ${{ secrets.REPO_ACCESS_TOKEN }} 87 | event-type: check-release 88 | 89 | -------------------------------------------------------------------------------- /NoiseTool/NoiseTexture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "FastNoise/FastNoise.h" 14 | #include "MultiThreadQueues.h" 15 | 16 | namespace Magnum 17 | { 18 | class NoiseTexture 19 | { 20 | public: 21 | enum GenType 22 | { 23 | GenType_2D, 24 | GenType_2DTiled, 25 | GenType_3D, 26 | GenType_4D, 27 | GenType_Count 28 | }; 29 | 30 | inline static const char* GenTypeStrings = 31 | "2D\0" 32 | "2D Tiled\0" 33 | "3D Slice\0" 34 | "4D Slice\0"; 35 | 36 | NoiseTexture(); 37 | ~NoiseTexture(); 38 | 39 | void Draw(); 40 | void ReGenerate( FastNoise::SmartNodeArg<> generator ); 41 | 42 | private: 43 | struct BuildData 44 | { 45 | FastNoise::SmartNode generator; 46 | Vector2i size; 47 | Vector4 offset; 48 | float frequency; 49 | int32_t seed; 50 | uint64_t iteration; 51 | GenType generationType; 52 | }; 53 | 54 | struct TextureData 55 | { 56 | TextureData() = default; 57 | 58 | TextureData( uint64_t iter, Vector2i s, FastNoise::OutputMinMax mm, const std::vector& v ) : minMax( mm ), size( s ), iteration( iter ) 59 | { 60 | if( v.empty() ) 61 | { 62 | return; 63 | } 64 | 65 | uint32_t* texDataPtr = new uint32_t[v.size()]; 66 | 67 | std::memcpy( texDataPtr, v.data(), v.size() * sizeof( float ) ); 68 | 69 | textureData = { texDataPtr, v.size() }; 70 | } 71 | 72 | void Free() 73 | { 74 | delete[] textureData.data(); 75 | 76 | textureData = nullptr; 77 | } 78 | 79 | Containers::ArrayView textureData; 80 | FastNoise::OutputMinMax minMax; 81 | Vector2i size; 82 | uint64_t iteration; 83 | }; 84 | 85 | static TextureData BuildTexture( const BuildData& buildData ); 86 | static void GenerateLoopThread( GenerateQueue& generateQueue, CompleteQueue& completeQueue ); 87 | 88 | void DoExport(); 89 | void SetupSettingsHandlers(); 90 | void SetPreviewTexture( ImageView2D& imageView ); 91 | 92 | GL::Texture2D mNoiseTexture; 93 | uint64_t mCurrentIteration = 0; 94 | 95 | BuildData mBuildData; 96 | BuildData mExportBuildData; 97 | FastNoise::OutputMinMax mMinMax; 98 | 99 | std::thread mExportThread; 100 | std::vector mThreads; 101 | GenerateQueue mGenerateQueue; 102 | CompleteQueue mCompleteQueue; 103 | }; 104 | } -------------------------------------------------------------------------------- /include/FastNoise/Generators/BasicGenerators.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "BasicGenerators.h" 4 | #include "Utils.inl" 5 | 6 | template 7 | class FS_T : public virtual FastNoise::Constant, public FS_T 8 | { 9 | FASTSIMD_DECLARE_FS_TYPES; 10 | FASTNOISE_IMPL_GEN_T; 11 | 12 | template 13 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 14 | { 15 | return float32v( mValue ); 16 | } 17 | }; 18 | 19 | template 20 | class FS_T : public virtual FastNoise::White, public FS_T 21 | { 22 | FASTSIMD_DECLARE_FS_TYPES; 23 | FASTNOISE_IMPL_GEN_T; 24 | 25 | template 26 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 27 | { 28 | size_t idx = 0; 29 | ((pos = FS_Casti32_f32( (FS_Castf32_i32( pos ) ^ (FS_Castf32_i32( pos ) >> 16)) * int32v( FnPrimes::Lookup[idx++] ) )), ...); 30 | 31 | return FnUtils::GetValueCoord( seed, FS_Castf32_i32( pos )... ); 32 | } 33 | }; 34 | 35 | template 36 | class FS_T : public virtual FastNoise::Checkerboard, public FS_T 37 | { 38 | FASTSIMD_DECLARE_FS_TYPES; 39 | FASTNOISE_IMPL_GEN_T; 40 | 41 | template 42 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 43 | { 44 | float32v multiplier = FS_Reciprocal_f32( float32v( mSize ) ); 45 | 46 | int32v value = (FS_Convertf32_i32( pos * multiplier ) ^ ...); 47 | 48 | return float32v( 1.0f ) ^ FS_Casti32_f32( value << 31 ); 49 | } 50 | }; 51 | 52 | template 53 | class FS_T : public virtual FastNoise::SineWave, public FS_T 54 | { 55 | FASTSIMD_DECLARE_FS_TYPES; 56 | FASTNOISE_IMPL_GEN_T; 57 | 58 | template 59 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 60 | { 61 | float32v multiplier = FS_Reciprocal_f32( float32v( mScale ) ); 62 | 63 | return (FS_Sin_f32( pos * multiplier ) * ...); 64 | } 65 | }; 66 | 67 | template 68 | class FS_T : public virtual FastNoise::PositionOutput, public FS_T 69 | { 70 | FASTSIMD_DECLARE_FS_TYPES; 71 | FASTNOISE_IMPL_GEN_T; 72 | 73 | template 74 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 75 | { 76 | size_t offsetIdx = 0; 77 | size_t multiplierIdx = 0; 78 | 79 | (((pos += float32v( mOffset[offsetIdx++] )) *= float32v( mMultiplier[multiplierIdx++] )), ...); 80 | return (pos + ...); 81 | } 82 | }; 83 | 84 | template 85 | class FS_T : public virtual FastNoise::DistanceToPoint, public FS_T 86 | { 87 | FASTSIMD_DECLARE_FS_TYPES; 88 | FASTNOISE_IMPL_GEN_T; 89 | 90 | template 91 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 92 | { 93 | size_t pointIdx = 0; 94 | 95 | ((pos -= float32v( mPoint[pointIdx++] )), ...); 96 | return FnUtils::CalcDistance( mDistanceFunction, pos... ); 97 | } 98 | }; 99 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/DomainWarpFractal.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "DomainWarpFractal.h" 4 | 5 | template 6 | class FS_T : public virtual FastNoise::DomainWarpFractalProgressive, public FS_T, FS> 7 | { 8 | FASTSIMD_DECLARE_FS_TYPES; 9 | FASTNOISE_IMPL_GEN_T; 10 | 11 | template 12 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 13 | { 14 | auto* warp = this->GetSourceSIMD( mSource ); 15 | 16 | float32v amp = float32v( mFractalBounding ) * this->GetSourceValue( warp->GetWarpAmplitude(), seed, pos... ); 17 | float32v weightedStrength = this->GetSourceValue( mWeightedStrength, seed, pos... ); 18 | float32v freq = float32v( warp->GetWarpFrequency() ); 19 | int32v seedInc = seed; 20 | 21 | float32v gain = this->GetSourceValue( mGain, seed, pos... ); 22 | float32v lacunarity( mLacunarity ); 23 | 24 | float32v strength = warp->Warp( seedInc, amp, (pos * freq)..., pos... ); 25 | 26 | for (int i = 1; i < mOctaves; i++) 27 | { 28 | seedInc -= int32v( -1 ); 29 | freq *= lacunarity; 30 | amp *= FnUtils::Lerp( float32v( 1 ), float32v( 1 ) - strength, weightedStrength ); 31 | amp *= gain; 32 | strength = warp->Warp( seedInc, amp, (pos * freq)..., pos... ); 33 | } 34 | 35 | return this->GetSourceValue( warp->GetWarpSource(), seed, pos... ); 36 | } 37 | }; 38 | 39 | template 40 | class FS_T : public virtual FastNoise::DomainWarpFractalIndependant, public FS_T, FS> 41 | { 42 | FASTSIMD_DECLARE_FS_TYPES; 43 | FASTNOISE_IMPL_GEN_T; 44 | 45 | template 46 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 47 | { 48 | return [this, seed] ( std::remove_reference_t

... noisePos, std::remove_reference_t

... warpPos ) 49 | { 50 | auto* warp = this->GetSourceSIMD( mSource ); 51 | 52 | float32v amp = float32v( mFractalBounding ) * this->GetSourceValue( warp->GetWarpAmplitude(), seed, noisePos... ); 53 | float32v weightedStrength = this->GetSourceValue( mWeightedStrength, seed, noisePos... ); 54 | float32v freq = float32v( warp->GetWarpFrequency() ); 55 | int32v seedInc = seed; 56 | 57 | float32v gain = this->GetSourceValue( mGain, seed, noisePos... ); 58 | float32v lacunarity( mLacunarity ); 59 | 60 | float32v strength = warp->Warp( seedInc, amp, (noisePos * freq)..., warpPos... ); 61 | 62 | for( int i = 1; i < mOctaves; i++ ) 63 | { 64 | seedInc -= int32v( -1 ); 65 | freq *= lacunarity; 66 | amp *= FnUtils::Lerp( float32v( 1 ), float32v( 1 ) - strength, weightedStrength ); 67 | amp *= gain; 68 | strength = warp->Warp( seedInc, amp, (noisePos * freq)..., warpPos... ); 69 | } 70 | 71 | return this->GetSourceValue( warp->GetWarpSource(), seed, warpPos... ); 72 | 73 | } ( pos..., pos... ); 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub Actions CI](https://img.shields.io/github/workflow/status/Auburn/FastNoise2/CI?style=flat-square&logo=GitHub "GitHub Actions CI")](https://github.com/Auburn/FastNoise2/actions?query=workflow%3ACI) 2 | [![Discord](https://img.shields.io/discord/703636892901441577?style=flat-square&logo=discord "Discord")](https://discord.gg/SHVaVfV) 3 | 4 | # FastNoise2 5 | 6 | WIP successor to [FastNoiseSIMD](https://github.com/Auburn/FastNoiseSIMD) 7 | 8 | Modular node based noise generation library using SIMD, modern C++17 and templates 9 | 10 | FastNoise2 is a fully featured noise generation library which aims to meet all your coherent noise needs while being extremely fast 11 | 12 | Uses FastSIMD to compile classes with multiple SIMD types and selects the fastest supported SIMD level at runtime 13 | - Scalar (non-SIMD) 14 | - SSE2 15 | - SSE4.1 16 | - AVX2 17 | - AVX512 18 | 19 | Supports: 20 | - 32/64 bit 21 | - Windows 22 | - Linux 23 | - MacOS 24 | - MSVC 25 | - Clang 26 | - GCC 27 | 28 | Bindings: 29 | - [C#](https://github.com/Auburn/FastNoise2Bindings) 30 | - [Unreal Engine CMake](https://github.com/caseymcc/UE4_FastNoise2) 31 | - [Unreal Engine Blueprint](https://github.com/DoubleDeez/UnrealFastNoise2) 32 | 33 | Roadmap: 34 | - [Vague collection of ideas](https://github.com/users/Auburn/projects/1) 35 | 36 | ## Noise Tool 37 | 38 | The FastNoise2 noise tool provides a node graph editor to create trees of FastNoise2 nodes. Node trees can be exported as serialised strings and loaded into the FastNoise2 library in your own code. The noise tool has 2D and 3D previews for the node graph output, see screenshots below for examples. 39 | 40 | Check the [Releases](https://github.com/Auburn/FastNoise2/releases/latest) for compiled NoiseTool binaries 41 | 42 | ![NoiseTool](https://user-images.githubusercontent.com/1349548/90967950-4e8da600-e4de-11ea-902a-94e72cb86481.png) 43 | 44 | ## Performance 45 | 46 | FastNoise2 has continuous benchmarking to track of performance for each node type across commits 47 | 48 | Results can be found here: https://auburn.github.io/fastnoise2benchmarking/ 49 | 50 | ### Library Comparisons 51 | 52 | Benchmarked using [NoiseBenchmarking](https://github.com/Auburn/NoiseBenchmarking) 53 | 54 | - CPU: Intel 7820X @ 4.9Ghz 55 | - OS: Win10 x64 56 | - Compiler: clang-cl 10.0.0 -m64 /O2 57 | 58 | Million points of noise generated per second (higher = better) 59 | 60 | | 3D | Value | Perlin | (*Open)Simplex | Cellular | 61 | |--------------------|--------|--------|----------------|----------| 62 | | FastNoise Lite | 64.13 | 47.93 | 36.83* | 12.49 | 63 | | FastNoise (Legacy) | 49.34 | 37.75 | 44.74 | 13.27 | 64 | | FastNoise2 (AVX2) | 494.49 | 261.10 | 268.44 | 52.43 | 65 | | libnoise | | 27.35 | | 0.65 | 66 | | stb perlin | | 34.32 | | | 67 | 68 | | 2D | Value | Perlin | Simplex | Cellular | 69 | |--------------------|--------|--------|---------|----------| 70 | | FastNoise Lite | 114.01 | 92.83 | 71.30 | 39.15 | 71 | | FastNoise (Legacy) | 102.12 | 87.99 | 65.29 | 36.84 | 72 | | FastNoise2 (AVX2) | 776.33 | 624.27 | 466.03 | 194.30 | 73 | 74 | # Getting Started 75 | 76 | See [documentation](https://github.com/Auburn/FastNoise2/wiki) 77 | -------------------------------------------------------------------------------- /src/FastSIMD/Example/Example.inl: -------------------------------------------------------------------------------- 1 | #define FASTSIMD_INTELLISENSE 2 | #include "Example.h" 3 | 4 | //template// Generic function, used if no specialised function found 5 | //FS_CLASS( Example ) < T, FS_SIMD_CLASS::SIMD_Level >::FS_CLASS( Example )() 6 | //{ 7 | // int test = 1; 8 | // 9 | // test += test; 10 | //} 11 | 12 | template // Generic function, used if no specialised function found 13 | void FS_CLASS( Example )::DoStuff( int* data ) 14 | { 15 | int32v a = int32v( 1 ); 16 | 17 | FS_Store_i32( data, a ); 18 | } 19 | 20 | //template // Different function for level SSE2 or AVX2 21 | //void FS_CLASS( Example )::DoStuff( int* data ) 22 | //{ 23 | // int32v a = _mm_loadu_si128( reinterpret_cast<__m128i const*>(data) ); 24 | // 25 | // a += _mm_set_epi32( 2, 3, 4, 5 ); 26 | // 27 | // a -= _mm_castps_si128( FS_VecZero_f32( ) ); 28 | // 29 | // FS_Store_i32( data, a ); 30 | //} 31 | // 32 | // 33 | //template 34 | //void FS_CLASS( Example )::DoArray( int* data0, int* data1, int size ) 35 | //{ 36 | // for ( int i = 0; i < size; i += FS_VectorSize_i32() ) 37 | // { 38 | // int32v a = FS_Load_i32( &data0[i] ); 39 | // int32v b = FS_Load_i32( &data1[i] ); 40 | // 41 | // a *= b; 42 | // 43 | // a <<= 1; 44 | // 45 | // a -= FS_VecZero_i32(); 46 | // 47 | // (~a); 48 | // 49 | // FS_Store_i32( &data0[i], a ); 50 | // } 51 | //} 52 | 53 | template 54 | void FS_CLASS( Example )::DoArray( int* data0, int* data1, int size ) 55 | { 56 | for ( size_t i = 0; i < size; i += int32v::FS_Size() ) 57 | { 58 | int32v a = FS_Load_i32( &data0[i] ); 59 | int32v b = FS_Load_i32( &data1[i] ); 60 | 61 | a += b; 62 | 63 | a <<= 1; 64 | 65 | a *= b; 66 | 67 | a -= int32v::FS_Zero(); 68 | 69 | (~a); 70 | 71 | FS_Store_i32( &data0[i], a ); 72 | } 73 | } 74 | 75 | template 76 | class FS_CLASS( Example ) : public FS_CLASS( Example ) 77 | { 78 | //typedef FastSIMD_AVX2 T_FS; 79 | FASTSIMD_CLASS_SETUP( FastSIMD::COMPILED_SIMD_LEVELS ); 80 | 81 | public: 82 | void DoArray( int* data0, int* data1, int size ) 83 | { 84 | for ( size_t i = 0; i < size; i += int32v::FS_Size() ) 85 | { 86 | int32v a = FS_Load_i32( &data0[i] ); 87 | int32v b = FS_Load_i32( &data1[i] ); 88 | 89 | //a += gfhfdghdfgh(); 90 | 91 | a += b; 92 | 93 | a <<= 2; 94 | 95 | a *= b; 96 | 97 | a -= int32v::FS_Zero(); 98 | 99 | (~a); 100 | 101 | FS_Store_i32( &data0[i], a ); 102 | } 103 | } 104 | }; 105 | 106 | // 107 | //template 108 | //typename std::enable_if<(T::SIMD_Level <= 1)>::type FS_CLASS( Example )::DoArray( int* data0, int* data1, int size ) 109 | //{ 110 | // for ( int i = 0; i < size; i += FS_VectorSize_i32() ) 111 | // { 112 | // int32v a = FS_Load_i32( &data0[i] ); 113 | // int32v b = FS_Load_i32( &data1[i] ); 114 | // 115 | // a += b; 116 | // 117 | // a <<= 1; 118 | // 119 | // a -= FS_VecZero_i32(); 120 | // 121 | // (~a); 122 | // 123 | // FS_Store_i32( &data0[i], a ); 124 | // } 125 | //} 126 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | # Controls when the action will run. Triggers the workflow on push or pull request 4 | # events but only for the master branch 5 | on: 6 | push: 7 | branches: [master] 8 | pull_request: 9 | branches: [master] 10 | release: 11 | types: [published] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | ci-matrix: 16 | name: ${{ matrix.name }} 17 | runs-on: ${{ matrix.os }} 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | include: 22 | - os: windows-latest 23 | name: Win32-MSVC 24 | cmake_options: -A Win32 25 | - os: windows-latest 26 | name: Win64-MSVC 27 | cmake_options: -A x64 28 | - os: windows-latest 29 | name: Win64-ClangCL 30 | cmake_options: -A x64 -T ClangCL 31 | - os: ubuntu-latest 32 | name: Linux64-GCC 33 | cmake_options: -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ 34 | - os: ubuntu-latest 35 | name: Linux64-Clang 36 | cmake_options: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ 37 | - os: macos-latest 38 | name: MacOS64-Clang 39 | cmake_options: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ 40 | 41 | steps: 42 | - name: 'Install OpenGL & xorg' 43 | if: matrix.os == 'ubuntu-latest' 44 | run: | 45 | sudo apt-get update 46 | sudo apt-get install libgl1-mesa-dev xorg-dev 47 | 48 | - name: 'Checkout' 49 | uses: actions/checkout@v2 50 | 51 | - name: 'CMake Build Debug' 52 | run: cmake -S ${{ github.workspace }} -B ${{ github.workspace }}/debug -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/install/FastNoise2" -DFASTNOISE2_NOISETOOL=OFF -DFASTNOISE2_TESTS=OFF ${{ matrix.cmake_options }} 53 | 54 | - name: 'CMake Install Debug' 55 | run: cmake --build ${{ github.workspace }}/debug --config Debug --target install --parallel 4 56 | 57 | - name: 'CMake Build Release' 58 | run: cmake -S ${{ github.workspace }} -B ${{ github.workspace }}/release -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/install/FastNoise2" -DFASTNOISE2_NOISETOOL=ON -DFASTNOISE2_TESTS=ON ${{ matrix.cmake_options }} 59 | 60 | - name: 'CMake Install Release' 61 | run: cmake --build ${{ github.workspace }}/release --config Release --target install --parallel 4 62 | 63 | - if: runner.os != 'Windows' 64 | run: chmod +x ${{ github.workspace }}/install/FastNoise2/bin/NoiseTool 65 | 66 | - name: 'Upload artifact' 67 | uses: actions/upload-artifact@v2 68 | with: 69 | name: ${{ matrix.name }} 70 | path: ${{ github.workspace }}/install/ 71 | 72 | - name: 'Zip artifacts' 73 | if: github.event_name == 'release' 74 | uses: papeloto/action-zip@v1 75 | with: 76 | files: install/ 77 | recursive: true 78 | dest: ${{ matrix.name }}.zip 79 | 80 | - name: 'Upload release artifacts' 81 | if: github.event_name == 'release' 82 | uses: svenstaro/upload-release-action@v2 83 | with: 84 | repo_token: ${{ secrets.GITHUB_TOKEN }} 85 | file: ${{ github.workspace }}/${{ matrix.name }}.zip 86 | asset_name: FastNoise2-${{ github.event.release.tag_name }}-${{ matrix.name }}.zip 87 | tag: ${{ github.ref }} 88 | -------------------------------------------------------------------------------- /src/FastSIMD/Internal/VecTools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "FastSIMD/FastSIMD.h" 6 | #include "FastSIMD/FunctionList.h" 7 | 8 | #define FASTSIMD_INTERNAL_TYPE_SET( CLASS, TYPE ) \ 9 | TYPE vector; \ 10 | FS_INLINE CLASS() { } \ 11 | FS_INLINE CLASS( const TYPE& v ) : vector(v) {}; \ 12 | FS_INLINE CLASS& operator = ( const TYPE& v ) { vector = v; return *this; } \ 13 | FS_INLINE operator TYPE() const { return vector; } 14 | 15 | #define FASTSIMD_INTERNAL_OPERATOR( TYPE, TYPE2, OPERATOR, OPERATOREQUALS ) \ 16 | FS_INLINE static TYPE operator OPERATOR ( TYPE lhs, TYPE2 rhs ) \ 17 | { \ 18 | lhs OPERATOREQUALS rhs; \ 19 | return lhs; \ 20 | } 21 | 22 | #define FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, TYPE2, OPERATOR, OPERATOREQUALS ) \ 23 | template \ 24 | FS_INLINE static TYPE operator OPERATOR ( TYPE lhs, TYPE2 rhs ) \ 25 | { \ 26 | lhs OPERATOREQUALS rhs; \ 27 | return lhs; \ 28 | } 29 | 30 | #define FASTSIMD_INTERNAL_OPERATORS_FLOAT( TYPE ) \ 31 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, +, += ) \ 32 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, -, -= ) \ 33 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, *, *= ) \ 34 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, /, /= ) \ 35 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, &, &= ) \ 36 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, |, |= ) \ 37 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, ^, ^= ) 38 | 39 | #define FASTSIMD_INTERNAL_OPERATORS_FLOAT_TEMPLATED( TYPE ) \ 40 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, +, += ) \ 41 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, -, -= ) \ 42 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, *, *= ) \ 43 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, /, /= ) \ 44 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, &, &= ) \ 45 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, |, |= ) \ 46 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, ^, ^= ) 47 | 48 | #define FASTSIMD_INTERNAL_OPERATORS_INT( TYPE, TYPE2 ) \ 49 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, +, += ) \ 50 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, -, -= ) \ 51 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, *, *= ) \ 52 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, &, &= ) \ 53 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, |, |= ) \ 54 | FASTSIMD_INTERNAL_OPERATOR( TYPE, const TYPE&, ^, ^= ) \ 55 | FASTSIMD_INTERNAL_OPERATOR( TYPE, TYPE2, >>, >>= ) \ 56 | FASTSIMD_INTERNAL_OPERATOR( TYPE, TYPE2, <<, <<= ) 57 | 58 | #define FASTSIMD_INTERNAL_OPERATORS_INT_TEMPLATED( TYPE, TYPE2 ) \ 59 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, +, += ) \ 60 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, -, -= ) \ 61 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, *, *= ) \ 62 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, &, &= ) \ 63 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, |, |= ) \ 64 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, const TYPE&, ^, ^= ) \ 65 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, TYPE2, >>, >>= ) \ 66 | FASTSIMD_INTERNAL_OPERATOR_TEMPLATED( TYPE, TYPE2, <<, <<= ) 67 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Fractal.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "Fractal.h" 4 | 5 | template 6 | class FS_T, FS> : public virtual FastNoise::Fractal, public FS_T 7 | { 8 | 9 | }; 10 | 11 | template 12 | class FS_T : public virtual FastNoise::FractalFBm, public FS_T, FS> 13 | { 14 | FASTSIMD_DECLARE_FS_TYPES; 15 | FASTNOISE_IMPL_GEN_T; 16 | 17 | template 18 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 19 | { 20 | float32v gain = this->GetSourceValue( mGain , seed, pos... ); 21 | float32v weightedStrength = this->GetSourceValue( mWeightedStrength, seed, pos... ); 22 | float32v lacunarity( mLacunarity ); 23 | float32v amp( mFractalBounding ); 24 | float32v noise = this->GetSourceValue( mSource, seed, pos... ); 25 | 26 | float32v sum = noise * amp; 27 | 28 | for( int i = 1; i < mOctaves; i++ ) 29 | { 30 | seed -= int32v( -1 ); 31 | amp *= FnUtils::Lerp( float32v( 1 ), (noise + float32v( 1 )) * float32v( 0.5f ), weightedStrength ); 32 | amp *= gain; 33 | 34 | noise = this->GetSourceValue( mSource, seed, (pos *= lacunarity)... ); 35 | sum += noise * amp; 36 | } 37 | 38 | return sum; 39 | } 40 | }; 41 | 42 | template 43 | class FS_T : public virtual FastNoise::FractalRidged, public FS_T, FS> 44 | { 45 | FASTSIMD_DECLARE_FS_TYPES; 46 | FASTNOISE_IMPL_GEN_T; 47 | 48 | template 49 | FS_INLINE float32v GenT(int32v seed, P... pos) const 50 | { 51 | float32v gain = this->GetSourceValue( mGain, seed, pos... ); 52 | float32v weightedStrength = this->GetSourceValue( mWeightedStrength, seed, pos... ); 53 | float32v lacunarity( mLacunarity ); 54 | float32v amp( mFractalBounding ); 55 | float32v noise = FS_Abs_f32( this->GetSourceValue( mSource, seed, pos... ) ); 56 | 57 | float32v sum = (noise * float32v( -2 ) + float32v( 1 )) * amp; 58 | 59 | for( int i = 1; i < mOctaves; i++ ) 60 | { 61 | seed -= int32v( -1 ); 62 | amp *= FnUtils::Lerp( float32v( 1 ), float32v( 1 ) - noise, weightedStrength ); 63 | amp *= gain; 64 | 65 | noise = FS_Abs_f32( this->GetSourceValue( mSource, seed, (pos *= lacunarity)... ) ); 66 | sum += (noise * float32v( -2 ) + float32v( 1 )) * amp; 67 | } 68 | 69 | return sum; 70 | } 71 | }; 72 | 73 | template 74 | class FS_T : public virtual FastNoise::FractalPingPong, public FS_T, FS> 75 | { 76 | FASTSIMD_DECLARE_FS_TYPES; 77 | FASTNOISE_IMPL_GEN_T; 78 | 79 | static float32v PingPong( float32v t ) 80 | { 81 | t -= FS_Round_f32( t * float32v( 0.5f ) ) * float32v( 2 ); 82 | return FS_Select_f32( t < float32v( 1 ), t, float32v( 2 ) - t ); 83 | } 84 | 85 | template 86 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 87 | { 88 | float32v gain = this->GetSourceValue( mGain , seed, pos... ); 89 | float32v weightedStrength = this->GetSourceValue( mWeightedStrength, seed, pos... ); 90 | float32v pingPongStrength = this->GetSourceValue( mPingPongStrength, seed, pos... ); 91 | float32v lacunarity( mLacunarity ); 92 | float32v amp( mFractalBounding ); 93 | float32v noise = PingPong( (this->GetSourceValue( mSource, seed, pos... ) + float32v( 1 )) * pingPongStrength ); 94 | 95 | float32v sum = noise * amp; 96 | 97 | for( int i = 1; i < mOctaves; i++ ) 98 | { 99 | seed -= int32v( -1 ); 100 | amp *= FnUtils::Lerp( float32v( 1 ), (noise + float32v( 1 )) * float32v( 0.5f ), weightedStrength ); 101 | amp *= gain; 102 | 103 | noise = PingPong( (this->GetSourceValue( mSource, seed, (pos *= lacunarity)... ) + float32v( 1 )) * pingPongStrength ); 104 | sum += noise * amp; 105 | } 106 | 107 | return sum; 108 | } 109 | }; 110 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Fractal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | namespace FastNoise 5 | { 6 | template 7 | class Fractal : public virtual Generator 8 | { 9 | public: 10 | void SetSource( SmartNodeArg gen ) { this->SetSourceMemberVariable( mSource, gen ); } 11 | void SetGain( float value ) { mGain = value; CalculateFractalBounding(); } 12 | void SetGain( SmartNodeArg<> gen ) { mGain = 1.0f; this->SetSourceMemberVariable( mGain, gen ); CalculateFractalBounding(); } 13 | void SetWeightedStrength( float value ) { mWeightedStrength = value; } 14 | void SetWeightedStrength( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mWeightedStrength, gen ); } 15 | void SetOctaveCount( int value ) { mOctaves = value; CalculateFractalBounding(); } 16 | void SetLacunarity( float value ) { mLacunarity = value; } 17 | 18 | protected: 19 | GeneratorSourceT mSource; 20 | HybridSource mGain = 0.5f; 21 | HybridSource mWeightedStrength = 0.0f; 22 | 23 | int mOctaves = 3; 24 | float mLacunarity = 2.0f; 25 | float mFractalBounding = 1.0f / 1.75f; 26 | 27 | virtual void CalculateFractalBounding() 28 | { 29 | float gain = std::abs( mGain.constant ); 30 | float amp = gain; 31 | float ampFractal = 1.0f; 32 | for( int i = 1; i < mOctaves; i++ ) 33 | { 34 | ampFractal += amp; 35 | amp *= gain; 36 | } 37 | mFractalBounding = 1.0f / ampFractal; 38 | } 39 | }; 40 | 41 | #ifdef FASTNOISE_METADATA 42 | template 43 | struct MetadataT> : MetadataT 44 | { 45 | MetadataT( const char* sourceName = "Source" ) 46 | { 47 | groups.push_back( "Fractal" ); 48 | 49 | this->AddGeneratorSource( sourceName, &Fractal::SetSource ); 50 | this->AddHybridSource( "Gain", 0.5f, &Fractal::SetGain, &Fractal::SetGain ); 51 | this->AddHybridSource( "Weighted Strength", 0.0f, &Fractal::SetWeightedStrength, &Fractal::SetWeightedStrength ); 52 | this->AddVariable( "Octaves", 3, &Fractal::SetOctaveCount, 2, 16 ); 53 | this->AddVariable( "Lacunarity", 2.0f, &Fractal::SetLacunarity ); 54 | } 55 | }; 56 | #endif 57 | 58 | class FractalFBm : public virtual Fractal<> 59 | { 60 | public: 61 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 62 | const Metadata& GetMetadata() const override; 63 | }; 64 | 65 | #ifdef FASTNOISE_METADATA 66 | template<> 67 | struct MetadataT : MetadataT> 68 | { 69 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 70 | }; 71 | #endif 72 | 73 | class FractalRidged : public virtual Fractal<> 74 | { 75 | public: 76 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 77 | const Metadata& GetMetadata() const override; 78 | }; 79 | 80 | #ifdef FASTNOISE_METADATA 81 | template<> 82 | struct MetadataT : MetadataT> 83 | { 84 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 85 | }; 86 | #endif 87 | 88 | class FractalPingPong : public virtual Fractal<> 89 | { 90 | public: 91 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 92 | const Metadata& GetMetadata() const override; 93 | 94 | void SetPingPongStrength( float value ) { mPingPongStrength = value; } 95 | void SetPingPongStrength( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mPingPongStrength, gen ); } 96 | 97 | protected: 98 | HybridSource mPingPongStrength = 0.0f; 99 | }; 100 | 101 | #ifdef FASTNOISE_METADATA 102 | template<> 103 | struct MetadataT : MetadataT> 104 | { 105 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 106 | 107 | MetadataT() 108 | { 109 | this->AddHybridSource( "Ping Pong Strength", 2.0f, &FractalPingPong::SetPingPongStrength, &FractalPingPong::SetPingPongStrength ); 110 | } 111 | }; 112 | #endif 113 | } 114 | -------------------------------------------------------------------------------- /include/FastNoise/FastNoise_BuildList.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FASTSIMD_BUILD_CLASS 4 | #error Do not include this file 5 | #endif 6 | 7 | #ifndef FASTNOISE_CLASS 8 | #define FASTNOISE_CLASS( CLASS ) FastNoise::CLASS 9 | #endif 10 | 11 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 12 | #include "Generators/Generator.h" 13 | #else 14 | #include "Generators/Generator.inl" 15 | #endif 16 | 17 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 18 | #include "Generators/BasicGenerators.h" 19 | #else 20 | #include "Generators/BasicGenerators.inl" 21 | #endif 22 | 23 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 24 | #include "Generators/Value.h" 25 | #else 26 | #include "Generators/Value.inl" 27 | #endif 28 | 29 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 30 | #include "Generators/Perlin.h" 31 | #else 32 | #include "Generators/Perlin.inl" 33 | #endif 34 | 35 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 36 | #include "Generators/Simplex.h" 37 | #else 38 | #include "Generators/Simplex.inl" 39 | #endif 40 | 41 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 42 | #include "Generators/Cellular.h" 43 | #else 44 | #include "Generators/Cellular.inl" 45 | #endif 46 | 47 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 48 | #include "Generators/Fractal.h" 49 | #else 50 | #include "Generators/Fractal.inl" 51 | #endif 52 | 53 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 54 | #include "Generators/DomainWarp.h" 55 | #else 56 | #include "Generators/DomainWarp.inl" 57 | #endif 58 | 59 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 60 | #include "Generators/DomainWarpFractal.h" 61 | #else 62 | #include "Generators/DomainWarpFractal.inl" 63 | #endif 64 | 65 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 66 | #include "Generators/Modifiers.h" 67 | #else 68 | #include "Generators/Modifiers.inl" 69 | #endif 70 | 71 | #ifdef FASTSIMD_INCLUDE_HEADER_ONLY 72 | #include "Generators/Blends.h" 73 | #else 74 | #include "Generators/Blends.inl" 75 | #endif 76 | 77 | // Nodes 78 | // Order is important! 79 | // Always add to bottom of list, 80 | // inserting will break existing encoded node trees 81 | 82 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Constant ) ) 83 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( White ) ) 84 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Checkerboard ) ) 85 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( SineWave ) ) 86 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( PositionOutput ) ) 87 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DistanceToPoint ) ) 88 | 89 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Value ) ) 90 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Perlin ) ) 91 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Simplex ) ) 92 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( OpenSimplex2 ) ) 93 | 94 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( CellularValue ) ) 95 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( CellularDistance ) ) 96 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( CellularLookup ) ) 97 | 98 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( FractalFBm ) ) 99 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( FractalPingPong ) ) 100 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( FractalRidged ) ) 101 | 102 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainWarpGradient ) ) 103 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainWarpFractalProgressive ) ) 104 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainWarpFractalIndependant ) ) 105 | 106 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainScale ) ) 107 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainOffset ) ) 108 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainRotate ) ) 109 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( SeedOffset ) ) 110 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Remap ) ) 111 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( ConvertRGBA8 ) ) 112 | 113 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Add ) ) 114 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Subtract ) ) 115 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Multiply ) ) 116 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Divide ) ) 117 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Min ) ) 118 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Max ) ) 119 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( MinSmooth ) ) 120 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( MaxSmooth ) ) 121 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Fade ) ) 122 | 123 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( Terrace ) ) 124 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( PowFloat ) ) 125 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( PowInt ) ) 126 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( DomainAxisScale ) ) 127 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( AddDimension ) ) 128 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( RemoveDimension ) ) 129 | FASTSIMD_BUILD_CLASS( FASTNOISE_CLASS( GeneratorCache ) ) 130 | -------------------------------------------------------------------------------- /NoiseTool/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CPMAddPackage( 2 | NAME corrade 3 | GITHUB_REPOSITORY mosra/corrade 4 | GIT_TAG d44ca683c12ed28fce1d27662f24edee2d7e2c6a 5 | GIT_SUBMODULES "src" 6 | EXCLUDE_FROM_ALL YES 7 | OPTIONS 8 | "BUILD_STATIC ON" 9 | "WITH_INTERCONNECT OFF" 10 | "WITH_TESTSUITE OFF" 11 | ) 12 | 13 | CPMAddPackage( 14 | NAME GLFW 15 | GITHUB_REPOSITORY glfw/glfw 16 | GIT_TAG 3.3.7 17 | EXCLUDE_FROM_ALL YES 18 | OPTIONS 19 | "BUILD_SHARED_LIBS OFF" 20 | "GLFW_INSTALL OFF" 21 | "GLFW_BUILD_TESTS OFF" 22 | "GLFW_BUILD_EXAMPLES OFF" 23 | "GLFW_BUILD_DOCS OFF" 24 | ) 25 | 26 | CPMAddPackage( 27 | NAME magnum 28 | GITHUB_REPOSITORY mosra/magnum 29 | GIT_TAG a218ddfa9434201aaca207ea9c8e87fea91a0757 30 | GIT_SUBMODULES "src" 31 | EXCLUDE_FROM_ALL YES 32 | OPTIONS 33 | "BUILD_STATIC ON" 34 | "BUILD_PLUGINS_STATIC ON" 35 | "WITH_GLFWAPPLICATION ON" 36 | "WITH_MESHTOOLS OFF" 37 | "WITH_TRADE OFF" 38 | "WITH_TEXT OFF" 39 | "WITH_TEXTURETOOLS OFF" 40 | ) 41 | 42 | CPMAddPackage( 43 | NAME imgui 44 | GITHUB_REPOSITORY ocornut/imgui 45 | GIT_TAG 1ee252772ae9c0a971d06257bb5c89f628fa696a 46 | EXCLUDE_FROM_ALL YES 47 | ) 48 | # Set dir for find_package(ImGui) 49 | set(IMGUI_DIR ${imgui_SOURCE_DIR}) 50 | 51 | CPMAddPackage( 52 | NAME magnum-integration 53 | GITHUB_REPOSITORY mosra/magnum-integration 54 | GIT_TAG 6fa1a7754bf8bc612befdc9ec543f8420a0111cc 55 | GIT_SUBMODULES "src" 56 | EXCLUDE_FROM_ALL YES 57 | OPTIONS 58 | "BUILD_STATIC ON" 59 | "WITH_IMGUI ON" 60 | ) 61 | 62 | CPMAddPackage( 63 | NAME imnodes 64 | GITHUB_REPOSITORY Auburn/imnodes 65 | GIT_TAG d88f99125bb72cdb71b4c27ff6eb7f318d89a4c5 66 | GIT_SUBMODULES ".github" 67 | EXCLUDE_FROM_ALL YES 68 | DOWNLOAD_ONLY YES 69 | ) 70 | 71 | CPMAddPackage( 72 | NAME robinhoodhashing 73 | GITHUB_REPOSITORY martinus/robin-hood-hashing 74 | GIT_TAG 3.11.5 75 | EXCLUDE_FROM_ALL YES 76 | ) 77 | 78 | # Use modules from magnum-integration since it has everything we need 79 | set(CMAKE_MODULE_PATH "${magnum-integration_SOURCE_DIR}/modules" ${CMAKE_MODULE_PATH}) 80 | 81 | find_package(Magnum REQUIRED GL GlfwApplication) 82 | find_package(MagnumIntegration REQUIRED ImGui) 83 | find_package(ImGui REQUIRED SourcesMiscCpp) 84 | 85 | # Ensure FastNoise.dll is built into the same dir as NoiseTool.exe 86 | set_target_properties(FastNoise 87 | PROPERTIES 88 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} 89 | LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} 90 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} 91 | ) 92 | 93 | # Bundle a better font 94 | # Configure resource file for imgui source dir variable 95 | set(NoiseTool_RESOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 96 | configure_file("resources.conf" "${CMAKE_CURRENT_BINARY_DIR}/resources.conf") 97 | corrade_add_resource(NoiseTool_RESOURCES "${CMAKE_CURRENT_BINARY_DIR}/resources.conf") 98 | 99 | add_executable(NoiseTool 100 | "NoiseToolApp.cpp" 101 | "FastNoiseNodeEditor.cpp" 102 | "MeshNoisePreview.cpp" 103 | "NoiseTexture.cpp" 104 | "${imnodes_SOURCE_DIR}/imnodes.cpp" 105 | ${NoiseTool_RESOURCES} 106 | ) 107 | 108 | # Include imnodes in NoiseTool project since setting up separate cmake library with imgui dependancy was causing issues 109 | target_include_directories(NoiseTool PRIVATE 110 | "${imnodes_SOURCE_DIR}") 111 | 112 | target_link_libraries(NoiseTool PRIVATE 113 | FastNoise 114 | Magnum::Application 115 | Magnum::Shaders 116 | Magnum::SceneGraph 117 | MagnumIntegration::ImGui 118 | ImGui::SourcesMiscCpp 119 | robin_hood 120 | ) 121 | 122 | # Windows HiDPI support 123 | if(CORRADE_TARGET_WINDOWS) 124 | target_sources(NoiseTool PRIVATE WindowsHiDPI.manifest) 125 | endif() 126 | 127 | if (UNIX) 128 | target_link_options(NoiseTool PRIVATE -pthread) 129 | 130 | if(APPLE) 131 | set_property(TARGET NoiseTool PROPERTY 132 | INSTALL_RPATH "@loader_path/../lib") 133 | else() 134 | set_property(TARGET NoiseTool PROPERTY 135 | INSTALL_RPATH "\$ORIGIN/../lib") 136 | endif() 137 | endif() 138 | 139 | if (MSVC) 140 | target_compile_definitions(NoiseTool PRIVATE _CRT_SECURE_NO_WARNINGS=1) 141 | endif() 142 | 143 | set(install_targets ${install_targets} NoiseTool PARENT_SCOPE) 144 | 145 | # Make the executable a default target to build & run in Visual Studio 146 | set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT NoiseTool) 147 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeList.txt : CMake project for FastNoise2 2 | cmake_minimum_required(VERSION 3.7.1) 3 | 4 | project(FastNoise2 VERSION 0.9.4) 5 | set(CMAKE_CXX_STANDARD 17) 6 | 7 | # determine whether this is a standalone project or included by other projects 8 | if (NOT DEFINED FASTNOISE2_STANDALONE_PROJECT) 9 | if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 10 | set(FASTNOISE2_STANDALONE_PROJECT ON) 11 | else() 12 | set(FASTNOISE2_STANDALONE_PROJECT OFF) 13 | endif () 14 | endif() 15 | 16 | # Build DLL 17 | #set(BUILD_SHARED_LIBS ON) 18 | 19 | option(FASTNOISE2_NOISETOOL "Build NoiseTool application" ${FASTNOISE2_STANDALONE_PROJECT}) 20 | option(FASTNOISE2_TESTS "Build tests" OFF) 21 | 22 | if(MSVC) 23 | #setup pdb target location 24 | set(pdb_output_dir "${CMAKE_CURRENT_BINARY_DIR}/pdb-files") 25 | 26 | set(CMAKE_PDB_OUTPUT_DIRECTORY "${pdb_output_dir}") 27 | set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${pdb_output_dir}") 28 | 29 | #need to sync pdb files 30 | add_compile_options("/FS") 31 | endif() 32 | 33 | # Introduce variables: 34 | # * CMAKE_INSTALL_LIBDIR 35 | # * CMAKE_INSTALL_BINDIR 36 | include(GNUInstallDirs) 37 | set(install_targets "") 38 | 39 | add_subdirectory(src) 40 | 41 | if(FASTNOISE2_NOISETOOL) 42 | include(cmake/CPM.cmake) 43 | add_subdirectory(NoiseTool) 44 | endif() 45 | 46 | if(FASTNOISE2_TESTS) 47 | include(cmake/CPM.cmake) 48 | add_subdirectory(tests) 49 | endif() 50 | 51 | 52 | #Install ----------------------------------------------------------- 53 | 54 | # Layout. This works for all platforms: 55 | # * /lib*/cmake/ 56 | # * /lib*/ 57 | # * /include/ 58 | set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") 59 | set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") 60 | 61 | # Configuration 62 | set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") 63 | set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake") 64 | set(targets_export_name "${PROJECT_NAME}Targets") 65 | set(namespace "${PROJECT_NAME}::") 66 | 67 | # Include module with fuction 'write_basic_package_version_file' 68 | include(CMakePackageConfigHelpers) 69 | 70 | # Configure 'ConfigVersion.cmake' 71 | # Use: 72 | # * PROJECT_VERSION 73 | write_basic_package_version_file( 74 | "${version_config}" COMPATIBILITY SameMajorVersion 75 | ) 76 | 77 | # Configure 'Config.cmake' 78 | # Use variables: 79 | # * TARGETS_EXPORT_NAME 80 | # * PROJECT_NAME 81 | configure_package_config_file( 82 | "cmake/Config.cmake.in" 83 | "${project_config}" 84 | INSTALL_DESTINATION "${config_install_dir}" 85 | ) 86 | 87 | # Targets: 88 | # * /lib/libname.a 89 | # * header location after install: /include/${PROJECT_NAME}/include.hpp 90 | # * headers can be included by C++ code `#include <${PROJECT_NAME}/include.hpp>` 91 | install( 92 | TARGETS ${install_targets} 93 | EXPORT "${targets_export_name}" 94 | LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" 95 | ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" 96 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 97 | INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" 98 | ) 99 | 100 | # Headers: 101 | install( 102 | FILES ${install_fastsimd_headers} 103 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/FastSIMD" 104 | ) 105 | install( 106 | FILES ${install_fastnoise_headers} 107 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/FastNoise" 108 | ) 109 | install( 110 | FILES ${install_fastnoise_generators_headers} 111 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/FastNoise/Generators" 112 | ) 113 | 114 | # Config 115 | # * /lib/cmake/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake 116 | # * /lib/cmake/${PROJECT_NAME}/${PROJECT_NAME}ConfigVersion.cmake 117 | install( 118 | FILES "${project_config}" "${version_config}" 119 | DESTINATION "${config_install_dir}" 120 | ) 121 | 122 | # Config 123 | # * /lib/cmake/${PROJECT_NAME}/${PROJECT_NAME}Targets.cmake 124 | install( 125 | EXPORT "${targets_export_name}" 126 | NAMESPACE "${namespace}" 127 | DESTINATION "${config_install_dir}" 128 | ) 129 | 130 | if(MSVC) 131 | #install pdbs 132 | get_cmake_property(is_multi GENERATOR_IS_MULTI_CONFIG) 133 | 134 | if(is_multi) 135 | set(config_suffix "$") 136 | else() 137 | set(config_suffix "") 138 | endif() 139 | 140 | if(BUILD_SHARED_LIBS) 141 | set(pdb_dst ${CMAKE_INSTALL_BINDIR}) 142 | else() 143 | set(pdb_dst ${CMAKE_INSTALL_LIBDIR}) 144 | endif() 145 | 146 | install( 147 | DIRECTORY "${pdb_output_dir}/${config_suffix}/" 148 | DESTINATION ${pdb_dst} 149 | ) 150 | endif() 151 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Cellular.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | #include 5 | 6 | namespace FastNoise 7 | { 8 | class Cellular : public virtual Generator 9 | { 10 | public: 11 | void SetJitterModifier( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mJitterModifier, gen ); } 12 | void SetJitterModifier( float value ) { mJitterModifier = value; } 13 | void SetDistanceFunction( DistanceFunction value ) { mDistanceFunction = value; } 14 | 15 | protected: 16 | HybridSource mJitterModifier = 1.0f; 17 | DistanceFunction mDistanceFunction = DistanceFunction::EuclideanSquared; 18 | }; 19 | 20 | #ifdef FASTNOISE_METADATA 21 | template<> 22 | struct MetadataT : MetadataT 23 | { 24 | MetadataT() 25 | { 26 | groups.push_back( "Coherent Noise" ); 27 | this->AddHybridSource( "Jitter Modifier", 1.0f, &Cellular::SetJitterModifier, &Cellular::SetJitterModifier ); 28 | this->AddVariableEnum( "Distance Function", DistanceFunction::EuclideanSquared, &Cellular::SetDistanceFunction, kDistanceFunction_Strings ); 29 | } 30 | }; 31 | #endif 32 | 33 | class CellularValue : public virtual Cellular 34 | { 35 | public: 36 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 37 | const Metadata& GetMetadata() const override; 38 | 39 | static const int kMaxDistanceCount = 4; 40 | 41 | void SetValueIndex( int value ) { mValueIndex = std::min( std::max( value, 0 ), kMaxDistanceCount - 1 ); } 42 | 43 | protected: 44 | int mValueIndex = 0; 45 | }; 46 | 47 | #ifdef FASTNOISE_METADATA 48 | template<> 49 | struct MetadataT : MetadataT 50 | { 51 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 52 | 53 | MetadataT() 54 | { 55 | this->AddVariable( "Value Index", 0, &CellularValue::SetValueIndex, 0, CellularValue::kMaxDistanceCount - 1 ); 56 | } 57 | }; 58 | #endif 59 | 60 | class CellularDistance : public virtual Cellular 61 | { 62 | public: 63 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 64 | const Metadata& GetMetadata() const override; 65 | 66 | enum class ReturnType 67 | { 68 | Index0, 69 | Index0Add1, 70 | Index0Sub1, 71 | Index0Mul1, 72 | Index0Div1 73 | }; 74 | 75 | static const int kMaxDistanceCount = 4; 76 | 77 | void SetDistanceIndex0( int value ) { mDistanceIndex0 = std::min( std::max( value, 0 ), kMaxDistanceCount - 1 ); } 78 | void SetDistanceIndex1( int value ) { mDistanceIndex1 = std::min( std::max( value, 0 ), kMaxDistanceCount - 1 ); } 79 | void SetReturnType( ReturnType value ) { mReturnType = value; } 80 | 81 | protected: 82 | ReturnType mReturnType = ReturnType::Index0; 83 | int mDistanceIndex0 = 0; 84 | int mDistanceIndex1 = 1; 85 | }; 86 | 87 | #ifdef FASTNOISE_METADATA 88 | template<> 89 | struct MetadataT : MetadataT 90 | { 91 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 92 | 93 | MetadataT() 94 | { 95 | this->AddVariable( "Distance Index 0", 0, &CellularDistance::SetDistanceIndex0, 0, CellularDistance::kMaxDistanceCount - 1 ); 96 | this->AddVariable( "Distance Index 1", 1, &CellularDistance::SetDistanceIndex1, 0, CellularDistance::kMaxDistanceCount - 1 ); 97 | this->AddVariableEnum( "Return Type", CellularDistance::ReturnType::Index0, &CellularDistance::SetReturnType, "Index0", "Index0Add1", "Index0Sub1", "Index0Mul1", "Index0Div1" ); 98 | } 99 | }; 100 | #endif 101 | 102 | class CellularLookup : public virtual Cellular 103 | { 104 | public: 105 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 106 | const Metadata& GetMetadata() const override; 107 | 108 | void SetLookup( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mLookup, gen ); } 109 | void SetLookupFrequency( float freq ) { mLookupFreq = freq; } 110 | 111 | protected: 112 | GeneratorSource mLookup; 113 | float mLookupFreq = 0.1f; 114 | }; 115 | 116 | #ifdef FASTNOISE_METADATA 117 | template<> 118 | struct MetadataT : MetadataT 119 | { 120 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 121 | 122 | MetadataT() 123 | { 124 | this->AddGeneratorSource( "Lookup", &CellularLookup::SetLookup ); 125 | this->AddVariable( "Lookup Frequency", 0.1f, &CellularLookup::SetLookupFrequency ); 126 | } 127 | }; 128 | #endif 129 | } 130 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Value.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "Value.h" 4 | #include "Utils.inl" 5 | 6 | template 7 | class FS_T : public virtual FastNoise::Value, public FS_T 8 | { 9 | FASTSIMD_DECLARE_FS_TYPES; 10 | 11 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const final 12 | { 13 | float32v xs = FS_Floor_f32( x ); 14 | float32v ys = FS_Floor_f32( y ); 15 | 16 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 17 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 18 | int32v x1 = x0 + int32v( FnPrimes::X ); 19 | int32v y1 = y0 + int32v( FnPrimes::Y ); 20 | 21 | xs = FnUtils::InterpHermite( x - xs ); 22 | ys = FnUtils::InterpHermite( y - ys ); 23 | 24 | return FnUtils::Lerp( 25 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0 ), FnUtils::GetValueCoord( seed, x1, y0 ), xs ), 26 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1 ), FnUtils::GetValueCoord( seed, x1, y1 ), xs ), ys ); 27 | } 28 | 29 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const final 30 | { 31 | float32v xs = FS_Floor_f32( x ); 32 | float32v ys = FS_Floor_f32( y ); 33 | float32v zs = FS_Floor_f32( z ); 34 | 35 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 36 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 37 | int32v z0 = FS_Convertf32_i32( zs ) * int32v( FnPrimes::Z ); 38 | int32v x1 = x0 + int32v( FnPrimes::X ); 39 | int32v y1 = y0 + int32v( FnPrimes::Y ); 40 | int32v z1 = z0 + int32v( FnPrimes::Z ); 41 | 42 | xs = FnUtils::InterpHermite( x - xs ); 43 | ys = FnUtils::InterpHermite( y - ys ); 44 | zs = FnUtils::InterpHermite( z - zs ); 45 | 46 | return FnUtils::Lerp( FnUtils::Lerp( 47 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0, z0 ), FnUtils::GetValueCoord( seed, x1, y0, z0 ), xs ), 48 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1, z0 ), FnUtils::GetValueCoord( seed, x1, y1, z0 ), xs ), ys ), 49 | FnUtils::Lerp( 50 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0, z1 ), FnUtils::GetValueCoord( seed, x1, y0, z1 ), xs ), 51 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1, z1 ), FnUtils::GetValueCoord( seed, x1, y1, z1 ), xs ), ys ), zs ); 52 | } 53 | 54 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const final 55 | { 56 | float32v xs = FS_Floor_f32( x ); 57 | float32v ys = FS_Floor_f32( y ); 58 | float32v zs = FS_Floor_f32( z ); 59 | float32v ws = FS_Floor_f32( w ); 60 | 61 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 62 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 63 | int32v z0 = FS_Convertf32_i32( zs ) * int32v( FnPrimes::Z ); 64 | int32v w0 = FS_Convertf32_i32( ws ) * int32v( FnPrimes::W ); 65 | int32v x1 = x0 + int32v( FnPrimes::X ); 66 | int32v y1 = y0 + int32v( FnPrimes::Y ); 67 | int32v z1 = z0 + int32v( FnPrimes::Z ); 68 | int32v w1 = w0 + int32v( FnPrimes::W ); 69 | 70 | xs = FnUtils::InterpHermite( x - xs ); 71 | ys = FnUtils::InterpHermite( y - ys ); 72 | zs = FnUtils::InterpHermite( z - zs ); 73 | ws = FnUtils::InterpHermite( w - ws ); 74 | 75 | return FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( 76 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0, z0, w0 ), FnUtils::GetValueCoord( seed, x1, y0, z0, w0 ), xs ), 77 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1, z0, w0 ), FnUtils::GetValueCoord( seed, x1, y1, z0, w0 ), xs ), ys ), 78 | FnUtils::Lerp( 79 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0, z1, w0 ), FnUtils::GetValueCoord( seed, x1, y0, z1, w0 ), xs ), 80 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1, z1, w0 ), FnUtils::GetValueCoord( seed, x1, y1, z1, w0 ), xs ), ys ), zs ), 81 | FnUtils::Lerp( FnUtils::Lerp( 82 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0, z0, w1 ), FnUtils::GetValueCoord( seed, x1, y0, z0, w1 ), xs ), 83 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1, z0, w1 ), FnUtils::GetValueCoord( seed, x1, y1, z0, w1 ), xs ), ys ), 84 | FnUtils::Lerp( 85 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y0, z1, w1 ), FnUtils::GetValueCoord( seed, x1, y0, z1, w1 ), xs ), 86 | FnUtils::Lerp( FnUtils::GetValueCoord( seed, x0, y1, z1, w1 ), FnUtils::GetValueCoord( seed, x1, y1, z1, w1 ), xs ), ys ), zs ), ws ); 87 | } 88 | }; 89 | -------------------------------------------------------------------------------- /include/FastNoise/FastNoise_C.h: -------------------------------------------------------------------------------- 1 | #ifndef FASTNOISE_C_H 2 | #define FASTNOISE_C_H 3 | 4 | #include "FastNoise_Export.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | FASTNOISE_API void* fnNewFromEncodedNodeTree( const char* encodedString, unsigned /*FastSIMD::eLevel*/ simdLevel /*0 = Auto*/ ); 11 | 12 | FASTNOISE_API void fnDeleteNodeRef( void* node ); 13 | 14 | FASTNOISE_API unsigned fnGetSIMDLevel( const void* node ); 15 | FASTNOISE_API int fnGetMetadataID( const void* node ); 16 | 17 | FASTNOISE_API void fnGenUniformGrid2D( const void* node, float* noiseOut, 18 | int xStart, int yStart, 19 | int xSize, int ySize, 20 | float frequency, int seed, float* outputMinMax /*nullptr or float[2]*/ ); 21 | 22 | FASTNOISE_API void fnGenUniformGrid3D( const void* node, float* noiseOut, 23 | int xStart, int yStart, int zStart, 24 | int xSize, int ySize, int zSize, 25 | float frequency, int seed, float* outputMinMax /*nullptr or float[2]*/ ); 26 | 27 | FASTNOISE_API void fnGenUniformGrid4D( const void* node, float* noiseOut, 28 | int xStart, int yStart, int zStart, int wStart, 29 | int xSize, int ySize, int zSize, int wSize, 30 | float frequency, int seed, float* outputMinMax /*nullptr or float[2]*/ ); 31 | 32 | FASTNOISE_API void fnGenPositionArray2D( const void* node, float* noiseOut, int count, 33 | const float* xPosArray, const float* yPosArray, 34 | float xOffset, float yOffset, 35 | int seed, float* outputMinMax /*nullptr or float[2]*/ ); 36 | 37 | FASTNOISE_API void fnGenPositionArray3D( const void* node, float* noiseOut, int count, 38 | const float* xPosArray, const float* yPosArray, const float* zPosArray, 39 | float xOffset, float yOffset, float zOffset, 40 | int seed, float* outputMinMax /*nullptr or float[2]*/ ); 41 | 42 | FASTNOISE_API void fnGenPositionArray4D( const void* node, float* noiseOut, int count, 43 | const float* xPosArray, const float* yPosArray, const float* zPosArray, const float* wPosArray, 44 | float xOffset, float yOffset, float zOffset, float wOffset, 45 | int seed, float* outputMinMax /*nullptr or float[2]*/ ); 46 | 47 | FASTNOISE_API void fnGenTileable2D( const void* node, float* noiseOut, 48 | int xSize, int ySize, 49 | float frequency, int seed, float* outputMinMax /*nullptr or float[2]*/ ); 50 | 51 | FASTNOISE_API float fnGenSingle2D( const void* node, float x, float y, int seed ); 52 | FASTNOISE_API float fnGenSingle3D( const void* node, float x, float y, float z, int seed ); 53 | FASTNOISE_API float fnGenSingle4D( const void* node, float x, float y, float z, float w, int seed ); 54 | 55 | FASTNOISE_API int fnGetMetadataCount(); 56 | FASTNOISE_API const char* fnGetMetadataName( int id ); // valid IDs up to `fnGetMetadataCount() - 1` 57 | FASTNOISE_API void* fnNewFromMetadata( int id, unsigned /*FastSIMD::eLevel*/ simdLevel /*0 = Auto*/ ); 58 | 59 | FASTNOISE_API int fnGetMetadataVariableCount( int id ); 60 | FASTNOISE_API const char* fnGetMetadataVariableName( int id, int variableIndex ); 61 | FASTNOISE_API int fnGetMetadataVariableType( int id, int variableIndex ); 62 | FASTNOISE_API int fnGetMetadataVariableDimensionIdx( int id, int variableIndex ); 63 | FASTNOISE_API int fnGetMetadataEnumCount( int id, int variableIndex ); 64 | FASTNOISE_API const char* fnGetMetadataEnumName( int id, int variableIndex, int enumIndex ); 65 | FASTNOISE_API bool fnSetVariableFloat( void* node, int variableIndex, float value ); 66 | FASTNOISE_API bool fnSetVariableIntEnum( void* node, int variableIndex, int value ); 67 | 68 | FASTNOISE_API int fnGetMetadataNodeLookupCount( int id ); 69 | FASTNOISE_API const char* fnGetMetadataNodeLookupName( int id, int nodeLookupIndex ); 70 | FASTNOISE_API int fnGetMetadataNodeLookupDimensionIdx( int id, int nodeLookupIndex ); 71 | FASTNOISE_API bool fnSetNodeLookup( void* node, int nodeLookupIndex, const void* nodeLookup ); 72 | 73 | FASTNOISE_API int fnGetMetadataHybridCount( int id ); 74 | FASTNOISE_API const char* fnGetMetadataHybridName( int id, int hybridIndex ); 75 | FASTNOISE_API int fnGetMetadataHybridDimensionIdx( int id, int hybridIndex ); 76 | FASTNOISE_API bool fnSetHybridNodeLookup( void* node, int hybridIndex, const void* nodeLookup ); 77 | FASTNOISE_API bool fnSetHybridFloat( void* node, int hybridIndex, float value ); 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_STANDARD 17) 2 | 3 | set(install_targets ${install_targets} FastNoise PARENT_SCOPE) 4 | 5 | file(GLOB_RECURSE FastSIMD_headers "../include/FastSIMD/*.h") 6 | file(GLOB_RECURSE FastSIMD_include_inl "../include/FastSIMD/*.inl") 7 | file(GLOB FastSIMD_inline "FastSIMD/*.inl") 8 | file(GLOB_RECURSE FastSIMD_internal_headers "FastSIMD/Internal/*.h") 9 | file(GLOB_RECURSE FastSIMD_internal_inl "FastSIMD/Internal/*.inl") 10 | 11 | set(install_fastsimd_headers ${FastSIMD_headers} PARENT_SCOPE) 12 | 13 | list(APPEND FastSIMD_headers ${FastSIMD_inline}) 14 | list(APPEND FastSIMD_headers ${FastSIMD_include_inl}) 15 | list(APPEND FastSIMD_internal_headers ${FastSIMD_internal_inl}) 16 | 17 | set(FastSIMD_sources 18 | FastSIMD/FastSIMD.cpp 19 | FastSIMD/FastSIMD_Level_AVX2.cpp 20 | FastSIMD/FastSIMD_Level_AVX512.cpp 21 | FastSIMD/FastSIMD_Level_NEON.cpp 22 | FastSIMD/FastSIMD_Level_Scalar.cpp 23 | FastSIMD/FastSIMD_Level_SSE2.cpp 24 | FastSIMD/FastSIMD_Level_SSE3.cpp 25 | FastSIMD/FastSIMD_Level_SSE41.cpp 26 | FastSIMD/FastSIMD_Level_SSE42.cpp 27 | FastSIMD/FastSIMD_Level_SSSE3.cpp 28 | ) 29 | 30 | file(GLOB FastNoise_headers "../include/FastNoise/*.h") 31 | file(GLOB FastNoise_inl "../include/FastNoise/*.inl") 32 | file(GLOB_RECURSE FastNoise_generators_headers "../include/FastNoise/Generators/*.h") 33 | file(GLOB_RECURSE FastNoise_generators_inl "../include/FastNoise/Generators/*.inl") 34 | 35 | set(install_fastnoise_headers ${FastNoise_headers} PARENT_SCOPE) 36 | set(install_fastnoise_generators_headers ${FastNoise_generators_headers} PARENT_SCOPE) 37 | 38 | list(APPEND FastNoise_headers ${FastNoise_inl}) 39 | list(APPEND FastNoise_generators_headers ${FastNoise_generators_inl}) 40 | 41 | set(FastNoise_source 42 | FastNoise/Metadata.cpp 43 | FastNoise/SmartNode.cpp 44 | FastNoise/FastNoise_C.cpp) 45 | 46 | source_group("FastSIMD" FILES ${FastSIMD_headers}) 47 | source_group("FastSIMD" FILES ${FastSIMD_sources}) 48 | source_group("FastSIMD\\internals" FILES ${FastSIMD_internal_headers}) 49 | 50 | source_group("FastNoise" FILES ${FastNoise_headers}) 51 | source_group("FastNoise" FILES ${FastNoise_source}) 52 | source_group("FastNoise\\Generators" FILES ${FastNoise_generators_headers}) 53 | 54 | add_library(FastNoise 55 | ${FastNoise_headers} 56 | ${FastNoise_source} 57 | ${FastNoise_generators_headers} 58 | ${FastSIMD_headers} 59 | ${FastSIMD_internal_headers} 60 | ${FastSIMD_sources} 61 | ) 62 | 63 | add_library(FastNoise2 ALIAS FastNoise) 64 | 65 | target_include_directories(FastNoise PUBLIC 66 | $ 67 | $ 68 | ) 69 | 70 | if(NOT BUILD_SHARED_LIBS) 71 | target_compile_definitions(FastNoise PUBLIC FASTNOISE_STATIC_LIB) 72 | endif() 73 | 74 | set_target_properties(FastNoise PROPERTIES 75 | DEFINE_SYMBOL FASTNOISE_EXPORT 76 | DEBUG_POSTFIX D 77 | COMPILE_PDB_NAME_DEBUG FastNoiseD) 78 | 79 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") 80 | target_compile_options(FastNoise PRIVATE /GL- /GS- /fp:fast /wd4251) 81 | 82 | if(CMAKE_SIZEOF_VOID_P EQUAL 4) 83 | set_source_files_properties(FastSIMD/FastSIMD_Level_Scalar.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE") 84 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE2.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE2") 85 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE3.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE2") 86 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSSE3.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE2") 87 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE41.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE2") 88 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE42.cpp PROPERTIES COMPILE_FLAGS "/arch:SSE2") 89 | endif() 90 | set_source_files_properties(FastSIMD/FastSIMD_Level_AVX2.cpp PROPERTIES COMPILE_FLAGS "/arch:AVX2") 91 | set_source_files_properties(FastSIMD/FastSIMD_Level_AVX512.cpp PROPERTIES COMPILE_FLAGS "/arch:AVX512") 92 | 93 | elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") 94 | if(MSVC) 95 | target_compile_options(FastNoise PRIVATE /GL- /GS- /fp:fast) 96 | else() 97 | target_compile_options(FastNoise PRIVATE -ffast-math -fno-stack-protector) 98 | endif() 99 | 100 | if(CMAKE_SIZEOF_VOID_P EQUAL 4 OR "${CMAKE_CXX_FLAGS}" MATCHES "-m32") 101 | set_source_files_properties(FastSIMD/FastSIMD_Level_Scalar.cpp PROPERTIES COMPILE_FLAGS "-msse") 102 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE2.cpp PROPERTIES COMPILE_FLAGS "-msse2") 103 | endif() 104 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE3.cpp PROPERTIES COMPILE_FLAGS "-msse3") 105 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSSE3.cpp PROPERTIES COMPILE_FLAGS "-mssse3") 106 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE41.cpp PROPERTIES COMPILE_FLAGS "-msse4.1") 107 | set_source_files_properties(FastSIMD/FastSIMD_Level_SSE42.cpp PROPERTIES COMPILE_FLAGS "-msse4.2") 108 | set_source_files_properties(FastSIMD/FastSIMD_Level_AVX2.cpp PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") 109 | set_source_files_properties(FastSIMD/FastSIMD_Level_AVX512.cpp PROPERTIES COMPILE_FLAGS "-mavx512f -mavx512dq -mfma") 110 | endif() 111 | 112 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/BasicGenerators.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | namespace FastNoise 5 | { 6 | class Constant : public virtual Generator 7 | { 8 | public: 9 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 10 | const Metadata& GetMetadata() const override; 11 | 12 | void SetValue( float value ) { mValue = value; } 13 | 14 | protected: 15 | float mValue = 1.0f; 16 | }; 17 | 18 | #ifdef FASTNOISE_METADATA 19 | template<> 20 | struct MetadataT : MetadataT 21 | { 22 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 23 | 24 | MetadataT() 25 | { 26 | groups.push_back( "Basic Generators" ); 27 | this->AddVariable( "Value", 1.0f, &Constant::SetValue ); 28 | } 29 | }; 30 | #endif 31 | 32 | class White : public virtual Generator 33 | { 34 | public: 35 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 36 | const Metadata& GetMetadata() const override; 37 | }; 38 | 39 | #ifdef FASTNOISE_METADATA 40 | template<> 41 | struct MetadataT : MetadataT 42 | { 43 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 44 | 45 | MetadataT() 46 | { 47 | groups.push_back( "Basic Generators" ); 48 | } 49 | }; 50 | #endif 51 | 52 | class Checkerboard : public virtual Generator 53 | { 54 | public: 55 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 56 | const Metadata& GetMetadata() const override; 57 | 58 | void SetSize( float value ) { mSize = value; } 59 | 60 | protected: 61 | float mSize = 1.0f; 62 | }; 63 | 64 | #ifdef FASTNOISE_METADATA 65 | template<> 66 | struct MetadataT : MetadataT 67 | { 68 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 69 | 70 | MetadataT() 71 | { 72 | groups.push_back( "Basic Generators" ); 73 | this->AddVariable( "Size", 1.0f, &Checkerboard::SetSize ); 74 | } 75 | }; 76 | #endif 77 | 78 | class SineWave : public virtual Generator 79 | { 80 | public: 81 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 82 | const Metadata& GetMetadata() const override; 83 | 84 | void SetScale( float value ) { mScale = value; } 85 | 86 | protected: 87 | float mScale = 1.0f; 88 | }; 89 | 90 | #ifdef FASTNOISE_METADATA 91 | template<> 92 | struct MetadataT : MetadataT 93 | { 94 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 95 | 96 | MetadataT() 97 | { 98 | groups.push_back( "Basic Generators" ); 99 | this->AddVariable( "Scale", 1.0f, &SineWave::SetScale ); 100 | } 101 | }; 102 | #endif 103 | 104 | class PositionOutput : public virtual Generator 105 | { 106 | public: 107 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 108 | const Metadata& GetMetadata() const override; 109 | 110 | template 111 | void Set( float multiplier, float offset = 0.0f ) { mMultiplier[(int)D] = multiplier; mOffset[(int)D] = offset; } 112 | 113 | protected: 114 | PerDimensionVariable mMultiplier = 0.0f; 115 | PerDimensionVariable mOffset = 0.0f; 116 | 117 | template 118 | friend struct MetadataT; 119 | }; 120 | 121 | #ifdef FASTNOISE_METADATA 122 | template<> 123 | struct MetadataT : MetadataT 124 | { 125 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 126 | 127 | MetadataT() 128 | { 129 | groups.push_back( "Basic Generators" ); 130 | this->AddPerDimensionVariable( "Multiplier", 0.0f, []( PositionOutput* p ) { return std::ref( p->mMultiplier ); } ); 131 | this->AddPerDimensionVariable( "Offset", 0.0f, []( PositionOutput* p ) { return std::ref( p->mOffset ); } ); 132 | } 133 | }; 134 | #endif 135 | 136 | class DistanceToPoint : public virtual Generator 137 | { 138 | public: 139 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 140 | const Metadata& GetMetadata() const override; 141 | 142 | void SetSource( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mSource, gen ); } 143 | void SetDistanceFunction( DistanceFunction value ) { mDistanceFunction = value; } 144 | 145 | template 146 | void SetScale( float value ) { mPoint[(int)D] = value; } 147 | 148 | protected: 149 | GeneratorSource mSource; 150 | DistanceFunction mDistanceFunction = DistanceFunction::EuclideanSquared; 151 | PerDimensionVariable mPoint = 0.0f; 152 | 153 | template 154 | friend struct MetadataT; 155 | }; 156 | 157 | #ifdef FASTNOISE_METADATA 158 | template<> 159 | struct MetadataT : MetadataT 160 | { 161 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 162 | 163 | MetadataT() 164 | { 165 | groups.push_back( "Basic Generators" ); 166 | this->AddVariableEnum( "Distance Function", DistanceFunction::Euclidean, &DistanceToPoint::SetDistanceFunction, kDistanceFunction_Strings ); 167 | this->AddPerDimensionVariable( "Point", 0.0f, []( DistanceToPoint* p ) { return std::ref( p->mPoint ); } ); 168 | } 169 | }; 170 | #endif 171 | } 172 | -------------------------------------------------------------------------------- /NoiseTool/FastNoiseNodeEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "FastNoise/FastNoise.h" 14 | #include "FastNoise/Metadata.h" 15 | 16 | #include "MeshNoisePreview.h" 17 | #include "NoiseTexture.h" 18 | 19 | namespace Magnum 20 | { 21 | class FastNoiseNodeEditor 22 | { 23 | public: 24 | FastNoiseNodeEditor(); 25 | void Draw( const Matrix4& transformation, const Matrix4& projection, const Vector3& cameraPosition ); 26 | void SetSIMDLevel( FastSIMD::eLevel lvl ); 27 | 28 | static const char* GetSIMDLevelName( FastSIMD::eLevel lvl ); 29 | 30 | private: 31 | struct Node 32 | { 33 | Node( FastNoiseNodeEditor& editor, FastNoise::NodeData* nodeData, bool generatePreview = true, int id = 0 ); 34 | Node( FastNoiseNodeEditor& editor, std::unique_ptr&& nodeData, bool generatePreview = true, int id = 0 ); 35 | void GeneratePreview( bool nodeTreeChanged = true, bool benchmark = false ); 36 | std::vector GetNodeIDLinks(); 37 | uint64_t GetLocalGenerateNs(); 38 | FastNoise::NodeData*& GetNodeLink( int attributeId ); 39 | void AutoPositionChildNodes( ImVec2 nodePos, float verticalSpacing = 380.0f ); 40 | void SerialiseIncludingDependancies( struct ImGuiSettingsHandler* handler, struct ImGuiTextBuffer* buffer, std::unordered_set& serialisedNodeIds ); 41 | 42 | static constexpr int AttributeBitCount = 8; 43 | static constexpr int AttributeBitMask = ( 1 << AttributeBitCount ) - 1; 44 | 45 | static int GetNodeIdFromAttribute( int attributeId ) 46 | { 47 | return (int)((unsigned int)attributeId >> AttributeBitCount); 48 | } 49 | 50 | int GetStartingAttributeId() const 51 | { 52 | return nodeId << AttributeBitCount; 53 | } 54 | 55 | int GetOutputAttributeId() const 56 | { 57 | return GetStartingAttributeId() | AttributeBitMask; 58 | } 59 | 60 | FastNoiseNodeEditor& editor; 61 | std::unique_ptr data; 62 | std::string serialised; 63 | const int nodeId; 64 | 65 | int64_t totalGenerateNs = 0; 66 | std::vector generateAverages; 67 | 68 | static const int NoiseSize = 224; 69 | GL::Texture2D noiseTexture; 70 | }; 71 | 72 | struct MetadataMenu 73 | { 74 | virtual ~MetadataMenu() = default; 75 | virtual const char* GetName() const = 0; 76 | virtual bool CanDraw( std::function isValid = nullptr ) const = 0; 77 | virtual const FastNoise::Metadata* DrawUI( std::function isValid = nullptr, bool drawGroups = true ) const = 0; 78 | }; 79 | 80 | struct MetadataMenuItem : MetadataMenu 81 | { 82 | MetadataMenuItem( const FastNoise::Metadata* metadata ) : metadata( metadata ) {} 83 | 84 | const char* GetName() const final { return metadata->name; } 85 | bool CanDraw( std::function isValid ) const final; 86 | const FastNoise::Metadata* DrawUI( std::function isValid, bool drawGroups ) const final; 87 | 88 | const FastNoise::Metadata* metadata; 89 | }; 90 | 91 | struct MetadataMenuGroup : MetadataMenu 92 | { 93 | MetadataMenuGroup( const char* name ) : name( name ) {} 94 | 95 | const char* GetName() const final { return name; } 96 | bool CanDraw( std::function isValid ) const final; 97 | const FastNoise::Metadata* DrawUI( std::function isValid, bool drawGroups ) const final; 98 | 99 | const char* name; 100 | std::vector items; 101 | }; 102 | 103 | Node& AddNode( ImVec2 startPos, const FastNoise::Metadata* metadata, bool generatePreview = true ); 104 | bool AddNodeFromEncodedString( const char* string, ImVec2 nodePos ); 105 | FastNoise::SmartNode<> GenerateSelectedPreview(); 106 | FastNoise::OutputMinMax GenerateNodePreviewNoise( FastNoise::Generator* gen, float* noise ); 107 | Node* FindNodeFromId( int id ); 108 | int GetFreeNodeId(); 109 | void ChangeSelectedNode( FastNoise::NodeData* newId ); 110 | void DeleteNode( FastNoise::NodeData* nodeData ); 111 | void DoNodeBenchmarks(); 112 | void SetupSettingsHandlers(); 113 | 114 | void CheckLinks(); 115 | void DoHelp(); 116 | void DoContextMenu(); 117 | void DoNodes(); 118 | void UpdateSelected(); 119 | 120 | std::unordered_map mNodes; 121 | FastNoise::NodeData* mDroppedLinkNode = nullptr; 122 | bool mDroppedLink = false; 123 | 124 | ImVec2 mContextStartPos; 125 | std::vector> mContextMetadata; 126 | std::string mImportNodeString; 127 | bool mImportNodeModal = false; 128 | 129 | MeshNoisePreview mMeshNoisePreview; 130 | NoiseTexture mNoiseTexture; 131 | 132 | FastNoise::NodeData* mSelectedNode = nullptr; 133 | Node mOverheadNode; 134 | int32_t mNodeBenchmarkIndex = 0; 135 | int32_t mNodeBenchmarkMax = 128; 136 | 137 | float mNodeFrequency = 0.02f; 138 | int mNodeSeed = 1337; 139 | NoiseTexture::GenType mNodeGenType = NoiseTexture::GenType_2D; 140 | 141 | FastSIMD::eLevel mMaxSIMDLevel = FastSIMD::Level_Null; 142 | FastSIMD::eLevel mActualSIMDLevel = FastSIMD::Level_Null; 143 | }; 144 | } -------------------------------------------------------------------------------- /src/FastNoise/Base64.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace FastNoise 9 | { 10 | /** https://gist.github.com/tomykaira/f0fd86b6c73063283afe550bc5d77594 11 | * The MIT License (MIT) 12 | * Copyright (c) 2016 tomykaira 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | namespace Base64 34 | { 35 | static std::string Encode( const std::vector& data ) 36 | { 37 | static constexpr char sEncodingTable[] = { 38 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 39 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 40 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 41 | 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 42 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 43 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 44 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', 45 | '4', '5', '6', '7', '8', '9', '+', '/' 46 | }; 47 | 48 | size_t in_len = data.size(); 49 | size_t out_len = 4 * ((in_len + 2) / 3); 50 | std::string ret( out_len, '\0' ); 51 | size_t i; 52 | char* p = const_cast(ret.c_str()); 53 | 54 | for( i = 0; i < in_len - 2; i += 3 ) 55 | { 56 | *p++ = sEncodingTable[(data[i] >> 2) & 0x3F]; 57 | *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)]; 58 | *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | ((int)(data[i + 2] & 0xC0) >> 6)]; 59 | *p++ = sEncodingTable[data[i + 2] & 0x3F]; 60 | } 61 | if( i < in_len ) 62 | { 63 | *p++ = sEncodingTable[(data[i] >> 2) & 0x3F]; 64 | if( i == (in_len - 1) ) 65 | { 66 | *p++ = sEncodingTable[((data[i] & 0x3) << 4)]; 67 | *p++ = '='; 68 | } 69 | else 70 | { 71 | *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int)(data[i + 1] & 0xF0) >> 4)]; 72 | *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)]; 73 | } 74 | *p++ = '='; 75 | } 76 | 77 | return ret; 78 | } 79 | 80 | static std::vector Decode( const char* input ) 81 | { 82 | static constexpr unsigned char kDecodingTable[] = { 83 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 84 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 85 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 86 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 87 | 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 88 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 89 | 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 90 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 91 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 92 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 93 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 94 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 95 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 96 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 97 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 98 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 99 | }; 100 | 101 | size_t in_len = std::strlen( input ); 102 | if( in_len % 4 != 0 ) return {}; 103 | 104 | size_t out_len = in_len / 4 * 3; 105 | if( input[in_len - 1] == '=' ) out_len--; 106 | if( input[in_len - 2] == '=' ) out_len--; 107 | 108 | std::vector out( out_len ); 109 | 110 | for( size_t i = 0, j = 0; i < in_len; ) 111 | { 112 | uint32_t a = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; 113 | uint32_t b = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; 114 | uint32_t c = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; 115 | uint32_t d = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast(input[i++])]; 116 | 117 | uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6); 118 | 119 | if( j < out_len ) out[j++] = (triple >> 2 * 8) & 0xFF; 120 | if( j < out_len ) out[j++] = (triple >> 1 * 8) & 0xFF; 121 | if( j < out_len ) out[j++] = (triple >> 0 * 8) & 0xFF; 122 | } 123 | 124 | return out; 125 | } 126 | }; 127 | } 128 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Blends.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "Blends.h" 4 | 5 | template 6 | class FS_T : public virtual FastNoise::Add, public FS_T 7 | { 8 | FASTSIMD_DECLARE_FS_TYPES; 9 | FASTNOISE_IMPL_GEN_T; 10 | 11 | template 12 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 13 | { 14 | return this->GetSourceValue( mLHS, seed, pos... ) + this->GetSourceValue( mRHS, seed, pos... ); 15 | } 16 | }; 17 | 18 | template 19 | class FS_T : public virtual FastNoise::Subtract, public FS_T 20 | { 21 | FASTSIMD_DECLARE_FS_TYPES; 22 | FASTNOISE_IMPL_GEN_T; 23 | 24 | template 25 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 26 | { 27 | return this->GetSourceValue( mLHS, seed, pos... ) - this->GetSourceValue( mRHS, seed, pos... ); 28 | } 29 | }; 30 | 31 | template 32 | class FS_T : public virtual FastNoise::Multiply, public FS_T 33 | { 34 | FASTSIMD_DECLARE_FS_TYPES; 35 | FASTNOISE_IMPL_GEN_T; 36 | 37 | template 38 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 39 | { 40 | return this->GetSourceValue( mLHS, seed, pos... ) * this->GetSourceValue( mRHS, seed, pos... ); 41 | } 42 | }; 43 | 44 | template 45 | class FS_T : public virtual FastNoise::Divide, public FS_T 46 | { 47 | FASTSIMD_DECLARE_FS_TYPES; 48 | FASTNOISE_IMPL_GEN_T; 49 | 50 | template 51 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 52 | { 53 | return this->GetSourceValue( mLHS, seed, pos... ) / this->GetSourceValue( mRHS, seed, pos... ); 54 | } 55 | }; 56 | 57 | template 58 | class FS_T : public virtual FastNoise::PowFloat, public FS_T 59 | { 60 | FASTSIMD_DECLARE_FS_TYPES; 61 | FASTNOISE_IMPL_GEN_T; 62 | 63 | template 64 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 65 | { 66 | return FS_Pow_f32( this->GetSourceValue( mValue, seed, pos... ), this->GetSourceValue( mPow, seed, pos... ) ); 67 | } 68 | }; 69 | 70 | template 71 | class FS_T : public virtual FastNoise::PowInt, public FS_T 72 | { 73 | FASTSIMD_DECLARE_FS_TYPES; 74 | FASTNOISE_IMPL_GEN_T; 75 | 76 | template 77 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 78 | { 79 | float32v value = this->GetSourceValue( mValue, seed, pos... ); 80 | float32v pow = value * value; 81 | 82 | for( int i = 2; i < mPow; i++ ) 83 | { 84 | pow *= value; 85 | } 86 | 87 | return pow; 88 | } 89 | }; 90 | 91 | template 92 | class FS_T : public virtual FastNoise::Min, public FS_T 93 | { 94 | FASTSIMD_DECLARE_FS_TYPES; 95 | FASTNOISE_IMPL_GEN_T; 96 | 97 | template 98 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 99 | { 100 | return FS_Min_f32( this->GetSourceValue( mLHS, seed, pos... ), this->GetSourceValue( mRHS, seed, pos... ) ); 101 | } 102 | }; 103 | 104 | template 105 | class FS_T : public virtual FastNoise::Max, public FS_T 106 | { 107 | FASTSIMD_DECLARE_FS_TYPES; 108 | FASTNOISE_IMPL_GEN_T; 109 | 110 | template 111 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 112 | { 113 | return FS_Max_f32( this->GetSourceValue( mLHS, seed, pos... ), this->GetSourceValue( mRHS, seed, pos... ) ); 114 | } 115 | }; 116 | 117 | template 118 | class FS_T : public virtual FastNoise::MinSmooth, public FS_T 119 | { 120 | FASTSIMD_DECLARE_FS_TYPES; 121 | FASTNOISE_IMPL_GEN_T; 122 | 123 | template 124 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 125 | { 126 | float32v a = this->GetSourceValue( mLHS, seed, pos... ); 127 | float32v b = this->GetSourceValue( mRHS, seed, pos... ); 128 | float32v smoothness = FS_Max_f32( float32v( 1.175494351e-38f ), FS_Abs_f32( this->GetSourceValue( mSmoothness, seed, pos... ) ) ); 129 | 130 | float32v h = FS_Max_f32( smoothness - FS_Abs_f32( a - b ), float32v( 0.0f ) ); 131 | 132 | h *= FS_Reciprocal_f32( smoothness ); 133 | 134 | return FS_FNMulAdd_f32( float32v( 1.0f / 6.0f ), h * h * h * smoothness, FS_Min_f32( a, b ) ); 135 | } 136 | }; 137 | 138 | template 139 | class FS_T : public virtual FastNoise::MaxSmooth, public FS_T 140 | { 141 | FASTSIMD_DECLARE_FS_TYPES; 142 | FASTNOISE_IMPL_GEN_T; 143 | 144 | template 145 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 146 | { 147 | float32v a = -this->GetSourceValue( mLHS, seed, pos... ); 148 | float32v b = -this->GetSourceValue( mRHS, seed, pos... ); 149 | float32v smoothness = FS_Max_f32( float32v( 1.175494351e-38f ), FS_Abs_f32( this->GetSourceValue( mSmoothness, seed, pos... ) ) ); 150 | 151 | float32v h = FS_Max_f32( smoothness - FS_Abs_f32( a - b ), float32v( 0.0f ) ); 152 | 153 | h *= FS_Reciprocal_f32( smoothness ); 154 | 155 | return -FS_FNMulAdd_f32( float32v( 1.0f / 6.0f ), h * h * h * smoothness, FS_Min_f32( a, b ) ); 156 | } 157 | }; 158 | 159 | template 160 | class FS_T : public virtual FastNoise::Fade, public FS_T 161 | { 162 | FASTSIMD_DECLARE_FS_TYPES; 163 | FASTNOISE_IMPL_GEN_T; 164 | 165 | template 166 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 167 | { 168 | float32v fade = FS_Abs_f32( this->GetSourceValue( mFade, seed, pos... ) ); 169 | 170 | return FS_FMulAdd_f32( this->GetSourceValue( mA, seed, pos... ), float32v( 1 ) - fade, this->GetSourceValue( mB, seed, pos... ) * fade ); 171 | } 172 | }; 173 | 174 | -------------------------------------------------------------------------------- /tests/FastNoiseBenchmark.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "FastNoise/FastNoise.h" 3 | #include "FastNoise/Metadata.h" 4 | 5 | #include "../NoiseTool/DemoNodeTrees.inl" 6 | 7 | #include "magic_enum.h" 8 | 9 | static const size_t gPositionCount = 8192; 10 | static float gPositionFloats[gPositionCount]; 11 | 12 | FastNoise::SmartNode<> BuildGenerator( benchmark::State& state, const FastNoise::Metadata* metadata, FastSIMD::eLevel level ) 13 | { 14 | FastNoise::SmartNode<> generator = metadata->CreateNode( level ); 15 | 16 | FastNoise::SmartNode<> source = FastNoise::New( level ); 17 | 18 | for( const auto& memberNode : metadata->memberNodeLookups ) 19 | { 20 | if( !memberNode.setFunc( generator.get(), source ) ) 21 | { 22 | // If constant source is not valid try all other node types in order 23 | for( const FastNoise::Metadata* tryMetadata : FastNoise::Metadata::GetAll() ) 24 | { 25 | FastNoise::SmartNode<> trySource = tryMetadata->CreateNode( level ); 26 | 27 | // Other node types may also have sources 28 | if( memberNode.setFunc( generator.get(), trySource ) ) 29 | { 30 | for( const auto& tryMemberNode : tryMetadata->memberNodeLookups ) 31 | { 32 | if( !tryMemberNode.setFunc( trySource.get(), source ) ) 33 | { 34 | state.SkipWithError( "Could not set valid sources for generator" ); 35 | return {}; 36 | } 37 | } 38 | break; 39 | } 40 | } 41 | } 42 | } 43 | return generator; 44 | } 45 | 46 | void BenchFastNoiseGenerator2D( benchmark::State& state, const FastNoise::SmartNode<> generator ) 47 | { 48 | if (!generator) return; 49 | 50 | float* data = new float[gPositionCount]; 51 | size_t totalData = 0; 52 | int seed = 0; 53 | 54 | for( auto _ : state ) 55 | { 56 | (void)_; 57 | generator->GenPositionArray2D( data, gPositionCount, gPositionFloats, gPositionFloats, 0, 0, seed++ ); 58 | totalData += gPositionCount; 59 | } 60 | 61 | delete[] data; 62 | state.SetItemsProcessed( totalData ); 63 | } 64 | 65 | void BenchFastNoiseGenerator3D( benchmark::State& state, const FastNoise::SmartNode<> generator ) 66 | { 67 | if (!generator) return; 68 | 69 | float* data = new float[gPositionCount]; 70 | size_t totalData = 0; 71 | int seed = 0; 72 | 73 | for( auto _ : state ) 74 | { 75 | (void)_; 76 | generator->GenPositionArray3D( data, gPositionCount, gPositionFloats, gPositionFloats, gPositionFloats, 0, 0, 0, seed++ ); 77 | totalData += gPositionCount; 78 | } 79 | 80 | delete[] data; 81 | state.SetItemsProcessed( totalData ); 82 | } 83 | 84 | void BenchFastNoiseGenerator4D( benchmark::State& state, const FastNoise::SmartNode<> generator ) 85 | { 86 | if (!generator) return; 87 | 88 | float* data = new float[gPositionCount]; 89 | size_t totalData = 0; 90 | int seed = 0; 91 | 92 | for( auto _ : state ) 93 | { 94 | (void)_; 95 | generator->GenPositionArray4D( data, gPositionCount, gPositionFloats, gPositionFloats, gPositionFloats, gPositionFloats, 0, 0, 0, 0, seed++ ); 96 | totalData += gPositionCount; 97 | } 98 | 99 | delete[] data; 100 | state.SetItemsProcessed( totalData ); 101 | } 102 | 103 | template 104 | void RegisterBenchmarks( FastSIMD::eLevel level, const char* groupName, const char* name, T generatorFunc ) 105 | { 106 | std::string benchName = "0D/"; 107 | 108 | #ifdef MAGIC_ENUM_SUPPORTED 109 | auto enumName = magic_enum::flags::enum_name( level ); 110 | auto find = enumName.find( '_' ); 111 | if( find != std::string::npos ) 112 | { 113 | benchName += enumName.data() + find + 1; 114 | } 115 | else 116 | { 117 | benchName += enumName; 118 | } 119 | #else 120 | benchName += std::to_string( (int)level ); 121 | #endif 122 | 123 | 124 | benchName += '/'; 125 | benchName += groupName; 126 | benchName += '/'; 127 | benchName += name; 128 | 129 | benchName[0] = '4'; 130 | benchmark::RegisterBenchmark( benchName.c_str(), [=]( benchmark::State& st ) { BenchFastNoiseGenerator4D( st, generatorFunc( st ) ); } ); 131 | 132 | benchName[0] = '3'; 133 | benchmark::RegisterBenchmark( benchName.c_str(), [=]( benchmark::State& st ) { BenchFastNoiseGenerator3D( st, generatorFunc( st ) ); } ); 134 | 135 | benchName[0] = '2'; 136 | benchmark::RegisterBenchmark( benchName.c_str(), [=]( benchmark::State& st ) { BenchFastNoiseGenerator2D( st, generatorFunc( st ) ); } ); 137 | } 138 | 139 | int main( int argc, char** argv ) 140 | { 141 | benchmark::Initialize( &argc, argv ); 142 | 143 | for( size_t idx = 0; idx < gPositionCount; idx++ ) 144 | { 145 | gPositionFloats[idx] = (float)idx * 0.6f; 146 | } 147 | 148 | for( FastSIMD::eLevel level = FastSIMD::CPUMaxSIMDLevel(); level != FastSIMD::Level_Null; level = (FastSIMD::eLevel)(level >> 1) ) 149 | { 150 | if( !(level & FastSIMD::COMPILED_SIMD_LEVELS & FastNoise::SUPPORTED_SIMD_LEVELS) ) 151 | { 152 | continue; 153 | } 154 | 155 | for( const FastNoise::Metadata* metadata : FastNoise::Metadata::GetAll() ) 156 | { 157 | const char* groupName = "Misc"; 158 | 159 | if( !metadata->groups.empty() ) 160 | { 161 | groupName = metadata->groups[metadata->groups.size() - 1]; 162 | } 163 | 164 | std::string nodeName = FastNoise::Metadata::FormatMetadataNodeName( metadata, false ); 165 | 166 | RegisterBenchmarks( level, groupName, nodeName.c_str(), [=]( benchmark::State& st ) { return BuildGenerator( st, metadata, level ); } ); 167 | } 168 | 169 | for( const auto& nodeTree : gDemoNodeTrees ) 170 | { 171 | RegisterBenchmarks( level, "Node Trees", nodeTree[0], [=]( benchmark::State& st ) 172 | { 173 | FastNoise::SmartNode<> rootNode = FastNoise::NewFromEncodedNodeTree( nodeTree[1], level ); 174 | 175 | if( !rootNode ) 176 | { 177 | st.SkipWithError( "Could not generate node tree from encoded string" ); 178 | } 179 | 180 | return rootNode; 181 | } ); 182 | 183 | } 184 | } 185 | 186 | benchmark::RunSpecifiedBenchmarks(); 187 | 188 | return 0; 189 | } 190 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Perlin.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "Perlin.h" 4 | #include "Utils.inl" 5 | 6 | template 7 | class FS_T : public virtual FastNoise::Perlin, public FS_T 8 | { 9 | FASTSIMD_DECLARE_FS_TYPES; 10 | 11 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const final 12 | { 13 | float32v xs = FS_Floor_f32( x ); 14 | float32v ys = FS_Floor_f32( y ); 15 | 16 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 17 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 18 | int32v x1 = x0 + int32v( FnPrimes::X ); 19 | int32v y1 = y0 + int32v( FnPrimes::Y ); 20 | 21 | float32v xf0 = xs = x - xs; 22 | float32v yf0 = ys = y - ys; 23 | float32v xf1 = xf0 - float32v( 1 ); 24 | float32v yf1 = yf0 - float32v( 1 ); 25 | 26 | xs = FnUtils::InterpQuintic( xs ); 27 | ys = FnUtils::InterpQuintic( ys ); 28 | 29 | return float32v( 0.579106986522674560546875f ) * FnUtils::Lerp( 30 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0 ), xf0, yf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0 ), xf1, yf0 ), xs ), 31 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1 ), xf0, yf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1 ), xf1, yf1 ), xs ), ys ); 32 | } 33 | 34 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const final 35 | { 36 | float32v xs = FS_Floor_f32( x ); 37 | float32v ys = FS_Floor_f32( y ); 38 | float32v zs = FS_Floor_f32( z ); 39 | 40 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 41 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 42 | int32v z0 = FS_Convertf32_i32( zs ) * int32v( FnPrimes::Z ); 43 | int32v x1 = x0 + int32v( FnPrimes::X ); 44 | int32v y1 = y0 + int32v( FnPrimes::Y ); 45 | int32v z1 = z0 + int32v( FnPrimes::Z ); 46 | 47 | float32v xf0 = xs = x - xs; 48 | float32v yf0 = ys = y - ys; 49 | float32v zf0 = zs = z - zs; 50 | float32v xf1 = xf0 - float32v( 1 ); 51 | float32v yf1 = yf0 - float32v( 1 ); 52 | float32v zf1 = zf0 - float32v( 1 ); 53 | 54 | xs = FnUtils::InterpQuintic( xs ); 55 | ys = FnUtils::InterpQuintic( ys ); 56 | zs = FnUtils::InterpQuintic( zs ); 57 | 58 | return float32v( 0.964921414852142333984375f ) * FnUtils::Lerp( FnUtils::Lerp( 59 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0, z0 ), xf0, yf0, zf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0, z0 ), xf1, yf0, zf0 ), xs ), 60 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1, z0 ), xf0, yf1, zf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1, z0 ), xf1, yf1, zf0 ), xs ), ys ), 61 | FnUtils::Lerp( 62 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0, z1 ), xf0, yf0, zf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0, z1 ), xf1, yf0, zf1 ), xs ), 63 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1, z1 ), xf0, yf1, zf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1, z1 ), xf1, yf1, zf1 ), xs ), ys ), zs ); 64 | } 65 | 66 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const final 67 | { 68 | float32v xs = FS_Floor_f32( x ); 69 | float32v ys = FS_Floor_f32( y ); 70 | float32v zs = FS_Floor_f32( z ); 71 | float32v ws = FS_Floor_f32( w ); 72 | 73 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 74 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 75 | int32v z0 = FS_Convertf32_i32( zs ) * int32v( FnPrimes::Z ); 76 | int32v w0 = FS_Convertf32_i32( ws ) * int32v( FnPrimes::W ); 77 | int32v x1 = x0 + int32v( FnPrimes::X ); 78 | int32v y1 = y0 + int32v( FnPrimes::Y ); 79 | int32v z1 = z0 + int32v( FnPrimes::Z ); 80 | int32v w1 = w0 + int32v( FnPrimes::W ); 81 | 82 | float32v xf0 = xs = x - xs; 83 | float32v yf0 = ys = y - ys; 84 | float32v zf0 = zs = z - zs; 85 | float32v wf0 = ws = w - ws; 86 | float32v xf1 = xf0 - float32v( 1 ); 87 | float32v yf1 = yf0 - float32v( 1 ); 88 | float32v zf1 = zf0 - float32v( 1 ); 89 | float32v wf1 = wf0 - float32v( 1 ); 90 | 91 | xs = FnUtils::InterpQuintic( xs ); 92 | ys = FnUtils::InterpQuintic( ys ); 93 | zs = FnUtils::InterpQuintic( zs ); 94 | ws = FnUtils::InterpQuintic( ws ); 95 | 96 | return float32v( 0.964921414852142333984375f ) * FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( 97 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0, z0, w0 ), xf0, yf0, zf0, wf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0, z0, w0 ), xf1, yf0, zf0, wf0 ), xs ), 98 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1, z0, w0 ), xf0, yf1, zf0, wf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1, z0, w0 ), xf1, yf1, zf0, wf0 ), xs ), ys ), 99 | FnUtils::Lerp( 100 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0, z1, w0 ), xf0, yf0, zf1, wf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0, z1, w0 ), xf1, yf0, zf1, wf0 ), xs ), 101 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1, z1, w0 ), xf0, yf1, zf1, wf0 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1, z1, w0 ), xf1, yf1, zf1, wf0 ), xs ), ys ), zs ), 102 | FnUtils::Lerp( FnUtils::Lerp( 103 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0, z0, w1 ), xf0, yf0, zf0, wf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0, z0, w1 ), xf1, yf0, zf0, wf1 ), xs ), 104 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1, z0, w1 ), xf0, yf1, zf0, wf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1, z0, w1 ), xf1, yf1, zf0, wf1 ), xs ), ys ), 105 | FnUtils::Lerp( 106 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y0, z1, w1 ), xf0, yf0, zf1, wf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y0, z1, w1 ), xf1, yf0, zf1, wf1 ), xs ), 107 | FnUtils::Lerp( FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x0, y1, z1, w1 ), xf0, yf1, zf1, wf1 ), FnUtils::GetGradientDot( FnUtils::HashPrimes( seed, x1, y1, z1, w1 ), xf1, yf1, zf1, wf1 ), xs ), ys ), zs ), ws ); 108 | } 109 | }; 110 | -------------------------------------------------------------------------------- /NoiseTool/MeshNoisePreview.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "FastNoise/FastNoise.h" 19 | #include "MultiThreadQueues.h" 20 | 21 | namespace Magnum 22 | { 23 | class MeshNoisePreview 24 | { 25 | public: 26 | MeshNoisePreview(); 27 | ~MeshNoisePreview(); 28 | 29 | void ReGenerate( FastNoise::SmartNodeArg<> generator ); 30 | 31 | void Draw( const Matrix4& transformation, const Matrix4& projection, const Vector3& cameraPosition ); 32 | 33 | private: 34 | enum MeshType 35 | { 36 | MeshType_Voxel3D, 37 | MeshType_Heightmap2D, 38 | MeshType_Count 39 | }; 40 | 41 | inline static const char* MeshTypeStrings = 42 | "Voxel 3D\0" 43 | "Heightmap 2D\0"; 44 | 45 | class VertexLightShader : public GL::AbstractShaderProgram 46 | { 47 | public: 48 | typedef GL::Attribute<0, Vector4> PositionLight; 49 | 50 | explicit VertexLightShader(); 51 | explicit VertexLightShader( NoCreateT ) noexcept : AbstractShaderProgram{ NoCreate } {} 52 | 53 | VertexLightShader( const VertexLightShader& ) = delete; 54 | VertexLightShader( VertexLightShader&& ) noexcept = default; 55 | VertexLightShader& operator=( const VertexLightShader& ) = delete; 56 | VertexLightShader& operator=( VertexLightShader&& ) noexcept = default; 57 | 58 | VertexLightShader& SetTransformationProjectionMatrix( const Matrix4& matrix ); 59 | VertexLightShader& SetColorTint( const Color3& color ); 60 | 61 | private: 62 | GL::Shader CreateShader( GL::Version version, GL::Shader::Type type ); 63 | 64 | int mTransformationProjectionMatrixUniform = 0; 65 | int mColorTintUniform = 1; 66 | }; 67 | 68 | class Chunk 69 | { 70 | public: 71 | struct VertexData 72 | { 73 | VertexData( Vector3 p, float c ) : 74 | posLight( p, c ) {} 75 | 76 | Vector4 posLight; 77 | }; 78 | 79 | struct MeshData 80 | { 81 | MeshData() = default; 82 | 83 | MeshData( Vector3i p, FastNoise::OutputMinMax mm, 84 | const std::vector& v, const std::vector& i, 85 | float minAir = INFINITY, float maxSolid = -INFINITY ) : 86 | pos( p ), minMax( mm ), minAirY( minAir ), maxSolidY( maxSolid ) 87 | { 88 | if( v.empty() ) 89 | { 90 | return; 91 | } 92 | 93 | size_t vertSize = sizeof( VertexData ) * v.size(); 94 | size_t indSize = sizeof( uint32_t ) * i.size(); 95 | 96 | void* vertexDataPtr = std::malloc( vertSize + indSize ); 97 | void* indiciesPtr = (uint8_t*)vertexDataPtr + vertSize; 98 | 99 | std::memcpy( vertexDataPtr, v.data(), vertSize ); 100 | std::memcpy( indiciesPtr, i.data(), indSize ); 101 | 102 | vertexData = { (VertexData*)vertexDataPtr, v.size() }; 103 | indicies = { (uint32_t*)indiciesPtr, i.size() }; 104 | } 105 | 106 | void Free() 107 | { 108 | std::free( vertexData.data() ); 109 | 110 | vertexData = nullptr; 111 | indicies = nullptr; 112 | } 113 | 114 | Vector3i pos; 115 | Containers::ArrayView vertexData; 116 | Containers::ArrayView indicies; 117 | FastNoise::OutputMinMax minMax; 118 | float minAirY, maxSolidY; 119 | }; 120 | 121 | struct BuildData 122 | { 123 | FastNoise::SmartNode generator; 124 | Vector3i pos; 125 | Color3 color; 126 | float frequency, isoSurface, heightmapMultiplier; 127 | int32_t seed; 128 | MeshType meshType; 129 | uint32_t genVersion; 130 | }; 131 | 132 | static MeshData BuildMeshData( const BuildData& buildData ); 133 | static MeshNoisePreview::Chunk::MeshData BuildVoxel3DMesh( const BuildData& buildData, float* densityValues, std::vector& vertexData, std::vector& indicies ); 134 | static MeshNoisePreview::Chunk::MeshData BuildHeightMap2DMesh( const BuildData& buildData, float* densityValues, std::vector& vertexData, std::vector& indicies ); 135 | 136 | Chunk( MeshData& meshData ); 137 | 138 | GL::Mesh* GetMesh() { return mMesh.get(); } 139 | Vector3i GetPos() const { return mPos; } 140 | 141 | static constexpr uint32_t SIZE = 128; 142 | static constexpr Vector3 LIGHT_DIR = { 3, 4, 2 }; 143 | static constexpr float AMBIENT_LIGHT = 0.3f; 144 | static constexpr float AO_STRENGTH = 0.6f; 145 | 146 | private: 147 | static void AddQuadAO( std::vector& verts, std::vector& indicies, const float* density, float isoSurface, 148 | int32_t idx, int32_t facingIdx, int32_t offsetA, int32_t offsetB, float light, Vector3 pos00, Vector3 pos01, Vector3 pos11, Vector3 pos10 ); 149 | 150 | static constexpr uint32_t SIZE_GEN = SIZE + 2; 151 | 152 | Vector3i mPos; 153 | std::unique_ptr mMesh; 154 | }; 155 | 156 | struct Vector3iHash 157 | { 158 | size_t operator()( const Vector3i& v ) const 159 | { 160 | return robin_hood::hash()( 161 | (size_t)v.x() ^ 162 | ((size_t)v.y() << sizeof( size_t ) * 2) ^ 163 | ((size_t)v.z() << sizeof( size_t ) * 4) ); 164 | } 165 | }; 166 | 167 | static void GenerateLoopThread( GenerateQueue& generateQueue, CompleteQueue& completeQueue ); 168 | 169 | void UpdateChunksForPosition( Vector3 position ); 170 | void UpdateChunkQueues( const Vector3& position ); 171 | float GetLoadRangeModifier(); 172 | 173 | void StartTimer(); 174 | float GetTimerDurationMs(); 175 | void SetupSettingsHandlers(); 176 | 177 | robin_hood::unordered_set mRegisteredChunkPositions; 178 | std::vector mChunks; 179 | 180 | bool mEnabled = true; 181 | Chunk::BuildData mBuildData; 182 | float mLoadRange = 300.0f; 183 | float mAvgNewChunks = 1.0f; 184 | uint32_t mTriLimit = 35000000; // 35 mil 185 | uint32_t mTriCount = 0; 186 | uint32_t mMeshesCount = 0; 187 | int mStaggerCheck = 0; 188 | 189 | FastNoise::OutputMinMax mMinMax; 190 | float mMinAirY, mMaxSolidY; 191 | 192 | GenerateQueue mGenerateQueue; 193 | CompleteQueue mCompleteQueue; 194 | std::vector mThreads; 195 | std::chrono::high_resolution_clock::time_point mTimerStart; 196 | 197 | VertexLightShader mShader; 198 | }; 199 | } 200 | -------------------------------------------------------------------------------- /src/FastSIMD/FastSIMD.cpp: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/FastSIMD.h" 2 | 3 | #include 4 | #include 5 | 6 | #ifdef __GNUG__ 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | #include "FastSIMD/SIMDTypeList.h" 13 | 14 | static_assert(FastSIMD::SIMDTypeList::MinimumCompiled & FastSIMD::COMPILED_SIMD_LEVELS, "FASTSIMD_FALLBACK_SIMD_LEVEL is not a compiled SIMD level, check FastSIMD_Config.h"); 15 | 16 | #if FASTSIMD_x86 17 | // Define interface to cpuid instruction. 18 | // input: eax = functionnumber, ecx = 0 19 | // output: eax = output[0], ebx = output[1], ecx = output[2], edx = output[3] 20 | static void cpuid( int output[4], int functionnumber ) 21 | { 22 | #if defined( __GNUC__ ) || defined( __clang__ ) // use inline assembly, Gnu/AT&T syntax 23 | 24 | int a, b, c, d; 25 | __asm("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(functionnumber), "c"(0) : ); 26 | output[0] = a; 27 | output[1] = b; 28 | output[2] = c; 29 | output[3] = d; 30 | 31 | #elif defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) // Microsoft or Intel compiler, intrin.h included 32 | 33 | __cpuidex( output, functionnumber, 0 ); // intrinsic function for CPUID 34 | 35 | #else // unknown platform. try inline assembly with masm/intel syntax 36 | 37 | __asm 38 | { 39 | mov eax, functionnumber 40 | xor ecx, ecx 41 | cpuid; 42 | mov esi, output 43 | mov[esi], eax 44 | mov[esi + 4], ebx 45 | mov[esi + 8], ecx 46 | mov[esi + 12], edx 47 | } 48 | 49 | #endif 50 | } 51 | 52 | // Define interface to xgetbv instruction 53 | static int64_t xgetbv( int ctr ) 54 | { 55 | #if (defined( _MSC_FULL_VER ) && _MSC_FULL_VER >= 160040000) || (defined( __INTEL_COMPILER ) && __INTEL_COMPILER >= 1200) // Microsoft or Intel compiler supporting _xgetbv intrinsic 56 | 57 | return _xgetbv( ctr ); // intrinsic function for XGETBV 58 | 59 | #elif defined( __GNUC__ ) // use inline assembly, Gnu/AT&T syntax 60 | 61 | uint32_t a, d; 62 | __asm("xgetbv" : "=a"(a), "=d"(d) : "c"(ctr) : ); 63 | return a | (uint64_t( d ) << 32); 64 | 65 | #else // #elif defined (_WIN32) // other compiler. try inline assembly with masm/intel/MS syntax 66 | 67 | uint32_t a, d; 68 | __asm { 69 | mov ecx, ctr 70 | _emit 0x0f 71 | _emit 0x01 72 | _emit 0xd0; // xgetbv 73 | mov a, eax 74 | mov d, edx 75 | } 76 | return a | (uint64_t( d ) << 32); 77 | 78 | #endif 79 | } 80 | #endif 81 | 82 | FASTSIMD_API FastSIMD::eLevel FastSIMD::CPUMaxSIMDLevel() 83 | { 84 | static eLevel simdLevel = Level_Null; 85 | 86 | if ( simdLevel > Level_Null ) 87 | { 88 | return simdLevel; 89 | } 90 | 91 | #if FASTSIMD_x86 92 | int abcd[4] = { 0,0,0,0 }; // cpuid results 93 | 94 | #if !FASTSIMD_64BIT 95 | simdLevel = Level_Scalar; // default value 96 | 97 | cpuid( abcd, 0 ); // call cpuid function 0 98 | if ( abcd[0] == 0 ) 99 | return simdLevel; // no further cpuid function supported 100 | 101 | cpuid( abcd, 1 ); // call cpuid function 1 for feature flags 102 | if ( (abcd[3] & (1 << 0)) == 0 ) 103 | return simdLevel; // no floating point 104 | if ( (abcd[3] & (1 << 23)) == 0 ) 105 | return simdLevel; // no MMX 106 | if ( (abcd[3] & (1 << 15)) == 0 ) 107 | return simdLevel; // no conditional move 108 | if ( (abcd[3] & (1 << 24)) == 0 ) 109 | return simdLevel; // no FXSAVE 110 | if ( (abcd[3] & (1 << 25)) == 0 ) 111 | return simdLevel; // no SSE 112 | simdLevel = Level_SSE; 113 | // 1: SSE supported 114 | 115 | if ( (abcd[3] & (1 << 26)) == 0 ) 116 | return simdLevel; // no SSE2 117 | #else 118 | cpuid( abcd, 1 ); // call cpuid function 1 for feature flags 119 | #endif 120 | 121 | simdLevel = Level_SSE2; // default value for 64bit 122 | // 2: SSE2 supported 123 | 124 | if ( (abcd[2] & (1 << 0)) == 0 ) 125 | return simdLevel; // no SSE3 126 | simdLevel = Level_SSE3; 127 | // 3: SSE3 supported 128 | 129 | if ( (abcd[2] & (1 << 9)) == 0 ) 130 | return simdLevel; // no SSSE3 131 | simdLevel = Level_SSSE3; 132 | // 4: SSSE3 supported 133 | 134 | if ( (abcd[2] & (1 << 19)) == 0 ) 135 | return simdLevel; // no SSE4.1 136 | simdLevel = Level_SSE41; 137 | // 5: SSE4.1 supported 138 | 139 | if ( (abcd[2] & (1 << 23)) == 0 ) 140 | return simdLevel; // no POPCNT 141 | if ( (abcd[2] & (1 << 20)) == 0 ) 142 | return simdLevel; // no SSE4.2 143 | simdLevel = Level_SSE42; 144 | // 6: SSE4.2 supported 145 | 146 | if ( (abcd[2] & (1 << 26)) == 0 ) 147 | return simdLevel; // no XSAVE 148 | if ( (abcd[2] & (1 << 27)) == 0 ) 149 | return simdLevel; // no OSXSAVE 150 | if ( (abcd[2] & (1 << 28)) == 0 ) 151 | return simdLevel; // no AVX 152 | 153 | uint64_t osbv = xgetbv( 0 ); 154 | if ( (osbv & 6) != 6 ) 155 | return simdLevel; // AVX not enabled in O.S. 156 | simdLevel = Level_AVX; 157 | // 7: AVX supported 158 | 159 | cpuid( abcd, 7 ); // call cpuid leaf 7 for feature flags 160 | if ( (abcd[1] & (1 << 5)) == 0 ) 161 | return simdLevel; // no AVX2 162 | simdLevel = Level_AVX2; 163 | // 8: AVX2 supported 164 | 165 | if( (osbv & (0xE0)) != 0xE0 ) 166 | return simdLevel; // AVX512 not enabled in O.S. 167 | if ( (abcd[1] & (1 << 16)) == 0 ) 168 | return simdLevel; // no AVX512 169 | cpuid( abcd, 0xD ); // call cpuid leaf 0xD for feature flags 170 | if ( (abcd[0] & 0x60) != 0x60 ) 171 | return simdLevel; // no AVX512 172 | // 9: AVX512 supported 173 | 174 | cpuid( abcd, 7 ); // call cpuid leaf 7 for feature flags 175 | if ( (abcd[1] & (1 << 31)) == 0 ) 176 | return simdLevel; // no AVX512VL 177 | // 10: AVX512VL supported 178 | 179 | if ( (abcd[1] & 0x40020000) != 0x40020000 ) 180 | return simdLevel; // no AVX512BW, AVX512DQ 181 | simdLevel = Level_AVX512; 182 | // 11: AVX512BW & AVX512DQ supported 183 | #endif 184 | 185 | #if FASTSIMD_ARM 186 | simdLevel = Level_NEON; 187 | #endif 188 | 189 | return simdLevel; 190 | } 191 | 192 | template 193 | CLASS_T* SIMDLevelSelector( FastSIMD::eLevel maxSIMDLevel, FastSIMD::MemoryAllocator allocator ) 194 | { 195 | if constexpr( ( CLASS_T::Supported_SIMD_Levels & SIMD_LEVEL ) != 0 ) 196 | { 197 | CLASS_T* newClass = SIMDLevelSelector>( maxSIMDLevel, allocator ); 198 | 199 | if( !newClass && SIMD_LEVEL <= maxSIMDLevel ) 200 | { 201 | return FastSIMD::ClassFactory( allocator ); 202 | } 203 | 204 | return newClass; 205 | } 206 | else 207 | { 208 | if constexpr( SIMD_LEVEL == FastSIMD::Level_Null ) 209 | { 210 | return nullptr; 211 | } 212 | 213 | return SIMDLevelSelector>( maxSIMDLevel, allocator ); 214 | } 215 | } 216 | 217 | template 218 | CLASS_T* FastSIMD::New( eLevel maxSIMDLevel, FastSIMD::MemoryAllocator allocator ) 219 | { 220 | if( maxSIMDLevel == Level_Null ) 221 | { 222 | maxSIMDLevel = CPUMaxSIMDLevel(); 223 | } 224 | else 225 | { 226 | maxSIMDLevel = std::min( maxSIMDLevel, CPUMaxSIMDLevel() ); 227 | } 228 | 229 | static_assert(( CLASS_T::Supported_SIMD_Levels & FastSIMD::SIMDTypeList::MinimumCompiled ), "MinimumCompiled SIMD Level must be supported by this class" ); 230 | return SIMDLevelSelector( maxSIMDLevel, allocator ); 231 | } 232 | 233 | #define FASTSIMD_BUILD_CLASS( CLASS ) \ 234 | template FASTSIMD_API CLASS* FastSIMD::New( FastSIMD::eLevel, FastSIMD::MemoryAllocator ); 235 | 236 | #define FASTSIMD_INCLUDE_HEADER_ONLY 237 | #include "FastSIMD_BuildList.inl" 238 | -------------------------------------------------------------------------------- /include/FastNoise/SmartNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "FastNoise_Config.h" 10 | 11 | namespace FastNoise 12 | { 13 | class FASTNOISE_API SmartNodeManager 14 | { 15 | public: 16 | static constexpr uint64_t kInvalidReferenceId = (uint64_t)-1; 17 | 18 | SmartNodeManager() = delete; 19 | 20 | static void SetMemoryPoolSize( uint32_t size ); 21 | 22 | private: 23 | template 24 | friend struct MetadataT; 25 | 26 | template 27 | friend class SmartNode; 28 | 29 | template 30 | friend SmartNode New( FastSIMD::eLevel ); 31 | 32 | static uint64_t GetReference( const void* ptr ); 33 | 34 | static void IncReference( uint64_t id ); 35 | 36 | static void DecReference( uint64_t id, void* ptr, void ( *destructorFunc )( void* ) ); 37 | 38 | static uint32_t ReferenceCount( uint64_t id ); 39 | 40 | static void* Allocate( size_t size, size_t align ); 41 | }; 42 | 43 | template 44 | class SmartNode 45 | { 46 | public: 47 | static_assert( std::is_base_of::value, "SmartNode should only be used for FastNoise node classes" ); 48 | 49 | template 50 | static SmartNode DynamicCast( SmartNode node ) 51 | { 52 | if( T* dynamicCast = dynamic_cast( node.get() ) ) 53 | { 54 | return FastNoise::SmartNode( node, dynamicCast ); 55 | } 56 | 57 | return nullptr; 58 | } 59 | 60 | constexpr SmartNode( std::nullptr_t = nullptr ) noexcept : 61 | mReferenceId( SmartNodeManager::kInvalidReferenceId ), 62 | mPtr( nullptr ) 63 | {} 64 | 65 | SmartNode( const SmartNode& node ) 66 | { 67 | TryInc( node.mReferenceId ); 68 | mReferenceId = node.mReferenceId; 69 | mPtr = node.mPtr; 70 | } 71 | 72 | template 73 | SmartNode( const SmartNode& node ) 74 | { 75 | TryInc( node.mReferenceId ); 76 | mReferenceId = node.mReferenceId; 77 | mPtr = node.mPtr; 78 | } 79 | 80 | template 81 | SmartNode( const SmartNode& node, T* ptr ) 82 | { 83 | assert( ptr ); 84 | 85 | TryInc( node.mReferenceId ); 86 | mReferenceId = node.mReferenceId; 87 | mPtr = ptr; 88 | } 89 | 90 | SmartNode( SmartNode&& node ) noexcept 91 | { 92 | mReferenceId = node.mReferenceId; 93 | mPtr = node.mPtr; 94 | 95 | node.mReferenceId = SmartNodeManager::kInvalidReferenceId; 96 | node.mPtr = nullptr; 97 | } 98 | 99 | template 100 | SmartNode( SmartNode&& node ) noexcept 101 | { 102 | mReferenceId = node.mReferenceId; 103 | mPtr = node.mPtr; 104 | 105 | node.mReferenceId = SmartNodeManager::kInvalidReferenceId; 106 | node.mPtr = nullptr; 107 | } 108 | 109 | ~SmartNode() 110 | { 111 | Release(); 112 | } 113 | 114 | SmartNode& operator=( SmartNode&& node ) noexcept 115 | { 116 | swap( node ); 117 | return *this; 118 | } 119 | 120 | template 121 | SmartNode& operator=( SmartNode&& node ) noexcept 122 | { 123 | if( mReferenceId == node.mReferenceId ) 124 | { 125 | mPtr = node.mPtr; 126 | } 127 | else 128 | { 129 | Release(); 130 | mReferenceId = node.mReferenceId; 131 | mPtr = node.mPtr; 132 | 133 | node.mReferenceId = SmartNodeManager::kInvalidReferenceId; 134 | node.mPtr = nullptr; 135 | } 136 | 137 | return *this; 138 | } 139 | 140 | SmartNode& operator=( const SmartNode& node ) noexcept 141 | { 142 | if( mReferenceId != node.mReferenceId ) 143 | { 144 | TryInc( node.mReferenceId ); 145 | Release(); 146 | mReferenceId = node.mReferenceId; 147 | } 148 | mPtr = node.mPtr; 149 | 150 | return *this; 151 | } 152 | 153 | template 154 | SmartNode& operator=( const SmartNode& node ) noexcept 155 | { 156 | if( mReferenceId != node.mReferenceId ) 157 | { 158 | TryInc( node.mReferenceId ); 159 | Release(); 160 | mReferenceId = node.mReferenceId; 161 | } 162 | mPtr = node.mPtr; 163 | 164 | return *this; 165 | } 166 | 167 | template 168 | friend bool operator==( const SmartNode& lhs, const SmartNode& rhs ) noexcept 169 | { 170 | return lhs.get() == rhs.get(); 171 | } 172 | 173 | template 174 | friend bool operator!=( const SmartNode& lhs, const SmartNode& rhs ) noexcept 175 | { 176 | return lhs.get() != rhs.get(); 177 | } 178 | 179 | T& operator*() const noexcept 180 | { 181 | return *mPtr; 182 | } 183 | 184 | T* operator->() const noexcept 185 | { 186 | return mPtr; 187 | } 188 | 189 | explicit operator bool() const noexcept 190 | { 191 | return mPtr; 192 | } 193 | 194 | T* get() const noexcept 195 | { 196 | return mPtr; 197 | } 198 | 199 | void reset( T* ptr = nullptr ) 200 | { 201 | *this = SmartNode( ptr ); 202 | } 203 | 204 | void swap( SmartNode& node ) noexcept 205 | { 206 | std::swap( mReferenceId, node.mReferenceId ); 207 | std::swap( mPtr, node.mPtr ); 208 | } 209 | 210 | long use_count() const noexcept 211 | { 212 | if( mReferenceId == SmartNodeManager::kInvalidReferenceId ) 213 | { 214 | return 0; 215 | } 216 | 217 | return (long)SmartNodeManager::ReferenceCount( mReferenceId ); 218 | } 219 | 220 | bool unique() const noexcept 221 | { 222 | return use_count() == 1; 223 | } 224 | 225 | private: 226 | template 227 | friend SmartNode New( FastSIMD::eLevel ); 228 | 229 | template 230 | friend struct MetadataT; 231 | 232 | template 233 | friend class SmartNode; 234 | 235 | explicit SmartNode( T* ptr ) : 236 | mReferenceId( SmartNodeManager::GetReference( ptr ) ), 237 | mPtr( ptr ) 238 | { 239 | SmartNodeManager::IncReference( mReferenceId ); 240 | } 241 | 242 | void Release() 243 | { 244 | using U = typename std::remove_const::type; 245 | 246 | if( mReferenceId != SmartNodeManager::kInvalidReferenceId ) 247 | { 248 | SmartNodeManager::DecReference( mReferenceId, const_cast( mPtr ), []( void* ptr ) { ( (U*)ptr )->~T(); } ); 249 | } 250 | 251 | mReferenceId = SmartNodeManager::kInvalidReferenceId; 252 | mPtr = nullptr; 253 | } 254 | 255 | static void TryInc( uint64_t id ) 256 | { 257 | if( id != SmartNodeManager::kInvalidReferenceId ) 258 | { 259 | SmartNodeManager::IncReference( id ); 260 | } 261 | } 262 | 263 | uint64_t mReferenceId; 264 | T* mPtr; 265 | }; 266 | } // namespace FastNoise 267 | 268 | namespace std 269 | { 270 | template 271 | struct hash> 272 | { 273 | size_t operator()( const FastNoise::SmartNode& node ) const noexcept 274 | { 275 | return std::hash( node.get() ); 276 | } 277 | }; 278 | } 279 | -------------------------------------------------------------------------------- /include/FastNoise/Metadata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "FastNoise_Config.h" 9 | 10 | #pragma warning( push ) 11 | #pragma warning( disable : 4251 ) 12 | 13 | namespace FastNoise 14 | { 15 | class Generator; 16 | template 17 | struct PerDimensionVariable; 18 | struct Metadata; 19 | struct NodeData; 20 | 21 | namespace Impl 22 | { 23 | template 24 | FASTNOISE_API const Metadata& GetMetadata(); 25 | } 26 | 27 | // Stores definition of a FastNoise node class 28 | // Node name, member name+types, functions to set members 29 | struct FASTNOISE_API Metadata 30 | { 31 | virtual ~Metadata() = default; 32 | 33 | /// Array containing metadata for every FastNoise node type 34 | static const std::vector& GetAll() 35 | { 36 | return sAllMetadata; 37 | } 38 | 39 | /// Metadata for given Metadata::id 40 | static const Metadata* GetFromId( uint16_t nodeId ) 41 | { 42 | if( nodeId < sAllMetadata.size() ) 43 | { 44 | return sAllMetadata[nodeId]; 45 | } 46 | 47 | return nullptr; 48 | } 49 | 50 | /// Metadata for given node class 51 | template 52 | static const Metadata& Get() 53 | { 54 | static_assert( std::is_base_of::value, "This function should only be used for FastNoise node classes, for example FastNoise::Simplex" ); 55 | static_assert( std::is_member_function_pointer::value, "Cannot get Metadata for abstract node class, use a derived class, for example: Fractal -> FractalFBm" ); 56 | 57 | return Impl::GetMetadata(); 58 | } 59 | 60 | ///

61 | /// Serialise node data and any source node datas (recursive) 62 | /// 63 | /// Root node data 64 | /// Remove dependency loops and invalid node types 65 | /// Empty string on error 66 | static std::string SerialiseNodeData( NodeData* nodeData, bool fixUp = false ); 67 | 68 | /// 69 | /// Deserialise a string created from SerialiseNodeData to a node data tree 70 | /// 71 | /// Encoded string to deserialise 72 | /// Storage for new node data 73 | /// Root node 74 | static NodeData* DeserialiseNodeData( const char* serialisedBase64NodeData, std::vector>& nodeDataOut ); 75 | 76 | // Base member struct 77 | struct Member 78 | { 79 | const char* name; 80 | int dimensionIdx = -1; 81 | }; 82 | 83 | /// 84 | /// Add spaces to node names: DomainScale -> Domain Scale 85 | /// 86 | /// FastNoise node metadata 87 | /// Removes metadata groups from name: FractalFBm -> FBm 88 | /// string with formatted name 89 | static std::string FormatMetadataNodeName( const Metadata* metadata, bool removeGroups = false ); 90 | 91 | /// 92 | /// Adds dimension prefix to member varibles that per-dimension: 93 | /// DomainAxisScale::Scale -> X Scale 94 | /// 95 | /// FastNoise node metadata member 96 | /// string with formatted name 97 | static std::string FormatMetadataMemberName( const Member& member ); 98 | 99 | // float, int or enum value 100 | struct MemberVariable : Member 101 | { 102 | enum eType 103 | { 104 | EFloat, 105 | EInt, 106 | EEnum 107 | }; 108 | 109 | union ValueUnion 110 | { 111 | float f; 112 | int i; 113 | 114 | ValueUnion( float v = 0 ) 115 | { 116 | f = v; 117 | } 118 | 119 | ValueUnion( int v ) 120 | { 121 | i = v; 122 | } 123 | 124 | operator float() 125 | { 126 | return f; 127 | } 128 | 129 | operator int() 130 | { 131 | return i; 132 | } 133 | 134 | bool operator ==( const ValueUnion& rhs ) const 135 | { 136 | return i == rhs.i; 137 | } 138 | }; 139 | 140 | eType type; 141 | ValueUnion valueDefault, valueMin, valueMax; 142 | std::vector enumNames; 143 | 144 | // Function to set value for given generator 145 | // Returns true if Generator is correct node class 146 | std::function setFunc; 147 | }; 148 | 149 | // Node lookup (must be valid for node to function) 150 | struct MemberNodeLookup : Member 151 | { 152 | // Function to set source for given generator 153 | // Returns true if Generator* is correct node class and SmartNodeArg<> is correct node class 154 | std::function )> setFunc; 155 | }; 156 | 157 | // Either a constant float or node lookup 158 | struct MemberHybrid : Member 159 | { 160 | float valueDefault = 0.0f; 161 | 162 | // Function to set value for given generator 163 | // Returns true if Generator is correct node class 164 | std::function setValueFunc; 165 | 166 | // Function to set source for given generator 167 | // Source takes priority if value is also set 168 | // Returns true if Generator is correct node class and SmartNodeArg<> is correct node class 169 | std::function )> setNodeFunc; 170 | }; 171 | 172 | uint16_t id; 173 | const char* name; 174 | std::vector groups; 175 | 176 | std::vector memberVariables; 177 | std::vector memberNodeLookups; 178 | std::vector memberHybrids; 179 | 180 | /// 181 | /// Create new instance of a FastNoise node from metadata 182 | /// 183 | /// 184 | /// auto node = metadata->CreateNode(); 185 | /// metadata->memberVariables[0].setFunc( node.get(), 1.5f ); 186 | /// 187 | /// Max SIMD level, Null = Auto 188 | /// SmartNode is guaranteed not nullptr 189 | virtual SmartNode<> CreateNode( FastSIMD::eLevel maxSimdLevel = FastSIMD::Level_Null ) const = 0; 190 | 191 | protected: 192 | Metadata() 193 | { 194 | id = AddMetadata( this ); 195 | } 196 | 197 | private: 198 | static uint16_t AddMetadata( const Metadata* newMetadata ) 199 | { 200 | sAllMetadata.emplace_back( newMetadata ); 201 | 202 | return (uint16_t)sAllMetadata.size() - 1; 203 | } 204 | 205 | static std::vector sAllMetadata; 206 | }; 207 | 208 | // Stores data to create an instance of a FastNoise node 209 | // Node type, member values 210 | struct FASTNOISE_API NodeData 211 | { 212 | NodeData( const Metadata* metadata ); 213 | 214 | const Metadata* metadata; 215 | std::vector variables; 216 | std::vector nodeLookups; 217 | std::vector> hybrids; 218 | 219 | bool operator ==( const NodeData& rhs ) const 220 | { 221 | return metadata == rhs.metadata && 222 | variables == rhs.variables && 223 | nodeLookups == rhs.nodeLookups && 224 | hybrids == rhs.hybrids; 225 | } 226 | }; 227 | } 228 | 229 | #pragma warning( pop ) 230 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Blends.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Generator.h" 3 | 4 | #include 5 | 6 | namespace FastNoise 7 | { 8 | class OperatorSourceLHS : public virtual Generator 9 | { 10 | public: 11 | void SetLHS( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mLHS, gen ); } 12 | void SetRHS( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mRHS, gen ); } 13 | void SetRHS( float value ) { mRHS = value; } 14 | 15 | protected: 16 | GeneratorSource mLHS; 17 | HybridSource mRHS = 0.0f; 18 | }; 19 | 20 | #ifdef FASTNOISE_METADATA 21 | template<> 22 | struct MetadataT : MetadataT 23 | { 24 | MetadataT() 25 | { 26 | groups.push_back( "Blends" ); 27 | this->AddGeneratorSource( "LHS", &OperatorSourceLHS::SetLHS ); 28 | this->AddHybridSource( "RHS", 0.0f, &OperatorSourceLHS::SetRHS, &OperatorSourceLHS::SetRHS ); 29 | } 30 | }; 31 | #endif 32 | 33 | class OperatorHybridLHS : public virtual Generator 34 | { 35 | public: 36 | void SetLHS( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mLHS, gen ); } 37 | void SetLHS( float value ) { mLHS = value; } 38 | void SetRHS( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mRHS, gen ); } 39 | void SetRHS( float value ) { mRHS = value; } 40 | 41 | protected: 42 | HybridSource mLHS = 0.0f; 43 | HybridSource mRHS = 0.0f; 44 | }; 45 | 46 | #ifdef FASTNOISE_METADATA 47 | template<> 48 | struct MetadataT : MetadataT 49 | { 50 | MetadataT() 51 | { 52 | groups.push_back( "Blends" ); 53 | this->AddHybridSource( "LHS", 0.0f, &OperatorHybridLHS::SetLHS, &OperatorHybridLHS::SetLHS ); 54 | this->AddHybridSource( "RHS", 0.0f, &OperatorHybridLHS::SetRHS, &OperatorHybridLHS::SetRHS ); 55 | } 56 | }; 57 | #endif 58 | 59 | class Add : public virtual OperatorSourceLHS 60 | { 61 | public: 62 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 63 | const Metadata& GetMetadata() const override; 64 | }; 65 | 66 | #ifdef FASTNOISE_METADATA 67 | template<> 68 | struct MetadataT : MetadataT 69 | { 70 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 71 | }; 72 | #endif 73 | 74 | class Subtract : public virtual OperatorHybridLHS 75 | { 76 | public: 77 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 78 | const Metadata& GetMetadata() const override; 79 | }; 80 | 81 | #ifdef FASTNOISE_METADATA 82 | template<> 83 | struct MetadataT : MetadataT 84 | { 85 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 86 | }; 87 | #endif 88 | 89 | class Multiply : public virtual OperatorSourceLHS 90 | { 91 | public: 92 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 93 | const Metadata& GetMetadata() const override; 94 | }; 95 | 96 | #ifdef FASTNOISE_METADATA 97 | template<> 98 | struct MetadataT : MetadataT 99 | { 100 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 101 | }; 102 | #endif 103 | 104 | class Divide : public virtual OperatorHybridLHS 105 | { 106 | public: 107 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 108 | const Metadata& GetMetadata() const override; 109 | }; 110 | 111 | #ifdef FASTNOISE_METADATA 112 | template<> 113 | struct MetadataT : MetadataT 114 | { 115 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 116 | }; 117 | #endif 118 | 119 | class Min : public virtual OperatorSourceLHS 120 | { 121 | public: 122 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 123 | const Metadata& GetMetadata() const override; 124 | }; 125 | 126 | #ifdef FASTNOISE_METADATA 127 | template<> 128 | struct MetadataT : MetadataT 129 | { 130 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 131 | }; 132 | #endif 133 | 134 | class Max : public virtual OperatorSourceLHS 135 | { 136 | public: 137 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 138 | const Metadata& GetMetadata() const override; 139 | }; 140 | 141 | #ifdef FASTNOISE_METADATA 142 | template<> 143 | struct MetadataT : MetadataT 144 | { 145 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 146 | }; 147 | #endif 148 | 149 | class PowFloat : public virtual Generator 150 | { 151 | public: 152 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 153 | const Metadata& GetMetadata() const override; 154 | 155 | void SetValue( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mValue, gen ); } 156 | void SetValue( float value ) { mValue = value; } 157 | void SetPow( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mPow, gen ); } 158 | void SetPow( float value ) { mPow = value; } 159 | 160 | protected: 161 | HybridSource mValue = 2.0f; 162 | HybridSource mPow = 2.0f; 163 | }; 164 | 165 | #ifdef FASTNOISE_METADATA 166 | template<> 167 | struct MetadataT : MetadataT 168 | { 169 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 170 | 171 | MetadataT() 172 | { 173 | groups.push_back( "Blends" ); 174 | this->AddHybridSource( "Value", 2.0f, &PowFloat::SetValue, &PowFloat::SetValue ); 175 | this->AddHybridSource( "Pow", 2.0f, &PowFloat::SetPow, &PowFloat::SetPow ); 176 | } 177 | }; 178 | #endif 179 | 180 | class PowInt : public virtual Generator 181 | { 182 | public: 183 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 184 | const Metadata& GetMetadata() const override; 185 | 186 | void SetValue( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mValue, gen ); } 187 | void SetPow( int value ) { mPow = value; } 188 | 189 | protected: 190 | GeneratorSource mValue; 191 | int mPow = 2; 192 | }; 193 | 194 | #ifdef FASTNOISE_METADATA 195 | template<> 196 | struct MetadataT : MetadataT 197 | { 198 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 199 | 200 | MetadataT() 201 | { 202 | groups.push_back( "Blends" ); 203 | this->AddGeneratorSource( "Value", &PowInt::SetValue ); 204 | this->AddVariable( "Pow", 2, &PowInt::SetPow, 2, INT_MAX ); 205 | } 206 | }; 207 | #endif 208 | 209 | class MinSmooth : public virtual OperatorSourceLHS 210 | { 211 | public: 212 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 213 | const Metadata& GetMetadata() const override; 214 | 215 | void SetSmoothness( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mSmoothness, gen ); } 216 | void SetSmoothness( float value ) { mSmoothness = value; } 217 | 218 | protected: 219 | HybridSource mSmoothness = 0.1f; 220 | }; 221 | 222 | #ifdef FASTNOISE_METADATA 223 | template<> 224 | struct MetadataT : MetadataT 225 | { 226 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 227 | 228 | MetadataT() 229 | { 230 | this->AddHybridSource( "Smoothness", 0.1f, &MinSmooth::SetSmoothness, &MinSmooth::SetSmoothness ); 231 | } 232 | }; 233 | #endif 234 | 235 | class MaxSmooth : public virtual OperatorSourceLHS 236 | { 237 | public: 238 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 239 | const Metadata& GetMetadata() const override; 240 | 241 | void SetSmoothness( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mSmoothness, gen ); } 242 | void SetSmoothness( float value ) { mSmoothness = value; } 243 | 244 | protected: 245 | HybridSource mSmoothness = 0.1f; 246 | }; 247 | 248 | #ifdef FASTNOISE_METADATA 249 | template<> 250 | struct MetadataT : MetadataT 251 | { 252 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 253 | 254 | MetadataT() 255 | { 256 | this->AddHybridSource( "Smoothness", 0.1f, &MaxSmooth::SetSmoothness, &MaxSmooth::SetSmoothness ); 257 | } 258 | }; 259 | #endif 260 | 261 | class Fade : public virtual Generator 262 | { 263 | public: 264 | FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS ); 265 | const Metadata& GetMetadata() const override; 266 | void SetA( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mA, gen ); } 267 | void SetB( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mB, gen ); } 268 | 269 | void SetFade( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mFade, gen ); } 270 | void SetFade( float value ) { mFade = value; } 271 | 272 | protected: 273 | GeneratorSource mA; 274 | GeneratorSource mB; 275 | HybridSource mFade = 0.5f; 276 | }; 277 | 278 | #ifdef FASTNOISE_METADATA 279 | template<> 280 | struct MetadataT : MetadataT 281 | { 282 | SmartNode<> CreateNode( FastSIMD::eLevel ) const override; 283 | 284 | MetadataT() 285 | { 286 | groups.push_back( "Blends" ); 287 | this->AddGeneratorSource( "A", &Fade::SetA ); 288 | this->AddGeneratorSource( "B", &Fade::SetB ); 289 | this->AddHybridSource( "Fade", 0.5f, &Fade::SetFade, &Fade::SetFade ); 290 | } 291 | }; 292 | #endif 293 | } 294 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/Modifiers.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "Modifiers.h" 4 | 5 | template 6 | class FS_T : public virtual FastNoise::DomainScale, public FS_T 7 | { 8 | FASTSIMD_DECLARE_FS_TYPES; 9 | FASTNOISE_IMPL_GEN_T; 10 | 11 | template 12 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 13 | { 14 | return this->GetSourceValue( mSource, seed, (pos * float32v( mScale ))... ); 15 | } 16 | }; 17 | 18 | template 19 | class FS_T : public virtual FastNoise::DomainOffset, public FS_T 20 | { 21 | FASTSIMD_DECLARE_FS_TYPES; 22 | FASTNOISE_IMPL_GEN_T; 23 | 24 | template 25 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 26 | { 27 | return [this, seed]( std::remove_reference_t

... sourcePos, std::remove_reference_t

... offset ) 28 | { 29 | size_t idx = 0; 30 | ((offset += this->GetSourceValue( mOffset[idx++], seed, sourcePos... )), ...); 31 | 32 | return this->GetSourceValue( mSource, seed, offset... ); 33 | } (pos..., pos...); 34 | } 35 | }; 36 | 37 | template 38 | class FS_T : public virtual FastNoise::DomainRotate, public FS_T 39 | { 40 | FASTSIMD_DECLARE_FS_TYPES; 41 | 42 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const final 43 | { 44 | if( mPitchSin == 0.0f && mRollSin == 0.0f ) 45 | { 46 | return this->GetSourceValue( mSource, seed, 47 | FS_FNMulAdd_f32( y, float32v( mYawSin ), x * float32v( mYawCos ) ), 48 | FS_FMulAdd_f32( x, float32v( mYawSin ), y * float32v( mYawCos ) ) ); 49 | } 50 | 51 | return Gen( seed, x, y, float32v( 0 ) ); 52 | } 53 | 54 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const final 55 | { 56 | return this->GetSourceValue( mSource, seed, 57 | FS_FMulAdd_f32( x, float32v( mXa ), FS_FMulAdd_f32( y, float32v( mXb ), z * float32v( mXc ) ) ), 58 | FS_FMulAdd_f32( x, float32v( mYa ), FS_FMulAdd_f32( y, float32v( mYb ), z * float32v( mYc ) ) ), 59 | FS_FMulAdd_f32( x, float32v( mZa ), FS_FMulAdd_f32( y, float32v( mZb ), z * float32v( mZc ) ) ) ); 60 | } 61 | 62 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const final 63 | { 64 | // No rotation for 4D yet 65 | return this->GetSourceValue( mSource, seed, x, y, z, w ); 66 | } 67 | }; 68 | 69 | template 70 | class FS_T : public virtual FastNoise::SeedOffset, public FS_T 71 | { 72 | FASTSIMD_DECLARE_FS_TYPES; 73 | FASTNOISE_IMPL_GEN_T; 74 | 75 | template 76 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 77 | { 78 | return this->GetSourceValue( mSource, seed + int32v( mOffset ), pos... ); 79 | } 80 | }; 81 | 82 | template 83 | class FS_T : public virtual FastNoise::Remap, public FS_T 84 | { 85 | FASTSIMD_DECLARE_FS_TYPES; 86 | FASTNOISE_IMPL_GEN_T; 87 | 88 | template 89 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 90 | { 91 | float32v source = this->GetSourceValue( mSource, seed, pos... ); 92 | 93 | return float32v( mToMin ) + (( source - float32v( mFromMin ) ) / float32v( mFromMax - mFromMin ) * float32v( mToMax - mToMin )); 94 | } 95 | }; 96 | 97 | template 98 | class FS_T : public virtual FastNoise::ConvertRGBA8, public FS_T 99 | { 100 | FASTSIMD_DECLARE_FS_TYPES; 101 | FASTNOISE_IMPL_GEN_T; 102 | 103 | template 104 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 105 | { 106 | float32v source = this->GetSourceValue( mSource, seed, pos... ); 107 | 108 | source = FS_Min_f32( source, float32v( mMax )); 109 | source = FS_Max_f32( source, float32v( mMin )); 110 | source -= float32v( mMin ); 111 | 112 | source *= float32v( 255.0f / (mMax - mMin) ); 113 | 114 | int32v byteVal = FS_Convertf32_i32( source ); 115 | 116 | int32v output = int32v( 255 << 24 ); 117 | output |= byteVal; 118 | output |= byteVal << 8; 119 | output |= byteVal << 16; 120 | 121 | return FS_Casti32_f32( output ); 122 | } 123 | }; 124 | 125 | template 126 | class FS_T : public virtual FastNoise::Terrace, public FS_T 127 | { 128 | FASTSIMD_DECLARE_FS_TYPES; 129 | FASTNOISE_IMPL_GEN_T; 130 | 131 | template 132 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 133 | { 134 | float32v source = this->GetSourceValue( mSource, seed, pos... ); 135 | 136 | source *= float32v( mMultiplier ); 137 | float32v rounded = FS_Round_f32( source ); 138 | 139 | if( mSmoothness != 0.0f ) 140 | { 141 | float32v diff = rounded - source; 142 | mask32v diffSign = diff < float32v( 0 ); 143 | 144 | diff = FS_Abs_f32( diff ); 145 | diff = float32v( 0.5f ) - diff; 146 | 147 | diff *= float32v( mSmoothnessRecip ); 148 | diff = FS_Min_f32( diff, float32v( 0.5f ) ); 149 | diff = FS_Select_f32( diffSign, float32v( 0.5f ) - diff, diff - float32v( 0.5f ) ); 150 | 151 | rounded += diff; 152 | } 153 | 154 | return rounded * float32v( mMultiplierRecip ); 155 | } 156 | }; 157 | 158 | template 159 | class FS_T : public virtual FastNoise::DomainAxisScale, public FS_T 160 | { 161 | FASTSIMD_DECLARE_FS_TYPES; 162 | FASTNOISE_IMPL_GEN_T; 163 | 164 | template 165 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 166 | { 167 | size_t idx = 0; 168 | ((pos *= float32v( mScale[idx++] )), ...); 169 | 170 | return this->GetSourceValue( mSource, seed, pos... ); 171 | } 172 | }; 173 | 174 | template 175 | class FS_T : public virtual FastNoise::AddDimension, public FS_T 176 | { 177 | FASTSIMD_DECLARE_FS_TYPES; 178 | FASTNOISE_IMPL_GEN_T; 179 | 180 | template 181 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 182 | { 183 | if constexpr( sizeof...(P) == (size_t)FastNoise::Dim::Count ) 184 | { 185 | return this->GetSourceValue( mSource, seed, pos... ); 186 | } 187 | else 188 | { 189 | return this->GetSourceValue( mSource, seed, pos..., this->GetSourceValue( mNewDimensionPosition, seed, pos... ) ); 190 | } 191 | } 192 | }; 193 | 194 | template 195 | class FS_T : public virtual FastNoise::RemoveDimension, public FS_T 196 | { 197 | FASTSIMD_DECLARE_FS_TYPES; 198 | 199 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const final 200 | { 201 | return this->GetSourceValue( mSource, seed, x, y ); 202 | } 203 | 204 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const final 205 | { 206 | switch( mRemoveDimension ) 207 | { 208 | case FastNoise::Dim::X: 209 | return this->GetSourceValue( mSource, seed, y, z ); 210 | case FastNoise::Dim::Y: 211 | return this->GetSourceValue( mSource, seed, x, z ); 212 | case FastNoise::Dim::Z: 213 | return this->GetSourceValue( mSource, seed, x, y ); 214 | default: 215 | return this->GetSourceValue( mSource, seed, x, y, z ); 216 | } 217 | } 218 | 219 | float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const final 220 | { 221 | switch( mRemoveDimension ) 222 | { 223 | case FastNoise::Dim::X: 224 | return this->GetSourceValue( mSource, seed, y, z, w ); 225 | case FastNoise::Dim::Y: 226 | return this->GetSourceValue( mSource, seed, x, z, w ); 227 | case FastNoise::Dim::Z: 228 | return this->GetSourceValue( mSource, seed, x, y, w ); 229 | case FastNoise::Dim::W: 230 | return this->GetSourceValue( mSource, seed, x, y, z ); 231 | default: 232 | return this->GetSourceValue( mSource, seed, x, y, z, w ); 233 | } 234 | } 235 | }; 236 | 237 | template 238 | class FS_T : public virtual FastNoise::GeneratorCache, public FS_T 239 | { 240 | FASTSIMD_DECLARE_FS_TYPES; 241 | FASTNOISE_IMPL_GEN_T; 242 | 243 | template 244 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 245 | { 246 | thread_local static const void* CachedGenerator = nullptr; 247 | thread_local static float CachedValue[FS_Size_32()]; 248 | thread_local static float CachedPos[FS_Size_32()][sizeof...( P )]; 249 | // TLS is not always aligned (compiler bug), need to avoid using SIMD types 250 | 251 | float32v arrayPos[] = { pos... }; 252 | 253 | bool isSame = (CachedGenerator == mSource.simdGeneratorPtr); 254 | 255 | for( size_t i = 0; i < sizeof...( P ); i++ ) 256 | { 257 | isSame &= !FS_AnyMask_bool( arrayPos[i] != FS_Load_f32( &CachedPos[i] ) ); 258 | } 259 | 260 | if( !isSame ) 261 | { 262 | CachedGenerator = mSource.simdGeneratorPtr; 263 | 264 | float32v value = this->GetSourceValue( mSource, seed, pos... ); 265 | FS_Store_f32( &CachedValue, value ); 266 | 267 | for( size_t i = 0; i < sizeof...(P); i++ ) 268 | { 269 | FS_Store_f32( &CachedPos[i], arrayPos[i] ); 270 | } 271 | 272 | return value; 273 | } 274 | 275 | return FS_Load_f32( &CachedValue ); 276 | } 277 | }; 278 | -------------------------------------------------------------------------------- /include/FastNoise/Generators/DomainWarp.inl: -------------------------------------------------------------------------------- 1 | #include "FastSIMD/InlInclude.h" 2 | 3 | #include "DomainWarp.h" 4 | #include "Utils.inl" 5 | 6 | template 7 | class FS_T : public virtual FastNoise::DomainWarp, public FS_T 8 | { 9 | FASTSIMD_DECLARE_FS_TYPES; 10 | FASTNOISE_IMPL_GEN_T; 11 | 12 | template 13 | FS_INLINE float32v GenT( int32v seed, P... pos ) const 14 | { 15 | Warp( seed, this->GetSourceValue( mWarpAmplitude, seed, pos... ), (pos * float32v( mWarpFrequency ))..., pos... ); 16 | 17 | return this->GetSourceValue( mSource, seed, pos...); 18 | } 19 | 20 | public: 21 | float GetWarpFrequency() const { return mWarpFrequency; } 22 | const FastNoise::HybridSource& GetWarpAmplitude() const { return mWarpAmplitude; } 23 | const FastNoise::GeneratorSource& GetWarpSource() const { return mSource; } 24 | 25 | virtual float32v FS_VECTORCALL Warp( int32v seed, float32v warpAmp, float32v x, float32v y, float32v& xOut, float32v& yOut ) const = 0; 26 | virtual float32v FS_VECTORCALL Warp( int32v seed, float32v warpAmp, float32v x, float32v y, float32v z, float32v& xOut, float32v& yOut, float32v& zOut ) const = 0; 27 | virtual float32v FS_VECTORCALL Warp( int32v seed, float32v warpAmp, float32v x, float32v y, float32v z, float32v w, float32v& xOut, float32v& yOut, float32v& zOut, float32v& wOut ) const = 0; 28 | }; 29 | 30 | template 31 | class FS_T : public virtual FastNoise::DomainWarpGradient, public FS_T 32 | { 33 | FASTSIMD_DECLARE_FS_TYPES; 34 | 35 | public: 36 | float32v FS_VECTORCALL Warp( int32v seed, float32v warpAmp, float32v x, float32v y, float32v& xOut, float32v& yOut ) const final 37 | { 38 | float32v xs = FS_Floor_f32( x ); 39 | float32v ys = FS_Floor_f32( y ); 40 | 41 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 42 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 43 | int32v x1 = x0 + int32v( FnPrimes::X ); 44 | int32v y1 = y0 + int32v( FnPrimes::Y ); 45 | 46 | xs = FnUtils::InterpHermite( x - xs ); 47 | ys = FnUtils::InterpHermite( y - ys ); 48 | 49 | #define GRADIENT_COORD( _x, _y )\ 50 | int32v hash##_x##_y = FnUtils::HashPrimesHB(seed, x##_x, y##_y );\ 51 | float32v x##_x##_y = FS_Converti32_f32( hash##_x##_y & int32v( 0xffff ) );\ 52 | float32v y##_x##_y = FS_Converti32_f32( (hash##_x##_y >> 16) & int32v( 0xffff ) ); 53 | 54 | GRADIENT_COORD( 0, 0 ); 55 | GRADIENT_COORD( 1, 0 ); 56 | GRADIENT_COORD( 0, 1 ); 57 | GRADIENT_COORD( 1, 1 ); 58 | 59 | #undef GRADIENT_COORD 60 | 61 | float32v normalise = float32v( 1.0f / (0xffff / 2.0f) ); 62 | 63 | float32v xWarp = (FnUtils::Lerp( FnUtils::Lerp( x00, x10, xs ), FnUtils::Lerp( x01, x11, xs ), ys ) - float32v( 0xffff / 2.0f )) * normalise; 64 | float32v yWarp = (FnUtils::Lerp( FnUtils::Lerp( y00, y10, xs ), FnUtils::Lerp( y01, y11, xs ), ys ) - float32v( 0xffff / 2.0f )) * normalise; 65 | 66 | xOut = FS_FMulAdd_f32( xWarp, warpAmp, xOut ); 67 | yOut = FS_FMulAdd_f32( yWarp, warpAmp, yOut ); 68 | 69 | float32v warpLengthSq = FS_FMulAdd_f32( xWarp, xWarp, yWarp * yWarp ); 70 | 71 | return warpLengthSq * FS_InvSqrt_f32( warpLengthSq ); 72 | } 73 | 74 | float32v FS_VECTORCALL Warp( int32v seed, float32v warpAmp, float32v x, float32v y, float32v z, float32v& xOut, float32v& yOut, float32v& zOut ) const final 75 | { 76 | float32v xs = FS_Floor_f32( x ); 77 | float32v ys = FS_Floor_f32( y ); 78 | float32v zs = FS_Floor_f32( z ); 79 | 80 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 81 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 82 | int32v z0 = FS_Convertf32_i32( zs ) * int32v( FnPrimes::Z ); 83 | int32v x1 = x0 + int32v( FnPrimes::X ); 84 | int32v y1 = y0 + int32v( FnPrimes::Y ); 85 | int32v z1 = z0 + int32v( FnPrimes::Z ); 86 | 87 | xs = FnUtils::InterpHermite( x - xs ); 88 | ys = FnUtils::InterpHermite( y - ys ); 89 | zs = FnUtils::InterpHermite( z - zs ); 90 | 91 | #define GRADIENT_COORD( _x, _y, _z )\ 92 | int32v hash##_x##_y##_z = FnUtils::HashPrimesHB( seed, x##_x, y##_y, z##_z );\ 93 | float32v x##_x##_y##_z = FS_Converti32_f32( hash##_x##_y##_z & int32v( 0x3ff ) );\ 94 | float32v y##_x##_y##_z = FS_Converti32_f32( (hash##_x##_y##_z >> 10) & int32v( 0x3ff ) );\ 95 | float32v z##_x##_y##_z = FS_Converti32_f32( (hash##_x##_y##_z >> 20) & int32v( 0x3ff ) ); 96 | 97 | GRADIENT_COORD( 0, 0, 0 ); 98 | GRADIENT_COORD( 1, 0, 0 ); 99 | GRADIENT_COORD( 0, 1, 0 ); 100 | GRADIENT_COORD( 1, 1, 0 ); 101 | GRADIENT_COORD( 0, 0, 1 ); 102 | GRADIENT_COORD( 1, 0, 1 ); 103 | GRADIENT_COORD( 0, 1, 1 ); 104 | GRADIENT_COORD( 1, 1, 1 ); 105 | 106 | #undef GRADIENT_COORD 107 | 108 | float32v x0z = FnUtils::Lerp( FnUtils::Lerp( x000, x100, xs ), FnUtils::Lerp( x010, x110, xs ), ys ); 109 | float32v y0z = FnUtils::Lerp( FnUtils::Lerp( y000, y100, xs ), FnUtils::Lerp( y010, y110, xs ), ys ); 110 | float32v z0z = FnUtils::Lerp( FnUtils::Lerp( z000, z100, xs ), FnUtils::Lerp( z010, z110, xs ), ys ); 111 | 112 | float32v x1z = FnUtils::Lerp( FnUtils::Lerp( x001, x101, xs ), FnUtils::Lerp( x011, x111, xs ), ys ); 113 | float32v y1z = FnUtils::Lerp( FnUtils::Lerp( y001, y101, xs ), FnUtils::Lerp( y011, y111, xs ), ys ); 114 | float32v z1z = FnUtils::Lerp( FnUtils::Lerp( z001, z101, xs ), FnUtils::Lerp( z011, z111, xs ), ys ); 115 | 116 | float32v normalise = float32v( 1.0f / (0x3ff / 2.0f) ); 117 | 118 | float32v xWarp = (FnUtils::Lerp( x0z, x1z, zs ) - float32v( 0x3ff / 2.0f )) * normalise; 119 | float32v yWarp = (FnUtils::Lerp( y0z, y1z, zs ) - float32v( 0x3ff / 2.0f )) * normalise; 120 | float32v zWarp = (FnUtils::Lerp( z0z, z1z, zs ) - float32v( 0x3ff / 2.0f )) * normalise; 121 | 122 | xOut = FS_FMulAdd_f32( xWarp, warpAmp, xOut ); 123 | yOut = FS_FMulAdd_f32( yWarp, warpAmp, yOut ); 124 | zOut = FS_FMulAdd_f32( zWarp, warpAmp, zOut ); 125 | 126 | float32v warpLengthSq = FS_FMulAdd_f32( xWarp, xWarp, FS_FMulAdd_f32( yWarp, yWarp, zWarp * zWarp ) ); 127 | 128 | return warpLengthSq * FS_InvSqrt_f32( warpLengthSq ); 129 | } 130 | 131 | float32v FS_VECTORCALL Warp( int32v seed, float32v warpAmp, float32v x, float32v y, float32v z, float32v w, float32v& xOut, float32v& yOut, float32v& zOut, float32v& wOut ) const final 132 | { 133 | float32v xs = FS_Floor_f32( x ); 134 | float32v ys = FS_Floor_f32( y ); 135 | float32v zs = FS_Floor_f32( z ); 136 | float32v ws = FS_Floor_f32( w ); 137 | 138 | int32v x0 = FS_Convertf32_i32( xs ) * int32v( FnPrimes::X ); 139 | int32v y0 = FS_Convertf32_i32( ys ) * int32v( FnPrimes::Y ); 140 | int32v z0 = FS_Convertf32_i32( zs ) * int32v( FnPrimes::Z ); 141 | int32v w0 = FS_Convertf32_i32( ws ) * int32v( FnPrimes::W ); 142 | int32v x1 = x0 + int32v( FnPrimes::X ); 143 | int32v y1 = y0 + int32v( FnPrimes::Y ); 144 | int32v z1 = z0 + int32v( FnPrimes::Z ); 145 | int32v w1 = w0 + int32v( FnPrimes::W ); 146 | 147 | xs = FnUtils::InterpHermite( x - xs ); 148 | ys = FnUtils::InterpHermite( y - ys ); 149 | zs = FnUtils::InterpHermite( z - zs ); 150 | ws = FnUtils::InterpHermite( w - ws ); 151 | 152 | #define GRADIENT_COORD( _x, _y, _z, _w )\ 153 | int32v hash##_x##_y##_z##_w = FnUtils::HashPrimesHB( seed, x##_x, y##_y, z##_z, w##_w );\ 154 | float32v x##_x##_y##_z##_w = FS_Converti32_f32( hash##_x##_y##_z##_w & int32v( 0xff ) );\ 155 | float32v y##_x##_y##_z##_w = FS_Converti32_f32( (hash##_x##_y##_z##_w >> 8) & int32v( 0xff ) );\ 156 | float32v z##_x##_y##_z##_w = FS_Converti32_f32( (hash##_x##_y##_z##_w >> 16) & int32v( 0xff ) );\ 157 | float32v w##_x##_y##_z##_w = FS_Converti32_f32( (hash##_x##_y##_z##_w >> 24) & int32v( 0xff ) ); 158 | 159 | GRADIENT_COORD( 0, 0, 0, 0 ); 160 | GRADIENT_COORD( 1, 0, 0, 0 ); 161 | GRADIENT_COORD( 0, 1, 0, 0 ); 162 | GRADIENT_COORD( 1, 1, 0, 0 ); 163 | GRADIENT_COORD( 0, 0, 1, 0 ); 164 | GRADIENT_COORD( 1, 0, 1, 0 ); 165 | GRADIENT_COORD( 0, 1, 1, 0 ); 166 | GRADIENT_COORD( 1, 1, 1, 0 ); 167 | GRADIENT_COORD( 0, 0, 0, 1 ); 168 | GRADIENT_COORD( 1, 0, 0, 1 ); 169 | GRADIENT_COORD( 0, 1, 0, 1 ); 170 | GRADIENT_COORD( 1, 1, 0, 1 ); 171 | GRADIENT_COORD( 0, 0, 1, 1 ); 172 | GRADIENT_COORD( 1, 0, 1, 1 ); 173 | GRADIENT_COORD( 0, 1, 1, 1 ); 174 | GRADIENT_COORD( 1, 1, 1, 1 ); 175 | 176 | #undef GRADIENT_COORD 177 | 178 | float32v x0w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( x0000, x1000, xs ), FnUtils::Lerp( x0100, x1100, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( x0010, x1010, xs ), FnUtils::Lerp( x0110, x1110, xs ), ys ), zs ); 179 | float32v y0w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( y0000, y1000, xs ), FnUtils::Lerp( y0100, y1100, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( y0010, y1010, xs ), FnUtils::Lerp( y0110, y1110, xs ), ys ), zs ); 180 | float32v z0w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( z0000, z1000, xs ), FnUtils::Lerp( z0100, z1100, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( z0010, z1010, xs ), FnUtils::Lerp( z0110, z1110, xs ), ys ), zs ); 181 | float32v w0w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( w0000, w1000, xs ), FnUtils::Lerp( w0100, w1100, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( w0010, w1010, xs ), FnUtils::Lerp( w0110, w1110, xs ), ys ), zs ); 182 | 183 | float32v x1w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( x0001, x1001, xs ), FnUtils::Lerp( x0101, x1101, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( x0011, x1011, xs ), FnUtils::Lerp( x0111, x1111, xs ), ys ), zs ); 184 | float32v y1w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( y0001, y1001, xs ), FnUtils::Lerp( y0101, y1101, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( y0011, y1011, xs ), FnUtils::Lerp( y0111, y1111, xs ), ys ), zs ); 185 | float32v z1w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( z0001, z1001, xs ), FnUtils::Lerp( z0101, z1101, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( z0011, z1011, xs ), FnUtils::Lerp( z0111, z1111, xs ), ys ), zs ); 186 | float32v w1w = FnUtils::Lerp( FnUtils::Lerp( FnUtils::Lerp( w0001, w1001, xs ), FnUtils::Lerp( w0101, w1101, xs ), ys ), FnUtils::Lerp( FnUtils::Lerp( w0011, w1011, xs ), FnUtils::Lerp( w0111, w1111, xs ), ys ), zs ); 187 | 188 | float32v normalise = float32v( 1.0f / (0xff / 2.0f) ); 189 | 190 | float32v xWarp = (FnUtils::Lerp( x0w, x1w, ws ) - float32v( 0xff / 2.0f )) * normalise; 191 | float32v yWarp = (FnUtils::Lerp( y0w, y1w, ws ) - float32v( 0xff / 2.0f )) * normalise; 192 | float32v zWarp = (FnUtils::Lerp( z0w, z1w, ws ) - float32v( 0xff / 2.0f )) * normalise; 193 | float32v wWarp = (FnUtils::Lerp( w0w, w1w, ws ) - float32v( 0xff / 2.0f )) * normalise; 194 | 195 | xOut = FS_FMulAdd_f32( xWarp, warpAmp, xOut ); 196 | yOut = FS_FMulAdd_f32( yWarp, warpAmp, yOut ); 197 | zOut = FS_FMulAdd_f32( zWarp, warpAmp, zOut ); 198 | wOut = FS_FMulAdd_f32( wWarp, warpAmp, wOut ); 199 | 200 | float32v warpLengthSq = FS_FMulAdd_f32( xWarp, xWarp, FS_FMulAdd_f32( yWarp, yWarp, FS_FMulAdd_f32( zWarp, zWarp, wWarp * wWarp ) ) ); 201 | 202 | return warpLengthSq * FS_InvSqrt_f32( warpLengthSq ); 203 | } 204 | }; 205 | 206 | --------------------------------------------------------------------------------