关于《Thinking in Unity3D

笔者在研究和使用Unity3D的过程中,获得了一些Unity3D方面的信息,同时也感叹Unity3D设计之精妙。不得不说,笔者最近几年的引擎研发工作中,早已习惯性的从Unity3D中寻找解决方案。

Unity3D虽比不上UE那么老练沉稳,气势磅礴。也比不上CE那样炫丽多姿,盛气凌人。但它的发展势如破竹,早已遍地生花!故而在此记录一些自己的心得体会,供大家参详交流。若有欠妥之处,还望各位及时指正。
 
Thinking in Unity3D由一系列文章组成,文章列表地址:http://www.cnblogs.com/geniusalex/p/5321545.html
 

什么是材质?


材质是一个相对广泛的概念,不同的专业领域有不同的定义。 在此也不一一举例说明了,我们只说在3D游戏引擎中,材质的定义。

材质的本质定义,是指能够描述一个物体的显示外观的一系列数据。它包括几个方面

1、渲染状态

渲染状态是指早期的setRenderState那一套东西。比如,前后面裁剪,是否开启混合,混合因子等等。

2、着色方式

着色方式,在固定管线年代,是通过一系列的API进设置。 在可编程管线年代。就对应的是我们的着色器代码。

3、参数

不管是固定管线还是非固定管线,我们都可以设置一些参数用于着色计算。比如颜色,光源信息等等

4、纹理贴图

纹理贴图是表现一个物体表现的颜色细节的必不可少的东西。就是一张张图片。

有了上面的这些数据后,我们就可以根据一定的运算规则,将一个几何体的质感显示为我们想要的样子。

材质、Shader、模型关系图

材质系统的常见需求


一个工具或者系统的设计不可能是凭空而出的。 一定是根据需求和经验的积累,才形成了我们今天这种“材质系统”的概念。 说到这里,那么我们常见的材质系统需要做到什么样子呢。

一、模板 + 实例

材质是一个模板,通过对某一个材质进行实例化,指定不同的数据和贴图,就可以让物体表现出不同的显示效果。 和Class + Object的关系很像。

二、多Pass

有时候,我们为了实现一个绘制效果,靠单次绘制是无法实现的。比如描边效果。 这就要求我们单个物体能够在进行绘制的时候,多次提交材质并绘制。

三、多Technique

多Technique是指一个材质中,应该包含不只一个实现方案。 这样当我们进行材质更替,或者进行高中低端机适配的时候。 就不会那么麻烦。 同时在数据管理上,也显得更为规范。

四、高中低端机适配

高中低端机适配是一个很重要的特性,因为玩家的机型不可能是一样的。 在需要保证效率的情况下,我们很多时候需要降低物体渲染的复杂度。在《3D游戏中的画质与效率适配》一文中。笔者也描述过,有两种方案。 一种是通过宏定义,一种是动态切换Technique。

总结下来,就是说一个材质模板文件应该像这样的一个结构

MaterialTemplate
{
Technique
{
Pass{}
Pass{}
}
Technique
{
Pass{}
Pass{}
}
}

Unity3D中的材质系统


在说到Unity3D中的材质系统的时候,我们先来看一下我们创建一个材质需要做的事情。

一、创建一个Shader并编写出自己想要的效果

二、创建一个Material并将这个Material的Shader指定为自己的材质

三、为这个Material设置参数,赋上贴图等

四、将创建好的Material拖到对象上

我们再来看一个典型的Shader应该具备的内容

Shader "MyShader" {
Properties {
_MyTexture ("My Texture", 2D) = "white" { }
// other properties like colors or vectors go here as well
}
SubShader { LOD
// here goes the 'meat' of your
// - surface shader or
// - vertex and program shader or
// - fixed function shader Pass{} Pass{} }
SubShader { LOD
// here goes a simpler version of the SubShader
// above than can run on older graphics cards Pass{} Pass{}
}
}

我们可以看到。 每一个Shader有多个SubShader,每一个SubShader有多个Pass。 这样看起来和我们前面提到的MaterialTemplate结构几乎一致。

而在Unity3D中。Shader就是材质模版。 Material就是一个材质实例。 每一个Material你可以认为是一个材质实例的序列化存储。

Unity3D中的材质LOD


那对于前面提到的 高中低端机适配。 有两种方法解决。一是通过宏定义,这个并不是Unity3D的推荐方式,且需要Shader编写的相关知识,在这里不作详细讨论。 如果有兴趣的朋友,可以访问括号中的链接(http://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html),以后的文章在涉及Unity3D的Shader编写方面的内容时,再进行讨论。 在此主要讨论Unity3D中通过材质LOD进行画质控制。

在Unity3D的Shader中,可以为每一个SubShader指定一个LOD值,这个LOD值可以通过设置Shader.globalMaximumLODShader.maximumLOD来实现SubShader的切换。所有的SubShader按顺序进行判定,当一个SubShader满足下面两个条件时,才表明可用。

1、SubShaderLOD值小于设定的值。(你可以把LOD看作是开销,开销越大的SubShader指定越高的LOD值)

2、SubShader所有Pass使用到的显卡特性被当前设备支持。

:Shader API文档地址:http://docs.unity3d.com/ScriptReference/Shader.html

:Shader LOD文档地址:http://docs.unity3d.com/Manual/SL-ShaderLOD.html

:Unity3D为每一档的内置Shader都设置了一个默认值,在LOD文档中有

:如果不指定LOD值,那LOD=infinite 。 你可以当它是一个小于0的值。

:这个值除了可以自己给以外,还可以在Edit->Project Settings->Quality面板中指定,如下图

设置面板

Unity3D中的材质替换


官方文档地址http://docs.unity3d.com/Manual/SL-ShaderReplacement.html

夜视效果

有时候,我们希望能够进行一些特殊操作。将场景物体的按另一种渲染方式渲染到RT中。 比如,仅渲染物体的深度,把物体渲染成纯白,把物体渲染成红绿热成像模式等等。但是,我们的材质在一开始就指定好了。如果要替换的话,就需要遍历所有对像,为它们重新指定材质。渲染完毕后,再切换回来。Unity3D为我们提供了更直接的方式。Camera.RenderWithShaderCamera.SetReplacementShader。前者是仅作用一次,后者是一直生效,如果想取消设置。 使用Camera.ResetReplacementShader即可


那么问题来了,我们有时候只想渲染一些特殊的物体。比如,我们想处理除主角以外的内容。 这就需要对主角进行剔除。 那上面两个函数的第二个参数replacementTag就起作用了。如果设置了它,在进行材质替换时,它会和SubShader中的 RenderType的值 进行比对。 比如,我们即将替换的材质如下。

Shader "EffectShader" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
...
}
}
SubShader {
Tags { "RenderType"="SomethingElse" }
Pass {
...
}
}
... }

如果我们调用了camera.SetReplacementShader (EffectShader, "RenderType");那么,一个物体在被渲染时,会产生以下几种结果。

1、如果物体当前激活的SubShader的RenderType是Opaque,那么将会采用EffectShader的第一个SubShader。

2、如果物体当前激活的SubShader的RenderType是SomethingElse,那么将会采用EffectShader的第二个SubShader。

3、如果物体当前激活的SubShader的RenderType在EffectShader中没有与之对应的项,此物体将会在渲染中被忽略。

4、如果物体当前激活的SubShader没有RenderType这个Tag,此物体将会在渲染中被忽略。

结束语


Unity3D拥有着一个灵活的渲染管线和自由的材质系统。与其它图形引擎不一样的是,Unity3D针对游戏需求所留出来的接口非常好用。

而本文仅仅是对Unity3D的材质系统进行初步的描述。要想完全把Unity3D的材质系统总结出来,不是一两篇文章可以搞定的。Unity3D文档中的 Shader Reference可以作为一个十分不错的开始http://docs.unity3d.com/Manual/SL-Reference.html

Thinking in Unity3D:材质系统概览的更多相关文章

  1. Thinking in Unity3D:基于物理着色(PBS)的材质系统

    关于<Thinking in Unity3D> 笔者在研究和使用Unity3D的过程中,获得了一些Unity3D方面的信息,同时也感叹Unity3D设计之精妙.不得不说,笔者最近几年的引擎 ...

  2. Unity3D 装备系统学习Inventory Pro 2.1.2 基础篇

    前言 前一篇 Unity3D 装备系统学习Inventory Pro 2.1.2 总结 基本泛泛的对于Inventory Pro 这个插件进行了讲解,主要是想提炼下通用装备系统结构和类体系.前两天又读 ...

  3. atitit 点播系统 概览 v2 qb1.docx

    atitit 点播系统 概览 v2 qb1.docx 1.1. 多界面(可以挂载多个不同的界面主题)1 1.2. 独立的选片模块(跨设备,跨平台)2 1.3. 跨设备平台(android安卓盒子,pc ...

  4. lumion材质系统室内渲染6.3

    材质系统是对于导入的模型,而不对自带的模型起作用.自带的模型有的能改变属性. 点击“材质”点击墙,出来材质库.为墙体赋予一种材质, 完成后点击保存,就可以保存了.然后给窗户添加玻璃材质. 可以看到墙, ...

  5. 【转载】iPhone系统概览

    iPhone OS OverviewiPhone系统概览iPhone OS comprises the operating system and technologies that you use t ...

  6. 【转】Android系统概览

    这篇文章其实原文叫 <老罗的Android之旅>导读PPT 是罗升阳的博客,我觉得用“Android系统概览”作为标题更贴切些,对于在应用层已经开发了一段时间的人来说,读完之后会有很多体会 ...

  7. Unity3D 装备系统学习Inventory Pro 2.1.2 总结

    前言 写在最前面,本文未必适合纯新手,但有一些C#开发经验的还是可以看懂的,虽然本人也是一位Unity3D新人,但是本文只是自己在学习Inventory Pro的学习总结,而不是教程,本人觉得要读懂理 ...

  8. unity3d 材质概述 ---- shader

    学习笔记:      材质概述:  物体呈现在我们前面除了形体外,还包括“固有颜色”和“质地”(质感与光学性质).固有颜色让物体的表面看起来是什么颜色,而质感决定了该物质是使用什么材质的.在三维建模软 ...

  9. Java——IO系统概览

    前言 对程序语言的设计者来说,创建一个好的输入/输出(IO)系统是一项艰难的任务.这艰难主要来自于要涵盖I/O的所有可能性.不仅存在各种I/O源端和想要与之通信的接收端(源端/接收端:文件.控制台和网 ...

随机推荐

  1. boost强分类器的实现

    boost.cpp文件下: bool CvCascadeBoost::train( const CvFeatureEvaluator* _featureEvaluator, int _numSampl ...

  2. SQL Server-聚焦计算列持久化(二十一)

    前言 上一节我们结束了Hash Match Aggregate和Stream Aggregate的讲解,本系列我们来讲讲关于SQL Server中的计算列问题,简短的内容,深入的理解,Always t ...

  3. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之目录导航

    ASP.NET MVC with Entity Framework and CSS是2016年出版的一本比较新的.关于ASP.NET MVC.EF以及CSS技术的图书,我将尝试着翻译本书以供日后查阅. ...

  4. 代码的坏味道(21)——中间人(Middle Man)

    坏味道--中间人(Middle Man) 特征 如果一个类的作用仅仅是指向另一个类的委托,为什么要存在呢? 问题原因 对象的基本特征之一就是封装:对外部世界隐藏其内部细节.封装往往伴随委托.但是人们可 ...

  5. java时间

    Calendar.getInstance().getTime() 获取当前时间(包括星期和时区 CST China Standard Time):  Fri Jan 06 21:03:36 CST 2 ...

  6. iOS 多线程之GCD的使用

    在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...

  7. iOS开发 判断当前APP版本和升级

    从iOS8系统开始,用户可以在设置里面设置在WiFi环境下,自动更新安装的App.此功能大大方便了用户,但是一些用户没有开启此项功能,因此还是需要在程序里面提示用户的 方法一:在服务器接口约定对应的数 ...

  8. photoshop:无法完成请求 因为暂存盘已满

    今天photoshop打开一个问题,提醒:无法完成请求因为暂存盘已满 不用担心这个问题很好解决可能是你做的图比较大并不需要清理C盘空间 选择:编辑→首选项→暂存盘 设置第一暂存盘为D盘或E盘 总之 第 ...

  9. Linux不能上网ping:unknown host问题怎么解决?

    Linux不能上网提示ping:unknown host 检查步骤 Linux系统跟windows平台有所不同的是,为了更好的做网络服务应用.Linux下多用于网络服务器,而且操作界面是字符界面.对于 ...

  10. 用 eric6 与 PyQt5 实现python的极速GUI编程(系列04)---- PyQt5自带教程:地址簿(address book)

    [引子] 在PyQt5自带教程中,地址簿(address book)程序没有完全实现界面与业务逻辑分离. 本文我打算用eric6+PyQt5对其进行改写,以实现界面与逻辑完全分离. [概览] 1.界面 ...