一、Unity中Shader的类型
1.固定管线着色器(Fixed Function Shader)
2.顶点/片元着色器(Vertex/Fragment Shader)
3.表面着色器(Surface Shader)
-------------------------------------------------------------------------------------------------------------------------------
三种着色器的相同点:
①都必须从唯一一个根Shader开始? ②Properties参数部分,作用及语法完全相同? ③具体功能都在SubShader里(Subshader会自上而下运行第一个硬件能支持的)? ④SubShader都可以打标签? ⑤都可以回滚? ⑥都可以处理基本的功能,例如光照漫反射(Diffuse)以及镜面反射(Specular)。但是Vertex and Fragment和Surface都能实现Fixed function实现不了的高级功能,例如基于uv计算的效果等等。
-------------------------------------------------------------------------------------------------------------------------------
三种着色器的不同点:
①Fixed function shader以及Vertex and Fragment Shader在subshader下面还有pass{}结构,但是Surface Shader,已经将具体内容打包在光照模型了,不能加pass{}? ②Fixed function shader每句代码之后没有分号“;”, 但是V&F shader以及Surface shader每句代码之后都必须加分号“;”? ③核心结构不同?
个人理解:Surface?Shader是Unity为了方便shader编写提供的特殊功能,它对底层的vertex/fragment shader做了封装,省去了一些重复代码编写的工作量。我的理解是它同时具有vertex/fragment shader的功能,只是写法上更加简洁,更容易上手。
二、Surface Shader语法
Shader "Custom/SurfaceShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
//----------------------------------------------------------------------------------------------------------------------
//定义着色器属性
//_Name(“Display Name”, type) = defaultValue[{options}] 属性定义格式
//Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
//2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
//Rect - 一个非2阶数大小的贴图;
//Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样;
//Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等);
//Float - 任意一个浮点数;
//Vector - 一个四维数;
//----------------------------------------------------------------------------------------------------------------------
}
SubShader
{
Tags { "RenderType"="Opaque" }
//----------------------------------------------------------------------------------------------------------------------
//Tags标签里面默认的“RenderType”=”Opaque”,是告诉系统应该在渲染非透明物体时调用这个SubShader
//“RenderType” = ”Transparent”表示在渲染含有透明效果的物体时调用该Sunshader,
//Tags里面还有许多其他的我们可选的标签
//①.“Queue”:定义渲染顺序。预制的值有这些
// ”Background”。值为1000。比如用于天空盒。
// ”Geometry”。值为2000。大部分物体在这个队列。不透明的物体也在这里。
// ”AlphaTest”。值为2450。已进行AlphaTest的物体在这个队列。
// ”Transparent”。值为3000。透明物体。
// ”Overlay”。值为4000。比如镜头光晕。
// 用户可以定义任意值,比如”Queue” = ”Geometry + 10”
//②.“RenderType”:定义渲染类型。预制的值有这些
// ”Opaque”:绝大部分不透明的物体都使用这个;
// ”Transparent”:绝大部分透明的物体、包括粒子特效都使用这个;
// ”Background”:天空盒都使用这个;
// “Overlay”:GUI、镜头光晕都使用这个;
//③.“ForceNoShadowCasting”:定义物体是否有阴影效果
// “true”。表示有阴影
// “false”。表示没有阴影
//----------------------------------------------------------------------------------------------------------------------
LOD 200
//Level of Detail的缩写,它表示着色器的细节层次效果。在某些硬件比较差的系统上,我们可以设置一个低一点的值,减少细节的显示。
CGPROGRAM
#pragma surface surf Standard fullforwardshadows
//----------------------------------------------------------------------------------------------------------------------
//编译指令
//#pragma surface surfaceFunction lightModel [optionalparams] 写法
//surface - 声明的是一个表面着色器
//surfaceFunction - 着色器代码的方法的名字
//lightModel - 使用的光照模型。
//
//拓展:光照模型
//ambert:该光照模型能很好的表示粗糙表面的光照,但不能表现出镜面反射高光
//Toon:最近在游戏中常用的风格之一即是Toon shading(又称 cel shading).这是一种非逼真渲染风格,通过改变了光在一个模型上反射实际情况来给人以手绘的感觉
//BlinnPhong:仿真镜面反射材料
//Standard:Unity5中默认的光照模式是Standard, 其引入了 物理渲染(PBR), 但是与其它光照模型没有什么不同。相比于朗伯反射, PBR提供了一个更加逼真的光线
//物体作用模型,PBR考虑了材料的物理属性, 比如能量守恒以及光的散射
//----------------------------------------------------------------------------------------------------------------------
#pragma target 3.0
sampler2D _MainTex;
half _Glossiness;
half _Metallic;
fixed4 _Color;
//----------------------------------------------------------------------------------------------------------------------
//我们可以发现 _Color,_MainTex,_Glossiness,_Metallic都shader属性的声明,在上面的Properties 中已经声明过了这些属性,但是在这段CG程序,要想访问在
//Properties中所定义的变量的话,必须使用和之前变量相同的名字再次进行声明,其实就是链接在上面properties中声明的属性。
//3种基本数值类型:float、half和fixed。
//这3种基本数值类型可以再组成vector和matrix,比如half3是由3个half组成、float4x4是由16个float组成。
// float:32位高精度浮点数。
// half:16位中精度浮点数。范围是[-65536, +65535],能精确到十进制的小数点后3.3位。
// fixed:11位低精度浮点数。范围是[-2, 2],精度是1 / 256。
// Sampler2D:2D纹理属性
//----------------------------------------------------------------------------------------------------------------------
struct Input
{
float2 uv_MainTex;
};
//输入结构体
//这个结构体和surf函数中的另一个参数inout结构体是相对的,一个代表输入,一个代表输出。我们可以这样理解这两个结构体,你定义输入数据结构(Inputs Struct)、
//编写自己的Surface函数处理输入、最终输出修改过后的SurfaceOutput。Input其实是需要我们去定义的结构,所以我们可以把所需要参与计算的数据都放到这个Input结构中,
//传入surf函数使用默认的Input结构体中有一个uv_MainTex参数,代表了纹理的UV值,我们便可以在surf函数中直接使用这个参数了。
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb; //将物体显示的漫反射颜色设置成在纹理的颜色值
o.Metallic = _Metallic; //将物体显示的金属光泽设置成在properties中的颜色值
o.Smoothness = _Glossiness; //设置物体显示的光泽度
o.Alpha = c.a; //设置物体显示的透明度
}
ENDCG
}
FallBack "Diffuse" //回滚
}
三、法线贴图
????????法线贴图就是在原物体的凹凸表面的每个点上均作法线,通过RGB颜色通道来标记法线的方向,你可以把它理解成与原凹凸表面平行的另一个不同的表面,但实际上它又只是一个光滑的平面。对于视觉效果而言,它的效率比原有的凹凸表面更高,若在特定位置上应用光源,可以让细节程度较低的表面生成高细节程度的精确光照方向和反射效果。
????????法线贴图是可以应用到3D表面的特殊纹理,不同于以往的纹理只可以用于2D表面。作为凹凸纹理的扩展,它使每个平面的各像素拥有了高度值,包含了许多细节的表面信息,能够在平平无奇的物体外形上,创建出许多种特殊的立体视觉效果。
????????最近法线贴图多用在CG动画的渲染以及游戏画面的制作上,将具有高细节的模型通过映射烘焙出法线贴图,然后贴在低端模型的法线贴图通道上,使其表面拥有光影分布的渲染效果,能大大降低表现物体渲染时需要的面数和计算内容,从而达到优化动画和游戏的渲染效果。法线贴图是最近比较被关注的技术,也将成为以后CG领域的一大主流技术,也就是游戏界被称为的次世代技术。法线贴图是一种显示三维模型更多细节的重要方法,它计算了模型表面因为灯光而产生的细节。这是一种2维的效果,所以它不会改变模型的形状,但是它计算了轮廓线以内的极大的额外细节。在处理能力受限的情况下,这对实时游戏引擎是非常有用的,另外当你渲染动画受到时间限制时,它也是极其有效的解决办法。
|