본문으로 바로가기
반응형

 

URP Shader Training 중급에서 사용할 example.

maskmap이랑 몇가지는 그냥 임의 커스텀(참고용). 이거저거 잡다하게 붙인...

 



  Shader "LightingExample/BlinnPhong"
  {
 
   Properties
  {    
     [Header(URP BlinnPhong Lighting)]
     [Space(20)]
     _TintColor ("Tint Color", color) = (1,1,1,1)
     _BaseMap("Albedo(RGB)", 2D) = "white" {}
     [Normal]_BumpMap("Normal texture", 2D) = "white" {}
     _MaskMap("Occlusion(G), Glossness(A)", 2D) = "white" {}
    
     [Space(20)][Header(Control slide bar)]
     _SpecColor("Specular Color", color) = (1,1,1,1)
     _Specular("Specular Intensity", Range(0, 10)) = 1
     _Glossness("Glossness", Range(0.1, 50)) = 1    
     _OcclusionInten("Occlusion Intensity", Range(0,1)) = 1
     _EnviIntensity("Environment Lighting", Range(0,1)) = 1
    } 

  SubShader
        {  
       Tags
        {
        "RenderPipeline"="UniversalPipeline"
        "RenderType"="Opaque"          
        "Queue"="Geometry"
         }
     Pass
     {
        Name "Universal Forward"
            Tags {"LightMode" = "UniversalForward"}

          HLSLPROGRAM
         #pragma prefer_hlslcc gles
         #pragma exclude_renderers d3d11_9x
         #pragma vertex vert
         #pragma fragment frag

       #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

        struct VertexInput
          {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
            float2 uv       : TEXCOORD0;
            float4 tangent : TANGENT;
          };

        struct VertexOutput
          {
            float4 vertex      : SV_POSITION;
            float3 normalWS    : NORMAL;
           
            float2 uv               : TEXCOORD0;
            float3 tangentWS    : TEXCOORD1;
            float3 bitangentWS  : TEXCOORD2;
            float3 viewDir         : TEXCOORD3;
            };

           float4 _BaseMap_ST;
           Texture2D _BaseMap, _BumpMap, _MaskMap;

           SamplerState sampler_BaseMap;
   
           float _Specular, _Glossness, _OcclusionInten, _EnviIntensity;
           half4 _TintColor, _SpecColor;

   VertexOutput vert(VertexInput v)
         {
          VertexOutput o;

          o.vertex    = TransformObjectToHClip(v.vertex.xyz);           
          o.normalWS  = TransformObjectToWorldNormal(v.normal.xyz);
          o.tangentWS = TransformObjectToWorldDir(v.tangent.xyz);
          o.bitangentWS = cross(o.normalWS, o.tangentWS) * v.tangent.w * unity_WorldTransformParams.w;

          o.viewDir = _WorldSpaceCameraPos.xyz - TransformObjectToWorld(v.vertex.xyz);
          o.uv = v.uv.xy * _BaseMap_ST.xy + _BaseMap_ST.zw;

          return o;
         }


//DX5기준으로 Legacy에서의 unpack normal을 그대로 사용. R/5bit, G/6bit, B/5bit, A/8bit를 R>G, G>A로 사용-사람의 눈이 녹색의 변화에 민감하기에 G가 1bit더 크다. mobile에서는 채널 변환 없이 *2.0 - 1.0으로 그냥 계산하게 된다.

//URP에서 unpack normal처리는 "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 에서 확인할 수 있다.

      inline half3 UnpackNormal(half4 packednormal)
        {
          half3 normal;
          normal.xy = packednormal.wy * 2 - 1;
          normal.z = sqrt(1 - normal.x * normal.x - normal.y * normal.y);
          return normal;
         }

           inline half3 TangentNormalToWorldNormal(half3 TangnetNormal, half3 T, half3  B, half3 N)
           {
             float3x3 TBN = float3x3(T, B, N);
             TBN = transpose(TBN);
             return mul(TBN, TangnetNormal);
            }

           half4 frag(VertexOutput i) : SV_Target
         {   
          float3 lightDir = _MainLightPosition.xyz;
          float3 lightColor = _MainLightColor.rgb;
          float3 viewDir = normalize(i.viewDir);

          half4 color = _BaseMap.Sample(sampler_BaseMap, i.uv) * _TintColor;
          half4 mask = _MaskMap.Sample(sampler_BaseMap, i.uv);
          half3 bump = UnpackNormal(_BumpMap.Sample(sampler_BaseMap, i.uv)) ;

          float3 worldNormal = TangentNormalToWorldNormal(bump, i.tangentWS, i.bitangentWS, i.normalWS);
          float NdotL = saturate(dot(worldNormal, lightDir));
          float3 hv = SafeNormalize(lightDir + viewDir);

        //  https://github.com/Unity-Technologies/Graphics/blob/master/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl

          float NdotH = saturate(dot(hv, normalize(worldNormal)));
      
          //Occlusion 처리는 임의로 계산한것이기 때문에 무시한다.
          float specular = pow(NdotH, _Glossness * mask.a) * _Specular + mask.g * _OcclusionInten;
          half3 ambient = SampleSH(i.normalWS);

         //ambient color처리는임의로 계산한 내용. blinnphong 수식에서는 무시한다.
          color.rgb = color.rgb * NdotL * lightColor * specular * _SpecColor.rgb  + ambient * (1.0 - NdotL) * _EnviIntensity;

          return color;
         }
   ENDHLSL  
   }
  }
}

 

반응형