其實學習shader的話,搞unity開發,就是《unity 3d shaderLab開發實戰詳解》。unity在opengl的基礎上又封裝了了一個表面着色器,本id其實並不怎麼喜歡寫表面着色器,因爲以前學習opengl的時候都沒有聽說過這個東西,其實表面着色器最終是要編譯成頂點和片元着色器的。
今天本id突然想說起這個,是因爲昨天下午被自己坑了一把,就導致了在unity編輯器上運行正常,手機上卻看不到效果。就是對於點光源的光照計算,當然如果是平行光就不會出現這種情況,unity對於點光源的計算在《unity 3d shaderLab開發實戰詳解》這本書上也是有介紹的,這是原文:
在 VcHexL⒒渲染模式下,FomardBasc和
FowardAdd的 ughtM。 de都 不被支持。 另外,FwdAddX.shadcr在
3個 渲染路徑下都沒有輸出,這
說明 FoⅢ ardAdd這個 Pass需
要和 FomardBasc— 起使用,否 則會被Unity所忽視掉。 在
Fomard
和 Dcfcrred渲
染路徑下,Fomard的 Pass均
能被正常渲染。
下面是關於光照的shader:
Shader "Custom/LightAndOutline" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_OutlineColor ("Outline Color", Color) = (1,1,1,1)
_Outline ("Outline width", Range (0.0, 0.03)) = .005
_MainTex ("Base (RGB)", 2D) = "white" { }
_BumpMap ("Bumpmap", 2D) = "bump" {}
}
SubShader {
//Tags { "Queue" = "Transparent" }
// 描邊通道
/*Pass {
CGINCLUDE
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : POSITION;
float4 color : COLOR;
};
uniform float _Outline;
uniform float4 _OutlineColor;
ENDCG
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Back
ZWrite Off
ZTest Less
//Blend Off
// you can choose what kind of blending mode you want for the outline
Blend SrcAlpha OneMinusSrcAlpha // Normal
//Blend One One // Additive
//Blend One OneMinusDstColor // Soft Additive
//Blend DstColor Zero // Multiplicative
//Blend DstColor SrcColor // 2x Multiplicative
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert(appdata v) {
// just make a copy of incoming vertex data but scaled according to normal direction
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 norm = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
float2 offset = TransformViewToProjection(norm.xy);
o.pos.xy += offset * o.pos.z * _Outline;
o.color = _OutlineColor;
return o;
}
half4 frag(v2f i) : COLOR {
return i.color;
}
ENDCG
}*/
Pass {
Tags{ "LightMode"="ForwardBase"}
Cull Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f_t {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f_t vert (appdata_t v)
{
v2f_t o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag (v2f_t i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.texcoord);
return col;
}
ENDCG
}
//光亮通道
Pass {
Tags{ "LightMode"="ForwardAdd"}
Cull Off
Blend One Zero
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f_t {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
float3 lightDir:TEXCOORD1;
float color : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f_t vert (appdata_t v)
{
v2f_t o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
float3 lightColor = _LightColor0.xyz;
o.lightDir = ObjSpaceLightDir(v.vertex);
float cos_a = saturate(dot(o.lightDir, v.normal));
cos_a = pow(lightColor*cos_a, 5);
o.color = cos_a + 0.9;
return o;
}
fixed4 frag (v2f_t i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.texcoord);
col.r = col.r*i.color;
col.g = col.g*i.color;
col.b = col.b*i.color;
return col;
}
ENDCG
}
}
Fallback "Diffuse"
}
注意,這裏的光照部分使用了兩個通道,我們的光照計算主要在Tags{ "LightMode"="ForwardAdd"}這個通道中,書上說,要使得這個通道有效,必須有一個Tags{ "LightMode"="ForwardBase"}通道,所以在Add通道中需要使用Blend One Zero,把前一個通道隱藏起來。
這裏只是簡單光照模型,見笑了