shdertoy学习系列4- 雷达(2)

上文中的雷达仅绘制了圆边和扫描线,渐变区域还未添加

#define PI 3.1415926535897932384626433832795


// 绘制线,传入参数,圆心,线的终点, 片元坐标
float LineToPointDistance2D( vec2 a, vec2 b, vec2 p)
{
    vec2 pa = p - a;    //片元坐标-圆心坐标
    vec2 ba = b - a;   // 线终点坐标-圆心坐标
    //片元坐标到圆心的距离/半径
    float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0); //clamp函数会将x限制在minVal和maxVal之间。float clamp(float x, float minVal, float maxVal)
    //片元坐标减去   半径*片元元坐标到圆心的距离/半径,当在圆外时,h为1 ,则长度为 pa-ba
    //当在圆内时,  长度大于pa-ba
    return length( pa - ba*h );
}

// 传入参数 传入圆心坐标,旋转的角度,返回的线终点坐标,
//传入了线的初始终点坐标
vec2 rotatePoint(vec2 center,float angle,vec2 p)
{
    float s = sin(angle);
    float c = cos(angle);

    // translate point back to origin:
    p.x -= center.x;
    p.y -= center.y;

    // rotate point
    float xnew = p.x * c - p.y * s;
    float ynew = p.x * s + p.y * c;

    // translate point back:
    p.x = xnew + center.x;
    p.y = ynew + center.y;
    return p;
}


void getBlips(float radius, out vec2[1] blipsOut)
{
    vec2 cen = iResolution.xy/2.0;
    float sec = iDate[3];
    float mdl = mod(sec,10.0);

    //From 1 to 6
    float cstepRot = ((sec-mdl)/10.0)+1.0;
    float factorRot = cstepRot/6.0;

    float factorLen = sin(factorRot)/2.0;
    float len = radius*factorLen;//0.5;);
    vec2 targetP = vec2(cen.x,cen.y+len);
    float ang  =  PI*factorRot*2.0;
    targetP = rotatePoint(cen,ang,targetP);

    blipsOut[0] = targetP;
}

//传入参数 归一化的 线终点坐标-圆心
// 归一化的 片元坐标-圆心坐标
float angleVec(vec2 a_, vec2 b_)
{
    vec3 a = vec3(a_, 0);
    vec3 b = vec3(b_, 0);
    float dotProd = dot(a,b);  //b在a向量上的投影长度
    vec3 crossprod = cross(a,b);// a,b的法向量
    float crossprod_l = length(crossprod); //法向量的长度
    float lenProd = length(a)*length(b);   // a向量和b向量的模长
    float cosa = dotProd/lenProd;       //cos a即为 a向量与 b向量的夹角  a·b = |a||b|cos∠(a, b)  点积公式
    float sina = crossprod_l/lenProd;     // sin 值  |a×b| = |a||b|sin∠(a,b)      叉积公式
    float angle = atan(sina, cosa);     //角度 返回值的在(-π - π)
    // x,y的符号 决定了反正切的结果,可判断xy所在的象限,反正弦与反余弦返回值在(-π/2 - π/2)之间,不能唯一确定
    //x和y的关系,因此选用反正切来判断x、y的关系

    //  法向量与 ab法向量的点积 ab cos a 如果小于0,则意味着a在第二象限(π/2- π)  则证明ab的法向量向下,
    if(dot(vec3(0,0,1), crossprod) < 0.0)
        angle=90.0;
    return (angle * (180.0 / PI));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 center =iResolution.xy/2.0; //获取片元中心坐标
    float minRes = min(center.x,center.y); //取x,y中较小的一个为中心,否则圆形会超出canvas的范围
    float radius =minRes-minRes*0.1; //半径为最小分辨率值的90%
    float circleWitdh = radius*0.02;//圆的宽度为半径*0.02
    float lineWitdh = circleWitdh*0.8;  //线的宽度为半径*0.8
    float angleStela = 180.0;  //角度
    vec2 lineEnd =  vec2(center.x,center.y+radius);    //线的终点,初始的时候即为中心点+圆的半径

    float blue =0.0;
    float green =0.0;//绿色分量默认为0

    float distanceToCenter = distance(center,fragCoord.xy);//计算中心到片元的距离
    float disPointToCircle=abs(distanceToCenter-radius);//片元到圆心的距离与半径判断

    //绘制圆圈,判断  片元到圆心的距离与半径 是否小于圆的宽度
    if (disPointToCircle<circleWitdh)
    {
        green= 1.0-(disPointToCircle/circleWitdh); //如果小于圆的宽度,则证明在圆内,赋值绿色分量
    }

    // 旋转线,角度=负的实践*1.2
    float angle = (-iTime*1.2);
    // 旋转点之后,重新获取线的终点
    lineEnd = rotatePoint(center,angle,lineEnd);

    // 绘制线,传入参数,圆心,线的终点, 片元坐标
    float distPointToLine = LineToPointDistance2D(center,lineEnd,fragCoord.xy);
    //如果点距离线的距离小于线的宽度
    if (distPointToLine<lineWitdh)
    {
        // 1减去 点到线的距离/线的宽度, 当先距离线越近时,颜色越深
        green = 1.0-distPointToLine/lineWitdh;

    }


    //绘制渐变扇形
    //传入参数 归一化的 线终点坐标-圆心
    // 归一化的 片元坐标-圆心坐标
    float angleStelaToApply = angleVec(normalize(lineEnd-center),normalize(fragCoord.xy-center));

    //angleStela =180° 如果待绘制的片元 与基准线的角度小于180
    //且距离圆心的距离小于半径- 原文是radius-circleWitdh/2.0+1.0 ,考虑了线宽因素,学习就简化了

    //此处angleStelaToApply<angleStela 是多余的判断,因为反正切已经在180°之内了
    if (distanceToCenter<radius)
    {
         //角度因子,1.0- 待用的角度/180 ,值在1.0之内
        float factorAngle = 1.0-angleStelaToApply/angleStela;
       //将值重新计算
        float finalFactorAngle = (factorAngle*0.5)-0.15;

         //如果最终的值大于原来的green了,则重新赋值
        //这是由于此前已经对圆边,扫描线赋值了,如果不进行判断,会将之前的值重写
        if (finalFactorAngle>green)
            green=finalFactorAngle;



     
    }
   // float jg=center.x>390.0?1.0:0.0;  //调试使用

    fragColor = vec4(0.0,green,blue,1.0);
}


现在这个结果就跟原文的差不多了,只要再添加随机点就可以了,

angleVec这个函数的最后一个返回还有点没太理解,先记录,理解了再补上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值