零、这个时代,太快


如果有朋友年龄和麒麟子相仿的话,小时候应该玩过DVD播放机,就下面图里这东西。

那么问题来了,你还记得,如果想要播放自己想看的内容,一共分几步吗?

和把大象装进冰箱一样简单,只需要三步:

第一步、出仓:弹出光盘托盘

第二步、换碟:把想放的光碟放进去

第三步、关仓:收回光盘托盘

如果我们想从刘德华的专辑切换到张学友的专辑,你需要重复上面的步骤。

如果我们想从听歌切换到某电影,你需要重复上面的步骤。

如果我们想从电视剧的某一集切换到另一集,你还是需要重复上面的步骤。

现在让你这样去播放节目,你肯定会觉得烦。

因为我们已经习惯了当下更先进的计算机系统和功能强大的多媒体软件。

不再需要从成堆的光碟中去寻找想要的内容。

不再需要从舒适的沙发里起身去更换想要播放的光碟。

不再需要担心心爱的光碟损坏或者被邻家王哥哥借走。

麒麟子学Shader也经历了类似的时代跨度。

80后嘛,总是免不了处于时代交叉口的命运。

十几年前,人们发现固定渲染管线(Fixed Render Pipeline)难以满足日益增长的画面要求,可编程渲染管线(Programmable Render Pipeline)应运而生。

可编程管线需要硬件支持,由于硬件更新的成本远远大于软件成本,普及速度并不能像软件那样快。

处于时代交替的3D引擎,为了兼顾所有用户的需求,一般都会支持固定管线可编程管线

那处于时代交叉口的程序员,别无选择,要同时掌握固定管线可编程管线,才能吃饱饭。

早期的可编程程管线就是在固定管线的基础上,将T&L(变换与光照)以Vertex Shader方式呈现,而纹理采样和混合则以Fragment Shader方式呈现。

随着固定管线的淘汰,可编程管线不再考虑兼容前者,如今的可编程管线不管是从功能性还是便利性而言,早已经是当初的版本无法比拟的了。

为什么麒麟子要浪费大量篇幅来讲这个。

享受当下,畅想未来,回顾历史,可以让我们生活的充满诗意。

一、什么是Uniform


制服?统一的?似乎都不对。

UniformGLSL的关键字,当我们需要从外部传递参数给GLSL时,就需要申明一个uniform常量。比如 uniformfloattime

麒麟子觉得,Direct3D中的称呼更确切,它叫 constant, 常量。

它有两个特点

  • 可以通过图形API(如D3DOpenGLWebGL)修改
  • Shader内不可以修改

这也是为什么Direct3D要把它叫做常量

常量的传递需要使用GPU中的常量寄存器,显然显卡寄存器并非是一个无限资源。

我们可以通过GL的枚举来查看限制。

顶点着色器常量数量限制:GL_MAX_VERTEX_UNIFORM_COMPONENTS

像素着色器常量数量限制:GL_MAX_FRAGMENT_UNIFORM_COMPONENTS

好在,这些限制都比较大,对于日常开发,我们可以暂时不关注这个问题。

如果哪天遇上特殊需求,请记得,硬件资源不是无限的。

二、Cocos Shader中的Uniform


在Cocos中,我们可以使用如下常量类型

bool int float vec2 vec3 vec4

除了声明单个常量之外,我们还可以声明常量数组。

比如,引擎中的骨骼动画(在不使用顶点纹理的情况下),需要将整个骨骼矩阵传递过来,此时就需要用到数组。

接下来,我们将在通过在Cocos Shader中添加变量的方式,一步步让大家掌握Cocos Shader中uniform的使用。

三、第一个Uniform


请看上图的示例

Cocos Shader要求,常量需要定义在uniform-block中,麒麟子就直接翻译成常量块了。

不用去管为什么,先记住就行。

我们定义了一个vec4 mainColor和一个vec4 colorScaleAndCutoff

其中mainColor用于物体渲染时的颜色值r,g,b,a通道都用上

colorScaleAndCutoff中,colorScaleAndCutoff.rgb用于颜色因子调子,而colorScaleAndCutoff.w用于Alpha测试判断。

Alpha测试后面会讲,这里我们暂时忽略它。

渲染效果如下,由于我们没有设置变量值,常量的默认值是0.0,所以会渲染出黑色。

四、通过代码控制Uniform参数


为了照顾大家迫切的心情,我们先看看如何使用代码控制常量吧。

其实使用代码控制常量非常简单。

1、新建一个TS脚本

麒麟子把脚本取名为MaterialCtrl.ts 然后写上下面这样的代码。

这么少的代码,大家手抄吧。

2、将MaterialCtrl.ts挂在了球体上。

3、启动浏览器预览

在浏览器中,你就能看到一个紫色的球。

注意:在编辑器中是看不到紫色的,因为我们需要TS代码行执行起来才行。

五、通过属性面板(Inspector)控制Uniform参数


有的朋友应该发现了,刚刚我们添加的mainColorcolorScaleAndCutoff并没有出现在Inspector面板里。

接下来我们就来看看,如何将一个uniform显示在面板上。

cocos-shader-helloworld.effect中,我们添加上图红框部分的代码。再次回到编辑器,就可以看见材质面板上多出了mainColorcolorScale两个调节参数。

通过调节面板,我们就能在编辑器里看到直接的效果变化,是不是很棒?

麒麟子逐一解释一下各个部分的含义。

mainColor: { value: [1, 1, 1, 1], editor: { type: color } }

mainColor:是显示在面板上的属性名称,这个名称直接与下面的uniform Constant中的 vec4 uniform自动匹配。

value:默认值

editor:用于配置编辑器面板相关参数,比如 type则用于指定面板显示内容。如果不指定,mainColor将默认以vec4显示。

这里我们希望mainColor是一个颜色,所以我们指定为color

colorScale: { value: [1, 1, 1], target: colorScaleAndCutoff.xyz }

colorScale:是属性名称,它将显示在面板上。

value:默认值

target:用于指定需要使用的变量,在这里,我们使用colorScaleAndCutoffxyz三个通道。

掌握了上面的知识,足够满足日常Shader编写的需求。如果需要进一步研究的朋友,可以查看官方文档Pass Params对应部分。如下图所示:

六、需要注意的点


一、mainColor可以通过Color设置,也可以通过vec4设置。在Cocos代码中,Colorvec4有一个差别,就是Color的分量是按0~255取值的,注意这个细节就行。

二、在使用代码设置材质时,请注意target.sharedMaterialtarget.material的区别。

target.sharedMaterial会直接对材质进行设置,所有引用同一个材质文件的对象均会受到影响。

target.material 若未复制,则target.material会先复制一个sharedMaterial材质,再进行操作。这样设置后,不会对其他对象造成影响,但会影响GPU Instancing等优化效果。使用的时候要慎重。

三、使用代码控制材质,编辑器中看不到效果,需要运行后查看。

四、在使用代码设置时,对于像示例中colorScale这样的定义,我们既可以对colorScaleAndCutoff进行整体设置,也可以单独对colorScale进行设置。换句话说,setProperty方法既能识别Shader中的uniform定义,也能识别Pass描述中的属性定义.

七、总结


本文从uniform含义和用途解释了uniform存在的意义。

并以mainColorcolorScale两个uniform实例演示了如何在Cocos Shader中使用uniform

与此同时,也展示了如何通过代码进行uniform操控。

在掌握本文的内容后,朋友们应该对Cocos Shader的使用流程有了整体认识。

后面的内容虽然多,但已经不再有流程上的新增,只是内容会更丰富。

能走到这里的朋友已经很厉害了,悄悄告诉你。

离渲染出美妙的花花世界,只有一步之遥。

八、预告

下一篇文章 《Cocos Shader入门基础五:是纹理给了你这个花花世界》 中,麒麟子将会给大家介绍纹理相关知识。

  • 纹理坐标UV是什么?
  • 纹理类型
  • 纹理寻址方式
  • 纹理采样方式
  • 定义一个类型为smapler2Duniform

关注麒麟子,精彩文章


Cocos Shader入门基础四:Uniform与材质参数控制相关推荐

  1. Cocos Shader入门基础七:一文彻底读懂深度图。

    开篇 经过一段时间的持续输出,社区中越来越多的人踏上了3D图形渲染学习之旅,麒麟子非常开心,说明输出的内容对大家都产生了实际的帮助. 特别是上一篇 <用实时反射Shader增强画面颜值> ...

  2. java入门基础(四)

    文章目录 (一)对象和类 封装概述: (二)String对象 (三)StringBuilder对象 (四)集合ArrayList:可变的存储模型 练习 ArryayList练习 (一)对象和类 类:类 ...

  3. Unity 3D开发--Shader入门基础

    Shader "Unlit/xxShader" {Properties{//基础属性 并可以显示在属性板上_MainTex ("Texture", 2D) = ...

  4. java入门基础四(方法和数组)

    8.方法 方法简述: 概念:特定功能的代码块. 优点:减少了代码的冗余. 方法的分类:静态方法.成员方法.构造方法(此节主要在静态方法的基础上使用) 注意: 方法编写的位置:类里,与main方法并立. ...

  5. mybatis入门基础(四)----输入映射和输出映射

    阅读目录 一:输入映射 二:输出映射 回到顶部 一:输入映射 通过parameterType指定输入参数的类型,类型可以是简单类型.hashmap.pojo的包装类型. 1.1.传递pojo的包装对象 ...

  6. Python入门基础-四、案例1 汇率兑换 #分支语句if else# 循环语句while#函数#lambda函数

    (课程相关的所有资料代码,已上传至CSDN,请自行下载 https://download.csdn.net/download/qq_34243930/10764180 ) 汇率兑换 1.0(只考虑一种 ...

  7. Unity Shader入门学习(5):基础屏幕后处理

    1.后处理基类 //屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效. //基类的作用有二:检测平台是否支持后处理效果,及创建一个用于处理渲 ...

  8. Shader入门精要-2-shader入门/基础光照模型/纹理

    shader入门 类型 内置文件 三种精度 光照模型 标准光照模型: 方法: 半兰伯特光照模型 高光反射光照模型(Phong光照模型): 高光反射中反射方向计算: 高光反射光照模型(Blinn-Pho ...

  9. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

最新文章

  1. Synchronized的两个用法
  2. 六道面试中常见的智力题 来看看你会做几道?
  3. 研发的那些事3--接口之本
  4. git为私有仓库设置密码_dnf仓库密码设置不跳出 dnf仓库密码设置流程
  5. Netcdf中多变量导出代码示例
  6. 手把手教你编写接口需求文档
  7. Python与开源GIS:在OGR中使用SQL语句进行查询
  8. papers for mac 破解版永久激活方法
  9. 重学数据结构:三对角矩阵公式推导过程
  10. 网络安全工程师面试分享
  11. 我努力了18年,不是为了和你一起喝咖啡姐妹篇
  12. 什么是零点漂移,怎么抑制零点漂移?(硬件每日一题)
  13. 美国音乐学院计算机音乐专业排名2015年,美国音乐学院排名
  14. hive sql系列(七)——查询前20%时间的订单信息
  15. 清除服务器传输文件记录,Sqlserver2012清除服务器连接记录(服务器名称历史记录清除)...
  16. Linux 进程通信 -- 管道
  17. 2021消防设施操作员(初级)岗位考试模拟题库应急疏散逃生知识部分
  18. JSP开发模型与MVC设计模型
  19. centos安装telnet
  20. 全面认识Android OS

热门文章

  1. python文件打开的默认模式_怎么改变pycharm文件打开方式
  2. 尽管去做 ——无压工作的艺术
  3. STL用法(转自吉吉)
  4. Jquery和JS获取Table中tr标签的值以及赋值问题
  5. 经典Java面试题收集
  6. 日耳曼战车PK蓝白军团 大数据分析能否压中巅峰之战?
  7. angular:ng-star-inserted作用
  8. Html中select标签chang事件传值
  9. jmeter-性能测试9-测试场景与执行
  10. matlab seqfold,求教:m-fold cross validation 在matlab下如何实现?