Files
UnrealEngine/Engine/Source/Runtime/GeometryCore/Public/ProceduralNoise.h
2025-05-18 13:04:45 +08:00

77 lines
1.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Math/UnrealMathUtility.h"
#include "Math/Vector2D.h"
#include "MathUtil.h"
#include "GenericPlatform/GenericPlatformMath.h"
namespace UE {
namespace Geometry {
enum class EFBMMode : uint8
{
/**
* Classic Perlin Noise
*/
Standard,
/**
* Turbulent Modifier, creating upward bumps.
*/
Turbulent,
/**
* Ridge Modifier, creating sharper creases and ridges.
*/
Ridge
};
template <typename T>
T FractalBrownianMotionNoise(
const EFBMMode FBMMode,
const uint32 OctaveCount,
const Math::TVector2<T> Coords, //< sampling coordinates
const T Lacunarity, //< multiplier to apply to frequency from one octave to the next finer one
const T Gain, //< weight to apply to amplitude from one octave to the next finer one
const T Smoothness, //< smoothness amount to apply to turbulent and ridge modes
const T Gamma) //< gamma to apply to turbulent and ridge
{
T Amplitude{ 1. };
checkSlow(Smoothness >= T(0.));
checkSlow(Gain > T(0.));
checkSlow(Lacunarity > T(0.));
checkSlow(Gamma > T(0.));
const T SmoothEps = Smoothness * T(0.01);
FVector2d ST(Coords.X, Coords.Y);
T TotalOffset{ 0. };
for (uint32 Octave = 0; Octave < OctaveCount; ++Octave)
{
T Offset = FMath::PerlinNoise2D(ST);
switch (FBMMode) {
case EFBMMode::Standard:
// nothing to be done
break;
case EFBMMode::Turbulent:
Offset = FMath::Pow(2. * FMath::Sqrt(Offset * Offset + SmoothEps), Gamma);
break;
case EFBMMode::Ridge:
Offset = FMath::Pow(1. - FMath::Sqrt(Offset * Offset + SmoothEps), Gamma);
break;
};
TotalOffset += Amplitude * Offset;
ST *= Lacunarity;
Amplitude *= Gain;
}
return TotalOffset;
}
} // namespace Geometry
} // namespace UE