如何在Shader中绘制类似虚线的折线

该博客介绍了如何在Shader中利用距离场技术绘制动态虚线折线。通过计算像素到折线的距离,根据线宽选取范围,并结合时间变量实现流动效果。代码示例展示了从多个线段点计算距离并混合最终结果的过程,从而在屏幕上呈现连续的虚线折线动画。
摘要由CSDN通过智能技术生成

如何在Shader中绘制类似虚线的折线

实例代码可以参考shadertoy中的[例子](line with animation (shadertoy.com))

核心思想

绘制折线

在shader中无法通过顺序绘制的方式绘制折线,在参考现有的shadertoy中的例子后,决定采用距离场的方式绘制折线,即计算屏幕上每个像素到给定折线的距离,通过给定线宽来选取折线的范围。

绘制虚线

通过距离场明确线的范围后,可以将屏幕中每个像素投影到折线上,通过投影到折线上的距离来对线段进行分段,以实现间隔绘制效果。

效果图如下:

在这里插入图片描述

详细代码

sdLine_t方法用于绘制线段,方法中通过向量点乘的方式计算,给定点到线段的最短距离,其中c为计算得到的p距离向量ab的最短距离。t_lxsp在向量ab上的投影的距离。通过对c进行截取,仅保留给定线宽的计算结果,线宽范围外的赋值为0,即可得到折线的绘制范围。

通过对t_lxs取模,可以实现分段绘制,距离加时间可以实现流动效果。

最后cDistance_t方法实现多段线段的绘制,方法中使用max来混和多段线。

const float ELIPSE=.005;
const float LINEWIDTH=0.01;

float sdLine_t(in vec2 p,in vec2 a, in vec2 b){
    vec2 pa=p-a,ba=b-a;
    float t=dot(pa,ba)/dot(ba,ba);
    //p在ba上投影距离
    float t_lxs=dot(pa,ba)/length(ba);

    float c=length(pa-ba*clamp(t,0.0,1.0));
    c=1.-smoothstep(LINEWIDTH,LINEWIDTH+ELIPSE,c);

    return c*mod(t_lxs-iTime/10.,.1);
}

const vec2 p0 = vec2( 0.6, 0.1);
const vec2 p1 = vec2( 0.4, 0.3);
const vec2 p2 = vec2(-0.2, 0.5);
const vec2 p3 = vec2(-0.6, 0.4);
const vec2 p4 = vec2(-0.8, 0.1);
const vec2 p5 = vec2(-0.7,-0.1);
const vec2 p6 = vec2( 0.0,-0.2);
const vec2 p7 = vec2( 0.7,-0.2);

float cDistance_t( in vec2 v )
{
    float d0 = sdLine_t( v, p0, p1 );
    float d1 = sdLine_t( v, p1, p2 );
    float d2 = sdLine_t( v, p2, p3 );
    float d3 = sdLine_t( v, p3, p4 );
    float d4 = sdLine_t( v, p4, p5 );
    float d5 = sdLine_t( v, p5, p6 );
    float d6 = sdLine_t( v, p6, p7 );
    float d7 = sdLine_t( v, p7, p0 );
	//线宽范围外均为0,所以这里取最大值
    float t=max(d0,max(d1,max(d2,max(d3,max(d4,max(d5,d6))))));
    return t*8.;
}

void mainImage(out vec4 fragColor,in vec2 fragCoord){
    float m=min(iResolution.x,iResolution.y);
    vec2 p=(-iResolution.xy+2.*fragCoord.xy)/m;

    float c_lxs=cDistance_t(p);
    fragColor=vec4(vec3(c_lxs),1.0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值