////////////////////////////////////////////////////// // MK Toon ShadowCaster Program // // // // Created by Michael Kremmel // // www.michaelkremmel.de // // Copyright © 2020 All rights reserved. // ////////////////////////////////////////////////////// #ifndef MK_TOON_SHADOWCASTER #define MK_TOON_SHADOWCASTER #if defined(MK_URP) #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" #elif defined(MK_LWRP) #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Shadows.hlsl" #endif #include "../Surface.hlsl" #include "Data.hlsl" //This should be excluded from the CBuffer uniform float3 _LightDirection; uniform float3 _LightPosition; ///////////////////////////////////////////////////////////////////////////////////////////// // VERTEX SHADER ///////////////////////////////////////////////////////////////////////////////////////////// void ShadowCasterVert ( VertexInputShadowCaster VERTEX_INPUT, out VertexOutputShadowCaster vertexOutput ,out float4 svPositionClip : SV_POSITION ) { UNITY_SETUP_INSTANCE_ID(VERTEX_INPUT); INITIALIZE_STRUCT(VertexOutputShadowCaster, vertexOutput); UNITY_TRANSFER_INSTANCE_ID(VERTEX_INPUT, vertexOutput); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(vertexOutput); #ifdef MK_VERTEX_ANIMATION VERTEX_INPUT.vertex.xyz = VertexAnimation(PASS_VERTEX_ANIMATION_ARG(_VertexAnimationMap, PASS_VERTEX_ANIMATION_UV(VERTEX_INPUT.texcoord0.xy), _VertexAnimationIntensity, _VertexAnimationFrequency.xyz, VERTEX_INPUT.vertex.xyz, VERTEX_INPUT.normal)); #endif //CurvedWorldSupport //CurvedWorldVertexTransformations /* Replace on the Vertex Transformation code the following: - v.vertex => VERTEX_INPUT.vertex - v.normal => VERTEX_INPUT.normal - v.tangent => VERTEX_INPUT.tangent */ // #ifdef MK_VERTEX_COLOR_REQUIRED vertexOutput.color = VERTEX_INPUT.color; #endif #if defined(MK_TCM) vertexOutput.uv = VERTEX_INPUT.texcoord0.xy * _AlbedoMap_ST.xy + _AlbedoMap_ST.zw; #endif #if defined(MK_URP) || defined(MK_LWRP) half3 normalWorld = ComputeNormalWorld(VERTEX_INPUT.normal); #endif #ifdef MK_PARALLAX vertexOutput.viewTangent = ComputeViewTangent(ComputeViewObject(VERTEX_INPUT.vertex.xyz), VERTEX_INPUT.normal, VERTEX_INPUT.tangent.xyz, cross(VERTEX_INPUT.normal, VERTEX_INPUT.tangent.xyz) * VERTEX_INPUT.tangent.w * unity_WorldTransformParams.w); #endif #if defined(MK_URP) float3 positionWorld = mul(MATRIX_M, float4(VERTEX_INPUT.vertex.xyz, 1.0)).xyz; half3 lightDirection; #if defined(_CASTING_PUNCTUAL_LIGHT_SHADOW) && defined(MK_URP_2020_2_Or_Newer) lightDirection = MKSafeNormalize(_LightPosition - positionWorld); #else lightDirection = _LightDirection; #endif svPositionClip = mul(MATRIX_VP, float4(ApplyShadowBias(positionWorld, normalWorld, lightDirection), 1.0)); #if UNITY_REVERSED_Z svPositionClip.z = min(svPositionClip.z, UNITY_NEAR_CLIP_VALUE); #else svPositionClip.z = max(svPositionClip.z, UNITY_NEAR_CLIP_VALUE); #endif #elif defined(MK_LWRP) float3 positionWorld = mul(MATRIX_M, float4(VERTEX_INPUT.vertex.xyz, 1.0)).xyz; float invNdotL = 1.0 - saturate(dot(_LightDirection, normalWorld)); float scale = invNdotL * _ShadowBias.y; positionWorld = _LightDirection * _ShadowBias.xxx + positionWorld; positionWorld = normalWorld * scale.xxx + positionWorld; svPositionClip = mul(MATRIX_VP, float4(positionWorld, 1)); #if UNITY_REVERSED_Z svPositionClip.z = min(svPositionClip.z, UNITY_NEAR_CLIP_VALUE); #else svPositionClip.z = max(svPositionClip.z, UNITY_NEAR_CLIP_VALUE); #endif #else TRANSFER_SHADOW_CASTER_NOPOS(vertexOutput, svPositionClip) #endif #ifdef MK_BARYCENTRIC_POS_CLIP vertexOutput.positionClip = svPositionClip; #endif #ifdef MK_POS_NULL_CLIP vertexOutput.nullClip = ComputeObjectToClipSpace(0); #endif } ///////////////////////////////////////////////////////////////////////////////////////////// // FRAGMENT SHADER ///////////////////////////////////////////////////////////////////////////////////////////// half4 ShadowCasterFrag ( VertexOutputShadowCaster vertexOutput, float4 svPositionClip : SV_POSITION ) : SV_Target { UNITY_SETUP_INSTANCE_ID(vertexOutput); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(vertexOutput); #ifdef MK_LOD_FADE_CROSSFADE LODFadeCrossFade(svPositionClip); #endif MKSurfaceData surfaceData = ComputeSurfaceData ( svPositionClip, PASS_POSITION_WORLD_ARG(0) PASS_FOG_FACTOR_WORLD_ARG(0) PASS_BASE_UV_ARG(float4(vertexOutput.uv.xy, 0, 0)) PASS_LIGHTMAP_UV_ARG(0) PASS_VERTEX_COLOR_ARG(vertexOutput.color) PASS_NORMAL_WORLD_ARG(1) PASS_VERTEX_LIGHTING_ARG(0) PASS_TANGENT_WORLD_ARG(1) PASS_VIEW_TANGENT_ARG(vertexOutput.viewTangent) PASS_BITANGENT_WORLD_ARG(1) PASS_BARYCENTRIC_POSITION_CLIP_ARG(vertexOutput.positionClip) PASS_NULL_CLIP_ARG(vertexOutput.nullClip) PASS_FLIPBOOK_UV_ARG(0) ); Surface surface = InitSurface(surfaceData, PASS_SAMPLER_2D(_AlbedoMap), _AlbedoColor, float4(0,0,0,1)); #if defined(MK_URP) || defined(MK_LWRP) return 0; #else #ifdef MK_SURFACE_TYPE_TRANSPARENT #ifdef MK_TOON_DITHER_MASK /* #ifdef LOD_FADE_CROSSFADE #define _LOD_FADE_ON_ALPHA alpha *= unity_LODFade.y; #endif */ // dither mask alpha blending half alphaRef = tex3D(_DitherMaskLOD, float3(svPositionClip.xy*0.25,surface.alpha*0.9375)).a; clip(alphaRef - 0.01); #else clip(surface.alpha - 0.5); #endif /* //Disabled for now #ifdef LOD_FADE_CROSSFADE #ifdef _LOD_FADE_ON_ALPHA #undef _LOD_FADE_ON_ALPHA #else UnityApplyDitherCrossFade(vpos.xy); #endif #endif */ #endif SHADOW_CASTER_FRAGMENT(vertexOutput) #endif } #endif