前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >这5毛特效,做得牛了,好评!

这5毛特效,做得牛了,好评!

作者头像
张晓衡
发布2021-09-18 12:40:00
5480
发布2021-09-18 12:40:00
举报

没想到Graphics组件也能被玩出花来,先看看效果!

链接:https://store.cocos.com/app/detail/3199

不仅授人以鱼,还有授人以渔!下面是GT大佬对cc.Graphics组件自定义渲染Demo的详解。

背景

一直好奇 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(-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处理看不出效果,所以用absv_dist变成正数输出。 v_dist上一篇提到的SDF是同类数据,在这里表示当前片元到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://forum.cocos.org/t/topic/119268

[线上Demo体验地址]

https://caogtaa.gitee.io/ccdemos/?scene=SceneGraphics

Demo 中还有更多基于cc.Graphics的 Shader 效果,包括 Mesh 可视化外发光伪3D,留给下次详细介绍

。欢迎来论坛留言讨论!

更多精彩,请关注GT大佬公众号

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Creator星球游戏开发社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 看看shader
  • 改改 Shader
    • 从纹理文件采样
      • 从程序纹理(色板)采样
      • Demo和源码
        • [线上Demo体验地址]
          • https://caogtaa.gitee.io/ccdemos/?scene=SceneGraphics
            • Demo 中还有更多基于cc.Graphics的 Shader 效果,包括 Mesh 可视化、外发光、伪3D,留给下次详细介绍
            相关产品与服务
            对象存储
            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档