반응형
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
- 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 |