ODOShader

ODOS丨国王,乌鸦和出租车

by ERIN.Z, 2022-02-05


Snipaste_2022-02-06_00-05-27.png

写在前面

颇为感慨,竟然真的有用到建筑数学的一天。🤨 今天的学习资料是iq老师这个基于voronoi的shader,由于这个版权的限制比较严格,我们就点到为止,主要是学习一下变形的思路~更多参考了其原理展示iq

距离算法

在计算距离时,我们一般都是求两点之间的直线距离,也就是欧几里得距离,但常用的距离算法还有曼哈顿距离(出租车距离)切比雪夫距离(国王距离)。这不是一个数学博客,咱也解释不清,咱就不多说了,详细不如读wiki。 distance

回到Voronoi

Voronoi图是基于距离的算法,不同的距离算法就会产生不同的分格效果。 Voronoi 基于distance的算法,今天要拿WorleyNoise开刀,削一个帅气的随机立方体效果。

从泡泡到立方体

先整一个基础版的worley noise。我们需要一个2维的哈希函数来生成晶格中特征点的位置,这里就不上之前用的psrd了,码太长了。

    vec2  hash( vec2  p ) 
    {
        p = vec2( dot(p,vec2(137.1,373.7)), dot(p,vec2(269.5,183.7)) ); 
        return fract(sin(p)*43758.37); 
    }
    float worley(vec2 p){
        vec2 n = floor(p);
        vec2 f = fract(p);
        float d = 1.;
        for(int i=-2;i<=2;i++){
        for(int j=-2;j<=2;j++){
            float D1 = distance(hash(n+vec2(i,j))+vec2(i,j),f);//Euclidean
            d = min(d,D1);
        }
        }
        return d;
    }

worley noise 换上出租车和国王,可以看到Manhattan的距离场是十字星状,Chebyshev的距离场是斜十字星状。

        float D2 = abs(o.x-f.x)+abs(o.y-f.y);//Manhattan
        float D3 = max(abs(o.x-f.x),abs(o.y-f.y));//Chebyshev

manhatten&chebyshev 受Chebyshev距离场的启发,我们可以通过调整距离公式以获得轴测小立方体三条边的效果。 本视觉动物这样理解数学: triangular 套入距离公式,我们的效果已经初具雏形了!

        float D4 = max(abs(o.x-f.x)*0.866+(o.y-f.y)*0.5,-(o.y-f.y));//Triangle
        d = min(d,D4);

boxes 我们最开始的函数输出是一维的float,这里改成vec3以增加一些数据输出。x分量记录距离场;y分量记录归一化的特征点x坐标,用以作为随机颜色的seed;z分量计算产生一个以特征点为中心的mask。

        if(D4<r.x){
        r.x = D4;//distance
        r.y = (o.x-float(i))*0.5+0.5;//for colorseed
        r.z = 1.-step(0.0,0.5*abs(o.x-f.x)+0.866*(o.y-f.y))*(1.0+step(0.0,o.x-f.x))*0.4;//mask
        }

wow! 看起来不错! 接下来其实就可以做许多事,比如去掉hash的随机性,来获得一些规则图案—— pattern1 pattern2 (啊好气!因为根三的精度 差那么一丝丝🤬 比如利用距离场伪造一点AO—— AO 比如加点动画——

    o = sin(iTime + hash(n+vec2(i,j))*6.28)*0.5+0.5;//animate

animated 比如用魔法加一个描边——

    vec2 dp = 2.0*vec2( 1.0/iResolution.y, 0.0 );
    float d = abs(worley( 2.*(uv+dp.xy)).z - worley( 2.*(uv-dp.xy)).z )+
              abs(worley( 2.*(uv+dp.yx)).z - worley( 2.*(uv-dp.yx)).z );

outliner 还可以根据z分量的mask去扭曲uv,获得贴图坐标系,给每个面贴点小图案—— 哎呀这个详见原shader。不能再做了 再像要被骂了x 总之今天就到这里!晚安! finished 👉完整代码👈

ODOS —— One Day One Shader 努力日更的学习计划。 包括但不限于基于[Shadertoy][22]、UnityShaderLab等平台的shader学习笔记

by ERIN.Z

2024 © typecho & elise