参考:
【連載】Unity時代の3D入門 – 第9回「ノーマルマッピング」 – てっくぼっと!
【Unity】【シェーダ】Forward Renderingで複数のライトを取り扱う - LIGHT11
Shader "Arumogina/NormalMap"{ Properties{ _MainTex ("Texture", 2D) = "white" {} _NormalMap ("Normal map", 2D) = "bump" {} } SubShader{ Tags { "RenderType"="Opaque" } Pass{ Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #pragma target 3.0 #include "UnityCG.cginc" #include "AutoLight.cginc" #include "UnityStandardUtils.cginc" struct appdata{ half4 vertex : POSITION; half3 normal : NORMAL; half2 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; struct v2f{ half4 pos : SV_POSITION; half2 uv : TEXCOORD0; half3 normal: TEXCOORD1; half3 ambient: TEXCOORD2; half3 worldPos: TEXCOORD3; half3 lightDir : TEXCOORD4; half3 viewDir : TEXCOORD5; half2 uv_nor : TEXCOORD6; LIGHTING_COORDS(6, 7) }; sampler2D _MainTex; half4 _MainTex_ST; sampler2D _NormalMap; half4 _NormalMap_ST; half4 _LightColor0; v2f vert (appdata v){ v2f o = (v2f)0; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.uv_nor = TRANSFORM_TEX(v.texcoord, _NormalMap); o.normal = UnityObjectToWorldNormal(v.normal); o.worldPos = mul(unity_ObjectToWorld, v.vertex); TANGENT_SPACE_ROTATION; o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)); #if UNITY_SHOULD_SAMPLE_SH #if defined(VERTEXLIGHT_ON) o.ambient = Shade4PointLights( unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, unity_4LightAtten0, o.worldPos, o.normal ); #endif o.ambient = ShadeSHPerVertex(o.normal,o.ambient); #else o.ambient = 0; #endif TRANSFER_VERTEX_TO_FRAGMENT(o); return o; } fixed4 frag (v2f i) : SV_Target{ half4 col = tex2D(_MainTex, i.uv); i.lightDir = normalize(i.lightDir); i.viewDir = normalize(i.viewDir); half3 halfDir = normalize(i.lightDir + i.viewDir); half3 normal = UnpackNormal(tex2D(_NormalMap, i.uv_nor)); UNITY_LIGHT_ATTENUATION(attenuation, i, normal); half3 diff = saturate(dot(normal, i.lightDir)) * _LightColor0 * attenuation; col.rgb *= diff + i.ambient; return col; } ENDCG }//Pass /* Pass { Tags { "LightMode"="ForwardAdd" } Blend One One ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdadd #pragma target 3.0 #include "UnityCG.cginc" #include "AutoLight.cginc" struct appdata{ half4 vertex : POSITION; half3 normal : NORMAL; half2 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; struct v2f{ half4 pos : SV_POSITION; half2 uv : TEXCOORD0; half3 normal: TEXCOORD1; half3 ambient: TEXCOORD2; half3 worldPos: TEXCOORD3; half3 lightDir : TEXCOORD4; half3 viewDir : TEXCOORD5; half2 uv_nor : TEXCOORD6; LIGHTING_COORDS(6, 7) }; sampler2D _MainTex; sampler2D _NormalMap; half4 _MainTex_ST; half4 _NormalMap_ST; half4 _LightColor0; v2f vert (appdata v){ v2f o = (v2f)0; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.uv_nor = TRANSFORM_TEX(v.texcoord, _NormalMap); o.normal = UnityObjectToWorldNormal(v.normal); o.worldPos = mul(unity_ObjectToWorld, v.vertex); TANGENT_SPACE_ROTATION; float3 objSpaceLightPos = mul(unity_WorldToObject, _WorldSpaceLightPos0).xyz; if (_WorldSpaceLightPos0.w > 0) { o.lightDir = mul(rotation,objSpaceLightPos.xyz - v.vertex.xyz); }else { o.lightDir = mul(rotation,objSpaceLightPos); } o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)); TRANSFER_VERTEX_TO_FRAGMENT(o); return o; } half4 frag(v2f i) : COLOR{ half4 col = tex2D(_MainTex, i.uv); i.lightDir = normalize(i.lightDir); i.viewDir = normalize(i.viewDir); half3 halfDir = normalize(i.lightDir + i.viewDir); half3 normal = UnpackNormal(tex2D(_NormalMap, i.uv_nor)); UNITY_LIGHT_ATTENUATION(attenuation, i, normal); half3 diff = saturate(dot(normal, i.lightDir)) * _LightColor0 * attenuation; col.rgb *= diff + i.ambient; return col; } ENDCG }//pass */ } Fallback "Diffuse" //半透明を扱う場合 //Fallback "Transparent/Cutout/Diffuse" }
-------------------------------------------------------------------------------------------------------------------------------
Shader "LightTest-2"{ Properties{ _MainTex ("Texture", 2D) = "white" {} _NormalMap ("Normal map", 2D) = "bump" {} } SubShader{ Tags { "RenderType"="Opaque" } Pass{ Tags { "LightMode"="ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #pragma target 3.0 #include "UnityCG.cginc" #include "AutoLight.cginc" #include "UnityStandardUtils.cginc" struct appdata{ half4 vertex : POSITION; half3 normal : NORMAL; half2 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; struct v2f{ half4 pos : SV_POSITION; half2 uv : TEXCOORD0; half3 normal: TEXCOORD1; half3 ambient: TEXCOORD2; half3 worldPos: TEXCOORD3; half3 lightDir : TEXCOORD4; half3 viewDir : TEXCOORD5; LIGHTING_COORDS(6, 7) }; sampler2D _MainTex; half4 _MainTex_ST; sampler2D _NormalMap; half4 _LightColor0; v2f vert (appdata v){ v2f o = (v2f)0; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = UnityObjectToWorldNormal(v.normal); o.worldPos = mul(unity_ObjectToWorld, v.vertex); TANGENT_SPACE_ROTATION; /* 1pass目においてはこの処理は o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); と同じ結果になる。 float3 objSpaceLightPos = mul(unity_WorldToObject, _WorldSpaceLightPos0).xyz; if (_WorldSpaceLightPos0.w > 0) { o.lightDir = mul(rotation,objSpaceLightPos.xyz - v.vertex.xyz); }else { o.lightDir = mul(rotation,objSpaceLightPos); } */ o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)); #if UNITY_SHOULD_SAMPLE_SH #if defined(VERTEXLIGHT_ON) o.ambient = Shade4PointLights( unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, unity_4LightAtten0, o.worldPos, o.normal ); #endif o.ambient = ShadeSHPerVertex(o.normal,o.ambient); #else o.ambient = 0; #endif TRANSFER_VERTEX_TO_FRAGMENT(o); return o; } fixed4 frag (v2f i) : SV_Target{ half4 col = tex2D(_MainTex, i.uv); i.lightDir = normalize(i.lightDir); i.viewDir = normalize(i.viewDir); half3 halfDir = normalize(i.lightDir + i.viewDir); half3 normal = UnpackNormal(tex2D(_NormalMap, i.uv)); UNITY_LIGHT_ATTENUATION(attenuation, i, normal); half3 diff = saturate(dot(normal, i.lightDir)) * _LightColor0 * attenuation; col.rgb *= diff + i.ambient; return col; } ENDCG }//Pass Pass { Tags { "LightMode"="ForwardAdd" } Blend One One ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdadd #pragma target 3.0 #include "UnityCG.cginc" #include "AutoLight.cginc" struct appdata{ half4 vertex : POSITION; half3 normal : NORMAL; half2 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; struct v2f{ half4 pos : SV_POSITION; half2 uv : TEXCOORD0; half3 normal: TEXCOORD1; half3 ambient: TEXCOORD2; half3 worldPos: TEXCOORD3; half3 lightDir : TEXCOORD4; half3 viewDir : TEXCOORD5; LIGHTING_COORDS(6, 7) }; sampler2D _MainTex; sampler2D _NormalMap; half4 _MainTex_ST; half4 _LightColor0; v2f vert (appdata v){ v2f o = (v2f)0; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = UnityObjectToWorldNormal(v.normal); o.worldPos = mul(unity_ObjectToWorld, v.vertex); TANGENT_SPACE_ROTATION; float3 objSpaceLightPos = mul(unity_WorldToObject, _WorldSpaceLightPos0).xyz; if (_WorldSpaceLightPos0.w > 0) { o.lightDir = mul(rotation,objSpaceLightPos.xyz - v.vertex.xyz); }else { o.lightDir = mul(rotation,objSpaceLightPos); } o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)); TRANSFER_VERTEX_TO_FRAGMENT(o); return o; } half4 frag(v2f i) : COLOR{ half4 col = tex2D(_MainTex, i.uv); i.lightDir = normalize(i.lightDir); i.viewDir = normalize(i.viewDir); half3 halfDir = normalize(i.lightDir + i.viewDir); half3 normal = UnpackNormal(tex2D(_NormalMap, i.uv)); UNITY_LIGHT_ATTENUATION(attenuation, i, normal); half3 diff = saturate(dot(normal, i.lightDir)) * _LightColor0 * attenuation; col.rgb *= diff + i.ambient; return col; } ENDCG }//pass } //影の生成のために必要 //http://tsumikiseisaku.com/blog/shader-tutorial-transparent/ \ Fallback "Diffuse" //半透明を扱う場合 //Fallback "Transparent/Cutout/Diffuse" }