イラスト、モデリング、Unity、VR関連

unityとかblenderとかvr関連の作業メモ

shader normal map + multi lighting

f:id:arumogina:20191125154428p:plain

参考:

【連載】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"
}