MethaneAsteroids
105 строк · 4.3 Кб
1/******************************************************************************
2
3Copyright 2019-2023 Evgeny Gorodetskiy
4
5Licensed under the Apache License, Version 2.0 (the "License"),
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17*******************************************************************************
18
19FILE: PerlinNoise.cpp
20Multi-octave simplex noise generator in range [0, 1]
21
22******************************************************************************/
23
24#include "PerlinNoise.h"
25#include <Methane/Instrumentation.h>
26
27#include <hlsl++.h>
28#include <FastNoise/FastNoise.h>
29
30namespace Methane::Graphics
31{
32
33template<typename VectorType>
34float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const VectorType& pos, int seed) noexcept;
35
36template<> float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const hlslpp::float2& pos, int seed) noexcept { return simplex_noise.GenSingle2D(pos.x, pos.y, seed); }
37template<> float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const hlslpp::float3& pos, int seed) noexcept { return simplex_noise.GenSingle3D(pos.x, pos.y, pos.z, seed); }
38template<> float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const hlslpp::float4& pos, int seed) noexcept { return simplex_noise.GenSingle4D(pos.x, pos.y, pos.z, pos.w, seed); }
39
40template<> float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const Data::RawVector2F& pos, int seed) noexcept { return simplex_noise.GenSingle2D(pos[0], pos[1], seed); }
41template<> float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const Data::RawVector3F& pos, int seed) noexcept { return simplex_noise.GenSingle3D(pos[0], pos[1], pos[2], seed); }
42template<> float GetPerlinNoise(const FastNoise::Simplex& simplex_noise, const Data::RawVector4F& pos, int seed) noexcept { return simplex_noise.GenSingle4D(pos[0], pos[1], pos[2], pos[3], seed); }
43
44PerlinNoise::PerlinNoise(float persistence, size_t octaves_count, int seed)
45: m_weights(GetWeights(persistence, octaves_count))
46, m_norm_multiplier(0.5F / GetWeightsSum(m_weights))
47, m_seed(seed)
48{
49META_FUNCTION_TASK();
50}
51
52float PerlinNoise::operator()(const hlslpp::float2& pos) const noexcept { return GetValue(pos); }
53float PerlinNoise::operator()(const hlslpp::float3& pos) const noexcept { return GetValue(pos); }
54float PerlinNoise::operator()(const hlslpp::float4& pos) const noexcept { return GetValue(pos); }
55
56float PerlinNoise::operator()(const Data::RawVector2F& pos) const noexcept { return GetValue(pos); }
57float PerlinNoise::operator()(const Data::RawVector3F& pos) const noexcept { return GetValue(pos); }
58float PerlinNoise::operator()(const Data::RawVector4F& pos) const noexcept { return GetValue(pos); }
59
60template<typename VectorType>
61float PerlinNoise::GetValue(VectorType pos) const noexcept
62{
63META_FUNCTION_TASK();
64const FastNoise::Simplex& simplex_noise = GetSimplexNoise();
65float noise = 0.F;
66for (const float weight : m_weights)
67{
68noise += weight * GetPerlinNoise(simplex_noise, pos, m_seed);
69pos *= 2.F;
70}
71return noise * m_norm_multiplier + 0.5F;
72}
73
74PerlinNoise::Weights PerlinNoise::GetWeights(float persistence, size_t octaves_count) noexcept
75{
76META_FUNCTION_TASK();
77Weights weights;
78weights.reserve(octaves_count);
79for (size_t i = 0; i < octaves_count; ++i)
80{
81weights.emplace_back(persistence);
82persistence *= persistence;
83}
84return weights;
85}
86
87float PerlinNoise::GetWeightsSum(const PerlinNoise::Weights& weights) noexcept
88{
89META_FUNCTION_TASK();
90float weights_sum = 0.F;
91for(float weight : weights)
92{
93weights_sum += weight;
94}
95return weights_sum;
96}
97
98const FastNoise::Simplex& PerlinNoise::GetSimplexNoise() const
99{
100META_FUNCTION_TASK();
101static const auto s_simplex_noise_ptr = FastNoise::New<FastNoise::Simplex>();
102return *s_simplex_noise_ptr;
103}
104
105} // namespace Methane::Graphics
106