创文章如需转载请注明:转载自
风宇冲Unity3D教程学院
Shader第十四讲
Surface
Shader
用Shader来实现光照是比较复杂的,有不同的光类型,不同的阴影选项,不同的Render Path(forward和Deferred)。 Unity只是把光照模型封装处理了,Shader的代码还是用CG/HLSL编写的。
例一:最简单的Surface Shader
(2)把c.rgb赋给o.Albedo
(3) 把c.a赋给o.Alpha
表面处理函数surf的输入及输出
Surface Shader参数
- Shader "Custom/T_3_0" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- }
- SubShader {
- CGPROGRAM
- #pragma surface surf Lambert
- sampler2D _MainTex;
- struct Input {
- float2 uv_MainTex;
- } ;
- void surf (Input IN, inout SurfaceOutput o) {
- half4 c = tex2D (_MainTex, IN.uv_MainTex);
- o.Albedo = c.rgb;
- o.Alpha = c.a;
- }
- ENDCG
- }
- }
表面处理函数从顶点处理函数(这里自动顶点处理)接收参数Input IN,输出SurfaceOutput o至光照模型(这里是Lambert)。
这里我们就做了三件事:
(1)通过uv取得了贴图对应uv的颜色c
这就完成了。之后让任一物体使用该Shader,则不管加什么光都能正确显示。真的很简单!
(1)输入
- struct
Input { - float2 uv_MainTex;
- float3 viewDir;
- float4 anyName:COLOR;
- float4 screenPos;
-
float3 worldPos; - float3 worldRefl;
- } ;
uv_MainTex: uv
viewDir: 入视角
screenPos:裁剪空间位置
worldPos:世界空间位置
(2)输出
- struct SurfaceOutput {
-
half3 Albedo; -
half3 Normal; -
half3 Emission; -
half Specular; -
half Gloss; -
half Alpha; - };
Albedo:漫反射颜色
Normal: 法线
Emission:自发光颜色
Specular:镜面反射系数
Gloss:
Alpha:透明值
Surface Shader可以通过加参数实现额外的控制,例如加顶点处理函数,alpha混合等。
注意:
如果使用的
光照模型是Unity自带的Lambert或者BlinnPhong:
alpha混合,alpha混合等功能必须使用Surface Shader参数。
之前例如AlphaTest Greater 0.3 等代码就不能再加了。如果加了的话,光照失效,物体为一片漆黑。
如果使用的光照模型是自定义光照模型:
只要在surf中给o.Alpha正常赋值(如赋贴图颜色的a值),那么之前例如AlphaTest Greater 0.3 等代码依然可以照常使用。具体相关代码可以参考下一讲中的代码。
(1)alpha混合
直接加参数Alpha即可
#pragma surface surf BlinnPhong alpha
(2)alphatest
加入一个变量,这里起名为_Cutoff, 然后在#pragma
效果是alpha值大于_Cutoff时,才会输出颜色
- Shader "Custom/T_3_0" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
- }
- SubShader {
- CGPROGRAM
- #pragma surface surf Lambert alphatest:_Cutoff
- sampler2D _MainTex;
- struct Input {
- float2 uv_MainTex;
- } ;
- void surf (Input IN, inout SurfaceOutput o) {
- half4 c = tex2D (_MainTex, IN.uv_MainTex);
- o.Albedo = c.rgb;
- o.Alpha = c.a;
- }
- ENDCG
- }
- }
(3)顶点函数
例:臃肿的模型
实现方法,将顶点向法线方向延伸一段距离
-
Shader "Example/Normal Extrusion" { -
Properties { -
_MainTex ("Texture", 2D) = "white" {} -
_Amount ("Extrusion Amount", Range(-1,1)) = 0.5 -
} -
SubShader { -
Tags { "RenderType" = "Opaque" } -
CGPROGRAM -
#pragma surface surf Lambert vertex:vert -
struct Input { -
float2 uv_MainTex; -
}; -
float _Amount; -
void vert (inout appdata_full v) { -
v.vertex.xyz += v.normal * _Amount; -
} -
sampler2D _MainTex; -
void surf (Input IN, inout SurfaceOutput o) { -
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; -
} -
ENDCG -
} -
Fallback "Diffuse" -
}
(4)finalcolor
finalcolor:ColorFunction
对颜色输出作最后的更改
- Shader "Example/Tint Final Color" {
-
Properties { -
_MainTex ("Texture", 2D) = "white" {} -
_ColorTint ("Tint", Color) = (1.0, 0.6, 0.6, 1.0) -
} -
SubShader { -
CGPROGRAM -
#pragma surface surf Lambert finalcolor:mycolor -
struct Input { -
float2 uv_MainTex; -
}; -
fixed4 _ColorTint; -
void mycolor (Input IN, SurfaceOutput o, inout fixed4 color) -
{ - //在这里对最后输出的颜色color进行修改
-
color *= _ColorTint; -
} -
sampler2D _MainTex; -
void surf (Input IN, inout SurfaceOutput o) { -
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; -
} -
ENDCG -
} -
}