[Fragment Shader] Noise 2D 在Shader中实现

The Book of Shaders - Generative designs - Noise[1] 学习笔记.


1. Random 2D

首先实现之前学过的的2D随机函数, 即输入一个2D坐标, 输出(0,1)随机值:

float random(in vec2 st) 
{
    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}

在调用这个函数前, 用 floor 函数将坐标网格化:

void main() 
{
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    vec2 pos = floor(st*10.0);
    float n = random(pos);
    gl_FragColor = vec4(vec3(n), 1.0);
}

效果如下:
在这里插入图片描述

2. Noise 2D

然后实现2D噪声函数, 方法是获取周围4个点的随机值, 然后根据当前坐标的小数部分(利用 fract 函数), 插值得到最终噪声值. 插值时用到了之前学的 SmoothStep 进行非线性插值.
如图所示, 四个角的高度表示它们的随机值, 分别为代码中的a, b, c, d. 非线性插值获得中间的高度, 即所求噪声值.

借用The Book of Shaders的插图:
在这里插入图片描述
代码如下:

float noise(in vec2 st) 
{
    vec2 i = floor(st);
    vec2 f = fract(st);

    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));
    // smooth step
    vec2 u = f*f*(3.0-2.0*f);

    float ab = mix(a, b, u.x);
    float cd = mix(c, d, u.x);
    return mix(ab, cd, u.y);
    // 功能与上面三行相同
    // return mix(a, b, u.x) +
    //        (c - a)* u.y * (1.0 - u.x) +
    //        (d - b) * u.x * u.y;
}

在调用时, 直接传入坐标:

void main() 
{
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    vec2 pos = st*10.0;
    float n = noise(pos);
    gl_FragColor = vec4(vec3(n), 1.0);
}

效果如下:
在这里插入图片描述

3. Fractal Noise 2D

之前用 Shadershop 实现了1D的分形噪声, 原理是将多个缩放程度不同的 Noise 叠加起来, 现在也用 Noise2D 来实现分形噪声.

void main() 
{
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    
    float n = 0.0;
    n += noise(st*10.0);
	n += noise(st*20.0)/2.0;
    n += noise(st*40.0)/4.0;
    n += noise(st*80.0)/8.0;
    n += noise(st*160.0)/16.0;
    n += noise(st*320.0)/32.0;
    // 限制值在[0,1] 
    n = n*0.5;
    
    gl_FragColor = vec4(vec3(n), 1.0);
}

最终效果如下:
在这里插入图片描述


参考文献

[1] Patricio Gonzalez Vivo, Jen Lowe. The Book of Shaders. Retrieved Jan. 9, 2019, from https://thebookofshaders.com/11/?lan=ch

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity的火焰shader可以通过多种方式实现,下面是其一种实现方式: 1. 创建一个新的材质,并将其shader设置为“Standard”或“Standard (Specular Setup)”。 2. 在材质的属性面板添加一个新的纹理,用于表示火焰形状的alpha通道。这个纹理可以是一个黑色背景,心区域是白色火焰形状的灰度图像。 3. 添加一个新的颜色属性,用于定义火焰的颜色。 4. 在shader添加以下代码: ``` Shader "Custom/Flame" { Properties { _MainTex ("Flame Texture", 2D) = "white" {} _Color ("Flame Color", Color) = (1,1,1,1) _Speed ("Speed", Range(0, 10)) = 1 _Intensity ("Intensity", Range(0, 5)) = 1 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Transparent"} LOD 200 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _Color; float _Speed; float _Intensity; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } half4 frag (v2f i) : SV_Target { half4 texColor = tex2D(_MainTex, i.uv); float alpha = texColor.a; float t = _Time.y * _Speed; float sinx = sin(i.uv.x * 20 + t); float siny = sin(i.uv.y * 20 + t + 0.5); float noise = sin(sinx + siny) * 0.5 + 0.5; float intensity = pow(noise, _Intensity); return alpha * _Color * intensity; } ENDCG } } FallBack "Diffuse" } ``` 5. 将这个shader拖到材质,并将火焰纹理拖到“MainTex”属性。 6. 调整属性面板的“Color”、“Speed”和“Intensity”属性,直到得到满意的火焰效果。 这个shader使用了alpha通道纹理来定义火焰形状,并且根据时间和噪声函数来产生火焰动态效果。你可以根据自己的需求和创意来调整shader代码和属性面板的属性,以得到更加逼真和有趣的火焰效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值