Cocos Creator Shader入门实战(四):预处理宏定义和Chunk

news2025/3/18 22:23:16

引擎: 3.8.5

您好,我是鹤九日!



回顾


学习Shader,前期是让人烦躁无味的,后期可能就是各种的逻辑让人抓耳挠腮。

一成不变的内容:遵循引擎设定的规则,理解引擎要求的规范。

这里,简单回顾下前面所说的大概内容:

一、Shader的实现,需要Material材质和Effect Asset资源的配合

二、Effect Asset资源主要通过CCEffect配置渲染参数和属性, 通过CCProgram编写着色器片段代码

三、CCEffect的配置使用的是YAML,而CCProgram使用的则是GLSL



开篇


还记得,我们刚开始通过编译器创建的 传统无光照着色器(Effect) 的资源吗?

请添加图片描述

属性结构如下:

请添加图片描述

我当时说过:即使有着官方的文档加持,也是一脸的茫然,不知道这些代表着什么,以及如何使用。

今天的主题便是对EffectAsset资源的说明,看着很繁琐,其实没有那么的难。

简单的理解: 引擎对EffectAsset资源的预编译,其实就是借助了主要两点:

一、预处理宏定义

二、着色器片段Chunk



默认资源


正式开始之前,先做一个小小的延伸,也是自己偶然中的学习发现。

以我们创建的着色器资源,内容是从哪里来呢?

注:从严格意义来说,它不属于Shader的范畴,而是编译器的范畴。

请添加图片描述

标注的部分便是引擎的配置,甚至来说 …/default_file_content/scene 下的这个资源是否会很眼熟呢。

请添加图片描述

这些了解下就可以,万一有机会使用呢!



预处理宏定义


预处理宏定义,其实就是#define声明的的一些开关字段,使用的均为大写。

在任意EffectAsset的资源中,我们看到的Precompile Combinations属性展示开关,就是它。

请添加图片描述

在EffectAsset资源的CCProgram片段中,顶点着色器和片段着色器使用的一些宏,也是宏定义。

//  顶点着色器
CCProgram sprite-vs %{
  precision highp float;
  #include <builtin/uniforms/cc-global>
  #if USE_LOCAL
    #include <builtin/uniforms/cc-local>
  #endif
  #if SAMPLE_FROM_RT
    #include <common/common-define>
  #endif
  // ...
}
// 片段着色器
CCProgram sprite-fs %{
  // ...
  #if USE_TEXTURE
    in vec2 uv0;
    #pragma builtin(local)
    layout(set = 2, binding = 12) uniform sampler2D cc_spriteTexture;
  #endif
}

甚至,后面要讲到的material材质的属性里面,也包含着宏定义开关。

请添加图片描述

这里注意:宏定义的显示与否,最终还是受着EffectAsset下的CCEffect属性参数和CCProgram着色器代码控制的。

理由很简单:Effect资源负责编写渲染参数和着色器实现,而Material材质负责对Effect的数据包装和可视化。


优点

引擎提供预处理宏定义的支持,它的几个特性主要有:

一、更好的管理代码内容,根据不宏生成不同组合的代码

二、更好的可视化及控制,方便调试

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

这里注意:一般情况下,使用到的宏定义都会显示在属性面板上,但以CC_开头的不会显示。


内置宏定义

官方内置了很多的宏定义,这里简单罗列下常见的:

定义说明
USE_INSTANCING是否启用几何体实例化
USE_VERTEX_COLOR是否叠加顶点颜色和 Alpha 值
USE_TEXTURE是否使用主纹理(mainTexture)
USE_ALPHA_TEST是否进行半透明测试(AlphaTest)
SAMPLE_FROM_RT是否是从 RenderTexture 中采样

注:更多的内容可参考官方文档:

无光照宏

卡通渲染宏定义

PBR宏定义

这里注意,我们使用到的预处理定义宏,不仅包含着布尔类型,也会包含着常量、函数等。

在后面说到的Chunk中,它有一个通用的文件叫做:common-define.chunk

路径: ../internal/chunks/common/common-define

请添加图片描述

里面就包含了很多,常用的宏常量、函数等等。

注:如果仔细观察,引擎对EffectAsset资源预编译后

属性检查器中GLSL 300ES Output的输出就有它的影子。


用法

一般来说,使用#define常用于常量、布尔类型开关。比如:

#define USE_INSTANCING 0
#define USE_TWOSIDE 0
#define USE_ALBEDO_MAP 0

较为特殊的用法,便是引擎支持的设定指定的范围宏定义,主要有:

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

这里注意:

一、#pragma 是通用的预处理命令,可指定编译选项、定义元数据等

二、#define 用于修饰静态的,比如替换文本,定义常量。

三、#pragma define-meta 是Cocos Creator提供的特有指令,可用于定义动态参数。

这样的好处便是:我们不需要重新编译,并且能够在属性检查器中动态调整。

以EffectAsset的着色器片段为例,主要代码如下

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
      // gray
      float gray = (o.r + o.g + o.b)/3.0;
      o = vec4(gray, gray, gray, o.a);
    #elif FILTER_TYPE == 2 
       // ...
    #elif FILTER_TYPE == 3
      // ...
    #elif FILTER_TYPE == 4
      // ...
    #endif
    
    return o;
  }
}%

在Effect的属性检查器中,便可以看到它的属性:

请添加图片描述

而在对应的材质属性检查器中看到的属性,通过调整便可预览效果。

请添加图片描述



Chunk


Chunk听着好像是一个很高大上的名词儿,其实简单的理解就是#include

CCProgram sprite-vs %{
  precision highp float;
  #include <builtin/uniforms/cc-global>
  #if USE_LOCAL
    #include <builtin/uniforms/cc-local>
  #endif
}

在日常开发中,我们会对一些通用的常量、方法等,进行分文件存放,使用的时候引用即可。

这样的方式,可以最大程度的复用代码逻辑。

引擎同样也做了这样的事情,所有的封装文件都在:internal/chunks 中。

请添加图片描述

这些跨文件代码的chunk封装,即跨文件代码引用机制,对我们编写Shader是很有帮助的。

上面的例子中提到的一个common-define.chunk 便是一个很好的例子。

官方内置的Chunk有很多,这里不在一一列举,可参考官方文档:

内置全局Uniform

公共函数库

注:Chunk的使用,仅针对于GL SL 300ES


使用

除了内置的Chunk外,官方支持开发者自定义创建Chunk片段,如下图所示:

请添加图片描述

在我们学习参考的示例中,还记得创建无光照Effect资源时候的这段配置吗?

CCEffect %{
  techniques:
  - name: opaque
    passes:
    - vert: legacy/main-functions/general-vs:vert # builtin header
      frag: unlit-fs:frag
}%

如果学习使用,我们可以参考者将顶点着色器的逻辑,作为通用的chunk来使用。

比如,创建sprite-vs.chunk,只需要做到将CCProgram下的着色器代码拷贝过来,放进去就可以了。

precision highp float;
#include <builtin/uniforms/cc-global>
#if USE_LOCAL 
  #include <builtin/uniforms/cc-local>
#endif

in vec3 a_position; // 顶点的位置坐标(XYZ)
in vec2 a_texCoord; // 顶点的纹理坐标(UV),用于映射纹理
in vec4 a_color;    // 顶点的颜色值(RGBA)

out vec4 v_color;   // 用于向片元着色器传递顶点颜色,片元着色器中会插值处理
out vec2 v_uv0;     // 用于向片元着色器传递纹理坐标,用于纹理采样

vec4 vert() {
  vec4 pos = vec4(a_position, 1);

  #if USE_LOCAL
    // 从局部坐标系转换到世界坐标系
    pos = cc_matWorld * pos;
  #endif

  #if USE_PIXEL_ALIGNMENT
    // cc_matView 视图矩阵, 将世界坐标系转换到视图坐标系
    pos = cc_matView * pos;       
    pos.xyz = floor(pos.xyz);
    // cc_matProj 投影矩阵,将视图坐标转换为裁剪坐标
    pos = cc_matProj * pos;       
  #else 
    // cc_matViewProj 视图投影矩阵,将世界坐标转换为裁剪坐标
    pos = cc_matViewProj * pos;   
  #endif 

  v_uv0 = a_texCoord;
  v_color = a_color;

  return pos;
}

然后,在CCEffect的片段中,修改下顶点着色器的路径即可:

CCEffect %{
  techniques:
  - passes:
    - vert: ../res/effect/rgb/sprite-vs:vert
      frag: sprite-fs:frag
}%

延伸:GLSL 300ES

了解Chunk后,EffectAsset资源的着色器中关于output的预览代码就容易理解了。

由于Chunk基于GLSL 300 ES,那便以它为例,文件是builtin-sprite.effect的顶点着色器为例:

注:内容过多,只显示部分

// 着色器中调用的 #include <builtin/uniforms/cc-global>
// 引擎便将 ../chunks/builtin/unfiroms/cc-global的内容引用过来
layout(std140) uniform CCGlobal {
 highp   vec4 cc_time;
 mediump vec4 cc_screenSize;
 mediump vec4 cc_nativeSize;
 mediump vec4 cc_probeInfo;
 mediump vec4 cc_debug_view_mode;
};
// ...

// 着色器调用的#include <builtin/uniforms/cc-local>
// 引擎便将 ../chunks/builtin/unfiroms/cc-local的内容引用过来
#if USE_LOCALlayout(std140) uniform CCLocal {
   highp mat4 cc_matWorld;
   highp mat4 cc_matWorldIT;
   highp vec4 cc_lightingMapUVParam;
   highp vec4 cc_localShadowBias;
   highp vec4 cc_reflectionProbeData1;
   highp vec4 cc_reflectionProbeData2;
   highp vec4 cc_reflectionProbeBlendData1;
   highp vec4 cc_reflectionProbeBlendData2;
 };
#endif
// 引擎引用下的 ../common/common-define.chunk的通用宏定义相关
#if SAMPLE_FROM_RT
    #define QUATER_PI         0.78539816340
    #define HALF_PI           1.57079632679
    #define PI                3.14159265359
    // ...'
#endif 

// 着色器的片段实现相关
in vec3 a_position;
in vec2 a_texCoord;
in vec4 a_color;
out vec4 color;
out vec2 uv0;
vec4 vert () {
 // ...
}

// gl_Postion是GLSL语言中顶点着色器的最终输出
// main()接口的使用,是引擎在编译时自动添加的
// 这也是我们自定义着色器入口时不能使用main的原因
void main() { gl_Position = vert(); }


结尾

今天的文章到这里就算是结束了,如果理解有误,编写不当,希望您能指正一二。

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

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

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

相关文章

K8S快速部署

前置虚拟机环境正式部署BUG解决 前置虚拟机环境 每个虚拟机配置一次就好 #关闭防火墙 systemctl stop firewalld systemctl disable firewalld #关闭 selinux sed -i s/enforcing/disabled/ /etc/selinux/config # 永久 setenforce 0 # 临时 #关闭 swap swapoff -a # 临时 vi…

汽车PKE无钥匙进入系统一键启动系统定义与原理

汽车智能钥匙&#xff08;PKE无钥匙进入系统&#xff09;一键启动介绍 系统定义与原理 汽车无钥匙进入系统&#xff0c;简称PKE&#xff08;Passive Keyless Entry&#xff09;&#xff0c;该系统采用了RFID无线射频技术和车辆身份编码识别系统&#xff0c;率先应用小型化、小…

WPF程序使用AutoUpdate实现自动更新

AutoUpdate.NET使用 一、AutoUpdater.NET 简介 AutoUpdater.NET 是一个开源库&#xff0c;支持从各种源&#xff08;如GitHub、FTP、HTTP服务器等&#xff09;下载并安装更新。它提供了灵活的配置选项&#xff0c;允许开发者根据需求定制更新检查逻辑和用户体验。 二、安装 …

每日Attention学习28——Strip Pooling

模块出处 [CVPR 20] [link] Strip Pooling: Rethinking Spatial Pooling for Scene Parsing 模块名称 Strip Pooling (SP) 模块结构 模块特点 本质是空间注意力的一种使用横/纵两个方向的条形池化获得一维方向上的重要程度&#xff0c;结合后便可以扩展至二维方向 模块代码 …

ollama docker设置模型常驻显存

参考&#xff1a; https://github.com/ollama/ollama/issues/5272 https://deepseek.csdn.net/67cfd7c93b685529b708fdee.html 通过-e传入环境变量&#xff0c;ollama运行&#xff1a; docker run -d --gpusall -e OLLAMA_KEEP_ALIVE-1 -v ollama:/root/.ollama -p 11434:114…

无再暴露源站!群联AI云防护IP隐匿方案+防绕过实战

一、IP隐藏的核心原理 群联AI云防护通过三层架构实现源站IP深度隐藏&#xff1a; 流量入口层&#xff1a;用户访问域名解析至高防CNAME节点&#xff08;如ai-protect.example.com&#xff09;智能调度层&#xff1a;基于AI模型动态分配清洗节点&#xff0c;实时更新节点IP池回…

【深度学习|目标检测】YOLO系列anchor-based原理详解

YOLO之anchor-based 一、关于anchors的设置二、网络如何利用anchor来训练关于register_buffer训练阶段的anchor使用推理阶段的anchor使用 三、训练时的正负样本匹配静态策略&#xff1a;跨分支采样跨anchor采样跨grid采样 动态策略 总结起来其实就是&#xff1a;基于anchor-bas…

Linux 入门:权限的认识和学习

目录 一.shell命令以及运行原理 二.Linux权限的概念 1.Linux下两种用户 cannot open directory .: Permission denied 问题 2.Linux权限管理 1).是什么 2).为什么&#xff08;权限角色目标权限属性&#xff09; 3).文件访问者的分类&#xff08;角色&#xff09; 4).文…

搭建opensbi+kernel+rootfs及基本设备驱动开发流程

目录 一.编译qemu 运行opensbikernelrootfs 1.编译qemu-9.1.1 2.安装riscv64编译器 3. 编译opensbi 4.编译kernel 5.编译rootfs 设备驱动开发流程 1.安装 RISC-V 交叉编译工具链 2.驱动开发准备 3.编写简易中断控制器驱动&#xff08;PLIC&#xff09;​ 4.配置内核…

QT非UI设计器生成界面的国际化

目的 UI设计器生成界面的国际化&#xff0c;比较容易实现些&#xff0c;因为有现成的函数可以调用&#xff0c;基本过程如下&#xff1a; void MainWindow::on_actLang_CN_triggered() {//中文界面qApp->removeTranslator(trans);delete trans;transnew QTranslator;trans…

python | 输入日期,判断这一天是这一年的第几天

题目&#xff1a; 使用 python 编程&#xff0c;实现输入日期&#xff0c;判断这一天是这一年的第几天? 具体实现代码如下&#xff1a; import datetime year input(请输入年份&#xff1a;) month input(请输入月份&#xff1a;) day input(请输入天&#xff1a;) date…

单片机开发资源分析的实战——以STM32F103C8T6为例子的单片机资源分析

目录 第一点&#xff1a;为什么叫STM32F103C8T6 从资源手册拿到我们的对STM32F103C8T6的资源描述 第二件事情&#xff0c;关心我们的GPIO引脚输出 第三件事情&#xff1a;去找对应外设的说明部分 前言 本文章隶属于项目&#xff1a; Charliechen114514/BetterATK: This is…

Maven | 站在初学者的角度配置

目录 Maven 是什么 概述 常见错误 创建错误代码示例 正确代码示例 Maven 的下载 Maven 依赖源 Maven 环境 环境变量 CMD测试 Maven 文件配置 本地仓库 远程仓库 Maven 工程创建 IDEA配置Maven IDEA Maven插件 Maven 是什么 概述 Maven是一个项目管理和构建自…

【css酷炫效果】纯CSS实现3D翻转卡片动画

【css酷炫效果】纯CSS实现3D翻转卡片动画 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;https://download.csdn.net/download/u011561335/90490472 缘 创作随缘&#xff0c;不定时更新。 创作背景 刚看到csdn出活动了&am…

并发编程面试题二

1、java线程常见的基本状态有哪些&#xff0c;这些状态分别是做什么的 &#xff08;1&#xff09;创建&#xff08;New&#xff09;&#xff1a;new Thread()&#xff0c;生成线程对象。 &#xff08;2&#xff09;就绪&#xff08;Runnable&#xff09;:当调用线程对象的sta…

Spring Cloud Stream - 构建高可靠消息驱动与事件溯源架构

一、引言 在分布式系统中&#xff0c;传统的 REST 调用模式往往导致耦合&#xff0c;难以满足高并发和异步解耦的需求。消息驱动架构&#xff08;EDA, Event-Driven Architecture&#xff09;通过异步通信、事件溯源等模式&#xff0c;提高了系统的扩展性与可观测性。 作为 S…

突破连接边界!O9201PM Wi-Fi 6 + 蓝牙 5.4 模块重新定义笔记本无线体验

在当今数字化时代&#xff0c;笔记本电脑已成为人们工作、学习和娱乐的必备工具。而无线连接技术&#xff0c;作为笔记本电脑与外界交互的关键桥梁&#xff0c;其性能的优劣直接关乎用户体验的好坏。当下&#xff0c;笔记本电脑无线连接领域存在诸多痛点&#xff0c;严重影响着…

Python----计算机视觉处理(Opencv:图像颜色替换)

一、开运算 开运算就是对图像先进行腐蚀操作&#xff0c; 然后进行膨胀操作。开运算可以去除二值化图中的小的噪点&#xff0c;并分离相连的物体。 其主要目的就是消除那些小白点 在开运算组件中&#xff0c;有一个叫做kernel的参数&#xff0c;指的是核的大小&#xff0c;通常…

一周学会Flask3 Python Web开发-SQLAlchemy查询所有数据操作-班级模块

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 我们来新建一个的蓝图模块-班级模块&#xff0c;后面可以和学生模块&#xff0c;实现一对多的数据库操作。 blueprint下新建g…

Matlab 风力发电机磁悬浮轴承模型pid控制

1、内容简介 略 Matlab 174-风力发电机磁悬浮轴承模型pid控制 可以交流、咨询、答疑 2、内容说明 磁悬浮轴承具有无接触、无摩擦、高速度、高精度、能耗低、不需要需润滑无油污染、可靠性高、寿命长和密封等一系列显著的优点。将磁悬浮技术应用于风力发电机中可以降低风机切入…