风格化沙地shader

image

image

玩星际拓荒到灰烬双星,看到闪闪发光的沙子的效果挺有趣的,复现一下

image

常规渲染的基础上,主要是做了两步

其一,是使用随机方向去扰乱基础法线方向

随机方向是使用noise算法计算的,避免noise贴图的重复、或是aliasing问题

1
2
3
4
5
6
7
8
9
10
float3 RandomNoise(float3 p)
{
    // 通过对三维坐标进行哈希化,生成伪随机数
    float3 q = frac(sin(float3(
            dot(p, float3(127.1, 311.7, 74.7)),
            dot(p, float3(269.5, 183.3, 429.0)),
            dot(p, float3(323.1, 157.5, 431.8)))) * 43758.5453);
  
    return q * 2.0 - 1.0; // 输出 -1 到 1 范围内的随机值
}

然后和原法线混合

1
2
3
4
5
6
float3 SandNormal(float3 normalTS, float3 positionWS)
{
    float3 noiseNormal = RandomNoise(floor(positionWS*_SandNormalUVScale)/_SandNormalUVScale);
    float3 noiseN = normalize(noiseNormal.xyz * 2 - 1);
    return normalize(lerp(normalTS, noiseN, _SandStrength));
}

高光做了一些调整

image

其二,加入随光线、视线方向变化的闪光颗粒

1
2
3
4
5
6
7
8
9
float3 GlitterSpecular(float3 positionWS, float3 N, float3 L, float3 V)
{
    float3 G = RandomNoise(floor(positionWS*_SandNormalUVScale)/_SandNormalUVScale);
    float3 R = reflect(L, normalize(G));
    float RdotV = max(0, dot(R, V));
    float s = step(_GlitterThreshold, RdotV);

    return (1 - RdotV) * _GlitterColor * s;
}

因为想要让闪光随相机方向转动而变化,所以V需要传入的是相机的前方向,另外避免所有像素的V都是相同的,还要加上正宗的viewDir,最终V是:

1
2
float3 viewForwardWS = normalize(mul(UNITY_MATRIX_V, float3(0,0,1)));
float3 V =normalize(viewForwardWS + viewdirWS)