当前位置: 首页 > news >正文

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

引擎: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: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下的res/rgb

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

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

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


http://www.mrgr.cn/news/96564.html

相关文章:

  • AIGC1——AIGC技术原理与模型演进:从GAN到多模态融合的突破
  • 01-Docker 安装
  • 五.ubuntu20.04 - ffmpeg推拉流以及Nginx、SRS本地部署
  • YOLOv11模型的常见处理
  • 我的机器学习学习之路
  • 【TensorRT】TensorRT从安装到推理——Python 环境下 MobileNetV4 三分类任务
  • VUE如何前端控制及动态路由详细讲解
  • Go 语言常见错误
  • Java 大视界 -- Java 大数据在智慧矿山设备故障预测与预防性维护中的技术实现(163)
  • 【蓝桥杯—单片机】通信总线专项 | 真题整理、解析与拓展 (更新ing...)
  • 基于FPGA的ESP8266无线数据传输(温湿度DTH11、光照强度BH1750、WIFI模块)连接中国移动onenet云平台,仿真+上板通过+可视化平台搭建
  • Verilog中X态的危险:仿真漏掉的bug
  • 【区块链安全 | 第十四篇】类型之值类型(一)
  • 【多线程】单例模式和阻塞队列
  • 打车APP订单系统逻辑梳理与实现
  • vue如何实现前端控制动态路由
  • deepseek ai 输入法
  • 在rockylinux9.4安装mongodb报错:缺少:libcrypto.so.10文件库
  • Sentinel[超详细讲解]-3
  • UE5学习笔记 FPS游戏制作31 显示计分板