在 Cocos Creator 中自定义渲染 cc.Graphics

COCOS

共 6622字,需浏览 14分钟

 ·

2021-08-26 17:02

引言:

GT 是我们的 Cocos Star Writer,长期活跃于社区,最近输出了许多与 Shader 有关的内容,后续他还会为我们带来 SDF 方面的分享。


一直好奇 Cocos Creator cc.Graphics 组件是如何渲染的,打开 cc.Graphics 默认的 shader 看了下,好家伙原来 cc.GraphicsSDF 有很紧密的联系。


本文简单介绍下利用 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(-2131113823624675);
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处理看不出效果,所以用 absv_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.50.50.5);
    vec3 amp = vec3(1.1.1.);
    vec3 freq = vec3(1.1.1.);
    vec3 phase = vec3(0.0.33330.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个团队,被选中的团队将以短信形式通知。


点击【阅读原文】报名吧,期待你的加入!


往期精彩


浏览 61
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报