ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

WebGl简单实践-烧灼纸张效果[转]

2021-05-22 13:03:40  阅读:296  来源: 互联网

标签:fp 渐变 grandColor WebGl 烧灼 st vec2 ip 纸张


前言

最近想实现个酷炫的转场特效,想到了这个烧灼效果。最初想用svg滤镜实现,但动画效果非常卡,遂转而考虑使用webgl的片段着色器实现。下面是最终实现的效果

本文只关注片元着色器,WebGL基础知识可见一下链接:

WebGL 基础概念​webglfundamentals.org图标

 

画出烧焦的洞

我们使用放射渐变来实现,然后把中间不透明度为1的区域变成完全透明的。

放射渐变的实现非常简单,各像素的颜色仅需要通其到渐变中心的距离确定。

代码

float circle(vec2 st, vec2 center){
    return distance(st , center)*3.;
}

void main(){
    vec2 st = gl_FragCoord.xy / u_resolution;
    float color = circle(st , vec2(.5,.5));
    vec4 grandColor = mix(vec4(0. ,0. ,0. ,1.) , vec4(1.,1.,1.,0.) , smoothstep(.58 , .9 , color));

    if(grandColor.a == 1.)grandColor.a = 0.;
    gl_FragColor = grandColor;
}

效果

 

为烧焦的洞添加火焰边缘和熏黄效果

因为基本图形是使用放射渐变制作的,它的不透明度alpha从中间到周围由1渐变为0,所以我们可以利用渐变的值确定各部分位置,比如alpha在0.~.99间是纸张烧焦部分 ,在.99~1.间是火焰的位置,为1.时是中间烧掉的洞。烧焦部分由黑色到黄色的渐变效果,同样可以用alpha值作为度量。

代码

if(grandColor.a == 1.)grandColor.a = 0.;
else if(grandColor.a > .994 && grandColor.a <1.){
    grandColor = mix( vec4( 0.985,0.0,0.000 ,1.) , vec4(0.985,0.696,0.285 , 1.) , smoothstep(.994, .999 , grandColor.a) );
}
else{
    grandColor = vec4( mix(vec3(0.,0.,0.) , vec3(0.690,0.373,0.000 )  ,smoothstep(.23 , .55,1.- grandColor.a)) , grandColor.a*1.6);
}

 

制作不规则效果

上面的效果看起来完全不像一个烧焦的洞,它太规则了,为了得到形状更加自然的焦洞,可以使用一种名为柏林噪音(Perlin Noise)的技术。柏林噪音是一种梯度噪音,它的主要原理是在网格的顶点计算出随机的梯度,而后利用插值的方式利用周围顶点的梯度计算各点的噪声值。

这是柏林噪声的实现代码:

vec2 g_random(vec2 ip){
    return fract(sin(
        vec2(dot(ip,vec2(127.1,311.7)), dot(ip,vec2(269.5,183.3)))
    )* 44753.976967) *2. - 1.;
}

float g_noise(vec2 st){
    vec2 ip = floor(st);
    vec2 fp = fract(st);

    vec2 u = fp*fp*fp*(fp*(fp*6.-15.)+10.);//使用三次多项式进行插值
    return mix(
        mix(dot(g_random(ip) , fp-vec2(0.,0.)) , dot(g_random(ip+vec2(1.,0.)) , fp-vec2(1.,0.)) ,u.x),
        mix(dot(g_random(ip+vec2(0.,1.)) , fp-vec2(0.,1.)) , dot(g_random(ip+vec2(1.,1.)) ,fp-vec2(1.,1.)) , u.x),
        u.y
    );
}

在主函数中的相关代码:

vec2 copy = st;
copy *= vec2(4.,4.);
copy += g_noise(copy*3.);

//将放射渐变用噪声扭曲
color += (g_noise(copy) -.5)*.19;

效果

 

添加纹理

这下看起来好多了,不过还是有些奇怪——熏黄的部分颜色太平滑了,一般的纸张可不会这么光滑,最好再添加一点纹理。这里我们使用简单的噪声来实现

grandColor.a += (random(st*400.)-.5)*.2;

效果

 

动态效果

动态的实现非常简单,只要在着色器中添加时间的uniform即可。

 

完整代码:

BokunoMasayume/amazing-animation​github.com图标

 

发布于 2019-07-08 WebGL       前端开发      Canvas

 

标签:fp,渐变,grandColor,WebGl,烧灼,st,vec2,ip,纸张
来源: https://www.cnblogs.com/mazhenyu/p/14798575.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有