关于《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. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  2. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  3. H5坦克大战之【画出坦克】

    今天是个特殊的日子,圣诞节,也是周末,在这里先祝大家圣诞快乐!喜庆的日子,我们可以稍微放松一下,扯一扯昨天雷霆对战凯尔特人的比赛,这场比赛大威少又双叒叕拿下三双,而且是一个45+11+11的超级三双, ...

  4. php注册审核

    通过注册审核,判断刚创建的账户是否可以使用. 后台管理员审核通过后,账号可以使用. 通过session 设置只能通过登录入口进入网页. 原理:通过数据库设置账号的一个字段状态,例: isok:1, i ...

  5. [转载]Cookie/Session的机制与安全

    Cookie和Session是为了在无状态的HTTP协议之上维护会话状态,使得服务器可以知道当前是和哪个客户在打交道.本文来详细讨论Cookie和Session的实现机制,以及其中涉及的安全问题. 因 ...

  6. JDBC增加删除修改

    一.配置程序--让我们程序能找到数据库的驱动jar包 1.把.jar文件复制到项目中去,整合的时候方便. 2.在eclipse项目右击"构建路径"--"配置构建路径&qu ...

  7. html中返回上一页的各种写法【转】

    超链接返回上一页代码: <a href="#" onClick="javascript :history.back(-1);">返回上一页</ ...

  8. iOS开发--ChildViewController实现订单页的切换

    先不说废话, 上效果图, 代码量也不大, 也不上传github骗星星了, 你们复制粘贴下代码, 就可以轻而易举的弄出一个小demo. 这个代码的实现并不复杂, 甚至于说非常简单, 就是逻辑有点小绕, ...

  9. php安装threads多线程扩展

    php5.3或以上,且为线程安全版本.apache和php使用的编译器必须一致.通过phpinfo()查看Thread Safety为enabled则为线程安全版.通过phpinfo()查看Compi ...

  10. js格式化日期

    /** *对日期进行格式化, * @param date 要格式化的日期 * @param format 进行格式化的模式字符串 * 支持的模式字母有: * y:年, * M:年中的月份(1-12), ...