环境烘培与shader初步,学习笔记一

来源:互联网 发布:儿童拼音软件 编辑:程序博客网 时间:2024/05/01 09:15

         前面写了这么多东西,场景和人物弄到一起风格渐渐统一了,但环境效果差了些,游戏demo显得很简陋,如何让游戏的效果变得绚丽,这个就要考虑对场景环境做烘培,开始写shader了,shader这个东西我不是很在行,所以只能是现学现卖,不过好在网上现成的可利用的shader脚本还是很多的,unity商店里面的样例代码也不少,我在学习之前下载了3个插件,后面再说,先来看看shader是什么,

shader是一段规定好输入(颜色,贴图等)和输出(渲染器能够读懂的点和颜色的对应关系)的程序,结构呢我们看下

网上这个结构很直观

首先是一些属性定义,用来指定这段代码将有哪些输入。接下来是一个或者多个的子着色器,在实际运行中,哪一个子着色器被使用是由运行的平台所决定的。子着色器是代码的主体,每一个子着色器中包含一个或者多个的 Pass。在计算着色时,平台先选择最优先可以使用的着色器,然后依次运行其中的 Pass,然后得到输出的结果。最后指定一个回滚,用来处理所有 Subshader 都不能运行的情况。我们先安装一下sublime,然后在这里下载插件,为什么用这个呢,因为mono或者vs对shader的支持都很有限,而sublime配合专用的插件可以满足代码书写过程中的高亮,补全等等的要求, 尤其是补全,因为刚开始学习,对shader的一些关键字不是很熟悉,如果用自动补全可以减少拼写错误避免可能出现不必要的麻烦,

shader的属性

在 Properties{}中定义着色器属性,在这里定义的属性将被作为输入提供给所有的子着色器。每一条属性的定义的语法是这样的: 
_Name("Display Name", type) = defaultValue[{options}] 
 _Name  - 属性的名字,简单说就是变量名,在之后整个 Shader 代码中将使用这个名字来获取该属性的内容 
 Display Name  - 这个字符串将显示在 Unity 的材质编辑器中作为 Shader 的使用者可读的内容 
 type - 这个属性的类型,可能的 type 所表示的内容有以下几种: 
   --Color - 一种颜色,由 RGBA(红绿蓝和透明度)四个量来定义; 
   -- 2D - 一张2 的阶数大小(256,512 之类)的贴图。这张贴图将在采样后被转为对应基于模型 UV 的每个像素的颜色,最终被显示出来; 
   -- Rect - 一个非2 阶数大小的贴图; 
   -- Cube - 即 Cube map texture(立方体纹理),简单说就是6 张有联系的2D 贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样; 
   -- Range(min, max)  -  一个介于最小值和最大值之间的浮点数,一般用来当作调整
Shader 某些特性的参数(比如透明度渲染的截止值可以是从 0至1 的值等); 
   -- Float - 任意一个浮点数; 
  -- Vector - 一个四维数; 
 defaultValue 定义了这个属性的默认值,通过输入一个符合格式的默认值来指定对应属性的初始值(某些效果可能需要某些特定的参数值来达到需要的效果,虽然这些值可以
在之后在进行调整,但是如果默认就指定为想要的值的话就省去了一个个调整的时间,方便很多)。 
--Color - 以0~1 定义的 rgba 颜色,比如(1,1,1,1); 
--2D/Rect/Cube  - 对于贴图来说,默认值可以为一个代表默认 tint 颜色的字符串,可以是空字符串或者”white”,”black”,”gray”,”bump”中的一个 
--Float,Range - 某个指定的浮点数 
-- Vector - 一个4 维数,写为  (x,y,z,w) 
另外还有一个{option},它只对 2D,Rect 或者 Cube 贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{},当我们需要打开特定选项时可以把其写在这
对花括号内。如果需要同时打开多个选项,可以使用空白分隔。

Tags 

表面着色器可以被若干的标签(tags)所修饰,而硬件将通过判定这些标签来决定什么时候调用该着色器。

Tags { "RenderType"="Opaque" }表示系统应该在渲染非透明物体时调用

LOD是 Level of Detail 的缩写,在这里例子里我们指定了其为200(其实这是Unity 的内建 Diffuse 着色器的设定值)

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 

CGPROGRAM。是一个开始标记,表明从这里开始是一段 CG 程序(我们在写 Unity 的 Shader 时用的是 Cg/HLSL 语言)。最后一行的 ENDCG 与CGPROGRAM是对应的,表明 CG 程序到此结束。 

#pragma surface surf  Lambert语法是这样的

#pragma surface surfaceFunction lightModel [optionalparams] 
surface - 声明的是一个表面着色器 

surfaceFunction - 着色器代码的方法的名字 

lightModel - 使用的光照模型。 

sampler2D 是和 texture 所绑定的一个数据容器接口,sampler2D  _MainTex;做的事情就是再次声明并链接了_MainTex,使得接下来的 CG 程序能够使用这个变量。 

作为输入的结构体必须命名为 Input,这个结构体中定义了一个 float2 的变量…

surf 函数,它的两有参数,第一个是 Input,我们已经明白了:在计算输出时 Shader会多次调用 surf 函数,每次给入一个贴图上的点坐标,来计算输出。第二个参数是一个可
写的 SurfaceOutput,SurfaceOutput 是预定义的输出结构,我们的 surf 函数的目标就是根据输入把这个输出结构填上

<pre name="code" class="html"><span style="color:#ff0000;">SurfaceOutput</span> 结构体的定义如下

structSurfaceOutput{ half3 Albedo;//像素的颜色 half3 Normal;//像素的法向值 half3 Emission;//像素的发散颜色 half Specular;//像素的镜面高光 half Gloss;//像素的发光强度 half Alpha;//像素的透明度 };
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
tex2d在一张贴图中,对一个点进行采样,返回一个float4(half4是一种特殊的float4)

暂时我们了解了上面这些基础知识,就可以来看一些unity成熟的shader插件了,我这里推荐一个


ShadowGun这款插件的效果简直令人惊叹,有兴趣的小伙伴可以下载试试。

接下来我们来说说烘培,unity3d利用lighmapping(光照贴图技术)来烘培物体,这种技术是一种增强场景光照效果的技术,它可以通过较低的性能来使得场景看上去更加真实、丰富,以及更加有立体感。下面简单介绍一下如何烘培物体。

我们以国外的一个培训课程的场景为例


墙壁上面的灯光就是我们的光源,我们在场景中设定足够多的光线探测器,场景中光线照射的物体都要设置为static

单击菜单栏中的window,再单击lightmapping选项,会弹出lightmapping窗口。选择场景中的平行光,在lightmapping窗口的object标签下会出现该光源的设置在lightmapping窗口中的bake标签下,将mode选择为single lightmaps类型。更改bounce数字为2。调整resolution(分辨率)为70,让光影更精细些。

单击lightmapping窗口右下角的bake scen 按钮,即开始生成lightmaps。同时,主窗口右下角会出现进度条,待进度条完成后,就会在场景窗口中显示烘焙效果。

这样烘培场景的就完成了,烘培之后的作用是什么呢?就是根据光源的照射产生被照射物体的贴图,被照射物体尽量是静态物体,这么做可以减少电脑的及时运算量,好处不言而喻。不过因为贴图生成之后会一直存在,所以建议不要在运动物体中使用。

因为这个篇的东西我也属于初学阶段,所以只能当做学习笔记来说明,后面随着学习的不断深入,我也会循序渐进的更新shader的知识。好了,就到这里。

0 0
原创粉丝点击