圆形的绘制和随机变化

本文介绍了如何利用Three.js结合自定义Shader来绘制平滑的圆形和圆环,并展示了如何通过Shader消除图形的锯齿。通过调整顶点着色器和片元着色器中的代码,实现了圆的平滑过渡和圆环的绘制。此外,还探讨了如何通过三角函数实现圆环的波浪效果,提供了相关代码示例和最终效果展示。
摘要由CSDN通过智能技术生成

一.前言

除了矩形,圆形在实际的图形运用中也比较广泛。例如水波或光圈效果;若是用最基础的webgl理论来讲,我们都知道圆属于多边形的绘制,可以通过绘制圆上的各点,再将其连接起来通过gl.drawArrays方法,传入gl.TRIANGLE_FAN来进行绘制。今天我们介绍Three.js的绘制方法。

二.绘制原理

其实在three.js中,是有CircleGeometry圆几何体类的,我们可以很轻松的new一个来创建一个圆形平面,然后填充材质即可得到圆形的图案。那我们为什么要自己来绘制呢,原因很简单,自定义的shader易于扩展和变换,可以做一切你想做的事情。
言归正传,Three.js用shader画圆原理也非常简单

1.先创建一个矩形平面和自定义Shader材质

const geo = new THREE.PlaneBufferGeometry(this.width, this.height, 32, 32);   //创建plane类型的图形
const mat = new THREE.ShaderMaterial({                                        //shader材质
    vertexShader: vs,
    fragmentShader: fs,
    uniforms: this.uniforms,
    transparent: true,
    side: THREE.DoubleSide,     //双面材质
    wireframe: false,
});
this.shape = new THREE.Mesh(geo, mat);

2.片元着色器来确定点的绘制

这里我们只处理颜色,顶点着色器用默认的就好

void main() {
    vec2 st = 2.0 * v_uv - 1.0;               //坐标范围由[0,1]转化为[-1,1]

    vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
    float dist = distance(st, vec2(0.0));     //与vec2(0,0)之间得距离
    if (dist > u_radius) {                    //距离大于u_radius则用插值来确定该点的透明度
        color.a = 0.0;
    }
    gl_FragColor = color;
}

上面代码就是根据距离取确定点的透明度,大于半径color.a=0.0,小于等于半径color.a=1.0
得到如下图:

attachmentId-49

虽是成功绘制了圆,但我们仔细观察,圆周上可以看到很明显的锯齿。前面我们也分析过,圆就是"多边形",所以在shader绘制中不能得到理想的曲线。请继续往下看,后面会讲解如何消除锯齿

三.圆环的绘制

上面我们绘制了圆,如法炮制按照上述思想绘制圆环也十分容易,这里不讲解了直接上代码

vec4 getColor(vec2 st) {
    float dist = distance(st, vec2(0.0));                       //距离[0,0]的距离
    vec4 color = vec4(0.0);
    if (dist < u_radius && dist > u_radius - u_border) {        //u_radius-u_border ~ u_radius之间为非透明,即显示的环
        color.a = 1.0;
    }
    return color;
}

void main() {
    vec2 st = 2.0 * v_uv - 1.0;
    gl_FragColor = getColor(st);
}

u_radius,u_border值均由js传入,分别为圆的半径,环的宽度

四.消除圆的锯齿

在上一篇Metaballs的解析中,我们运用了smoothstep的平滑埃尔米特插值来处理融合部分。
这里我们也可以用它来处理圆周部分,使它的透明度0-1分界之间没有那么生硬
修改片元着色器绘制:

void main() {
    vec2 st = 2.0 * v_uv - 1.0;

    vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
    float dist = distance(st, vec2(0.0));     //与vec2(0,0)之间得距离
    if (dist > u_radius) {                    //距离大于u_radius则用插值来确定该点的透明度
        float sub = dist - u_radius;
        color.a = sub < 0.01 ? smoothstep(1.0, 0.0, sub/0.01): 0.0; 
    }
    gl_FragColor = color;
}

在半径周围0.01的范围处做透明度的平滑过渡,我们来看下修改之后的效果:

attachmentId-50

是不是平滑多了,看不到明显的锯齿了

五.圆环的随机变换

关于圆弧应用最广泛的应该使波浪效果了,那么波浪效果如何实现呢?如果你也想到了三角函数sin,cos 那么恭喜你。我们需要做的就是周期性的修改圆弧的顶点,再添加一些随机性就能实现波浪效果

1.通过顶点着色器对顶点进行偏移

void main() {
    v_uv = uv;

    float amplitude = sin(u_time) * 0.03 + 0.01;                    //振幅,随时间变化
    vec3 pos = position;
    pos.x += cos(14. * uv.y  + 8. * u_time) * amplitude ; //x偏移值随u_time变化 受amplitude影响 幅度也在一定范围内随机
    pos.y += sin(4. * uv.x  + 8. * u_time) * amplitude ;  //y偏移  同理与x的处理,将cos改成sin  

    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}

我们这里添加了多个半径不一圆圈的示例,得到的效果如下:

attachmentId-51

如果你熟悉三角函数,你可以做任意你想要的变化。比如:

attachmentId-52

这样螺旋变化,思考一下该如何实现呢, 自己尝试一下吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值