canvas系列-打造精灵涂鸦效果

1,130 阅读3分钟

精灵涂鸦效果的这篇文章是昨日在unity看到的,感觉将的很有意思,虽然内容不多,但是信息却饱含了很多,于是偷偷写了这篇小文章~

                                     

本文会涉及一些比较高级的话题,包括:反向运动学的数学原理和大气的瑞利散射效果。但是既对这些内容感兴趣,又有理解所需的必备技术知识的开发者其实并不多

这是原文的的话,但是很多人都不太理解反向运动学(IK)跟散射效果,其实这里因为操作还是在2d层面,散射效果可以忽略不计,那么主要的话题就是在IK

通过gif图,可以看得出图形的像素点在每帧都进行了大幅度的随机抖动,于是可以大体上把实现归结为

/*
*gl_Position  当前像素坐标
*a_position   传入的像素坐标
*u_offset   像素偏移量
*width  视图的宽度
* noiseWeights  影响的大小
*/
u_offset.x =  -1 + Math.random()*(gl_Position.x/width)    //以[-1,1]
u_offset.y =  -1 + Math.random()*(gl_Position.y/height)    //以[-1,1]
gl_Position.x = a_position.x + u_offset.x*noiseWeights
gl_Position.y = a_position.y + u_offset.y*noiseWeights  // 对像素进行偏移

这个时候就已经可以看出会对像素进行偏移操作,接下来就可以来讨论反向运动学的东西了,反向运动学的核心是由自由端来带动连接端,也就是说,我们需要由外面的点来带动中间的点,形成联动效果,这个时候,我们就需要对图像进行网格化,对网格进行拓扑处理,这样,就差不多可以实现了上方的效果。

但是!原文中还有一个概念点,就是对齐时间。

由于浏览器渲染是按帧渲染,但是我们并不需要这么高的渲染帧率,所以就需要一个函数来进行对齐时间

function _snap (time, snap) {
    return snap * Math.random()*(time / snap)
}

这里的time☞的在shader中的是_Time.y,如果有兴趣的可以去了解,原意的目的应该是为了使每次变换周期内的偏移影响会随着时间变化,最后再把对齐时间的影响返回到偏移函数中

u_offset.x =  -1 + Math.random()*(gl_Position.x/width) + _snap(_Time.y, noiseWeights)
u_offset.y =  -1 + Math.random()*(gl_Position.y/height)+ _snap(_Time.y, noiseWeights)
// 此处_Time.y的意思是变换周期,比如每3s为一个渲染周期。那么 运行的取值应该是
// 1s -> 1 
// 2s -> 2 
// 3s -> 3
// 4s -> 1

那么效果就应该可以实现了,昨晚突然看到感觉很棒,但是unity跟正常的开发还是有不少差异,正常的操作应该是交由shader来进行完成,但是奈何写不好,于是就整理了一下原分享者的思路,如果有疑问的,欢迎在下方提问哦~整理了思路,还没有来得及去code,如果有实现的老哥,记得艾特我丫。

原文是在unity的官方公众号看到的,如果有兴趣可以去看看,不过建议有unity跟shader经验的去看,因为它写的很简洁,而且都是直接shader操作,偏向于实战性的,门槛比较高