欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > Cocos Creator Shader入门实战(五):材质的了解、使用和动态构建

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

2025/3/26 4:21:12 来源:https://blog.csdn.net/qq_24726043/article/details/146443540  浏览:    关键词: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;});}
}


总结


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

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

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词