Cocos Creator Shader入门实战(五):材质的了解、使用和动态构建

引擎:3.8.5

您好,我是鹤九日!



回顾


前面的几篇文章,讲述的主要是Cocos引擎对Shader使用的一些固定规则,这里汇总下:

一、Shader实现基础是OpenGL ES可编程渲染管线,开发者只需关注顶点着色器片段着色器

二、Cocos引擎对Shader实现进行了多层封装,用于简化Shader的难度,以及更灵活管理,主要有:

  1. 封装了EffectAsset资源,主要包含CCEffectCCProgram两部分
  2. CCEffect部分, 采用YAML 1.2标准,与JSON兼容,并封装了渲染技术Technique、渲染过程Pass,以及Properties等多种属性配置
  3. CCProgram部分,采用GLSL语言,引擎封装了宏定义常量、函数以及Chunk等多种文件

三、Shader效果的实现,需要借助Effect Asset资源的属性配置和Material材质的数据包装。



简介


此篇文章,主要讲解关于材质Material部分,主要讲述内容:

一、材质的基本使用

二、使用iMaterialInfo动态初始化材质

三、材质的属性设置

四、材质的动态加载

正式开始之前,有两点需要注意:

  1. 材质是依托EffectAsset资源的,没有Effect资源,渲染材质无从谈起。
  2. 材质的作用,可以理解为两个:一、属性检查器的可视化调整; 二、通过脚本进行属性的动态调整

借助Cocos引擎实现Shader效果,简要的说,三个步骤:

一、创建EffectAsset资源,配置CCEffect渲染参数和编写CCProgram着色器片段

二、创建Material材质,设置属性检查器着色器资源,渲染技术、宏定义开关

三、渲染组件设置自定义材质属性



内置Effect

使用之前,首先我们需要有EffectAsset资源,可以通过编译器创建,也可以使用引擎内置的Effect资源。

内置Effect目录:../internal/effects
请添加图片描述

按照官方文档所言:

  • advanced 基于PBR着色器制作的一些高级效果,比如水面、皮肤、头发、玉石等,引擎会持续迭代
  • for2d 2D渲染相关着色器,比如:sprite、spine等
  • internal 引擎内置功能相关着色器,用户无需关注
  • particles 粒子相关特效
  • pipeline 管线着色器,比如延迟光照、后效和抗锯齿等

更多信息,可参考:内置着色器

本篇文章,便以内置的buitin-sprite.effect为例,主要原因有二:

  1. 精灵组件的Grayscale灰度渲染效果是它实现的
  2. CCEffect的属性配置和顶点着色器的片段代码,算是2D渲染中较为通用的。

内容如下:

  • CCEffect部分:
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
CCEffect %{# 渲染技术techniques:# 渲染过程- passes:# 顶点、片段着色器的名字和入口,必须参数- vert: sprite-vs:vertfrag: sprite-fs:frag# 深度和模板测试depthStencilState:depthTest: falsedepthWrite: false# 混合模式状态blendState:targets:- blend: trueblendSrc: src_alphablendDst: one_minus_src_alphablendDstAlpha: one_minus_src_alpha# 光栅化状态,禁用面剔除,常见参数有:front, back, nonerasterizerState:cullMode: none# 属性参数配置,可用于属性检查器的可视化调整或代码的传参properties:alphaThreshold: { value: 0.5 }
}%
  • CCProgram着色器部分:
// 顶点着色器
CCProgram sprite-vs %{// 精度的设置precision highp float;// 引擎的Chunk和宏定义开关#include <builtin/uniforms/cc-global>#if USE_LOCAL#include <builtin/uniforms/cc-local>#endif#if SAMPLE_FROM_RT#include <common/common-define>#endif// 应用程序传入的顶点参数,分别是:位置(xyZ), 纹理坐标(uv), 颜色(rgba)in vec3 a_position;in vec2 a_texCoord;in vec4 a_color;// 顶点着色器传给片段着色器的数据,颜色会经过光栅化采样,纹理坐标用于纹理采样out vec4 color;out vec2 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;#endifuv0 = a_texCoord;#if SAMPLE_FROM_RTCC_HANDLE_RT_SAMPLE_FLIP(uv0);#endifcolor = a_color;return pos;}
}%// 片段着色器
CCProgram sprite-fs %{precision highp float;#include <builtin/internal/embedded-alpha>#include <builtin/internal/alpha-test>in vec4 color;// 纹理采样相关#if USE_TEXTUREin vec2 uv0;#pragma builtin(local)layout(set = 2, binding = 12) uniform sampler2D cc_spriteTexture;#endifvec4 frag () {vec4 o = vec4(1, 1, 1, 1);#if USE_TEXTUREo *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv0);// 是否使用灰度测试#if IS_GRAYfloat gray  = 0.2126 * o.r + 0.7152 * o.g + 0.0722 * o.b;o.r = o.g = o.b = gray;#endif#endifo *= color;ALPHA_TEST(o);return o;}
}%

注: 注释相关在原有的文章中提及过,这里就当是加深印象吧!



基本使用


创建任意Effect资源,将builtin-sprite.effect内容复制粘贴进去。

然后创建Material材质,这里使用编译器直接构建普通材质Material即可。

请添加图片描述

其属性如下:

请添加图片描述

  • Effect :材质使用到的着色器资源EffectAsset,可通过下拉条进行选择。
  • Technique :Effect资源在CCEffect中所包含的渲染技术,可通过下拉条选择,用于设置不同的渲染效果。
  • Pass… :Effect资源在CCEffect中针对于每一个渲染技术所包含的渲染过程
  • USE… :预处理宏定义开关组合,不同宏定义的组合生成不同的代码,进而实现不同的效果。

这里我们只需关注Effect即可,选择我们添加的effect文件,保存。

请添加图片描述

构建任一页面,页面中包含一个Sprite组件,如下图所示:

请添加图片描述

将创建的demo.mtl材质拖拽进去,保存后,打开demo.mtl材质的属性检查器,如下图:

请添加图片描述

标记部分的勾选与否,便可直接预览灰度渲染效果。



自定义材质


Cocos引擎对Shader为开发者默默做了很多的事情。

上图中,我们借助的是Sprite渲染组件下的customMaterial ,即自定义材质。

我们可以这样认为:

一、对于任何持有CustomMaterial属性的UI和2D组件,我们都可以认为设置自定义材质

二、自定义材质属性即使为空,引擎也会进行默认配置

学习shader,customMateiral属性是一个很重要的入口。

注意:2D渲染对象不支持多材质,自定义材质数量最多为一个。

参考:2D渲染对象自定义材质



imaterialInfo初始化


材质的构建,编译器是最为直观、简洁的方式。那么它支持代码初始化吗?答案可以。

代码的动态初始化,与编译器的构建有相似之处。

引擎对于材质构建所需要的参数进行了封装叫做:IMaterialInfo,它的主要结构如下:

// 初始化材质的基本信息
export interface IMaterialInfo {// effectAsset资源引用,和effectName至少要指定一个effectAsset?: EffectAsset | null;// effect资源名,和effectAsset至少要指定一个effectName?: string;// 使用到的渲染技术,默认0technique?: number;// 使用到的预处理宏定义组合,默认全为0defines?: renderer.MacroRecord | renderer.MacroRecord[];// 自定义管线状态states?: renderer.PassOverrides | renderer.PassOverrides[];
}

使用的接口是Material下的initialize,代码的构建实例:

@ccclass('demo')
export class demo extends Component {@property(Sprite)sprite: Sprite = null!;@property(EffectAsset)effect: EffectAsset = null!;        // Effect资源引用          protected onLoad(): void {this.initMaterial();}// 初始化材质private initMaterial() {const material = new Material();const info: IMaterialInfo = {effectAsset: this.effect,technique: 0,defines: {USE_TEXTURE: true,      // 宏定义开关,使用纹理开启IS_GRAY: true,          // 宏定义开关,置灰开启}};material.initialize(info);// 设置精灵的自定义材质this.sprite.customMaterial = material;};
}

效果如下:

请添加图片描述



动态加载

不管是普通材质Material,还是物理材质Physics Material,它们都属于Asset资源的范畴。

  • 普通材质Material,主要用于渲染
  • 物理材质Physics Material,主要定义物体在物理模拟中的摩擦力、弹性等。

它们的继承结构如下:

Material
Asset
PhysicsMaterial

既然为Asset资源,那便支持动态加载,大概示例如下:

@ccclass('demo')
export class demo extends Component {@property(Sprite)sprite: Sprite = null!;       protected onLoad(): void {this.loadMateiral();}private loadMateiral() {// 资源路径,不需要后缀const url = "demo/demo";resources.load(url, Material, (err: Error, material: Material) => {if (err) {return console.error(err.message);}this.sprite.customMaterial = material;});}
}


总结


今天的文章到这里就结束了!

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

体育直播模板nba英超直播欧洲杯直播模板手机自适应

源码名称&#xff1a;体育直播模板nba英超直播欧洲杯直播模板手机自适应帝国cms 7.5模板 开发环境&#xff1a;帝国cms7.5 空间支持&#xff1a;phpmysql 带软件采集&#xff0c;可以挂着自动采集发布&#xff0c;无需人工操作&#xff01; 模板特点&#xff1a; 程序伪静态…

python基于spark的心脏病患分类及可视化(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;汽车数据分析平台当然不能排除在外。本次我所开发的心脏病患分类及可视化系统是在实际应用和软件工程的开发原理之上&#xff0c;运用Pyth…

SAP 附件增删改查与文件服务器交互应用

【需求背景】 非SAP标准附件应用&#xff0c;自定义一套&#xff0c;跟公司内部文档服务器交互&#xff0c;支持各个应用场景的附件增删改查等。 每个附件在文件服务器上都有一个文件唯一ID作为关键字。 应用分两块&#xff1a;SAP GUI端&#xff0c;跟WDA Portal端应用 GU…

Linux__之__基于UDP的Socket编程网络通信

前言 本篇博客旨在使用Linux系统接口进行网络通信, 帮助我们更好的熟悉使用socket套接字网络通信, 学会了socket网络通信, 就能发现所谓网络, 不过都是套路而已, 话不多说, 让我们直接进入代码编写部分. 1. 事先准备 今天我们先来模拟实现一个echo demo, 也就是客户端向服务…

【Agent】Dify Docker 安装问题 INTERNAL SERVER ERROR

总结&#xff1a;建议大家选择稳定版本的分支&#xff0c;直接拉取 master 分支&#xff0c;可能出现一下后面更新代码导致缺失一些环境内容。 启动报错 一直停留在 INSTALL 界面 我是通过 Docker 进行安装的&#xff0c;由于项目开发者不严谨导致&#xff0c;遇到一个奇怪的…

unity开发效率提升笔记

本文将记录提升Unity开发效率的若干细节&#xff0c;持续更新 一.VSCode文件标签多行显示 1.File->Preference->Settings (快捷键Ctrl 逗号) 2.搜索workbench.editor.wrapTabs 3.勾选上这个单选开关 若依然不是多行 4.搜索workbench.editor.tabSizing,选择fi…

python每日十题(6)

列表操作函数有&#xff08;假设列表名为ls&#xff09;&#xff1a; len(ls)&#xff1a;返回列表ls的元素个数&#xff08;长度&#xff09;。min(ls)&#xff1a;返回列表ls的最小元素。max(ls)&#xff1a;返回列表ls的最大元素。list(x)&#xff1a;将x转变为列表类型。使…

【Java】TCP网络编程:从可靠传输到Socket实战

活动发起人小虚竹 想对你说&#xff1a; 这是一个以写作博客为目的的创作活动&#xff0c;旨在鼓励大学生博主们挖掘自己的创作潜能&#xff0c;展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴&#xff0c;那么&#xff0c;快来参加吧&#xff01…

使用HAI来打通DeepSeek的任督二脉

一、什么是HAI HAI是一款专注于AI与科学计算领域的云服务产品&#xff0c;旨在为开发者、企业及科研人员提供高效、易用的算力支持与全栈解决方案。主要使用场景为&#xff1a; AI作画&#xff0c;AI对话/写作、AI开发/测试。 二、开通HAI 选择CPU算力 16核32GB&#xff0c;这…

mysql——第二课

学生表 CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT,name varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,sex varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,age int(11) DEFAULT NULL,c_id int(10) DEFAULT NULL,PRIMARY KEY (id),KEY c_id (c_id),CONSTR…

单播、广播、组播和任播

文章目录 一、单播二、广播三、组播四、任播代码示例&#xff1a; 五、各种播的比较 一、单播 单播&#xff08;Unicast&#xff09;是一种网络通信方式&#xff0c;它指的是在网络中从一个源节点到一个单一目标节点对的传输模式。单播传输时&#xff0c;数据包从发送端直接发…

1-1 MATLAB深度极限学习机

本博客来源于CSDN机器鱼&#xff0c;未同意任何人转载。 更多内容&#xff0c;欢迎点击本专栏目录&#xff0c;查看更多内容。 参考[1]魏洁.深度极限学习机的研究与应用[D].太原理工大学[2023-10-14].DOI:CNKI:CDMD:2.1016.714596. 目录 0.引言 1.ELM-AE实现 2.DE…

头歌 数据采集概述答案

问题1&#xff1a;以下哪个不是Scrapy体系架构的组成部分&#xff1f; 正确答案&#xff1a;B. 支持者(Support) 解释&#xff1a;Scrapy的主要组成部分包括&#xff1a; 爬虫(Spiders)&#xff1a;定义如何爬取网站和提取数据 引擎(Engine)&#xff1a;负责控制数据流在系统中…

【uniapp】记录tabBar不显示踩坑记录

由于很久没有使用uniapp了&#xff0c;官方文档看着又杂乱&#xff0c;底部tab导航栏一直没显示&#xff0c;苦思许久&#xff0c;没有发现原因&#xff0c;最后网上搜到帖子&#xff0c;list里的第一个数据&#xff0c;pages 的第一个 path 必须与 tabBar 的第一个 pagePath 相…

JVM 知识点梳理

JDK 、JRE、JVM JDK&#xff08; Java Development Kit &#xff09; Java开发工具包 JRE 开发命令工具&#xff08;运行java.exe、编译javac.exe、javaw.exe&#xff09; JRE&#xff08; Java Runtime Environment &#xff09;Java运行环境 JVM Java核心类库&#xff08;l…

蓝桥杯 之 第27场月赛总结

文章目录 习题1.抓猪拿国一2.蓝桥字符3.蓝桥大使4.拳头对决5.未来竞赛6.备份比赛数据 习题 比赛地址 1.抓猪拿国一 十分简单的签到题 print(sum(list(range(17))))2.蓝桥字符 常见的字符匹配的问题&#xff0c;是一个二维dp的问题&#xff0c;转化为对应的动态规划求解 力扣…

Ambari、Bigtop源码编译最新支持情况汇总

以下是目前的版本情况 支持了绝大部分的组件编译及安装 版本组件名称组件版本env 版本v1.0.5Ozone1.4.11.0.5Impala4.4.11.0.5Nightingale7.7.21.0.5Categraf0.4.11.0.5VictoriaMetrics1.109.11.0.5Cloudbeaver24.3.31.0.5Celeborn0.5.31.0.5v1.0.4Doris2.1.71.0.4v1.0.3Phoen…

仅靠prompt,Agent难以自救

Alexander的观点很明确&#xff1a;未来 AI 智能体的发展方向还得是模型本身&#xff0c;而不是工作流&#xff08;Work Flow&#xff09;。还拿目前很火的 Manus 作为案例&#xff1a;他认为像 Manus 这样基于「预先编排好的提示词与工具路径」构成的工作流智能体&#xff0c;…

【Docker系列一】Docker 简介

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Sqoop 常用命令

Sqoop 是用于在 Hadoop 和关系型数据库&#xff08;如 MySQL、Oracle 等&#xff09;之间高效传输数据的工具。以下是常用的 Sqoop 命令及示例&#xff1a; CREATE TABLE employees (id INT AUTO_INCREMENT PRIMARY KEY, -- 自增主键&#xff0c;用于唯一标识每一行name VAR…