分享一个Label Shader,艺术字

先看效果

思路

只取文字原图的透明度,使用此数据进行上色;加上更多的图层,进行颜色叠加(在主图层的透明部分叠加)

    float getA(vec2 p) {

        vec2 tp = vec2(p.x+.5, .5-p.y);

        float a = 0.0001;

        a += step(abs(p.x), .5)*step(abs(p.y), .5)*texture2D(texture, tp).a;

        return a;

    }

    vec4 transCol(vec4 c1, vec4 c2) {

        float k = (1.-c1.a)*c2.a/(c1.a+c2.a);

        vec4 c = vec4(.0);

        c.rgb = mix(c1.rgb, c2.rgb, k);

        c.a = c1.a+k*c2.a;

        return c;

    }

颜色渐变

上色只需要针对y值使用mix函数,就可以做出渐变色效果

    vec4 col = vec4(.0);

    float a = getA(uv);

    vec4 color1; //颜色

    vec4 color2; //颜色

    vec4 color3; //颜色

    //三色

    col = step(.0, uv.y)*mix(color1, color2, 1.-uv.y*2./scale);

    col += step(uv.y, .0)*mix(color2, color3, -uv.y*2./scale);

    //双色

    col = mix(color1, color2, uv.y/scale+.5);

    //单色

    col = color1;

    col.rgb *= step(.0, a);

    col.a *= a;

流光

加上一条色带,根据时间变换位置

    float t; //时间

    float color; //颜色

    float rad = 30.;

    float w = 0.2/cos(rad);

    float tan_rad = tan(rad);

    float t = fract(t)*(1.+w+abs(tan_rad))-w-step(.0, tan_rad)*abs(tan_rad);

    float x = uv.x-(1.-uv.y)*tan_rad;

    col.rgb = mix(col.rgb, color.rgb, step(t, x)*step(x, t+w)*(1.-smoothstep(.0, w*.5, abs(x-t-w*.5)))*color.a);

阴影(shadow)

加一层偏移的图层

    vec2 offset;

    float color; //颜色

    vec4 sc = vec4(color.rgb, color.a*getA(vec2(uv)+offset));

    col = transCol(col, sc);

描边(outline)

将像素往周围扩散固定距离,由于一般来说字体节点的长宽时不等的,这里使用到旋转椭圆公式:

    x = cos(γ))*cos(t)*R2-sin(γ)*sin(t)*R1

    y = sin(γ))*cos(t)*R2-cos(γ)*sin(t)*R1

使描边的宽度不会有问题;在此基础上也可以添加描边的阴影效果

    const float accuracy = 32.0; //取色精度

    vec2 w; //描边宽度(x向宽度和y向宽度)

    vec4 color; //描边颜色

    vec2 shadow_offset; //阴影偏移

    vec4 shadow_color; //阴影颜色

    float ola = .0;

    float ola_shadow = .0;

    float rot = PI*0.5;

    vec2 tuv = uv+shadow_offset;

    for(float i=.0;i<accuracy;i++) {

        float rad = PI*2./accuracy*i;

        vec2 uv_d;

        uv_d.x = cos(rot)*cos(rad)*w.y-sin(rot)*sin(rad)*w.x;

        uv_d.y = sin(rot)*cos(rad)*w.y+cos(rot)*sin(rad)*w.x;

        ola = max(ola, getA(tuv+uv_d));

        ola_shadow = max(ola_shadow, getA(tuv+shadow_offset+uv_d));

    }

    vec4 olc = vec4(color.rgb, color.a*ola);

    col = transCol(col, olc);

    vec4 olc_shadow = vec4(shadow_color.rgb, shadow_color.a*ola_shadow);

    col = transCol(col, olc_shadow);

看到循环,你应该知道,他可能会卡,32是我测试的一个不错的选择

外发光

外发光思路跟描边思路差不多,另外在他的基础上加了一个距离的分层显示

    const float accuracy = 32.0; //取色精度

    const float accuracy_glow = 8.0; //分层精度

    vec2 w; //外发光宽度(x向宽度和y向宽度)

    vec4 color; //外发光颜色

    float depth; //颜色的校正

    float ga = .0;

    float rot = PI*0.5;

    float tx = w.x+outline_w.x; //这里添加了一个描边的叠加处理

    float ty = w.y+outline_w.y;

    for(float i=.0;i<accuracy;i++) {

        float rad = PI*2./accuracy*i;

        for(float j=.0;j<accuracy_glow;j++) { //

            vec2 uv_d;

            uv_d.x = cos(rot)*cos(rad)*ty-sin(rot)*sin(rad)*tx;

            uv_d.y = sin(rot)*cos(rad)*ty+cos(rot)*sin(rad)*tx;

            uv_d *= j/accuracy_glow;

            ga += getA(uv+uv_d);

        }

    }

    ga /= accuracy*accuracy_glow;

    ga = smoothstep(.0, 1., ga*depth);

    vec4 gc = vec4(color.rgb, color.a*ga);

    col = transCol(col, gc);

看到双层循环,你应该知道,他可能会卡,请谨慎使用

项目地址:https://github.com/fh7315/ShaderTest

15赞

:laughing:感谢大佬的分享,大佬牛逼

感谢分享 :+1: :+1: :+1:

感谢感谢。。。。。