Cocos Creator Shader入门实战(七):RGB不同算法效果的实现,及渲染技术、宏定义、属性参数的延伸配置

news2025/4/3 1:07:11

引擎:3.8.5

您好,我是鹤九日!



回顾


上篇文章,讲解了Cocos Shader如何通过setProperty动态设置材质的属性,以及设置属性时候的一些注意事项,比如:

一、CCEffect部分properties参数的设定后,需要在片段着色器部分以结构体声明下

二、材质的获取,主要有两种方式:

  1. 通过customMateiral获取资源的材质实例

  2. 通过getSharedMaterial获取资源的共享材质

更多详情,可参考:

Cocos Creator Shader入门实战(六):使用setProperty动态设置材质属性,以及材质常用接口



资料


文章讲解到此处,相信您对Cocos Shader入门有了一定程度的了解。

因个人能力水平有限,所编写的内容可能有失偏颇,对您的学习造成不必要的困扰,这里请谅解。

Shader是门不好学的技术,牵扯的东西实在是太多了。

这里提供一些不错的学习资料或工具,希望对成长中的您有所帮助:

The Book of shaders 片段着色器的入门指南

Learn OpenGL 中文版 讲解Open GL的学习使用

CocosCreatorShader 木限东的Shader效果实现实例,这里感谢作者的公开分享。

慎入!史上最强 Cocos Shader 学习资源推荐(建议收藏) Cocos官方推荐的学习资源

Shadertoy教程 Shader在线工具的教程

Shadertoy Tool Shadertoy 在线工具模拟

注:其他的优秀资料有很多,这里就不在一一罗列了;这里再次表示感谢!



前言


抛开Open GL、Cocos引擎约定俗成的规则,将Shader的使用简单理解,其实就三步:

一、构建EffectAsset资源,设定渲染参数、着色器代码片段

二、构建Material材质资源,对EffectAsset进行数据封装,构建渲染的资源实例

三、通过引擎提供的接口setProperty,动态传递参数

这些,就是Cocos Shader 实现的基础流程。

我相信:您对Shader的理论有所了解的,理是这个理儿,但真正的用起来则是另一码事。

今天的内容,我们将RGB灰度渲染的效果进行拓展,通过不同的RGB公式实现更多的效果。

希望本篇文章能够给您带来帮助。



灰度渲染


RGB灰度渲染,算是Shader中实现的基础渲染效果了。

之前文章中提及过: Sprite组件的Grayscale的实现就是灰度渲染。

依然以builtin-sprite.effect为例:

注:后续的文章不再粘贴CCEffect和CCProgram的参数配置和代码了,只罗列关键部分

// builtin-sprite.effect 片段着色器部分
// 方式1: 加权平均值
float gray  = 0.2126 * o.r + 0.7152 * o.g + 0.0722 * o.b;
o.r = o.g = o.b = gray;

除了官方提供的以外,另外有两种方式:

vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);
    o *= CCSampleWithAlphaSeparated(cc_spriteTexture, v_uv0);

    // 方式1: 取三种颜色的平均值
    // float gray = (o.r + o.g + o.b)/3.0;
    // o = vec4(gray, gray, gray, o.a);

    // 方式2: 取三种颜色的最大值(最小值)
    // float gray = max(max(o.r, o.g), o.b);
    // o = vec4(gray, gray, gray, o.a);

    // 方式3: 加权平均值
    float gray  = 0.2126 * o.r + 0.7152 * o.g + 0.0722 * o.b;
    o.r = o.g = o.b = gray;
    
    return o;
  }

注: 可自行实现下效果,这里不再贴图展示了。



其他RGB渲染


通过不同的RGB计算公式,除了灰度渲染以外,可以实现很多的效果。先上示意图:

请添加图片描述

每个Sprite组件对应一个材质实例,一个Effect资源配置。资源的渲染参数配置、顶点着色器都是相同的。

随意罗列一个效果代码的实现:

// 暖色调增强
CCProgram sprite-fs %{
  // ...
  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);
    o *= CCSampleWithAlphaSeparated(cc_spriteTexture, v_uv0);

    // 暖色调增强
    o.r = o.r * 1.2;
    o.g = o.g * 1.1;
    o.b = o.b * 0.8;
    o = clamp(o, 0.0, 1.0);
    
    return o;
  }
}%

其他代码的核心逻辑如下:

冷色调增强

o.r = o.r * 0.8;
o.g = o.g * 0.9;
o.b = o.b * 1.2;
o = clamp(o, 0.0, 1.0);

老照片

float _r = o.r * 0.393 + o.g * 0.769 + o.b * 0.189;
float _g = o.r * 0.349 + o.g * 0.686 + o.b * 0.168;
float _b = o.r * 0.272 + o.g * 0.534 + o.b * 0.131;
o = vec4(_r, _g, _b, o.a);

卡通效果

float r = abs(o.g - o.b + o.g + o.r) * o.r;
float g = abs(o.b - o.g + o.b + o.r) * o.r;
float b = abs(o.b - o.g + o.b + o.r) * o.g;
o = vec4(r, g, b, o.a);

冰冻效果

float r = abs(o.r - o.g - o.b) * 1.5;
float g = abs(o.g - o.b - o.r) * 1.5;
float b = abs(o.b - o.r - o.g) * 1.5;
o = vec4(r, g, b, o.a);

赛博朋克

float neon = max(o.r, o.g);
o.r = neon * 1.2;
o.g = neon * 1.5;
o.b = o.b * 0.5;
o.a *= 1.1;
o = clamp(o, 0.0, 1.0);

复古胶片

float _r = o.r * 0.9 + o.g * 0.1;
float _g = o.r * 0.1 + o.g * 0.9 + o.b * 0.1;
float _b = o.b * 0.9 + o.r * 0.1;
o = vec4(_r, _g, _b, o.a);

反相

float _r = 255.0 / 256.0 - o.r;
float _g = 255.0 / 256.0 - o.g;
float _b = 255.0 / 256.0 - o.b;
o = vec4(_r, _g, _b, o.a);

高对比度

float avg = (o.r + o.g + o.b) / 3.0;
o.r = avg < 0.5 ? avg * 0.5 : avg * 1.5;
o.g = avg < 0.5 ? avg * 0.5 : avg * 1.5;
o.b = avg < 0.5 ? avg * 0.5 : avg * 1.5;
o = clamp(o, 0.0, 1.0); // 限制颜色值在0到1之间

如下是编译器的资源配置相关:
请添加图片描述

注:工程资源相关在文末



延伸


上面的编译器资源截图是有用意的,您可能已经猜到了,答案就是:简化和复用

这里,针对于RGB不同效果的实现,我们做下延伸,主要有如下几个方面:

一、Chunk封装顶点着色器

二、CCEffect渲染技术的拓展使用

三、预处理宏定义的使用

四、properties属性参数的配置


Chunks的封装

Chunks是Cocos引擎提供的封装,简单理解就是include的引用,我们将顶点着色的片段代码提取为Chunk。

然后在CCEffect顶点着色器入口部分,添加入口的引用即可。

简单的示例:

CCEffect %{
  techniques:
  - passes:
    - vert: ../resources/common/sprite-vs:vert
      frag: sprite-fs:frag

注:之前的博客提及过,可参考:入门实战(四):预处理宏定义和Chunk 中关于Chunk的说明。


CCEffect渲染技术

Cocos引擎针对于CCEffect的参数配置,设定了渲染技术Technique。

它的特点是:

一、渲染技术支持设定多个,但实际的运行只有一个。

二、渲染技术中的每个Pass渲染过程,必须带有顶点着色器和片段着色器的入口。

引擎针对于CCEffect参数配置,使用的是YAML,它有一大特性便是支持引用和继承。

因此我们的配置,可以是这样:

  • CCEffect部分:
​​CCEffect %{
  techniques:
  # 灰度
  - name: normal
    passes:
    # 顶点着色器引用通用的Chunk片段
    - vert: ../resources/common/sprite-vs:vert
      frag: normal-fs:frag
      # 深度、模板测试
      depthStencilState: &depthStencil
        depthTest: false
        depthWrite: false
      # 混合模式
      blendState: &blend
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendDstAlpha: one_minus_src_alpha
      # 光栅化状态
      rasterizerState: &rasterizer
        cullMode: none
      properties: &property
        alphaThreshold: { value: 0.5 }
  # 老照片
  - name: brown
    passes:
    - vert: ../resources/common/sprite-vs:vert
      frag: brown-fs:frag
      # 可选参数引用normal部分
      depthStencilState: *depthStencil
      blendState: *blend
      rasterizerState: *rasterizer
      properties: *property

注: YAML的引用和继承结构:

引用:&name*name

继承:&name<<: *name

  • 顶点片段着色器部分逻辑:
// 老照片
CCProgram brown-fs %{
  // ...
  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);
    o *= CCSampleWithAlphaSeparated(cc_spriteTexture, v_uv0);

    float _r = o.r * 0.393 + o.g * 0.769 + o.b * 0.189;
    float _g = o.r * 0.349 + o.g * 0.686 + o.b * 0.168;
    float _b = o.r * 0.272 + o.g * 0.534 + o.b * 0.131;
    o = vec4(_r, _g, _b, o.a);
    
    return o;
  }
}%

设定以后,我们便可以通过Material材质属性检查器,选择不同的渲染技术来查看效果了。

请添加图片描述

注:渲染技术的设定,除非是iMaterialInfo初始化,其他不支持运行过程中代码的动态改变。


宏定义

预处理宏定义不仅仅是引擎设定的规则,也是OpenGL的规则之一。

它的主要优点有:

一、不同的预处理开关生成不同组合的代码,实现不同效果

二、避免代码冗余,执行高效

三、属性检查器的宏定义开关,可以更好的控制可视化显示和调试效果。

由于RGB的渲染效果种类有很多,我们这里采用宏定义的范围参数来设定,结构如下:

// 通过range([min, max])设定连续数字的宏定义
#pragma define-meta FACTOR range([-5, 5])
// 通过options([...]) 设定指定数字的宏定义
#pragma define-meta FACTOR options([-3, -2, 5])

这里我们需要在片段着色器部分添加如下逻辑:

注:CCEffect配置采用通用部分即可,无须多个渲染技术了

CCProgram sprite-fs %{
  // ...
  #pragma define-mate FILTER_TYPE range([0, 4]);

  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);
    o *= CCSampleWithAlphaSeparated(cc_spriteTexture, v_uv0);

    #if FILTER_TYPE == 1
      // 老照片效果
      float _r = o.r * 0.393 + o.g * 0.769 + o.b * 0.189;
      float _g = o.r * 0.349 + o.g * 0.686 + o.b * 0.168;
      float _b = o.r * 0.272 + o.g * 0.534 + o.b * 0.131;
      o = vec4(_r, _g, _b, o.a);
    #elif FILTER_TYPE == 2 
       // ...
    #endif
    
    return o;
  }
}%

效果图如下:

请添加图片描述


properties属性参数

属性参数的设定,其着色器逻辑部分同宏定义有些类似。这里我们的主要配置如下:

  • CCEffect部分,配置定义属性参数:
properties:
    alphaThreshold: { value: 0.5 }
    filter_type: {value: 1.0, editor: {tooltip: "RGB类型"}}
  • 片段着色器部分,主要逻辑如下:
CCProgram sprite-fs %{
  // ...
  // 引擎规定,不允许离散使用Uniform
  // ARGS为任意命名
  // 设定以后,引擎会自动将ARGS内的参数与properties的属性相关联
  uniform ARGS {
    int filter_type;
  };

  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);
    o *= CCSampleWithAlphaSeparated(cc_spriteTexture, v_uv0);

    if (filter_type == 1) {
      // 老照片效果
      float _r = o.r * 0.393 + o.g * 0.769 + o.b * 0.189;
      float _g = o.r * 0.349 + o.g * 0.686 + o.b * 0.168;
      float _b = o.r * 0.272 + o.g * 0.534 + o.b * 0.131;
      o = vec4(_r, _g, _b, o.a);
    } else if (filter_type == 2) {
      // ...
    }

    return o;
  }
}%
  • 属性检查器中,我们便可以直接通过不同参数来预览效果了。

请添加图片描述



总结


延伸部分的例子,可能并不是太恰当,但对于新手而言,了解渲染技术、宏定义以及属性参数是很有益处的。

Demo的示例,可从个人Gitee获取: CocosShaderDemo

今天的文章,到这里就结束了,这里对于一些热心大佬的网络分享表示感谢!

可能理解有误,欢迎您的指出,如果觉得文章不错,期待您的点赞和留言,感谢!

我是鹤九日,祝您生活愉快!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法学习记录:递归

递归算法的关键在于回复现场&#xff0c;dfs&#xff08;&#xff09;函数返回值、结束条件、它的作用。 目录 1.综合练习 2. 二叉树的深搜 1.综合练习 39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; 关键在画出的决策树当中&#xff0c;前面使用过的2、3&#xff0c;…

可发1区的超级创新思路(python\matlab实现):MPTS+Lconv+注意力集成机制的Transformer时间序列模型

首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 应用场景 该模型主要用于时间序列数据预测问题,包含功率预测、电池寿命预测、电机故障检测等等。 一、模型整体架构(本文以光伏功率预测为例) 本模型由多尺度特征提取模块(MPTS)…

三、分类模块,通用组件顶部导航栏Navbar

1.封装通用组件顶部导航栏Navbar 不同效果 Component export struct MkNavbar {Prop title: string Prop leftIcon: ResourceStr $r("app.media.ic_public_left")ProprightIcon: ResourceStr $r("app.media.ic_public_more")PropshowLeftIcon: boolean…

PHY——LAN8720A 寄存器读写 (二)

文章目录 PHY——LAN8720A 寄存器读写 (二)工程配置引脚初始化代码以太网初始化代码PHY 接口实现LAN8720 接口实现PHY 接口测试 PHY——LAN8720A 寄存器读写 (二) 工程配置 这里以野火电子的 F429 开发板为例&#xff0c;配置以太网外设 这里有一点需要注意原理图 RMII_TXD0…

Flutter_学习记录_AppBar中取消leading的占位展示

将leading设置为null将automaticallyImplyLeading设置为false 看看automaticallyImplyLeading的说明&#xff1a; Controls whether we should try to imply the leading widget if null. If true and [AppBar.leading] is null, automatically try to deduce what the leading…

未来派几何风格包装徽标品牌海报标牌logo设计无衬线英文字体安装包 Myfonts – Trakya Sans Font Family

Trakya Sans 是一种具有几何风格的现代无衬线字体。Futura、Avant Garde 等。它具有现代条纹&#xff0c;这是宽度和高度协调的结果&#xff0c;尤其是在小写字母中&#xff0c;以支持易读性。 非常适合广告和包装、编辑和出版、徽标、品牌和创意产业、海报和广告牌、小文本、寻…

C语言深度解析:从零到系统级开发的完整指南

一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性&#xff0c;成为系统级开发的首选语言。例如&#xff0c;Linux内核通过C语言直接操作内存和硬件寄存器&#xff0c;实现高效进程调度。 关键点&#xff1a; malloc/free直接管理内存&#…

ctfshow WEB web8

首先确定注入点&#xff0c;输入以下payload使SQL恒成立 ?id-1/**/or/**/true 再输入一下payload 使SQL恒不成立 ?id-1/**/or/**/false 由于SQL恒不成立, 数据库查询不到任何数据, 从而导致页面空显示 由以上返回结果可知&#xff0c;该页面存在SQL注入&#xff0c;注入点…

【Linux】U-Boot 加载并启动 Linux 系统程序

U-Boot 加载并启动 Linux 系统程序 零、介绍 最近在玩一些嵌入式的开发板&#xff0c;在引导操作系统时需要用到U-Boot&#xff0c;故此研究一下。 U-Boot&#xff08;Universal Bootloader&#xff09;是一款开源的通用引导加载程序&#xff0c;专为嵌入式系统设计&#xff…

jarvisoj API调用 [JSON格式变XXE]

http://web.jarvisoj.com:9882/ 题目要求&#xff1a;请设法获得目标机器 /home/ctf/flag.txt 中的flag值 抓包得到&#xff1a; POST /api/v1.0/try HTTP/1.1 Host: web.jarvisoj.com:9882 Content-Length: 36 Accept-Language: zh-CN,zh;q0.9 User-Agent: Mozilla/5.0 (W…

机器学习的一百个概念(4)下采样

前言 本文隶属于专栏《机器学习的一百个概念》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…

NNI 适配 TensorRT10教程

引言 本文涉及两个框架及其版本分别为 NNI (Neural Network Intelligence) &#xff1a;3.0TensorRT&#xff1a;10.9.0.34 NNI 在文档 Speed Up Quantized Model with TensorRT里描述了如何使用 TensorRT 为NNI量化的模型实现加速&#xff0c;但是从NNI 的源代码https://gi…

多路径 TCP 调度的另一面

参考前面的文章 一个原教旨的多路径 TCP 和 MP-BBR 公平性推演&#xff0c;一直都破而不立&#xff0c;不能光说怎样不好&#xff0c;还得说说现状情况下&#xff0c;该如何是好。 如果 receiver 乱序重排的能力有限(拜 TCP 所赐)&#xff0c;如果非要在多路径上传输 TCP&…

vcpkg安装指定版本的库

一.vcpkg安装 使用git将vcpkg源码克隆到本地制定目录&#xff08;D:\vcpkg&#xff09;&#xff0c;并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下图&#xff1a; 二.安…

【工具变量】上市公司供应链稳定性数据两个维度(2013-2023年)

供应链稳定性是指供应链在面对各种内外部因素的冲击和不确定性时&#xff0c;能够保持持续、顺畅运作的能力&#xff0c;而供应链稳定性指数是用于评估企业在其供应链管理中保持稳定性的一个重要指标。本分享数据参考钟涛&#xff08;2022&#xff09;、董浩和闫晴&#xff08;…

Redis场景问题2:缓存击穿

Redis 缓存击穿是指在缓存系统中&#xff0c;大量请求&#xff08;高并发访问&#xff09;同时访问一个不存在于缓存中&#xff08;一般是因为缓存过期或者数据未被加载到缓存&#xff09;但在数据库中存在的热点数据&#xff0c;从而导致这些请求直接穿透缓存层&#xff0c;涌…

RocketMQ - 从消息可靠传输谈高可用

先稍微介绍下RocketMQ架构。 主从架构 Broker 集群&#xff1a;每个 Broker 分为 Master 和 Slave 角色&#xff0c;Master 负责读写&#xff0c;Slave 作为热备。 同步复制&#xff08;SYNC_MASTER&#xff09;&#xff1a;消息写入 Master 后&#xff0c;需等待 Slave 同步完…

ES拼音分词自动补全实现

#测试拼音分词 POST /_analyze { "text":"如家酒店真不错", "analyzer": "pinyin" } #这里把拼音的首字母放到这里&#xff0c;也说明了这句话没有被分词&#xff0c;而是作为一个整体出现的 #还把每一个字都形成了一个拼音&#…

EFISH-SBC-RK3576 + 5G模组:无线工业相机与分布式AI质检‌

在智能制造与仓储物流场景中&#xff0c;传统有线工业相机存在部署成本高、灵活性差等痛点。‌eFish-SBC-RK3576‌ 通过 ‌5G无线传输 分布式NPU协同‌&#xff0c;实现跨产线、跨工厂的AI质检系统&#xff0c;检测效率提升300%&#xff0c;布线复杂度降低90%。 ‌1. 系统架构…

C/C++ 基础 - 回调函数

目录 前言 回调函数预备知识 函数指针 什么是函数指针 函数指针的语法 如何用函数指针调用函数 函数指针作为函数的参数 函数指针作为函数返回类型 函数指针数组 回调函数 什么是回调函数 为什么要用回调函数 怎么使用回调函数 总结 前言 在写项目的时候&#x…