shader编程经典:分形--科赫(雪花)曲线

序言

科赫(雪花)曲线是一个经典分形图案,来一起领略下分形之美。本篇内容用到一些基础的内容,例如UV的理解和画线技巧,有需要的话可以参考合集的画圆和画线两篇文章。

示例

image
shadertoy 代码:

#define T .01

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = (fragCoord.xy-0.5 * iResolution.xy) / iResolution.y; 
    vec3 col = vec3(0.);
    float a = (4. / 6.) * 3.1415926;
    vec2 n = vec2(sin(a), cos(a));
    float s = 1.;
    int t = int(sin(iTime) * 2. + 3.);
    uv.x += .5;
    uv.y += .25;
    for (int i = 0; i < t; i++ )
    {
        s *= 3.;
        uv *= 3.;
        uv.x -= 1.5;

        uv.x = abs(uv.x);
        uv.x -= 0.5;

        uv -= n * min(0., dot(uv, n)) * 2.;
    }

    float d = length(uv - vec2(clamp(uv.x, -1., 1.), 0.));
    col += smoothstep(T, .0, d/s);
    fragColor = vec4(col, 1.);
}

注解

先简化一下问题--只考虑一次迭代
image
观察到上述代码有偏移和对称,其实我们只需要关心对称轴的一侧,来看图像的左半边的绘制
image
它大概的形状如上图中的绿色线所示,观察负半轴,负半轴绿色的线可以有紫色线沿着蓝色线为对称轴反转得到,之反转原理如下
image
(对应上述代码 uv -= n * min(0., dot(uv, n)) * 2.)

  • y 假设是对称轴
  • n 是y的法线(单位向量)
  • uv 是当前uv所在的位置
    则dot(uv, n) * n 是uv',这里稍微解释下
    image
    点乘的公式:dot(a, b) = |a||b|cosθ,a是单位向量,则dot(a, b) = |b|cosθ = |b'|,b'向量 = a * |b'|
    uv'与b'同理
    易求得uv'' = -dot(uv, n) * n * 2.
    uv -= dot(uv, n) * n * 2. 即从原uv点移动到了uv''所指的位置,从而画出绿线

再考虑多次迭代,其实就是不断重复上述过程,迭代uv,实现自相似(分形),其他的都比较好理解,相信大家仔细看看都能明白就不赘述了。

posted @ 2023-06-01 12:12  寡人正在Coding  阅读(500)  评论(0编辑  收藏  举报