Files
Gen_Hack-and-Slash-Roguelit…/Client/Assets/Scripts/Utils/PerlinNoise.cs
m0_75251201 6a222d82b2 (client) feat:实现摄像机跟踪,柏林噪声改为单例,角色渲染树支持指定像素密度
chore:将UI的Tick进行了显示时显式添加并作为预制体
2025-08-05 14:54:30 +08:00

132 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
namespace Utils
{
public class PerlinNoise : Utils.Singleton<PerlinNoise>
{
private int[] _p; // 混淆表
private const int DefaultSeed = 0; // 默认种子
public PerlinNoise()
{
Initialize(DefaultSeed);
}
// 初始化混淆表
private void Initialize(int seed)
{
_p = new int[512]; // 混淆表加倍以方便使用
var permutation = new int[256];
var random = new Random(seed);
// 填充数组为0-255
for (var i = 0; i < 256; i++) permutation[i] = i;
// 使用Fisher-Yates算法打乱数组
for (var i = 0; i < 256; i++)
{
var swapIndex = random.Next(256);
var temp = permutation[i];
permutation[i] = permutation[swapIndex];
permutation[swapIndex] = temp;
}
// 将打乱后的数组复制两次生成512个元素的混淆表
for (var i = 0; i < 256; i++)
{
_p[i] = permutation[i];
_p[i + 256] = permutation[i];
}
}
// 重新指定种子
public void Reinitialize(int seed)
{
Initialize(seed);
}
// 平滑函数 (6t^5 - 15t^4 + 10t^3)
private static double Fade(double t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
// 线性插值
private static double Lerp(double t, double a, double b)
{
return a + t * (b - a);
}
// 计算梯度向量和距离向量的点积
private static double Grad(int hash, double x, double y, double z)
{
return (hash & 0xF) switch // 取hash值的最后4位
{
0x0 => x + y,
0x1 => -x + y,
0x2 => x - y,
0x3 => -x - y,
0x4 => x + z,
0x5 => -x + z,
0x6 => x - z,
0x7 => -x - z,
0x8 => y + z,
0x9 => -y + z,
0xA => y - z,
0xB => -y - z,
0xC => y + x,
0xD => -y + x,
0xE => y - x,
0xF => -y - x,
_ => 0
};
}
/// <summary>
/// 为给定的(x, y, z)坐标生成3D Perlin噪声。
/// 输出值通常在-1到1之间。
/// </summary>
public double Noise(double x, double y=0, double z = 0)
{
var X = (int)Math.Floor(x) & 255;
var Y = (int)Math.Floor(y) & 255;
var Z = (int)Math.Floor(z) & 255;
x -= Math.Floor(x);
y -= Math.Floor(y);
z -= Math.Floor(z);
var u = Fade(x);
var v = Fade(y);
var w = Fade(z);
var A = _p[X] + Y;
var AA = _p[A] + Z;
var AB = _p[A + 1] + Z;
var B = _p[X + 1] + Y;
var BA = _p[B] + Z;
var BB = _p[B + 1] + Z;
var H000 = _p[AA];
var H100 = _p[BA];
var H010 = _p[AB];
var H110 = _p[BB];
var H001 = _p[AA + 1];
var H101 = _p[BA + 1];
var H011 = _p[AB + 1];
var H111 = _p[BB + 1];
double x0, x1, y0, y1;
x0 = Lerp(u, Grad(H000, x, y, z), Grad(H100, x - 1, y, z));
x1 = Lerp(u, Grad(H010, x, y - 1, z), Grad(H110, x - 1, y - 1, z));
y0 = Lerp(v, x0, x1);
x0 = Lerp(u, Grad(H001, x, y, z - 1), Grad(H101, x - 1, y, z - 1));
x1 = Lerp(u, Grad(H011, x, y - 1, z - 1), Grad(H111, x - 1, y - 1, z - 1));
y1 = Lerp(v, x0, x1);
return Lerp(w, y0, y1);
}
}
}