unity shader浅析

simaoshid1 2018-06-22

Shader(着色器)其实就是一小段程序,它负责将输入的网格或者贴图颜色等信息,进行组合或者变换换之后将其输出。之后再将写好的shader赋予材质,之后就可以由渲染器进行渲染。

Shader大体上可以分为两类:表面着色器(Surface Shader)和片段着色器(Fragment Shader)。这里主要介绍表面着色器。

我们先来看一段shader程序

Shader "Custom/Demo" { //shader的分类和命名

Properties{ //shader的一些属性

_MainTex("Texture",2D)="white"{}

_BumpMap("Bump Map",2D)="bump"{}

_RimColor("Rim Color",Color)=(0.26,0.19,0.16,0.0)

_RimPower("Rim Power",Range(1,10))=5.0

}

SubShader{

Tags { "RenderType" = "Opaque" }

LOD 200

CGPROGRAM //CG语言开始

#pragma surface surf Lambert //声明光照模式

#pragma target 3.0

sampler2D _MainTex;

sampler2D _BumpMap;

float4 _RimColor;

float _RimPower;

struct Input {

float2 uv_MainTex;

float2 uv_BumpMap;

float3 viewDir;

};

void surf (Input IN, inout SurfaceOutput o) {

o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;

//从凹凸纹理获取法线值

o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));

half rim = 1.0 - saturate(dot(normalize(IN.viewDir),o.Normal));

o.Emission = _RimColor.rgb*pow(rim,_RimPower);

}

ENDCG //CG语言结束

}

FallBack "Diffuse"

}

我们先来分析Properties(属性):

属性的语法定义是这样的

_Name("Display Name", type) = defaultValue[{options}]

_Name:属性的变量名,之后代码调用需要这个命名

Display Name:在unity编辑器里面显示的名字

type:type大概有下面几个种类

  • Color - 一种颜色,由RGBA四个量来定义;

  • 2D - 一张2的阶数大小的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,***终被显示出来;

  • Rect - 一个非2阶数大小的贴图;

  • Cube - 即Cube map texture,简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒)

  • Range(min, max) - 一个介于***小值和***大值之间的浮点数,一般用来当作调整Shader某些特性的参数

  • 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)

***于***后一个{options}只对贴图有关,这个以后再说

所以上面那个shader在编辑器里面看来是这样的

unity shader浅析

Subshader 子着色器

这个暂时不详细介绍

CG语言声明接口

请允许我把它叫做一个接口,上面我们在CG语言里面再次声明了两个变量,这里很多人就很奇怪,明明在属性里面已经声明过了,为什么还要再次声明一遍。这里的sampler 2D就相当于是一个接口,我们可以通过sampler2D来得到一张图的像素与坐标之间的对应关系。这样就可以的在CG语言里面对其进行运算。(注意:这里的命名要和属性里面的命名包保持一致)

sampler2D _MainTex;

sampler2D _BumpMap;

Input

Input就是表面的意思,输入。这是一个结构体,相信大家也不会陌生。也就是定义了要向输出函数里面输入什么东西。

void surf (Input IN, inout SurfaceOutput o)

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

SurfaceOutput结构体的定义如下:

struct SurfaceOutput{

half3 Albedo; //颜色

half3 Emission //发散颜色

half3 Normal //法向值

half Specular //镜面高光

half Gloss //发光强度

half Alpha //透明度

}

在上面的例子中,我们设置了它的颜色,法线还有发散颜色。

FallBack "Diffuse"

很多人认为,***后的FallBack"Diffuse"只是一个备胎,但其实并不是这样。我只能引用官方一句话:A fallback statement has the same effect as if all subshaders from the other shader would be inserted into its place.

unity shader浅析

发表评论

发表评论:

17601037727 1280857492