CocosCreator纹理画线之实践分享

之前看过一个微信公众号:白玉无冰, 讲解纹理画线,基于cc.Sprite 的Mesh渲染类型; 

本文章不会详细讲解和重复那篇公众号的内容,所以如果亲对Mesh渲染,纹理画线还不理解,请移进入作者公众号学习一下,然后再回来查看本文章;

实践过程中,里面的一些向量、顶点和三角形的计算很有意思,因为Mesh的顶点计算是在cpu端的,相应的api是cocos内置的,这样就可以在TypeScript的智能提示下编写类似shader的代码,来控制顶点,uv等,大家可以在不参考完整源代码的情况下跟着那个公众号的文章实现一遍,对于shader,图形学初学者已经初步入门的人,应该可以提高一些顶点,向量,uv的认识;


先看效果图:


不同点

绘制方式

站长本人测试时,不是用直线测试的, 也没有使用贝塞尔曲线等, 而是自由绘制,所以计算的顶点和三角形会比较多,同时复杂曲线的处理也带来一些挑战;

连接处的绘制

原作者是在连接处画圆来处理连接处的缝隙与缺口,这个比较适合处理大角度转折;
  1. 最开始是根据 原作者另一篇文章的凸顶点和凹顶点的方式计算缺口方向,然后画三角形,补齐缺口,但是效果不太理想,三角形过多;
  2. 然后尝试了直接新矩形的左边直接使用上一个矩形的右边作为顶点,效果居然还不错,关键是这样在小曲度的时候效果对图形的扭曲效果很不错,也减少了更多的三角形;
  3.  但是后来某些角度下,直接连接上一个矩形的右边顶点会导致过度扭曲,所以最终还是在大转折处绘制了圆形,不过经过一番思考,改成了画半圆减少计算;


连接处相关的代码:
let a = [lt, lb, rt, rb];
if (lastA) {

const ang = dir.signAngle(oldPre.sub(p_pre))
if (Math.abs(ang) < Math.PI / 5 * 3.5) {
startIndex = vs.x.length;

//圆心坐标
vs.x.push(p_pre.x);
vs.y.push(p_pre.y * -1);
len += h / 2;//半圆宽度延续
vs.nu.push(len / h);
vs.nv.push(0.5);

this.pg.circle(p_pre.x, p_pre.y, 2);


const dir_angle = dir.signAngle(cc.v2(-1, 0));
const firstP = lt.sub(p_pre);

const count = 6;
let tempP = cc.v2();


for (let j = 0; j <= count; j++) {
const r = Math.PI / count * j;
const cp = firstP.rotate(r);//这里与原作者使用的cos sin计算旋转的方向不太一样,注意踩坑
cp.add(p_pre, tempP);
vs.x.push(tempP.x);
vs.y.push(tempP.y * -1);//这里乘以-1可以不用在编辑器设置节点的ScaleY
this.pg.circle(tempP.x, tempP.y, 1);

//下面的uv计算其实有更加直观明了的方法,懂的留下评论,最佳答案会发红包
cp.rotate(dir_angle, tempP)
vs.nu.push(len / h - tempP.x / h);
vs.nv.push(tempP.y / h + 0.5);



if (j == count) break;
vs.triangles.push(startIndex, startIndex + j + 1, startIndex + j + 2)
}
} else {
a[0] = lastA[2];
a[1] = lastA[3];
}
}
lastA = a;

额外心得

性能挑战

前文说过,自由绘制会导致绘制的顶点与三角形数过多, cpu也会多一些计算,所以效率会很低;

解决方式有2个:
  1. 已经绘制并且不再改变的路径点可以跳过,减少重复计算;
  2. 绘制的时候控制一下采样率,2个点之间不足指定距离,就直接跳过,这样可以减少最终的三角形面数,以及绘制频率;

在线演示:

所以图形学入门之后,去实现一下这位作者的一些文章是很有必要的,有助于加深对一些常用图形学与几何相关函数的理解与记忆;


看到这里,相信你一定或多或少有点儿收获,站长会持续关注图形学大佬,同时本站公众号也会推荐更多大佬公众号给大家, 同时推送更多创新技术干货给大家;

这里是前文提到的纹理画线作者大佬公众号名称:白玉无冰 ,大家直接在微信搜索就可以了;

这是本站公众号: