본문으로 바로가기
반응형

character shader base form based on mobile platform. 2021.1.6f1
support cascade. thanks for madumpa !!!. : blog posting below link.
캐스캐이드가 작동하지 않기 때문에 아래 링크처럼 픽셀에서 shadowcoord를 처리해주면 제대로 작동
https://blog.naver.com/PostView.naver?blogId=mnpshino&logNo=222154224409&navType=tl

 

URP 셰이더 코딩 튜토리얼 A/S : 케스케이드 섀도우가 이상해요!

안녕하세요 마둠파입니다 전에 셰이더 코딩 튜토리얼 시리즈를 올려 뒀었는데요, 해당 셰이더로 케스케이드...

blog.naver.com


- support cascade shadow
- support single light pass
- does not support SSAO
- lighting model : BlinnPhong

include only forward pass, shadow pass, depth pass.

SSAO를 적용하는건 simpleLit이나 다른 코드에서 가져와 넣으면 작동한다.
추가 라이트의 BRDF와 하이라이트는 일단 귀찮아서 그냥 가져다 처리. 이 부분을 커스텀 하기 따라서 좀 더 다양한 느낌이 가능할듯

몇가지 compile 에러가 뜨는데 추후 수정예정.

정확하게 구현한건 아니고 기능적 구현에 우선한 것이라 참고용으로만 쓸것~

 


Shader "URPBlinnphongCustom"
{

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

[Space(5)][Header(AlphaTest)]
[Space(5)]
[Toggle] _AlphaTest("AlphaTest", float) = 0
_Cutoff("AlphaClip", Range(0,1)) = 0.5
[Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull Mode", Float) = 1
    } 

  SubShader
        {  
       Tags
        {
        "RenderPipeline"="UniversalPipeline"
        "RenderType"="Opaque"          
        "Queue"="Geometry"
         }

   LOD 100
       Cull[_Cull]

     Pass
     {
        Name "Universal Forward"
        Tags {"LightMode" = "UniversalForward"}

        HLSLPROGRAM
        
 #pragma prefer_hlslcc gles
 #pragma exclude_renderers gles gles3 glcore
 #pragma exclude_renderers d3d11_9x
 #pragma target 3.0
 
//AlphaTest
 #pragma shader_feature_local_fragment _ALPHATEST_ON
        
// Universal Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS 
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS        
#pragma multi_compile_fragment _ _SHADOWS_SOFT
        
// Unity defined keywords
#pragma multi_compile_fog

#pragma vertex vert
#pragma fragment frag

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"            
 
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float _Specular, _Glossness, _OcclusionInten, _EnviIntensity;
half _Cutoff, _NormalInten, _FrensnelTerm;
half4 _TintColor, _SpecColor;
CBUFFER_END
     
Texture2D _BaseMap, _BumpMap, _MaskMap;
SamplerState sampler_BaseMap;

        struct VertexInput
          {
            float4 positionOS : POSITION;
            float3 normalOS    : NORMAL;
            float2 uv         : TEXCOORD0;
            float4 tangentOS   : TANGENT;
          };

        struct VertexOutput
          {
            float4 positionCS  : SV_POSITION;
            float3 normalWS    : NORMAL;
           
            float2 uv           : TEXCOORD0;
            float3 tangentWS    : TEXCOORD1;
            float3 bitangentWS  : TEXCOORD2;
            float3 viewDirWS    : TEXCOORD3;
            half4  fogFactorAndVertexLight     : TEXCOORD4; // x: fogFactor, yzw: vertex light
            float4 shadowCoord  : TEXCOORD5;
            float3 positionWS   : TEXCOORD6;

            };

//vertex stage

VertexOutput vert(VertexInput v)
         {
          VertexOutput o = (VertexOutput)0;
  
          o.positionCS  = TransformObjectToHClip(v.positionOS.xyz);           
          o.normalWS  = TransformObjectToWorldNormal(v.normalOS.xyz);
          o.tangentWS = TransformObjectToWorldDir(v.tangentOS.xyz);
          o.bitangentWS = cross(o.normalWS, o.tangentWS) * v.tangentOS.w * unity_WorldTransformParams.w;
          o.positionWS = TransformObjectToWorld(v.positionOS.xyz);

          o.viewDirWS = _WorldSpaceCameraPos.xyz - TransformObjectToWorld(v.positionOS.xyz);
          o.uv = v.uv.xy * _BaseMap_ST.xy + _BaseMap_ST.zw;
  
         //VertexPositionInputs vertexInput = GetVertexPositionInputs(v.positionOS.xyz);
          half3 vertexLight = VertexLighting(o.positionWS, o.normalWS);
          half fogFactor = ComputeFogFactor(o.positionCS.z);   

       #ifdef _MAIN_LIGHT_SHADOWS   
        //o.shadowCoord = GetShadowCoord(vertexInput);
          o.shadowCoord = float4(0,0,0,0);
       #endif
           o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
   
          return o;
         }   

//Based on PCPlatform. R/5bit, G/6bit, B/5bit, A/8bit R>G, G>A if using mobile, modified *2.0 - 1.0.
//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);
         }

//pixel stage

half4 frag(VertexOutput i) : SV_Target
           {

//default function define     
float2 uv = i.uv;
float3 viewDir = normalize(i.viewDirWS);
i.shadowCoord = TransformWorldToShadowCoord(i.positionWS); 
Light mainlight = GetMainLight(i.shadowCoord);
 
            //texture sampling
half4 diffuse = _BaseMap.Sample(sampler_BaseMap, i.uv) * _TintColor;
half4 mask  = _MaskMap.Sample(sampler_BaseMap, i.uv);
half3 bump = UnpackNormal(_BumpMap.Sample(sampler_BaseMap, i.uv)) * half3(1, _NormalInten, 1) ;

float3 worldNormal = TangentNormalToWorldNormal(bump, i.tangentWS, i.bitangentWS, i.normalWS);
float NdotL = saturate(dot(worldNormal, mainlight.direction));
float3 hv = normalize(mainlight.direction + viewDir);
float NdotH = saturate(dot(hv, normalize(worldNormal)));

//lighting
half smoothness = mask.a * _Glossness ;
half specular =  pow(NdotH, smoothness) * _Specular;
half3 specularColor = specular * _SpecColor.rgb ;
   
//Environment Lighting. reflection probe does not work yet
half3 reflectVector = reflect(-viewDir, worldNormal);
half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, smoothness);
//half3 rfprobe = GlossyEnvironmentReflection(reflectVector,  smoothness, mask.g);

half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);

half3 diffuseColor = diffuse.rgb * NdotL * mainlight.color * mainlight.shadowAttenuation;

//fresnel term  
half fresnelTerm = saturate(dot(viewDir, worldNormal));
half3 rim = 1.0 - (pow(fresnelTerm, _FrensnelTerm)) ;

half3 ambient = SampleSH(worldNormal) * 0.212;

//additional light combine
#ifdef _ADDITIONAL_LIGHTS

uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, i.positionWS);

half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
diffuseColor += LightingLambert(attenuatedLightColor, light.direction, worldNormal) * 0.1 * mask.g;
//specularColor += LightingSpecular(attenuatedLightColor, light.direction, worldNormal, viewDir, specular, smoothness) * mask.a; 
}
#endif

#ifdef _ADDITIONAL_LIGHTS_VERTEX
diffuseColor += i.fogFactorAndVertexLight.yzw;;
#endif

//combine light
//diffuseColor += specularColor + irradiance * ambient *  mask.g * _OcclusionInten + rim * diffuse.r;
diffuseColor +=  irradiance * ambient *  mask.g * _OcclusionInten + rim * diffuse.r;

half4 color = half4(diffuseColor, diffuse.a);

#if _ALPHATEST_ON
clip(color.a - _Cutoff);
#endif
 
//apply fog
color.rgb = MixFog(color.rgb, i.fogFactorAndVertexLight.x);

return color;
}
ENDHLSL  
}


Pass
{
Name "ShadowCaster"

Tags{"LightMode" = "ShadowCaster"}

Cull Back

HLSLPROGRAM

#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0

#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment

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


CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float _Specular, _Glossness, _OcclusionInten, _EnviIntensity;
half _Cutoff, _NormalInten, _FrensnelTerm;
half4 _TintColor, _SpecColor;
CBUFFER_END

Texture2D _BaseMap;
SamplerState sampler_BaseMap;

 struct VertexInput
 {
 float4 positionOS : POSITION;
 float4 normalOS : NORMAL;

 #if  _ALPHATEST_ON
 float2 uv     : TEXCOORD0;
 #endif

 };

 struct VertexOutput
 {
 float4 positionCS : SV_POSITION;
 
 #if  _ALPHATEST_ON
 float2 uv     : TEXCOORD0;
 #endif
 };

 VertexOutput ShadowPassVertex(VertexInput v)
 {
   VertexOutput o;

   float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
   float3 normalWS = TransformObjectToWorldNormal(v.normalOS.xyz);

   o.positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _MainLightPosition.xyz));

  #if _ALPHATEST_ON
   o.uv = v.uv * _BaseMap_ST.xy + _BaseMap_ST.zw; 
  #endif 
  return o;
 }

 half4 ShadowPassFragment(VertexOutput i) : SV_TARGET
 {  
 #if _ALPHATEST_ON
 half alpha = _BaseMap.Sample(sampler_BaseMap, i.uv).a * _TintColor.a;
 clip(alpha - _Cutoff);
 #endif

 return 0;
 }  

 ENDHLSL
}

Pass
{
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
    
Zwrite On
ColorMask 0

Cull Back

HLSLPROGRAM

#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0

#pragma vertex vert
#pragma fragment frag

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

CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float _Specular, _Glossness, _OcclusionInten, _EnviIntensity;
half _Cutoff, _NormalInten, _FrensnelTerm;
half4 _TintColor, _SpecColor;
CBUFFER_END

struct VertexInput
{
float4 vertex : POSITION;
};

struct VertexOutput
{
float4 vertex : SV_POSITION;
};

VertexOutput vert(VertexInput v)
{
VertexOutput o;

o.vertex = TransformObjectToHClip(v.vertex.xyz);

return o;
}

half4 frag(VertexOutput IN) : SV_TARGET
{
return 0;
}
ENDHLSL
}
}
}

 

 

 

 

 

 

반응형

'Technical Report > Unity Shader' 카테고리의 다른 글

PBR-BRDF-Disney-Unity-1  (0) 2022.03.02
URP Realtime Shadow color control  (2) 2022.01.22
URP Shader BlinnPhong with Normal mapping  (0) 2021.07.08
URP Shader coding guide Basic term  (3) 2021.05.01
2D Signed Distance Field Basics  (0) 2021.02.10