Shader整理

/*
****************    Shader就是给定了输入,然后给出输出进行着色的代码   ************
一个Shader(着色器)包括:
属性定义(Property Definition)   : 用来指定这段代码将有哪些输入,定义的属性将被作为输入提供给所有的子着色器;
一个或者多个子着色器(Subshader) : 子着色器是代码的主体,每一个子着色器中包含一个或者多个的Pass,在计算着色时,平台先选择最优先可以使用的着色器,然后依次运行其中的Pass,然后得到输出的结果
回滚(Fallback)                  : 用来处理所有Subshader都不能运行的情况
*/




//Shader的声明并为其指定了一个名字   使用 : 在材质面板 -> Shader -> Custom -> NewSurfaceShader
Shader "Custom/NewSurfaceShader" {





/*
属性定义写法 : _Name("Display Name",type) = defaultValue[{options}] 


_Name        : 属性的名字(就是变量名),在之后的Shader代码中用这个名字来获取该属性的内容  --> 代码的中使用的变量
Display Name : 显示在Unity的材质编辑器中作为Shader的使用者可读的内容                     --> 选材质时候用的名字
type         : 这个属性的类型
{  type包含的种类有:
  Color           --> 颜色 由(RGBA)来定义
  2D              --> 一张2的幂次方(256,512....) 大小的贴图
  Rect            --> 一张非2的幂次方大小的贴图
  Cube            --> 立方体纹理,6张有联系的2D贴图的组合,主要做反射效果(天空盒和动态反射)
  Range(min,max)  --> 介于最小值和最大值之间的浮点数,一般用来调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值)
  Float           --> 任意一个浮点数
  Vector          --> 一个四维数
}
defaultValue  : 定义这个属性的默认值,格式要符合type定义的类型
{
  Color           --> (0,0,0,0) ~ (1,1,1,1)
  2D/Rect/Cube    --> 对于贴图,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者"white","black","gray","bump"中的一个
  Range、Float    --> 指定的浮点数
  Vector          --> (x,y,z,w)
}
{option}      : 只对2D,Rect或者Cube贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{},当我们需要打开特定选项时可以把其写在这对花括号内。如果需要同时打开多个选项,可以使用空白分隔。可能的选择有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一个,都是OpenGL中TexGen的模式
*/
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
}






/*
SubShader定义写法 : Tags {} + LOD + Shader本体
Tags    --> 表面着色器可以被若干标签修饰,硬件通过判定标签决定何时调用此着色器,Tags其实暗示了Shader输出的是什么
{  Tags包括:
"RenderType" = "Opaque"          --> 渲染非透明物体时调用
"RenderType" = "Transparent"     --> 渲染含有透明物体时调用
"IgnoreProjector" = "True"        --> 不被Projectors影响
"ForceNoShadowCasting"="True"     --> 从不产生阴影


"Queue"="xxx"                     --> 指定渲染顺序队列
Queue指定了物体的渲染顺序,预定义的Queue有:
  Background     --> 最早被调用的渲染,用来渲染天空盒或背景
  Geometry       --> 默认值,用来渲染非透明的物体(普通情况下,场景中绝大多数物体是非透明的)
  AlphaTest      --> 用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑
  Transparent    --> 以从后往前的顺序渲染透明物体
  Overlay        --> 用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效)
这些预定义的值本质上是一组定义整数,Background = 1000, Geometry = 2000, AlphaTest = 2450, Transparent = 3000,最后Overlay = 4000。在我们实际设置Queue值时,不仅能使用上面的几个预定义值,我们也可以指定自己的Queue值,写成类似这样:"Queue"="Transparent+100",表示一个在Transparent之后100的Queue上进行调用。通过调整Queue值,我们可以确保某些物体一定在另一些物体之前或者之后渲染,这个技巧有时候很有用处。
}

LOD 在这里例子里我们指定了其为200(是Unity的内建Diffuse着色器的设定值)。这个数值决定了我们能用什么样的Shader。在Unity的Quality Settings中我们可以设定允许的最大LOD,当设定的LOD小于SubShader所指定的LOD时,这个SubShader将不可用。Unity内建Shader定义了一组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
*/
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200




//************   主体部分:    ************


// 1、是一个开始标记,表明从这里开始是一段CG程序(写Shader用的是CG/HLSL语言),与最后一行的ENDCG对应,表明CG程序结束
CGPROGRAM


/*
2、编译指令: #pragma surface surfaceFunction lightModel [optionalparams]
surface         --> 声明的是一个表面着色器
surfaceFunction --> 着色器代码的方法的名字(在下面会找到)
lightModel      --> 使用的光照模型。
*/
#pragma surface surf Standard fullforwardshadows


// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0


/* sampler2D就是GLSL中的2D贴图的类型,也有sampler1D,sampler3D,samplerCube等格式。
  我们用来实例的这个shader其实是由两个相对独立的块组成的,外层的属性声明,回滚等等是Unity可以直接使用和编译的ShaderLab;
  而现在在CG代码块中,这是一段CG程序。对于这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字进行声明。于是其实sampler2D _MainTex,做的事情就是再次声明并链接了_MainTex,使得接下来的CG程序能够使用这个变量。
*/
sampler2D _MainTex;




//Input是自己定义的结构,作为surf方法的第一个参数,可以把所需要参与计算的数据都放到这个Input结构中,必须命名为Input
struct Input {
//float2 : float和vec都可以在之后加入一个2到4的数字,表示打包在一起的2到4个同类型数,可以只使用名称来获得整组值,也可以使用下标的方式(比如.xyzw,.rgba获得它们的部分比如.x等等)来获得某个值。
   /*UV mapping: 将一个2D贴图上的点按照一定规则映射到3D模型上,是3D渲染中最常见的一种顶点处理手段
 在CG程序中,在一个贴图变量(例子中是_MainTex)之前加上uv,就代表提取它的uv值(其实就是两个代表贴图上点的二维坐标)。我们之后就可以在surf程序中直接通过访问uv_MainTex来取得这张贴图当前需要计算的点的坐标值
*/
float2 uv_MainTex;
};


//一个可写的SurfaceOutputStandard,SurfaceOutputStandard是预定义的输出结构,surf函数的目标就是根据输入把这个输出结构填上。
struct SurfaceOutputStandard {
//half :  半精度浮点数,精度最低,运算性能比高浮点数高一些
half3 Albedo;  //像素的颜色
half3 Normal;  //像素的法向值
half3 Emission;  //像素的发散颜色
half Specular;  //像素的镜面高光
half Gloss;  //像素的发光强度
half Alpha;      //像素的透明度
};


half _Glossiness;
half _Metallic;
fixed4 _Color;




//Shader的工作核心方法: CG规定了声明为表面着色器的方法(surf)的参数类型和名字,因此不能修改surf的输入输出参数的类型,只能按照规定写。这个规定就是第一个参数是一个Input结构,第二个参数是一个inout的SurfaceOutput结构
//Input是自己定义好的结构体,而且必须命名为Input,在计算输出时Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出; SurfaceOutput是已经定义好了里面类型输出结构,但是一开始的时候内容暂时是空白的,我们需要向里面填写输出,这样就可以完成着色。
void surf (Input IN, inout SurfaceOutputStandard o) {


//我们做的事情:
//tex2D函数: CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。这里对_MainTex在输入点上进行了采样,并将其颜色的rbg值赋予了输出的像素颜色,将a值赋予透明度。着色器工作: 找到贴图上对应的uv点,直接使用颜色信息来进行着色
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值