PISCOnoob

导航

White Noise Shader

写在前面:

本文章为个人学习笔记,方便以后自己复习,也希望能帮助到他人。

由于本人水平有限难免出现错误,还请评论区指出,多多指教。

部分图元和素材来源于网络,如有侵权请联系本人删除。

参考资料与链接会在文章末尾贴出。

=======================================================================

本文将简单介绍如何在shader中生成White Noise(白噪声)。

先上效果:

 

1 Scalar noise from 3D Input

在本例子中我们将会用世界空间坐标(3D)为基础用作后续噪声计算,且为了后续的拓展性,我们一开始就把它封装成一个方法。

我们会用世界空间坐标作为输入与一随机三维向量做点乘得到一个一维标量,为防止结果过大,我们只使用小数部分:

我们从函数中获得的值的最大问题是我们可以很快看到它们不是“非常随机的”,我们可以看到 dot 函数创建的波段。这个解决方案可能看起来很老套,但它很快并且适用于我们的案例。在取分数之前,我们只需将随机值乘以一个非常高的数字,这样波段就变得非常小,我们再也看不到它们了。

现在结果看上去并不是那么“随机”,可以看到一层层的纹路。现在来做一个很“hacky”的操作:在做frac之前,把random先乘一个很大的数字:

但是,由此产生了一个新问题。因为我们乘了一个很大的数,当我们移动物体时,计算结果值可能会超出浮点数表示范围。

一个解决方法是在将random与大数相乘之前,使用将random的范围限制在一个小范围内。比如这里用一个正弦函数sin:

 

ps : sin函数在shader中会比加减乘除要贵一点,如果我们要追求某些项目上的性能优化,或许我们可以改成加减乘除的运算。

 

2 Different Input and Output

现在我们计算出一维结果作为颜色输出,我们可以输出更多的维度,但为了保证最后输出结果RGB通道都是不同的,我们最好是调用三次函数而不是在函数内计算好后输出三维结果,此外为了清晰让调用者知道函数做了啥,我们可以改一下函数名字:

如此就有了类似古董电视机信号不好一样的彩色噪声。这里函数第二个参数给了一个默认值,如果不传参的时候就会使用默认值。

由此我们可以设想,假如还有其他不同的输入输出,我们还要写很多函数,这样shader看上去会很臃肿,因此我们可以编写自己的cginc文件,把所有生成WhiteNoise的函数都放进去,这样下次其他shader用的时候只需要include一下改文件即可。

其中有3dTo1d,3dTo2d....2dTo1d...1dTo1d...一共九个函数,而其中有些函数是可以直接调用其他函数来完成的,比如3dTo3d其实可以是调用三次3dTo1d组合而成...

#ifndef WHITE_NOISE
#define WHITE_NOISE

// 1d output

float Rand_3dTo1d(float3 vec, float3 dotDir = float3(12.9898, 78.233, 37.719)) 
{
    float random = dot(vec, dotDir);
    random = sin(random);
    random = frac(random * 163758.3153);
    return random;
}

float Rand_2dTo1d(float2 vec, float2 dotDir = float2(12.9898, 78.233)) 
{
    float random = dot(vec, dotDir);
    random = sin(random);
    random = frac(random * 163758.3153);
    return random;
}

float Rand_1dTo1d(float value, float mutator = 37.719) 
{
    float random = frac(sin(valua + mutator) * 163758.3153)   
    return random;
}

// 2d output

float2 Rand_3dTo2d(float3 vec) 
{
    
    return float2(
    Rand_3dTo1d(vec, float3(12.989, 78.233, 37.719)),
    Rand_3dTo1d(vec, float3(89.138, 21.982, 67.739))
    )
}
...

// 3d output
...

#endif

包含保护首先通过#ifndef WHITE_NOISE 检查文件是否尚未包含,如果没有,我们可以将其声明为包含在#define WHITE_NOISE 行中,并且在文件末尾我们可以结束仅包含的部分当 #endif 未定义白噪声时使用。

当我们在shader中include的时候需要注意路径格式“./”表示当前shader同级文件夹内,“../”表示上一级文件夹,上上级文件夹则是“../../”。

比如我的:

Cells

有了生成WhiteNoise的函数,我们来尝试做更多东西。实际上我们最终图案的颜色或样式很大程度上取决于我们的输入。这部分我们来做点其他图案,我们把posWS做floor运算就会出现一个个格子,然后再加一个CellSize属性来控住格子大小:

最终效果:

posted on 2022-11-02 10:00  PISCOnoob  阅读(65)  评论(0编辑  收藏  举报