2D / 3D / 4D optimised Perlin Noise Cg/HLSL library (cginc)

Ooo! It does the in place value woobly change on teh Z value!!!
Thankyou @xesiomterim

Shader "Unlit/noise2"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TextureScalar ("texture scalar", Float) = 1
        _WooblyFactor ("Woobly", Float) = 1
        _Speed ("Speed", Float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Assets/ALT_PerlinNoiseSK01.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float _TextureScalar;
            float _WooblyFactor;
            float _Speed;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                i.uv.x += _Time * _Speed;
                i.uv *= _TextureScalar;
                float _p = perlinNoise(float3(i.uv.x, i.uv.y,_Time.x*_WooblyFactor));
                return float4(_p,_p,_p,1);
            }
            ENDCG
        }
    }
}
1 Like

I was still getting artifacts using the 3D noise function, so I checked against what the OP based their code off of, and there were some differences. After fixing them, the artifacts went away! Here’s the code:

// ----------------------------------- 3D -------------------------------------
float snoise(float3 v)
{
    const float2 C = float2(
        0.166666666666666667, // 1/6
        0.333333333333333333 // 1/3
    );
    const float4 D = float4(0.0, 0.5, 1.0, 2.0);
// First corner
    float3 i = floor(v + dot(v, C.yyy));
    float3 x0 = v - i + dot(i, C.xxx);
// Other corners
    float3 g = step(x0.yzx, x0.xyz);
    float3 l = 1 - g;
    float3 i1 = min(g.xyz, l.zxy);
    float3 i2 = max(g.xyz, l.zxy);
    float3 x1 = x0 - i1 + C.xxx;
    float3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
    float3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
    i = mod289(i);
    float4 p = permute(
        permute(
            permute(
                    i.z + float4(0.0, i1.z, i2.z, 1.0)
            ) + i.y + float4(0.0, i1.y, i2.y, 1.0)
        ) + i.x + float4(0.0, i1.x, i2.x, 1.0)
    );
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
    float n_ = 0.142857142857; // 1/7
    float3 ns = n_ * D.wyz - D.xzx;
    float4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
    float4 x_ = floor(j * ns.z);
    float4 y_ = floor(j - 7.0 * x_); // mod(j,N)
    float4 x = x_ * ns.x + ns.yyyy;
    float4 y = y_ * ns.x + ns.yyyy;
    float4 h = 1.0 - abs(x) - abs(y);
    float4 b0 = float4(x.xy, y.xy);
    float4 b1 = float4(x.zw, y.zw);
    //float4 s0 = float4(lessThan(b0,0.0))*2.0 - 1.0;
    //float4 s1 = float4(lessThan(b1,0.0))*2.0 - 1.0;
    float4 s0 = floor(b0) * 2.0 + 1.0;
    float4 s1 = floor(b1) * 2.0 + 1.0;
    float4 sh = -step(h, float4(0, 0, 0, 0));
    float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
    float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
    float3 p0 = float3(a0.xy, h.x);
    float3 p1 = float3(a0.zw, h.y);
    float3 p2 = float3(a1.xy, h.z);
    float3 p3 = float3(a1.zw, h.w);
//Normalise gradients
    float4 norm = rsqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
    p0 *= norm.x;
    p1 *= norm.y;
    p2 *= norm.z;
    p3 *= norm.w;
// Mix final noise value
    float4 m = max(0.5 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
    m = m * m;
    return 105.0 * dot(m * m, float4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
}
#endif
1 Like

fmod(x,y) in hlsl, i believe, is (x - trunc(x/y) * y), not (x - floor(x/y) * y), which the original hand coded mod289 uses. I’m not sure if it matters in this code, but when x is negative, trunc and floor will be different.