Cocos Creator Shader入门实战(七):RGB不同算法效果的实现,及渲染技术、宏定义、属性参数的延伸配置
引擎:3.8.5
您好,我是鹤九日!
回顾
上篇文章,讲解了Cocos Shader如何通过setProperty动态设置材质的属性,以及设置属性时候的一些注意事项,比如:
一、CCEffect部分properties参数的设定后,需要在片段着色器部分以结构体声明下
二、材质的获取,主要有两种方式:
-
通过
customMateiral获取资源的材质实例 -
通过
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:vertfrag: sprite-fs:frag
注:之前的博客提及过,可参考:入门实战(四):预处理宏定义和Chunk 中关于Chunk的说明。
CCEffect渲染技术
Cocos引擎针对于CCEffect的参数配置,设定了渲染技术Technique。
它的特点是:
一、渲染技术支持设定多个,但实际的运行只有一个。
二、渲染技术中的每个Pass渲染过程,必须带有顶点着色器和片段着色器的入口。
引擎针对于CCEffect参数配置,使用的是YAML,它有一大特性便是支持引用和继承。
因此我们的配置,可以是这样:
- CCEffect部分:
CCEffect %{techniques:# 灰度- name: normalpasses:# 顶点着色器引用通用的Chunk片段- vert: ../resources/common/sprite-vs:vertfrag: normal-fs:frag# 深度、模板测试depthStencilState: &depthStencildepthTest: falsedepthWrite: false# 混合模式blendState: &blendtargets:- blend: trueblendSrc: src_alphablendDst: one_minus_src_alphablendDstAlpha: one_minus_src_alpha# 光栅化状态rasterizerState: &rasterizercullMode: noneproperties: &propertyalphaThreshold: { value: 0.5 }# 老照片- name: brownpasses:- vert: ../resources/common/sprite-vs:vertfrag: brown-fs:frag# 可选参数引用normal部分depthStencilState: *depthStencilblendState: *blendrasterizerState: *rasterizerproperties: *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 // ...#endifreturn 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
今天的文章,到这里就结束了,这里对于一些热心大佬的网络分享表示感谢!
可能理解有误,欢迎您的指出,如果觉得文章不错,期待您的点赞和留言,感谢!
我是鹤九日,祝您生活愉快!
相关文章:
Cocos Creator Shader入门实战(七):RGB不同算法效果的实现,及渲染技术、宏定义、属性参数的延伸配置
引擎:3.8.5 您好,我是鹤九日! 回顾 上篇文章,讲解了Cocos Shader如何通过setProperty动态设置材质的属性,以及设置属性时候的一些注意事项,比如: 一、CCEffect部分properties参数的设定后&…...
leetcode102 二叉树的层次遍历 递归
(1) 找出重复的子问题。 层次遍历是每一层的节点从左到右的遍历,所以在遍历的时候我们可以先遍历左子树,再遍历右子树。 需要注意的是,在遍历左子树或者右子树的时候,涉及到向上或者向下遍历,为了让递归的过程中的同…...
Netty源码—10.Netty工具之时间轮二
大纲 1.什么是时间轮 2.HashedWheelTimer是什么 3.HashedWheelTimer的使用 4.HashedWheelTimer的运行流程 5.HashedWheelTimer的核心字段 6.HashedWheelTimer的构造方法 7.HashedWheelTimer添加任务和执行任务 8.HashedWheelTimer的完整源码 9.HashedWheelTimer的总结…...
算法学习记录:递归
递归算法的关键在于回复现场,dfs()函数返回值、结束条件、它的作用。 目录 1.综合练习 2. 二叉树的深搜 1.综合练习 39. 组合总和 - 力扣(LeetCode) 关键在画出的决策树当中,前面使用过的2、3,…...
启山智软实现b2c单商户商城对比传统单商户的优势在哪里?
启山智软实现 B2C 单商户商城具有以下对比优势: 技术架构方面 先进的框架选型:基于 SpringCloud 等主流框架开发,是百万真实用户沉淀并检验的商城系统,技术成熟稳定,能应对高并发场景,保证系统在大流量访…...
可发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 开发板为例,配置以太网外设 这里有一点需要注意原理图 RMII_TXD0…...
Flutter_学习记录_AppBar中取消leading的占位展示
将leading设置为null将automaticallyImplyLeading设置为false 看看automaticallyImplyLeading的说明: 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…...
PHP泛型与集合的未来:从动态类型到强类型的演进
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
未来派几何风格包装徽标品牌海报标牌logo设计无衬线英文字体安装包 Myfonts – Trakya Sans Font Family
Trakya Sans 是一种具有几何风格的现代无衬线字体。Futura、Avant Garde 等。它具有现代条纹,这是宽度和高度协调的结果,尤其是在小写字母中,以支持易读性。 非常适合广告和包装、编辑和出版、徽标、品牌和创意产业、海报和广告牌、小文本、寻…...
C语言深度解析:从零到系统级开发的完整指南
一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性,成为系统级开发的首选语言。例如,Linux内核通过C语言直接操作内存和硬件寄存器,实现高效进程调度。 关键点: malloc/free直接管理内存&#…...
ctfshow WEB web8
首先确定注入点,输入以下payload使SQL恒成立 ?id-1/**/or/**/true 再输入一下payload 使SQL恒不成立 ?id-1/**/or/**/false 由于SQL恒不成立, 数据库查询不到任何数据, 从而导致页面空显示 由以上返回结果可知,该页面存在SQL注入,注入点…...
【Linux】U-Boot 加载并启动 Linux 系统程序
U-Boot 加载并启动 Linux 系统程序 零、介绍 最近在玩一些嵌入式的开发板,在引导操作系统时需要用到U-Boot,故此研究一下。 U-Boot(Universal Bootloader)是一款开源的通用引导加载程序,专为嵌入式系统设计ÿ…...
jarvisoj API调用 [JSON格式变XXE]
http://web.jarvisoj.com:9882/ 题目要求:请设法获得目标机器 /home/ctf/flag.txt 中的flag值 抓包得到: 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…...
Spring学习笔记07——SpringBoot常用注解记录
一、Lombok 注解 Data:生成所有字段的 getter/setter、toString()、equals() 和 hashCode()。 Getter / Setter:单独为所有字段或指定字段生成 getter/setter。 import lombok.Data;Data public class User {private Long id;private String name; }编…...
深入解析最大公约数(GCD)与最小公倍数(LCM)的C++实现
深入解析最大公约数(GCD)与最小公倍数(LCM)的C实现 一、GCD与LCM的数学定义 1. 最大公约数(GCD) 两个或多个整数共有约数中最大的一个。 例如: GCD(12, 18) 6GCD(21, 14) 7 2. 最小公倍数…...
[Python] 贪心算法简单版
贪心算法-简单版 贪心算法的一般使用场景是给定一个列表ls, 让你在使用最少的数据的情况下达到或超过n. 我们就来使用上面讲到的这个朴素的例题来讲讲贪心算法的基本模板: 2-1.排序 既然要用最少的数据, 我们就要优先用大的数据拼, 为了实现这个效果, 我们得先给列表从大到小…...
机器学习的一百个概念(4)下采样
前言 本文隶属于专栏《机器学习的一百个概念》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…...
NNI 适配 TensorRT10教程
引言 本文涉及两个框架及其版本分别为 NNI (Neural Network Intelligence) :3.0TensorRT:10.9.0.34 NNI 在文档 Speed Up Quantized Model with TensorRT里描述了如何使用 TensorRT 为NNI量化的模型实现加速,但是从NNI 的源代码https://gi…...
Docker, Docker 镜像是什么,怎么创建, Docker有什么用
Docker, Docker 镜像是什么,怎么创建, Docker有什么用 Docker 镜像的概念 Docker 镜像可以理解为一个只读的模板,它包含了运行应用程序所需的所有文件、依赖项、环境变量和配置信息等。就像制作蛋糕的模具,利用这个模具可以制作出多个相同的蛋糕(这里的蛋糕就好比 Dock…...
多路径 TCP 调度的另一面
参考前面的文章 一个原教旨的多路径 TCP 和 MP-BBR 公平性推演,一直都破而不立,不能光说怎样不好,还得说说现状情况下,该如何是好。 如果 receiver 乱序重排的能力有限(拜 TCP 所赐),如果非要在多路径上传输 TCP&…...
vcpkg安装指定版本的库
一.vcpkg安装 使用git将vcpkg源码克隆到本地制定目录(D:\vcpkg),并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下图: 二.安…...
【工具变量】上市公司供应链稳定性数据两个维度(2013-2023年)
供应链稳定性是指供应链在面对各种内外部因素的冲击和不确定性时,能够保持持续、顺畅运作的能力,而供应链稳定性指数是用于评估企业在其供应链管理中保持稳定性的一个重要指标。本分享数据参考钟涛(2022)、董浩和闫晴(…...
Redis场景问题2:缓存击穿
Redis 缓存击穿是指在缓存系统中,大量请求(高并发访问)同时访问一个不存在于缓存中(一般是因为缓存过期或者数据未被加载到缓存)但在数据库中存在的热点数据,从而导致这些请求直接穿透缓存层,涌…...
RocketMQ - 从消息可靠传输谈高可用
先稍微介绍下RocketMQ架构。 主从架构 Broker 集群:每个 Broker 分为 Master 和 Slave 角色,Master 负责读写,Slave 作为热备。 同步复制(SYNC_MASTER):消息写入 Master 后,需等待 Slave 同步完…...
ES拼音分词自动补全实现
#测试拼音分词 POST /_analyze { "text":"如家酒店真不错", "analyzer": "pinyin" } #这里把拼音的首字母放到这里,也说明了这句话没有被分词,而是作为一个整体出现的 #还把每一个字都形成了一个拼音&#…...
golang 日志log与logrus
目录 一、Go 标准库 log 详解 1. 功能特点 2. 常用函数 3. 示例代码 4. 优势和局限 二、第三方库 logrus 详解 1. 功能特点 2. 核心功能 3. 示例代码 4. 优势和扩展性 三、总结 1. 何时选择 log? 2. 何时选择 logrus? 3. 对比总结 一、Go 标…...
EFISH-SBC-RK3576 + 5G模组:无线工业相机与分布式AI质检
在智能制造与仓储物流场景中,传统有线工业相机存在部署成本高、灵活性差等痛点。eFish-SBC-RK3576 通过 5G无线传输 分布式NPU协同,实现跨产线、跨工厂的AI质检系统,检测效率提升300%,布线复杂度降低90%。 1. 系统架构…...
C/C++ 基础 - 回调函数
目录 前言 回调函数预备知识 函数指针 什么是函数指针 函数指针的语法 如何用函数指针调用函数 函数指针作为函数的参数 函数指针作为函数返回类型 函数指针数组 回调函数 什么是回调函数 为什么要用回调函数 怎么使用回调函数 总结 前言 在写项目的时候&#x…...
