[很快啊-就问你6不6] cocos2d-x 入侵 Creator 插件系统 - 6

最后一篇文章,终于来了,这里先回顾下前面的文章:

[就问你6不6] cocos2dx 入侵 Creator 插件系统 - 0

[就问你6不6] cocos2dx 入侵 Creator 插件系统 - 1

[就问你6不6] cocos2dx 入侵 Creator 插件系统 - 2

[就问你6不6] cocos2dx 入侵 Creator 插件系统 - 3

[就问你6不6] cocos2dx 入侵 Creator 插件系统 - 4

[就问你6不6] creator 入侵 Creator 插件系统 - 5

不知不觉已经是系列结尾了。其实当初开始研究这些东西的初衷,是想要寻找,把自己做的一个还没有完成的编辑器,移植到 creator 中的可能性: 分享一下最近业余时间在做的一个库 SSRShaderFX

帖子里很多视频都已经失效了,这里重传一下B站,有兴趣的可以看下:

ssr_shaderfx_editor_making_fire

ssr_shaderfx_editor_import_fx

ssr_shaderfx_gallery

ssr_shaderfx_editor_displacement_uv

ssr_shaderfx_editor_beam

ssr_shaderfx_editor_making_fire

ssr_shaderfx_editor_live_preview

这个编辑器在做的时候已经是 cocos2d-x v3.1xCreator v1.x 的时期了。那时候 Creator 还不成熟更别提插件系统了。因此我选择了继续最熟悉的 cocos2d-x

之前的编辑器其实已经实现了很多的功能:

  • shader 完全的组件化
  • 多纹理支持
  • UV 动画支持
  • 优化树
  • 多通道输出支持
  • 连接线优化
  • 网格系统
  • 多选,移动
  • 场景移动,缩放
  • 快捷键系统
  • 弹出菜单
  • 场景导出 / 导入 / 恢复
  • 所有组件特效以及导出数据格式都使用 json
  • 游戏中导入 shader 特效直接使用 (json)
  • 文件另存对话框
  • 更多的内置 shader 组件
  • RGBA 输出支持实时预览
  • uniforms 面板支持收起展开
  • fx 组件面板支持信息说明
  • uniform 数字类型输入控件
  • 实时 shader 代码预览
  • shader + leancloud 云存储
  • shader + shadershop 实验
  • cocos2dx 全渲染类型 shader 支持解决方案
  • cc.Action 支持,实现 uniform 动画

想要移植到 creator 中,当初考虑过很多选择:

  • 方案1: 用插件系统做,选择如 react-diagram 优秀的控件来支持开发

但是 creator 的插件系统其实还不很成熟,再加上自己对 vuereact 几乎没什么掌握,已经前端匮乏的只是,这个难度实在不小。

  • 方案2: 用插件系统做,用 cocos2dx 入侵插件系统,优点是之前所做的工作能够最大程度的重用,缺点是不确定因素大,而且难度也很大。

  • 方案3: 用插件系统做,用 creator 入侵插件系统,好处是,自己入侵自己,不会排异,但是具体怎么做,没什么进一步的想法。

  • 方案4: 不用插件系统,直接在场景编辑器中想办法实现,加一些 gizmo。好处是一些节点的移动,框选,都是现成的,但是具体做起来,也肯定是困难重重。

而且我所追求的解决方案,是尽最大可能的,不对引擎做任何修改,通过引擎自身提供的功能模块,来实现我想要的所有功能。

这次的系列,主要就是针对方案2,3进行了研究。当然结果表明,自己还是对 cocos2dx 最为熟悉,虽然过程有很多难点,但是也一路都解决了。比较好的做到了 cocos2dx 入侵后。


虽然大致有了解决方案,不过也一直放着没有动手,因为还有一个问题没有解决,就是对于任意一个 shader 效果,怎么才能做到 cocos2dx 中实现的,对所有渲染对象都能同样的支持,无论是合图与否,还是静态图,帧动画,骨骼动画,UI控件

最近在研究 FBO 相关插件的时候,也顺利的找到了比较满意的解决方案: [cc.RenderTexture cc.Camera FBO] 截图, 放大镜, Shader 伴侣


到这里还是不够,想要做到以前编辑器的效果,必须做到能够在运行时,动态的修改 shader 的任意内容,并且实时的作用于渲染节点。

creator 中对这一块的自由度或者说是实现方式自然是很有别于 cocos2dx 的,所以也很难搞定。不过最近在有一次挑战,细度源码后,终于在不修改源码的基础上,也实现了这个效果,简单来说就是无中生有创造一个可以实际应用的 cc.Material


既然万事俱备了,那就开搞试试,周末小试了一下,很快啊,我没躲,刚正面,还是比较顺利的做出了个不错的效果:

shaderfx_cc_ccc

而且这种入侵还有一种好处,编辑器项目可以保持完全独立,在 web 直接运行,调试。也可以在无缝衔接,加载到 creator 的插件系统中。这对熟悉 cocos2dx 开发的我来说很是方便。

shaderfx_cc_ccc_debug


虽然小问题还是有不少,不过我想要的效果基本达到了,一些交互上的难点也都被一一解决了。

希望这一篇系列结束的文章,能是又一个新的起点。

15赞

666 ----

就问大佬的插件什么时候可以买

界面真好看

这个厉害了!!!

能坚持下来已经很不错了

期待大神的作品已經好幾年了 (( 跪

做 shader 的调试实在是麻烦,不能断点,不能打印输出,今天花了点时间,找了个偏门,在 shader 里面做输出打印,只是输出到渲染的纹理上。

这样就可以在 shader 里面输出一些变量,比如:

void main () {
    vec4 printfResult = ssr_print_vec2(u_resolution);
    vec4 c = texture2D(texture, v_uv0);
    gl_FragColor = c + printfResult;
}

顺便加强了下功能,现在可以打印字符,各种类型,还能定义颜色,字号,自动换行, 有时候对调试还是很有帮助的,后面有时候调试可以用用。

有兴趣的可以参考这个:

https://www.shadertoy.com/view/Mt2GWD

2赞

估计是有生之年了~~~ 要是年轻的时候还能通宵奋战,现在肝不动了 :zzz:

哈哈哈,那我继续肝~

2020-12-09T16:00:00Z

不愧是SSR :tea:

666终于等到了

楼主牛掰。。。

昨天试了下在 shader 把一些打印信息输出到纹理,实现简单的调试。
但是今天实际用了下,还是不够劲。最完美的解决方案肯定是能像调试 js 一样,才是最棒的。
于是想到了用 cpu 方式 gpu 方式来渲染 shader,这样就能实时断点调试了。
于是简单试了下。

比如这样:

上面是正常的 sprite,下面左侧是使用了简单模糊算法的 sprite,代码大致是:

void main () {
     vec2 uv = v_uv0;
     vec4 sum = vec4(0);
     vec2 offset = vec2(0.0);
     offset = u_normResolution * vec2(-1.0, -1.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(0.0, -1.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(1.0, -1.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(-1.0, 0.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(0.0, 0.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(1.0, 0.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(-1.0, 1.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(0.0, 1.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     offset = u_normResolution * vec2(1.0, 1.0) * u_intensity;
     sum += texture2D(texture, uv + offset) * v_color;
     gl_FragColor = vec4((sum / 9.0).rgb, texture2D(texture, uv).a);
}

很常见的算法。

右边的 sprite 一样是模糊 shader ,一样的算法,几乎一样的源码:

main: function(v_uv0) {
    let gl_FragColor = this.texture2D(this.texture, v_uv0);     
    let u_intensity = 4.0;
    let v_color = this.cpu.color;
    let sum = cc.v4(0);
    let offset = cc.v2(0.0);
    offset = cc.v2(-1.0 * u_intensity, -1.0 * u_intensity);
    let temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(0.0 * u_intensity, -1.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(1.0 * u_intensity, -1.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(-1.0 * u_intensity, 0.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(0.0 * u_intensity, 0.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(1.0 * u_intensity, 0.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(-1.0 * u_intensity, 1.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(0.0 * u_intensity, 1.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    offset = cc.v2(1.0 * u_intensity, 1.0 * u_intensity);
    temp = this.texture2D(this.texture, v_uv0.add(offset));
    sum.x += temp.r; sum.y += temp.g; sum.z += temp.b;
    gl_FragColor = cc.color(sum.x / 9.0, sum.y / 9.0, sum.z / 9.0, this.texture2D(this.texture, v_uv0).a);
    return gl_FragColor;
}

只是这是 cpu 渲染的,是 js 的代码,所以自然可以随意断点,随意调试。

eeeee.gif 22-51-45-908

现在代码还比较随意。如果可以写个好一点的解析器,把 shader 的语法自然的转到 js,那么可用性就会更好一点,毕竟可以随意断点调试 shader。当然还会有不少要处理的细节问题。

不过也算是个不错的解决方案。

3赞