【问题标题】:Perlin Noise wave effect on a 3d spherePerlin 噪声波对 3d 球体的影响
【发布时间】:2019-08-27 09:50:32
【问题描述】:

我一直在尝试弄清楚如何使用 Perlin Noise 在 3d 球体上创建波浪效果

我找到了一些关于如何在飞机上执行此操作的教程,但是在 3d 对象上没有, 这段代码在飞机上工作得很好,有人知道如何在 3d 球体上调整它吗? 提前感谢您的帮助

using UnityEngine;
using System.Collections;
public class PerlinTerrain : MonoBehaviour {

    public float perlinScale;
    public float waveSpeed;
    public float waveHeight;
    public float offset;

    void Update () {
        CalcNoise();
    }

    void CalcNoise() {
        MeshFilter mF = GetComponent<MeshFilter>();
        MeshCollider mC = GetComponent<MeshCollider>();

        mC.sharedMesh = mF.mesh;

        Vector3[] verts = mF.mesh.vertices;

        for (int i=0; i< verts.Length; i++) {
            float pX = (verts[i].x * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            float pZ = (verts[i].z * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            verts[i].y = Mathf.PerlinNoise(pX, pZ) * waveHeight;
        }

        mF.mesh.vertices = verts;
        mF.mesh.RecalculateNormals();
        mF.mesh.RecalculateBounds();
    }

}

【问题讨论】:

  • 如果您链接到您正在关注的教程,它可能会有所帮助。至少有 2 种非常不同的方式可以让您拥有基于 Perlin 噪声的球体:您可以从 3d 噪声中雕刻出一个球体,或者您可以用 2d 噪声覆盖球体的外部。

标签: c# unity3d wave perlin-noise


【解决方案1】:

最简单的方法是将 2D 噪波应用到表面。你可以通过使用顶点法线来知道你应该将位置移动到哪个方向来做到这一点。

在您的代码中,您只是在移动 Y 位置。对于平面,这意味着您将顶点沿其法线方向移动了噪声函数给您的量。对于一个球体,你可以这样做:

verts[i] = verts[i] + (Mathf.PerlinNoise(pX, pZ) * waveHeight * mF.mesh.normals[i].normalized);

这适用于任何网格,因为它会考虑其原始位置,并且只会沿其法线方向移动顶点。

这会将顶点向上移动,这意味着它总是高于原始位置,您可以对噪声函数应用一个简单的偏移以使其也降低

verts[i] = verts[i] + ((Mathf.PerlinNoise(pX, pZ) - 0.5f) * waveHeight * mF.mesh.normals[i].normalized);

我注意到您正在为这种噪声设置动画,每次更新都采用原始网格而不是应用了噪声的新网格很重要。所以最终它会看起来像这样

using UnityEngine;
using System.Collections;

public class PerlinTerrain : MonoBehaviour
{

    public float perlinScale;
    public float waveSpeed;
    public float waveHeight;
    public float offset;

    Vector3[] baseVertices;

    private void OnEnable()
    {
        MeshFilter mF = GetComponent<MeshFilter>();

        baseVertices = mF.mesh.vertices;
    }

    void Update()
    {
        CalcNoise();
    }

    void CalcNoise()
    {
        MeshFilter mF = GetComponent<MeshFilter>();

        mF.sharedMesh.vertices = baseVertices;
        mF.sharedMesh.RecalculateNormals();

        Vector3[] verts = mF.sharedMesh.vertices;

        for (int i = 0; i < verts.Length; i++)
        {
            float pX = (verts[i].x * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            float pZ = (verts[i].z * perlinScale) + (Time.timeSinceLevelLoad * waveSpeed) + offset;
            verts[i] = verts[i] + ((Mathf.PerlinNoise(pX, pZ)) * waveHeight * mF.sharedMesh.normals[i].normalized);
        }

        mF.sharedMesh.vertices = verts;
    }
}

但您仍有 1 个问题。有多个顶点具有相同的位置但具有不同的法线。您必须弄清楚哪些顶点是共享的并计算其法线。

按顶点的位置对顶点进行分组并取平均法线,并且只对每个唯一顶点迭代一次。

【讨论】:

    【解决方案2】:

    因为它会被称为单纯形噪声

    https://en.wikipedia.org/wiki/Simplex_noise

    Perlin 是 2D 版本的具体名称

    【讨论】:

    • 抱歉,Perlin Noise 只是 2D 而 Simplex 是 3D 表示在哪里说明?
    • 不是吗?那么什么是单纯形噪声?
    • 这个答案不正确。 “柏林噪声最常被实现为二维、三维或四维函数,但可以定义为任意数量的维度。” source。单纯形噪声是一种构建与 Perlin 噪声相当的 n 维噪声函数的方法……但方向伪影更少,并且在更高维度上,计算开销更低。它们是相似但不同的 n 维梯度噪声函数。
    • 这是我遵循的教程:pastebin.com/enKSz6Mm,你能帮我提出一个方法来实现代码到 3 维对象
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 2015-08-16
    • 2011-09-27
    • 2014-02-15
    • 2020-06-06
    相关资源
    最近更新 更多