unity3d 从C#工作代码在HLSL中生成Perlin噪声时出现问题

hgqdbh6s  于 2022-11-30  发布在  C#
关注(0)|答案(1)|浏览(204)

我正在尝试编写一个基于C#代码的计算着色器柏林噪音代码。
问题是我只得到了光滑的点。

左侧C#工作,右侧计算着色器,

均具有此值
如果我降低频率,点会变大:

这是我用的密码

#pragma kernel CSMain

RWTexture2D<float> Result;
RWStructuredBuffer<float> resfloat;

float res;
float frequency;
float octaves;
float lacunarity;
float persistence;

StructuredBuffer<float3> gradients3D;
StructuredBuffer<int> hash;

float lerp(float v0, float v1, float t);
float Dot(float3 g, float x, float y, float z);
float Smooth(float t);
float Perlin3D(float3 v, float frequency);
float noise(float3 v, float frequency, int octaves, float lacunarity, float persistence);

int hashMask = 255;
int gradientsMask3D = 15;

[numthreads(8, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    float3 v = float3(id.x, id.y, id.z) / res;
    float h = 0.0;
    h = noise(v, frequency, octaves, lacunarity, persistence);
    Result[id.xy] = float4(h, 0, 0, 0);
    resfloat[id.x + id.y * res] = h;
}

float lerp(float v0, float v1, float t) {
    return v0 + t * (v1 - v0);
}

float Smooth(float t) {
    return t * t * t * (t * (t * (float) 6 - (float) 15) + (float) 10);
}

float Perlin3D(float3 v, float frequency) {
    v *= frequency;
    int ix0 = (int) floor(v.x);
    int iy0 = (int) floor(v.y);
    int iz0 = (int) floor(v.z);
    float tx0 = v.x - ix0;
    float ty0 = v.y - iy0;
    float tz0 = v.z - iz0;
    float tx1 = tx0 - (float) 1;
    float ty1 = ty0 - (float) 1;
    float tz1 = tz0 - (float) 1;
    ix0 &= hashMask;
    iy0 &= hashMask;
    iz0 &= hashMask;
    int ix1 = ix0 + (float) 1;
    int iy1 = iy0 + (float) 1;
    int iz1 = iz0 + (float) 1;

    int h0 = hash[ix0];
    int h1 = hash[ix1];
    int h00 = hash[h0 + iy0];
    int h10 = hash[h1 + iy0];
    int h01 = hash[h0 + iy1];
    int h11 = hash[h1 + iy1];
    float3 g000 = gradients3D[hash[h00 + iz0] & gradientsMask3D];
    float3 g100 = gradients3D[hash[h10 + iz0] & gradientsMask3D];
    float3 g010 = gradients3D[hash[h01 + iz0] & gradientsMask3D];
    float3 g110 = gradients3D[hash[h11 + iz0] & gradientsMask3D];
    float3 g001 = gradients3D[hash[h00 + iz1] & gradientsMask3D];
    float3 g101 = gradients3D[hash[h10 + iz1] & gradientsMask3D];
    float3 g011 = gradients3D[hash[h01 + iz1] & gradientsMask3D];
    float3 g111 = gradients3D[hash[h11 + iz1] & gradientsMask3D];
    
    float v000 = dot(g000, float3(tx0, ty0, tz0));
    float v100 = dot(g100, float3(tx1, ty0, tz0));
    float v010 = dot(g010, float3(tx0, ty1, tz0));
    float v110 = dot(g110, float3(tx1, ty1, tz0));
    float v001 = dot(g001, float3(tx0, ty0, tz1));
    float v101 = dot(g101, float3(tx1, ty0, tz1));
    float v011 = dot(g011, float3(tx0, ty1, tz1));
    float v111 = dot(g111, float3(tx1, ty1, tz1));

    float tx = Smooth(tx0);
    float ty = Smooth(ty0);
    float tz = Smooth(tz0);
    return lerp(
        lerp(lerp(v000, v100, tx), lerp(v010, v110, tx), ty),
        lerp(lerp(v001, v101, tx), lerp(v011, v111, tx), ty),
        tz);
}

float noise(float3 v, float frequency, int octaves, float lacunarity, float persistence)
{
    float sum = Perlin3D(v, frequency);
    float amplitude = 1;
    float range = 1;
    for (int o = 1; o < octaves; o++) {
        frequency *= lacunarity;
        amplitude *= persistence;
        range += amplitude;
        sum += Perlin3D(v, frequency) * amplitude;
    }

    return sum / range;
}

This is the C# working code
And this is the C# code that calls the shader
我已经检查了StructuredBuffer(gradients3D和hash)和float参数是否正确加载。
有什么想法吗?

wxclj1h5

wxclj1h51#

问题是,由于某种原因,当函数Perlin3D,使用hashMaskgradientsMask3D时,它们有一个0
所以我把定义移到了函数上:

float Perlin3D(float3 v, float frequency)
{
    int hashMask = 255;
    int gradientsMask3D = 15;
    v *= frequency;
    int ix0 = (int) floor(v.x);

相关问题