在 Cocos Creator 中自定义渲染 cc.Graphics
共 6622字,需浏览 14分钟
·
2021-08-26 17:02
引言:
GT 是我们的 Cocos Star Writer,长期活跃于社区,最近输出了许多与 Shader 有关的内容,后续他还会为我们带来 SDF 方面的分享。
一直好奇 Cocos Creator cc.Graphics
组件是如何渲染的,打开 cc.Graphics
默认的 shader 看了下,好家伙原来 cc.Graphics
和 SDF
有很紧密的联系。
本文简单介绍下利用 SDF
信息自定义渲染 cc.Graphics
的一般方法,附上几个例子。本文所有内容基于 Cocos Creator 2.4.2。
看看 shader
cc.Graphics
默认的 shader 在下面位置(根据引擎安装位置和版本有所不同)
C:\CocosDashboard_1.0.12\resources.editors\Creator\2.4.2\resources\static\default-assets\resources\effects\builtin-2d-graphics.effect
片元着色器代码如下,笔者加了些注释帮助理解:
void main () {
vec4 o = v_color;
// alpha测试,这里不用管
ALPHA_TEST(o);
// 计算AA(反走样)距离,如果平台支持fwidth就尽量用,AA更加准确
#if CC_SUPPORT_standard_derivatives
float aa = fwidth(v_dist);
#else
float aa = 0.05;
#endif
// 在v_dist = 1或者-1附近进行AA处理
float alpha = 1. - smoothstep(-aa, 0., abs(v_dist) - 1.0);
o.rgb *= o.a;
o *= alpha;
gl_FragColor = o;
}
可以看到 shader 除了做 AA,几乎啥也没干,但是 v_dist
是干什么用的?
先用 cc.Graphics
画一个简单图形,把 v_dist
的内容输出看一下:
// 用cc.Graphics画一条Bezier曲线
graphics.strokeColor = cc.Color.WHITE;
graphics.lineWidth = 40;
graphics.moveTo(-212, -139);
graphics.bezierCurveTo(-213, 111, 38, 236, 246, 75);
graphics.stroke();
// 修改graphics默认shader代码
void main () {
// v_dist作为颜色值输出(取绝对值避免负数不显示)
gl_FragColor = vec4(abs(v_dist));
return;
}
右图 abs(v_dist)
中间黑(值是0),两边白(值是1),实际上 v_dist
的值范围是[-1, 1]。输出负数会被当0处理看不出效果,所以用 abs
将 v_dist
变成正数输出。
v_dist
在这里表示当前片元到 graphcis 中线的距离,1或-1表示最边缘,0表示在中线上。
改改 shader
从纹理文件采样
和普通的 cc.Sprite
不同,cc.Graphics
没有组装 UV 信息传到 shader。可以将 v_dist
从[-1, 1]映射到[0, 1]区间,然后直接在纹理上采样。
下面的代码大部分和原始 shader 相同,增加了 texture 变量和采样过程。
// 增加纹理uniform变量
uniform sampler2D texture;
void main () {
vec4 o = v_color;
ALPHA_TEST(o);
#if CC_SUPPORT_standard_derivatives
float aa = fwidth(v_dist);
#else
float aa = 0.05;
#endif
float alpha = smoothstep(aa, -aa, abs(v_dist) - 1.0);
// 将v_dist值从[-1, 1]区间映射到[0, 1]
float D = v_dist * 0.5 + 0.5;
// 采样纹理
o = texture2D(texture, vec2(D, 0.5));
o.rgb *= alpha;
gl_FragColor = o;
}
从程序纹理(色板)采样
和纹理文件采样的思路一样,都是将 v_dist
映射到某个颜色。
这里我们提供一个调色板函数实现这个映射,函数内部可以实现任何自己想要的渐变色。
// 一个彩虹色的色板,输入t的范围是[0, 1], 输出一个颜色值
vec3 Pallete(float t) {
// 滚动动起来
t += cc_time.x;
vec3 dcOffset = vec3(0.5, 0.5, 0.5);
vec3 amp = vec3(1., 1., 1.);
vec3 freq = vec3(1., 1., 1.);
vec3 phase = vec3(0., 0.3333, 0.6666);
return dcOffset + amp * cos(2. * 3.14159 * (freq * t + phase));
}
void main () {
// ...其他都一样
// 用一个Pallete函数完成映射,函数背后可以是采样,或者其他静态、动态纹理
// o = texture2D(texture, vec2(D, 0.5));
o.rgb = Pallete(D);
// ...其他都一样
}
顺便推荐一个在线渐变色配色网站:
http://dev.thi.ng/gradients/
上面代码中的色板系数从该网站获得。
Demo 和源码
• 代码:
https://github.com/caogtaa/CCTricks/tree/master/assets/Demo/Graphics
• 论坛讨论帖:
https://forum.cocos.org/t/topic/119268
• Demo 体验地址:
https://github.com/caogtaa/CCTricks/tree/master/assets/Demo/Graphics
>>左右滑动查看更多
Demo 中还有更多基于 cc.Graphics
的 shader 效果,包括 Mesh 可视化、外发光、伪 3D,留给下次详细介绍。欢迎在论坛留言讨论。
「Cocos 开发者沙龙」深圳站,将于9月4日下午14:00正式举行!
Cocos 引擎技术总监 Panda 将详解 Cocos Creator 3.3 最新技术突破与功能革新,更有腾讯光子高级工程师宝爷、亚马逊云科技资深解决方案架构师王泽耀、TradPlus 运营总监 Joyce、华为海思麒麟 GPU 团队资深工程师刘月、腾讯开心鼠、腾讯在线教育部终端开发工程师敖显厅重磅加盟,为大家带来一系列干货分享。
此外,本次依然开放「现场一对一技术支持」,限额 5 个团队。Cocos 引擎团队核心成员将全程驻场,你可以携带自己的作品和问题同他们进行一对一技术交流,名额有限,赶快扫描下方二维码报名吧!
>>一对一技术支持报名通道。我们将抽选5个团队,被选中的团队将以短信形式通知。
点击【阅读原文】报名吧,期待你的加入!
往期精彩