关键词不能为空

当前您在: 主页 > 英语 >

Unity3D Shader入门指南

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-03-01 02:06
tags:

-

2021年3月1日发(作者:转向轴)


Unity3D Shader


入门指南(一)



分类:



Unity3d


2014-04-28 17:40 16


人阅读



评论


(0)


收藏



举报



unity3dShader3d


渲染



目录


(?)[+]



本文转载自:


/2013/07/shader- tutorial-1/



动机


< /p>


自己使用


Unity3D


也有一段时间了 ,但是很多时候是流于表面,更多地是把这个引擎简单


地用作脚本控制,而对更深入一些 的层次几乎没有了解。


虽然说


Unity


引擎设计的初衷就是


创建简单的不需要开发者操心的谁都能用的


3D


引擎,但是只是肤浅的使用,可能是无法达


到随心所欲的 境地的,


因此,


这种状况必须改变!


从 哪里开始呢,


貌似有句话叫做会写


Shader


的都是高手,于是,想大概看看从


Shader


开始能 不能使自己到达的层次能再深入一些吧,


再于是,有了这个系列(希望我能坚持写完它, 虽然应该会拖个半年左右)。



Unity3D


的所有渲染工作都离不开着色器(


Shader


),如 果你和我一样最近开始对


Shader


编程比较感兴趣的话,< /p>


可能你和我有着同样的困惑:


如何开始?


Unity3D


提供了一些


Shader


的手册和文档(比如


这里



这里



这里


),但是一来内容比较分散,二来学 习阶梯稍微陡峭


了些。


这对于像我这样之前完全没有接触过有关 内容的新人来说是相当不友好的。


国内外虽


然也有一些


Shader


的介绍和心得,但是也同样存在内容分散的问题,很多教程 前一章就只


介绍了基本概念,接下来马上就搬出一个超复杂的例子,对于很多基本的用法 并没有解释。


也许对于


Shader


熟 练使用的开发者来说是没有问题,


但是我相信像我这样的入门者也并不

< br>在少数。在多方寻觅无果后,我觉得有必要写一份教程,来以一个入门者的角度介绍一些

< br>Shader


开发的基本步骤。其实与其说是教程,倒不如说是一份自我总结,希 望能够帮到有


需要的人。



所以,本< /p>



教程



的对象 是



?



总的 来说是新接触


Shader


开发的人:也许你知道什么是


Shader


,也会使用别人的


Shader



但是仅限于知道一些基本的内建


Sh ader


名字,


从来没有打开它们查看其源码。



?



想要更多了解


Shader


和有需求要进行


Shader


开发的开发者,但是之前并没有


Shader


开发的经验。



当然,因为我本身在


Shader


开发方面也是一个不折不扣的大菜鸟,本文很多内容也只是在


自己的理解加上一些可能不太靠谱的求证和总结。


本文中的示例应该会有更好 的方式来实现,


因此您是高手并且恰巧路过的话,如果有好的方式来实现某些内容,恳请 您不吝留下评论,


我会对本文进行不断更新和维护。



一些基本概念



Shader



Material



如果是进行


3D


游戏开发的话,


想必您 对着两个词不会陌生。


Shader


(着色器)实际上就是


一小段程序,它负责将输入的


Mesh


(网 格)以指定的方式和输入的贴图或者颜色等组合作


用,


然后输出 。


绘图单元可以依据这个输出来将图像绘制到屏幕上。


输入的贴 图或者颜色等,


加上对应的


Shader



以及对


Shader


的特定的参数 设置,


将这些内容



Shader


及输入参数)


打包存储在一起,得到的就是一个

Material


(材质)。之后,我们便可以将材质赋予合适的

< br>renderer


(渲染器)来进行渲染(输出)了。



所以说


Shader


并没有什么特别神 奇的,


它只是一段规定好输入


(颜色,


贴图等)


和输出


(渲


染器能够读懂的点 和颜色的对应关系)的程序。而


Shader


开发者要做的就是 根据输入,进


行计算变换,产生输出而已。


< br>Shader


大体上可以分为两类,简单来说



?



表面着色器(


Surface Shader




-


为你做了大部分的工作,只需要简单的技巧即可实现


很多不错的效果。类比卡片 机,上手以后不太需要很多努力就能拍出不错的效果。



?



片段着色器(


Fragment Shader




-


可以做的事情更多,但是也比较难写。使用片段着


色器的主要目的是可以在比较 低的层级上进行更复杂(或者针对目标设备更高效)的开


发。



因为是入门文章,所以之后的介绍将主要集中在表面着色器上。



Shader


程序的基本结构



因为着色器代码可以说专用性非常强,


因此人为地规定了它的基本结构 。


一个普通的着色器







< br>这



的:



Shader


程序的结构


< p>
一段


首先是一些属性定义,


用来指定这段代码将有 哪些输入。


接下来是一个或者多个的子着色器,


在实际运行中, 哪一个子着色器被使用是由运行的平台所决定的。子着色器是代码的主体,


每一个子着色 器中包含一个或者多个的


Pass


。在计算着色时,平台先选择 最优先可以使用


的着色器,然后依次运行其中的


Pass


,然后得到输出的结果。最后指定一个回滚,用来处


理所有

< p>
Subshader


都不能运行的情况(比如目标设备实在太老,所有


Subshader


中都有其


不支持的特性 )。



需要提前说明的是,在实际进行表面着色器的开发时,我 们将直接在


Subshader


这个层次


上写代码,系统将把我们的代码编译成若干个合适的


Pass


。废话到此为止,下面让我们真


正实际进入


Shader


的世界吧。



Hello Shader < /p>


百行文档不如一个实例,下面给出一段简单的


Shader


代码,然后根据代码来验证下上面说


到的结构和阐述一些基本的


Shader


语法。因为本文是针对


Unit y3D


来写


Shader


的,所以


也使用


Unity3D


来演示吧。


首先,


新建一个


Shader

< br>,


可以在


Project


面板中 找到,


Create



选择

< p>
Shader


,然后将其命名为


Diffuse Texture





Unity3D


中新建一个


Shader



随便用个文本编辑器打开刚才新建的


Shader




1


Shader


2


Properties {


3


_MainTex (


4


}


5


SubShader {


6


Tags {


7


LOD 200


8



9


CGPROGRAM


10


#pragma surface surf Lambert


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26



sampler2D _MainTex;



struct Input {


float2 uv_MainTex;


};



void surf (Input IN, inout SurfaceOutput o) {


half4 c = tex2D (_MainTex, _MainTex);


=


= c.a;


}


ENDCG


}


FallBack


}


如果您之 前没怎么看过


Shader


代码的话,估计细节上会看不太懂。 但是有了上面基本结构


的介绍,


您应该可以识别出这个


Shader


的构成,


比如一个


Properties


部分,


一个

SubShader



以及一个


F allBack


。另外,第一行只是这个


Shader


的声明并为其指定了一个名字,比如我


们的实例


Shader


,你可以在材质面板选择


Shader

< p>
时在对应的位置找到这个


Shader





Unity3D


中 找到


刚才新建的


Shader



接下来我们讲逐句讲解这个


Shader


,以 期明了每一个语句的意义。



属性


< /p>



Properties{}


中定义着色 器属性,在这里定义的属性将被作为输入提供给所有的子着


色器。每一条属性的定义的语 法是这样的:



_Name(



?



_Name -


属性的名字,简单说就是变量名,在之后整个


Shader

代码中将使用这个名字


来获取该属性的内容



?



Display


Name


-


这个字符串将显示在< /p>


Unity


的材质编辑器中作为


Shad er


的使用者可读


的内容



?



type -

< br>这个属性的类型,可能的


type


所表示的内容有以下几 种:



o



Color -


一种颜色,由


RGB A


(红绿蓝和透明度)四个量来定义;



o



2D -


一张


2


的阶数大小(


256



512


之类)的贴图。这张贴图将在采样后被 转为对应


基于模型


UV


的每个像素的颜 色,最终被显示出来;



o



Rect -


一个非


2


阶数大小的贴图;



o



Cube -



Cube map texture


(立方体纹理)



简单 说就是


6


张有联系的


2D


贴图的组


合,主要用来做反射效果(比如天空盒和动态反射)


,也会被转换为对应点的采样;



o



Range(min,


max)


-


一个介于最小值和最大 值之间的浮点数,一般用来当作调整


Shader


某些特性的参 数(比如透明度渲染的截止值可以是从


0


1


的值等)




o



Float -


任意一个浮点数;



o



Vector -


一个四维数;



?



defaultValue


定义了这个属性的默认值,通过输入一个符合格式的默认值来指定对应属

性的初始值(某些效果可能需要某些特定的参数值来达到需要的效果,虽然这些值可以


在之后在进行调整,但是如果默认就指定为想要的值的话就省去了一个个调整的时间,


方便很多)




o



Color -



0



1

定义的


rgba


颜色,比如


(1, 1,1,1)




o



2D/Rect/Cube


-


对于贴图来说,默认值可以为一个代表默认


tint


颜色的字符串,可


以是空字符串或者


”white”,”black”,”gray”,”bump”


中的一 个



o



Float



Range -


某个指定的浮点数



o



Vector -


一个


4


维数,写为



(x,y,z,w)


?


< p>
另外还有一个


{option}


,它只对


2D



Rect


或者< /p>


Cube


贴图有关,在写输入时我们最少要


在贴图之后写一对什么都不含的空白的


{}


,当我们需要打开 特定选项时可以把其写在这



花括


号内


。如


果需要同


时打

开多


个选


项,可以


使用

< p>
空白


分隔


。可能的


选择< /p>



ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal


中的一个, 这些都是


OpenGL



T

< p>
exGen


的模式,具体的留到后面有机会再说。



所以,一组属性的申明看起来也许会是这个样子的



1


//Define


a


color


with


a


default


value


of


semi-transparent


blue


2


_MainColor (


3


//Define a texture with a default of white


4


_Texture (


现在看懂上面那段


Shader



以 及其他所有


Shader




Properties


部分应该不会有任何问题


了。接下来就是


SubShader


部分了。

< br>


Tags



表面着色器可以被 若干的标签(


tags



所修饰,


而硬件将通过判定这些标签来决定什么时候


调用该着色器。比如我们 的例子中


SubShader


的第一句



Tags {



告诉了系统应该在渲 染非透明物体时调用我们。


Unity


定义了一些列这样的渲染 过程,与


RenderType



Op aque


相对应的显而易见的是



,表示


渲染含有透明效果的物体时调用。在这里


Tags


其实暗示了你的


Shader


输出的是什么,如


果输出中都是非透明物体,那写在


Opaque

里;如果想渲染透明或者半透明的像素,那应


该写在


Tra nsparent


中。



< p>














Projectors


< p>




< br>(从不产生阴影)以及



(指定渲染顺

序队列)。这里想要着重说一下的是


Queue


这个标签, 如果你使用


Unity


做过一些透明和


不透明物体的混合的话,


很可能已经遇到过不透明物体无法呈现在透明物体之后的情况。



种情况很可能是由于


Shader< /p>


的渲染顺序不正确导致的。


Queue


指 定了物体的渲染顺序,



定义的


Que ue


有:



?



?



Background -


最早被调用的渲染,用来渲染天空盒或者背景



Geometry -


这是默认值,


用来渲染非透明物体


(普通情况下,场景中的绝大多数物体应


该 是非透明的)



?



AlphaT


est -


用来渲染经过


Alpha T


est< /p>


的像素,单独为


AlphaTest


设定 一个


Queue


是出


于对效率的考虑< /p>



?



?



Transparent -


以从后往前的顺序渲染透明物体



Overlay -


用来渲染叠加的效果,是渲染的最后阶段 (比如镜头光晕等特效)



这些预定义的值本质上是一组定义整数,


Background


=


1000




Geometry


=


2000,


AlphaTest = 2450




Transparent = 3000


,最后


Overlay = 4000


。在我们实际设置


Queue


值时,

< br>不仅能使用上面的几个预定义值,


我们也可以指定自己的


Queue


值,


写成类似这样:




表示一个在


Transparent


之后


100



Que ue


上进行调用。


通过调整


Queue


值,我们可以确保某些物体一定在另一些物体之前或者之后渲染,这个技


巧有时候很有用处。



LOD



LOD


很简单,它是


Level


of


Detail


的缩写,在这里例 子里我们指定了其为


200


(其实这是


Unity


的内建


Diffuse


着色 器的设定值)。这个数值决定了我们能用什么样的


Shader


。在


Unity



Quality S ettings


中我们可以设定允许的最大


LOD



当设定的


LOD


小于


SubShader


所指定的


LOD


时,


这个


SubShader


将不可用。


Unity


内建


S hader


定义了一组


LOD


的数值,


我们在实现自己的


Shader


的时候 可以将其作为参考来设定自己的


LOD


数值,这样在之后


调整根据设备图形性能来调整画质时可以进行比较精确的控制。



?



?



?



?



?



?



?



?



VertexLit


及其系列



= 100


Decal, Reflective VertexLit = 150


Diffuse = 200


Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250


Bumped, Specular = 300


Bumped Specular = 400


Parallax = 500


Parallax Specular = 600


Shader


本体


< br>前面杂项说完了,


终于可以开始看看最主要的部分了,


也 就是将输入转变为输出的代码部分。


为了方便看,请容许我把上面的

SubShader


的主题部分抄写一遍



1


CGPROGRAM


2


#pragma surface surf Lambert


3



4


sampler2D _MainTex;


5



6


struct Input {


7


float2 uv_MainTex;


8


};


9



10


11


12


13


14


15


void surf (Input IN, inout SurfaceOutput o) {


half4 c = tex2D (_MainTex, _MainTex);


=


= c.a;


}


ENDCG


还是逐行来看,


首先是


CGPROGR AM



这是一个开始标记,


表明从这里 开始是一段


CG



序(我们在写


Unity



Shader

< br>时用的是


Cg/HLSL


语言)。最后一行的

< p>
ENDCG



CGPROGRAM


是对应的,表明


CG


程序到此结束。

< br>


接下来是是一个编译指令:


#pragma surface surf Lambert


,它声明了我们要写一个表



Shader


,并指定了光照模型。它的写法是这样 的



#pragma surface surfaceFunction lightModel [optionalparams]



?



?



?



surface -


声明的是一个表面着色器



surfaceFunction -


着色器代码的方法的名字



lightModel -


使用的光照模型。



所以在我们的例子 中,我们声明了一个表面着色器,实际的代码在


surf


函数中 (在下面能


找到该函数),使用


Lambert


(也就是普通的


diffuse


)作为光照模型。



接下来一句


sampler2D _Ma inTex;



sampler2D


是 个啥?其实在


CG


中,


sampler 2D



是和


texture

< p>
所绑定的一个数据容器接口。等等


..


这个说法还 是太复杂了,简单理解的话,


所谓加载以后的


texture< /p>


(贴图)


说白了不过是一块内存存储的,


使用了


RGB


(也许还有


A

< p>


通道,且每个通道


8bits

< br>的数据。而具体地想知道像素与坐标的对应关系,以及获取这些数


据,我们总不能 一次一次去自己计算内存地址或者偏移,因此可以通过


sampler2D


来对贴


图进行操作。更简单地理解,


sampler 2D


就是


GLSL


中的


2D


贴图的类型,相应的,还有


sampler1D< /p>



sampler3D



samplerCube


等等格式。



解释通了


sampler2D


是什么之后,还需要解释 下为什么在这里需要一句对


_MainTex


的声


明,之前我们不是已经在


Properties


里声 明过它是贴图了么。答案是我们用来实例的这



shader< /p>


其实是由两个相对独立的块组成的,外层的属性声明,回滚等等是


Unity


可以直


接使用和编译的


Sh aderLab


;而现在我们是在


CGPROGRAM...E NDCG


这样一个代码块中,


这是一段


CG


程序。对于这段


CG


程序,要想访 问在


Properties


中所定义的变量的话,


必须使用和之前变量相同的名字进行声明。于是其实


sampler2D < /p>


_MainTex;


做的事情就是


再次声 明并链接了


_MainTex


,使得接下来的

< br>CG


程序能够使用这个变量。



终于可以继续了。


接下来是一个


struct

< br>结构体。


相信大家对于结构体已经很熟悉了,


我们先


跳过之,直接看下面的的


surf


函数。上 面的


#pragma


段已经指出了我们的着色器代码的方


法的名字叫做


surf


那没跑儿了,


就是这段代码是我们的着色器的工作核心。


我 们已经说过


不止一次,着色器就是给定了输入,然后给出输出进行着色的代码。


CG


规定了声明为表面


着色器的方法(就是我们 这里的


surf


)的参数类型和名字,因此我们没有权利决定< /p>


surf



输入输出参数的类型,只能按 照规定写。这个规定就是第一个参数是一个


Input


结构,第 二


个参数是一个


inout



SurfaceOutput


结构。



它们分别是什么呢?


Input


其实是需要我们 去定义的结构,这给我们提供了一个机会,可以


把所需要参与计算的数据都放到这个


Input


结构中,传入


surf


函数使用;


SurfaceOutput



已经定义好了里面类型输出结构,


但是一开始的时候内容暂时是空白 的,


我们需要向里面填


写输出,这样就可以完成着色了。先仔细 看看


INPUT


吧,现在可以跳回来看上面定义的


INPUT


结构体了:



1


struct Input {


2


float2 uv_MainTex;


3


};


作为输入的结构体必须命名为


Input


,这个 结构体中定义了一个


float2


的变量



你没看错我


也没打错,


就是


float2


,表示浮点数的


float


后面紧跟一个数字


2


,这又是什么意思呢? 其实


没什么魔法,


float



vec


都可以在之后加入一个


2



4


的数字,来表示被打包在一起的


2



4


个同类型数。比如下面 的这些定义:



1


//Define a 2d vector variable


2


vec2 coordinate;


3


//Define a color variable


4


float4 color;


5


//Multiply out a color


6


float3 multipliedColor = * coordinate.x;


在访问这 些值时,我们即可以只使用名称来获得整组值,也可以使用下标的方式(比


< p>
.xyzw



.rgba


或它们的部分比如


.x


等等)来获得某个值。在这个例子里,我 们声明了一


个叫做


uv_MainTex


的包含两个浮点数的变量。



如果你对


3D


开发稍有耳闻的话,一定不会对


uv

这两个字母感到陌生。


UV


mapping


的作


用是将一个


2D


贴图上 的点按照一定规则映射到


3D


模型上,是


3D


渲染中最常见的一种顶


点处理手段。


CG


程序中,


我们有这样的约定 ,


在一个贴图变量


(在我们例子中是


_ MainTex



之前加上


uv


两个字母,


就代表提取它的


uv



(其实就是两个代表贴图上点的二维坐标





我们之后就可以在


surf


程序中直接通过访问


uv_MainTex


来取得这张贴图当前需要计算的


点的坐标值了。



如果你坚持看到这里了,那要恭喜你,因为离最后成功读完一个


Shader


只有一步之遥。我


们回到


surf


函数,


它的两有参数,


第一个 是


Input



我们已经明白了:


在计算输出时


Shader


会多次调用


surf


函数,每次给入一个贴图上的点坐标,来计算输出。第二个 参数是一个可


写的


SurfaceOutput



SurfaceOutput


是预定义的输出结构, 我们的


surf


函数的目标就是根


据输 入把这个输出结构填上。


SurfaceOutput


结构体的 定义如下



1


struct SurfaceOutput {


2


3


4


5


6


7


8


half3 Albedo; //


像素的颜色



half3 Normal; //


像素的法向值



half3 Emission; //


像素的发散颜色



half Specular; //


像素的镜面高光



half Gloss; //


像素的发光强度



half Alpha; //


像素的透明度



};

< p>
这里的


half


和我们常见


float



double


类似,< /p>


都表示浮点数,


只不过精度不一样。


也许 你很


熟悉单精度浮点数(


float


或 者


single


)和双精度浮点数(


d ouble


),这里的


half


指的是 半


精度浮点数,精度最低,运算性能相对比高精度浮点数高一些,因此被大量使用。



在例子中,我们做的事情非常简单:



1


half4 c = tex2D (_MainTex, _MainTex);


2


=


3


= c.a;


这里用到了一个


tex2d


函数,


这是


CG


程序中用来在一张贴图中对一个点进行采样的方法,


返回一个


float4


。这里对


_M ainTex


在输入点上进行了采样,并将其颜色的


rbg


值赋予了输


出的像素颜色,将


a

< p>
值赋予透明度。于是,着色器就明白了应当怎样工作:即找到贴图上


对应的


uv


点,直接使用颜色信息来进行着色,


over




接下来




我 想现在你已经能读懂一些最简单的


Shader


了,接下来我推 荐的是参考


Unity



Surfac e


Shader


Examples


多接触一些各种各样的基本


Shader


。在这篇教程的基础上 ,配合一些


google


的工作,完全看懂这个


shader


示例页面应该不成问题。如果能做到无压力看懂,那


说明你已经有良好的基础可以前进到


Shader


的 更深的层次了


(也许等不到我的下一篇教程


就可以自己开始动手 写些效果了);如果暂时还是有困难,那也没有关系,


Shader

学习绝


对是一个渐进的过程,因为有很多约定和常用技巧,多积累和实践自然会进步 并掌握。



在接下来的教程里,


打算通 过介绍一些实际例子以及从基础开始实际逐步动手实现一个复杂


一点的例子,让我们能看 到


shader


在真正使用中的威力。我希望能尽快写完这个系 列,但


是无奈时间确实有限,


所以我也不知道什么时候能出炉< /p>



写好的时候我会更改这段内容并指


向新 的文章。您要是担心错过的话,也可以使用


邮件订阅


或者


订阅本站的


rss


(


虽然


Google


Reader


已经关了


- -)




Unity3D Shader


入门指南(二)



关于本系列



这是


Unity3D


Shader< /p>


入门指南系列的第二篇,本系列面向的对象是新接触


Shader


开发的


Unity3D


使用者,因为我 本身自己也是


Shader


初学者,因此可能会存在错误或者疏 漏,如


果您在


Shader


开发上有所 心得,很欢迎并恳请您指出文中纰漏,我会尽快改正。在


之前的


开篇


中介绍了一些


Shader


的基本 知识,包括


ShaderLab


的基本结构和语法,以及简单逐


句地讲解了一个基本的


shader



在具有这些基础知识后,


阅读简单的


s hader


应该不会有太


大问题,在继续教程之前简单阅读一下


Unity



Surface


Shader


Example


,以检 验您是否


掌握了上一节的内容。如果您对阅读大部分示例


Sha der


并没有太大问题,可以正确地指出


Shader


的结构,声明和使用的话,就说明您已经准备好继续阅读本节的内容了。



法线贴图


(Normal Mapping)


法线贴图是凸凹贴图


(Bump


ma pping)


的一种常见应用,简单说就是在不增加模型多边形数


量的前提下,


通过渲染暗部和亮部的不同颜色深度,


来为原来 的贴图和模型增加视觉细节和


真实效果。


简单原理是在普通的贴 图的基础上,


再另外提供一张对应原来贴图的,


可以表示


渲染浓淡的贴图。


通过将这张附加的表示表面凸凹的贴图的因素于实际 的原贴图进行运算后,


可以得到新的细节更加丰富富有立体感的渲染效果。


在本节中,


我们将首先实现一个法线贴


图的


Shader


,然后对


Unity Shade r


的光照模型进行一些讨论,并实现一个自定义的光照模


型。最 后再通过更改


shader


模拟一个石头上的积雪效果,并对模 型顶点进行一些修改使积


雪效果看起来比较真实。


在本节结束的 时候,


我们就会有一个比较强大的可以满足一些真实


开发工作时 可用的


shader


了,而且更重要的是,我们将会掌握它是如 何被创造出来的。



关于法线贴图的效果图,

< br>可以对比看看下面。


模型面数为


500

< br>,


左侧只使用了简单的


Diffuse

< br>着色,


右侧使用了法线贴图。


比较两张图片不难发现,< /p>


使用了法线贴图的石头在暗部和亮部


都有着更好的表现。整体来说 ,凸凹感比


Diffuse


的结果增强许多,石头看起来更真实 也更


具有质感。



image



本节中需要用到的上面的 素材可以


在这里下载



其中包括上面的 石块的模型,


一张贴图以及


对应的法线贴图。

< br>将下载的


package


导入到工程中,


并新建一个


material



使用简单的


Diffuse



Sha der


(比如上一节我们实现的),再加上一个合适的平行光光源,就可以得到我们左< /p>


图的效果。另外,本节以及以后都会涉及到一些


Unity


内建的


Shader


的内容,比如一些标


准常用函数和常量定义等,相关内容可以在


Unity


的内建


Shader


中找到,内建

< br>Shader



以在


Unity


下载页面


的版本右侧找到。



接下来我们实现法线贴图。


在实现之前,


我们先 简单地稍微多了解一些法线贴图的基本知识。


大多数法线图一般都和下面的图类似,是一 张以蓝紫色为主的图。这张法线图其实是一张


RGB


贴图,其中 红,绿,蓝三个通道分别表示由高度图转换而来的该点的法线指向:


Nx



Ny



Nz


。在其中绝大部分点的法线都指向


z


方向,

< p>
因此图更偏向于蓝色。在


shader


进行处


理时,


我们将光照与该点的法线值进行点积后即可得到在该光线下应 有的明暗特性,


再将其


应用到原图上,即可反应在一定光照环境 下物体的凹凸关系了。关于法向贴图的更多信息,


可以参考


wi ki


上的相关条目




一张典


型的法线图


< br>回到正题,我们现在考虑的主要是


Shader


入门,而 不是图像学的原理。再上一节我们写的


Shader


的基础上稍 微做一些修改,


就可以得到适应并完成法线贴图渲染的新


Sha der



新加


入的部分进行了编号并在 之后进行说明。



1


Shader


2


Properties {


3


_MainTex (


4


-


-


-


-


-


-


-


-



本文更新与2021-03-01 02:06,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/685160.html

Unity3D Shader入门指南的相关文章