您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 广告经营 > Unity3D内部Shader详解
Unity3DBuilt-inShader详解一Unity3D的ShaderUnity里面的Shaders是使用一种叫ShaderLab的语言编写的,它同微软的.FX文件或者NVIDIA的CgFX有些类似。传统意义上的vertexshader和pixelshader还是使用标准的Cg/HLSL编程语言编写的。(因此Unity文档里面的Shader,都是指用ShaderLab编写的代码)然后我们来看下Unity3D自带的60多个Shader。这些Shader被分为五个大类:Normal,Transparent,TransparentCutout,Self-llluminated,Reflective。由于数量比较多,将分几个篇幅一一介绍。(一)NormalShaderFamily这个家族一共9个Shader,都是针对不透明的对象的。(1)Vertex-Lit:最简单的一种Shader之一,所有照射在该物体上的光在一个Pass里面渲染完,光源只在顶点计算。所以不会有任何基于像素渲染得效果,比如说:normalmapping,lightcookies和shadows.这个shader对模型的剖分(将一个物体从几何描述变为多边形表示的过程)非常敏感,如果你将一个点光源放在很靠近一个立方体的一个顶点那里,并且对立方体使用这个shader,光源只会在角落计算。基于像素光照的shader对剖分没有要求,在表现圆形高光上效果也很好。如果上述情况时你想要的效果,你可以考虑使用一个基于像素光照的shader或者增加模型的剖分。(增加顶点数)总的来说,这个shader的渲染代价比较小。这个shader包含了2个subshader,分别对应可编成管线和固定管线。是所有硬件都支持的一个最基本的shader。如果设备支持可编成管线,那使用可编成管线的subshader,否则使用固定管线的。(2)Diffuse:Diffuse基于一个简单的光照模型-Lambertian,光照强度随着物体表面和光入射角夹角的减小而减小(即光垂直于表面时强度最大)。光照的强度只和该角度有关系,和摄像机无关。由于这是一个基于像素光照的shader,因此他有这类shader的优势,同时他需要设备支持可编程管线,如果设备不支持,则自动使用Vertex-Lit这个Shader。总的来说,这个shader渲染代价比较小。(3)SpecularSpecular使用和Diffuse相同的光照模型,但是添加了一个和观察角度相关的反射高光。这个被称为Blinn-Phong光照模型。他包含了一个反射强光,这个反射高光物体表面角度,光的入射角度以及观察者角度都有关系。这种高光计算方法实际上是对实时光源模糊反射的一种具有可行性的模拟。模糊的等级通过inspector里面Shininess这个变量控制。主纹理的alpha通道被用来当作SpecularMap来使用(有时候也称glossmap),它定义了物体的反光率。纹理中alpha里面全黑的部分将完全不反光(即反光率为0%)。而全白的的部分反光率为100%。这个Map在你的物体在不同的部分有不同的反光率的时候非常有用。比如说,锈迹斑斑的金属会反光率低,而磨光的金属反光率比较高。口红的反光率比皮肤高,而皮肤的反光率比棉质衣服高。一个精心制作的SpecularMap将会让玩家身临其境。如果目标设备不支持可编程管线,则自动使用Vertex-Lit这个Shader。这个shader的渲染代价会比较大。(4)BumpedDiffuse同DiffuseShader一样,这个Shader基于Lambertian光照模型,同时使用了normalmapping技术来增加物体表面细节。相对于通过增加剖分来表现物体表面细节的方式,normalmapping并不改变物体的形状,而是使用一张称为NormalMap的特殊纹理来达到这种效果。在normalmap中,每个象素的颜色代表了该像素所在物体表面的法线,然后通过这个法线(而不是通过物体模型计算而来的法线)来计算光照。可以说NormalMap在计算光照的过程中“高效地修改”了整个模型。如何创建Normalmaps:你可以通过导入一张普通的灰度图(白色表示凸起,黑色表示凹进)Unity会自动将它转换为NormalMap。技术细节:这里使用Normalmap是一种“TangentspaceNormalMap”,Tangentspace(正切空间)是一个跟随模型物体表面的空间。在这个空间中,z轴始终从表面指向外面。TangentspaceNormalMap相对于另一种被称为“ObjectspaceNormalMap”来说有点复杂,但是他有一些优势。1)可以使用在各种奇形怪状的表面2)便于在同一物体不同区域或者不同物体间复用具体关于TangentSpaceNormalMap和ObjectSpaceNormalMap的区别,下次再讲。如果调用这个shader失败,则会调用Diffuse这个shader,一般而言,该shader渲染代价低。(5)BumpedSpecular和Specular一样的光照模型,相比Specular而言,它使用一张TangentSpaceNormalMap来描述物体表面法向量的变化,来增加物体细节。(关于normalmap具体见BumppedDiffuse)如果调用失败,则使用Specular这个shader,一般而言,这个shader的渲染代价会比较大。(6)ParallaxDiffuseParallaxNormalmapped与传统的normalmapped一样,但是对“深度”的模拟更佳。额外的深度效果是通过HeightMap(高度图)来实现的。HeightMap在Normalmap的alpha通道里面保存。全黑表示么有高度,而白色表示有高度。通常这用来表现石头或者砖块间的裂缝。Parallaxmapping的技术很简单,因此会有些人工痕迹或者不太正常的效果出现。尤其是,急剧陡峭的高低转换在高度图里面应该避免。在inspector里面调整height数值来调整高度的范围,有时候会造成物体不真实,凌乱的情况。因此建议使用高度变化平缓的高度图或者将高度数值设置比较低,让表面看起来比较平缓。这个shader的渲染代价相比bumpeddiffuse而言更大。如果调用这个Shader失败,则自动使用BumpedDiffuse。(7)ParallaxSpecular与BumpedSpcular相比,增加了一张HeightMap来描述深度细节。关于HeightMap,见parallaxDiffuse。如果调用失败,则调用BumpedSpecular这个Shader。(8)Decal这个Shader在unity文档里面的描述和Unity3.0有明显的实现区别,文档由于比较老,07年写的,官网下的Built-inShader里面,decal是使用可编程管线实现的,就是说,如果你的机器不支持可编程管线,会使用diffuse,因为diffuse也不需要可编程管线,所以只能使用vertex-lit。这个Shader除了主纹理之外,这个Shader还是用了第二张纹理用来描述细节。第二张用来Decal(贴花)的纹理使用alpha通道来确定是否覆盖主纹理。贴花用的纹理只是对主纹理的补充。比如说你有一个砖砌的墙壁,你可以使用一个砖块的纹理作为主纹理,然后使用带有alpha通道的Decal纹理在墙壁的不同地方涂鸦。(9)DiffuseDetail这是一个普通的diffuseshader加上一些额外数据的shader。它允许你定义第二张纹理,称为DetailTexture。当camera靠近的时候,DetailTexture逐渐显示出来,一般用于地形。比如说,当你使用一张低分辨率的纹理拉升到整个地形上的时候。随着camera逐渐拉近,低分辨率的纹理开始模糊,这不是我们想要的效果。为了避免这个效果,创建一张Detail纹理会将地形tile化。在这种模式下,随着camera逐渐拉近,额外的细节将会出现以避免出现模糊的效果。Detail纹理是覆盖在主纹理上面的。Detail纹理中深色的部分将会使得主纹理变深,而淡色的部分将会使主纹理变亮,Detail纹理通常是浅灰色。(与Decal里面Decal纹理不同的是,Decal纹理是RGBA,通过alpha控制DecalTexture与MainTexture的融合,而Detail的纹理是RGB,直接是两张纹理的rgb通道分别相乘再*2,就是说,Detail纹理中颜色数值=0.5不会改变主纹理颜色,0.5会变亮,0.5加深)UnityBuilt-inShader详解二这次主要讨论Unity自带的Shader中TransparentShaderFamily这个家族的Shader一共7种,原理和类型与Normal中的上差不多,只不过这些Shader是用在半透明或者全透明的物体上面的。他们的主纹理接受RGBA4个通道。如果你的模型一部分是半透明,一部分是不透明的。请分开使用两张材质,半透明的材质这个家族的Shader。这个家族的Shader的内容和Normal中同名的几乎一样,只是添加了半透明效果,因此不再做重复介绍。通过读取纹理中的alpha值,这个Transparent家族的shader可以让模型变成半透明或者全透明的。在alpha中,0表示全透明,255表示全白。如果你的主纹理不包含alpha通道,那么这个物体将会变成不透明的。在游戏中使用半透明的物体是比较有技巧性的,因为他们经常会导致排序问题。比如说,如果你透过两个窗口观察物体,发觉物体很异样,恭喜你,你正在经历着每个人都会遇到的使用半透明对象的问题。一条具有普遍性的规则是:有些时候一个半透明的对象会很诡异的绘制在另外一些对象前面,尤其当这些对象是互相交叉的,或者一个把另一个包围的抑或是。为此,当你需要半透明对象的时候,你应该使用它们,但是不要太过于依赖半透明对象(考虑到性能问题)。你也应该让你的设计者们了解到排序可能会出现问题,让他们做好为此调整的准备。(1)Vertex-Lit这个家族中最简单的Shader,同样有固定管线和可编程管线两个SubShader,适用于所有的硬件。所有的光只在顶点计算。除了支持半透明,其他特性和Normal里面的Vertex-Lit一致。(2)TransparentDiffuse同Normal中的Diffuse,支持了alpha。(3)TransparentSpecular同NormalSpecular,支持了半透明(4)TransparentBumpedDiffuse同Normal中的BumpedDiffuse(5)TransparentBumpedSpecular同Normal里面的BumpedSpecular,支持半透明(6)TransparentparallaxDiffuse同NormalparallaxDiffuse,支持半透明(7)TransparentParallaxSpecular同NormalParallaxSpecular,支持半透明。UnityBuilt-inShader详解三上次讲的是TransparentShaderFamily,他们是绘制半透明的对象使用的,但他们并不能满足我们全部的要求。TransparentCutoutShaderFamily是对半透明对象Shader的一类补充,与TransparentShaderFamily有所区别的是:CutoutShaderFaimily中的Shaders不允许绘制部分透明的区域。就是说,使用这种Shader绘制出来的对象,要么是全透明,要么是半透明。使用这个家族Shader的对象通常用来转换和接受阴影。半透明对象中常有的排序问题在使用这类Shader的时候不存在。这个家族里面的所有Shader都定义了一个AlphaCutout的数值,纹理中alpha大于AlphaCutout数值的,被认为是不透明的,否则就是全透明的。通过这个al
本文标题:Unity3D内部Shader详解
链接地址:https://www.777doc.com/doc-4762417 .html