Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Cast Shadow problem in vertex animation shader

Discussion in 'Shaders' started by Danistmein, May 16, 2021.

  1. Danistmein

    Danistmein

    Joined:
    Nov 15, 2018
    Posts:
    82
    Hi, everyone. I wrote my own shader based on the unity official version, that can play vertex animation. I also tried to create a custom ShadowCaster pass to it. I have searched for several days. But all of them don't work:(. could anyone can give some threads?

    upload_2021-5-16_13-26-24.png
    soldiers no shadows

    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. Shader "GPU/ToonOutLine"
    4. {
    5.     Properties
    6.     {
    7.         _ToonShade("ToonShader Cubemap(RGB)", CUBE) = "" { }
    8.  
    9.         _Color("Color", Color) = (1,1,1,1)
    10.         _MainTex("Albedo", 2D) = "white" {}
    11.  
    12.         _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
    13.  
    14.         _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
    15.         _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
    16.         [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0
    17.  
    18.         [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
    19.         _MetallicGlossMap("Metallic", 2D) = "white" {}
    20.  
    21.         [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
    22.         [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
    23.  
    24.         _BumpScale("Scale", Float) = 1.0
    25.         _BumpMap("Normal Map", 2D) = "bump" {}
    26.  
    27.         _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
    28.         _ParallaxMap ("Height Map", 2D) = "black" {}
    29.  
    30.         _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
    31.         _OcclusionMap("Occlusion", 2D) = "white" {}
    32.  
    33.         _EmissionColor("Color", Color) = (0,0,0)
    34.         _EmissionMap("Emission", 2D) = "white" {}
    35.  
    36.         _DetailMask("Detail Mask", 2D) = "white" {}
    37.  
    38.         _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
    39.         _DetailNormalMapScale("Scale", Float) = 1.0
    40.         _DetailNormalMap("Normal Map", 2D) = "bump" {}
    41.  
    42.         _TranslationTexture    ("Translation", 2D) = "white"{}
    43.         _RotationTexture    ("Rotation", 2D) = "white"{}
    44.  
    45.         [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0
    46.  
    47.  
    48.         // Blending state
    49.         [HideInInspector] _Mode ("__mode", Float) = 0.0
    50.         [HideInInspector] _SrcBlend ("__src", Float) = 1.0
    51.         [HideInInspector] _DstBlend ("__dst", Float) = 0.0
    52.         [HideInInspector] _ZWrite ("__zw", Float) = 1.0
    53.     }
    54.  
    55.     CGINCLUDE
    56.         #define UNITY_SETUP_BRDF_INPUT MetallicSetup
    57.     ENDCG
    58.  
    59.     SubShader
    60.     {
    61.         Tags { "RenderType"="Opaque" "PerformanceChecks"="False" }
    62.         LOD 300
    63.  
    64.         // ------------------------------------------------------------------
    65.         //  Deferred pass
    66.         Pass
    67.         {
    68.             Name "DEFERRED"
    69.             Tags { "LightMode" = "ForwardBase" }
    70.             ////Tags { "LightMode" = "Deferred" }
    71.  
    72.             CGPROGRAM
    73.             #pragma target 3.0
    74.             #pragma exclude_renderers nomrt
    75.  
    76.  
    77.             #pragma multi_compile_prepassfinal
    78.             #pragma multi_compile_instancing
    79.             // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes.
    80.             //#pragma multi_compile _ LOD_FADE_CROSSFADE
    81.  
    82.             #pragma vertex vertDeferredSkinning
    83.             #pragma fragment frag
    84.  
    85.             #pragma instancing_options procedural:setup
    86.  
    87.             #include "UnityStandardCore.cginc"
    88.             samplerCUBE _ToonShade;
    89.             sampler2D _AnimationTexture0;
    90.             sampler2D _AnimationTexture1;
    91.             sampler2D _AnimationTexture2;
    92.            
    93. #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    94.             //StructuredBuffer<float4x4> objectToWorldBuffer;
    95.             StructuredBuffer<float4> objectPositionsBuffer;
    96.             StructuredBuffer<float4> objectRotationsBuffer;
    97.             StructuredBuffer<float3> textureCoordinatesBuffer;
    98. #endif
    99.            
    100.            
    101.             //@TODO: use 4x3 matrix
    102.             inline float4x4 CreateMatrix(float texturePosition, float boneId)
    103.             {
    104.                 float4 row0 = tex2Dlod(_AnimationTexture0, float4(texturePosition, boneId, 0, 0));
    105.                 float4 row1 = tex2Dlod(_AnimationTexture1, float4(texturePosition, boneId, 0, 0));
    106.                 float4 row2 = tex2Dlod(_AnimationTexture2, float4(texturePosition, boneId, 0, 0));
    107.            
    108.                 float4x4 reconstructedMatrix = float4x4(row0, row1, row2, float4(0, 0, 0, 1));
    109.            
    110.                 return reconstructedMatrix;
    111.             }
    112.            
    113.             inline float4x4 CalculateSkinMatrix(float3 animationTextureCoords, float2 boneIds, float2 boneInfluences)
    114.             {
    115.                 // We interpolate between two matrices
    116.                 float4x4 frame0_BoneMatrix0 = CreateMatrix(animationTextureCoords.x, boneIds.x);
    117.                 float4x4 frame0_BoneMatrix1 = CreateMatrix(animationTextureCoords.y, boneIds.x);
    118.                 float4x4 frame0_BoneMatrix = frame0_BoneMatrix0 * (1 - animationTextureCoords.z) + frame0_BoneMatrix1 * animationTextureCoords.z;
    119.            
    120.                 float4x4 frame1_BoneMatrix0 = CreateMatrix(animationTextureCoords.x, boneIds.y);
    121.                 float4x4 frame1_BoneMatrix1 = CreateMatrix(animationTextureCoords.y, boneIds.y);
    122.                 float4x4 frame1_BoneMatrix = frame1_BoneMatrix0 * (1 - animationTextureCoords.z) + frame1_BoneMatrix1 * animationTextureCoords.z;
    123.            
    124.                 return frame0_BoneMatrix * boneInfluences.x + frame1_BoneMatrix * boneInfluences.y;
    125.             }
    126.  
    127.  
    128.             void setup()
    129.             {
    130.     #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    131.                 //unity_ObjectToWorld = objectToWorldBuffer[unity_InstanceID];
    132.                 //unity_WorldToObject = unity_ObjectToWorld;
    133.  
    134.                 // Construct an identity matrix
    135.                 unity_ObjectToWorld = float4x4(1, 0, 0, 0,
    136.                     0, 1, 0, 0,
    137.                     0, 0, 1, 0,
    138.                     0, 0, 0, 1);
    139.                 unity_WorldToObject = unity_ObjectToWorld;
    140.  
    141.                 unity_WorldToObject._14_24_34 *= -1;
    142.                 unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33;
    143.     #endif
    144.             }
    145.  
    146.             struct VertexInputSkinning
    147.             {
    148.             float4 vertex   : POSITION;
    149.             half3 normal    : NORMAL;
    150.             float2 uv0      : TEXCOORD0;
    151.             float2 boneIds  : TEXCOORD1;
    152.             float2 boneInfluences : TEXCOORD2;
    153. #ifdef _TANGENT_TO_WORLD
    154.             half4 tangent   : TANGENT;
    155. #endif
    156.  
    157.             UNITY_VERTEX_INPUT_INSTANCE_ID
    158.             };
    159.  
    160.             struct v2f
    161.             {
    162.                 UNITY_POSITION(pos);
    163.                 float4 tex                            : TEXCOORD3;
    164.                 float3 eyeVec                         : TEXCOORD4;
    165.                 ////float4 tangentToWorldAndPackedData[3] : TEXCOORD2;    // [3x3:tangentToWorld | 1x3:viewDirForParallax or worldPos]
    166.                 ////half4 ambientOrLightmapUV             : TEXCOORD5;    // SH or Lightmap UVs
    167.                 float3 cubenormal                      : TEXCOORD5;
    168.                 fixed4 diff : COLOR0; // diffuse lighting color
    169.                 float3 normalWorld                         :TEXCOORD6;
    170.             };
    171.  
    172.  
    173.             float4 TexCoordsSkin(VertexInputSkinning v)
    174.             {
    175.                 float4 texcoord;
    176.                 texcoord.xy = TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0
    177.                 texcoord.zw = TRANSFORM_TEX(((_UVSec == 0) ? v.uv0 : v.boneIds), _DetailAlbedoMap);
    178.                 return texcoord;
    179.             }
    180.  
    181.             inline float4 QuaternionMul(float4 v, float4 q)
    182.             {
    183.                 v = float4(v + 2 * cross(q.xyz, cross(q.xyz, v.xyz) + q.w * v), v.w);
    184.                 return v;
    185.             }
    186.  
    187.             v2f vertDeferredSkinning(VertexInputSkinning v)
    188.             {
    189.                 UNITY_SETUP_INSTANCE_ID(v);
    190.                 v2f o;
    191.                 UNITY_INITIALIZE_OUTPUT(v2f, o);
    192.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    193.  
    194.     #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    195.                 //unity_InstanceID  is the acutal Instance ID after UNITY_SETUP_INSTANCE_ID is called
    196.                 float3 animationTextureCoords = textureCoordinatesBuffer[unity_InstanceID];
    197.  
    198.                 float4x4 firstBoneMatrix0 = CreateMatrix(animationTextureCoords.x, v.boneIds.x);
    199.                 float4x4 firstBoneMatrix1 = CreateMatrix(animationTextureCoords.y, v.boneIds.x);
    200.                 float4x4 firstBoneMatrix = firstBoneMatrix0 * (1 - animationTextureCoords.z) + firstBoneMatrix1 * animationTextureCoords.z;
    201.  
    202.                 float4x4 secondBoneMatrix0 = CreateMatrix(animationTextureCoords.x, v.boneIds.y);
    203.                 float4x4 secondBoneMatrix1 = CreateMatrix(animationTextureCoords.y, v.boneIds.y);
    204.                 float4x4 secondBoneMatrix = secondBoneMatrix0 * (1 - animationTextureCoords.z) + secondBoneMatrix1 * animationTextureCoords.z;
    205.  
    206.                 float4x4 combinedMatrix = firstBoneMatrix * v.boneInfluences.x + secondBoneMatrix * v.boneInfluences.y;
    207.                                 float4 skinnedVertex = mul(combinedMatrix, v.vertex);
    208.                    
    209.                 skinnedVertex *= objectPositionsBuffer[unity_InstanceID].w;
    210.                 float4 posWorld = QuaternionMul(skinnedVertex, objectRotationsBuffer[unity_InstanceID]);
    211.                 posWorld.xyz = posWorld + objectPositionsBuffer[unity_InstanceID].xyz;
    212.  
    213.                 o.pos = UnityObjectToClipPos(posWorld);
    214.  
    215.                 o.tex = TexCoordsSkin(v);
    216.                 o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
    217.  
    218.                 float3 normalSkinningRotated = mul(combinedMatrix, float4(v.normal.xyz, 0));
    219.  
    220.                 o.normalWorld = QuaternionMul(float4(normalSkinningRotated, 1), objectRotationsBuffer[unity_InstanceID]);
    221.     #else
    222.  
    223.                 float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
    224.                 o.pos = UnityObjectToClipPos(v.vertex);
    225.  
    226.                 o.tex = TexCoordsSkin(v);
    227.                 o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
    228.                 float3 normalWorld = UnityObjectToWorldNormal(v.normal);
    229.  
    230.                 ////o.ambientOrLightmapUV = 0;
    231.  
    232.     #endif
    233.                 half nl = max(0, dot(o.normalWorld, _WorldSpaceLightPos0.xyz));
    234.                 // factor in the light color
    235.                 o.diff = nl * _LightColor0;
    236.  
    237.                 //// the only difference from previous shader:
    238.                 //// in addition to the diffuse lighting from the main light,
    239.                 //// add illumination from ambient or light probes
    240.                 //// ShadeSH9 function from UnityCG.cginc evaluates it,
    241.                 //// using world space normal
    242.                 o.diff.rgb += ShadeSH9(half4(o.normalWorld, 1));
    243.  
    244.                 UNITY_TRANSFER_FOG(o, o.pos);
    245.                 return o;
    246.             }
    247.  
    248.             fixed4 frag(v2f i) : SV_Target
    249.             {
    250.                 fixed4 col = _Color * tex2D(_MainTex, i.tex);
    251.                 fixed4 cube = texCUBE(_ToonShade, i.cubenormal);
    252.                 fixed4 c = fixed4(2.0f * cube.rgb * col.rgb, col.a);
    253.                 ////fixed4 c = col;
    254.                 ////c *= _Intensity;
    255.                 ////c = float4(1, 1, 1, 1)
    256.                 ////c *= i.diff;
    257.                 UNITY_APPLY_FOG(i.fogCoord, c);
    258.                 return c;
    259.                 ////return float4(i.normalWorld.x, i.normalWorld.y, i.normalWorld.z, 1);
    260.             }
    261.  
    262.  
    263.             ENDCG
    264.         }
    265.  
    266.         // Shadow Caster Pass
    267.         Pass
    268.         {
    269.             Tags { "LightMode" = "ShadowCaster" }
    270.        
    271.             CGPROGRAM
    272.             #include "UnityCG.cginc"
    273.  
    274.             #pragma target 3.0
    275.             #pragma multi_compile_shadowcaster
    276.             #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
    277.             #pragma multi_compile ___ ANIM_LOOP
    278.             #pragma multi_compile ___ RANDOM_PLAY
    279.  
    280.  
    281.             #pragma multi_compile_prepassfinal
    282.             #pragma vertex vertDeferredSkinning
    283.             #pragma fragment frag
    284.             #pragma instancing_options procedural:setup
    285.  
    286.             samplerCUBE _ToonShade;
    287.             sampler2D _AnimationTexture0;
    288.             sampler2D _AnimationTexture1;
    289.             sampler2D _AnimationTexture2;
    290.            
    291. #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    292.             //StructuredBuffer<float4x4> objectToWorldBuffer;
    293.             StructuredBuffer<float4> objectPositionsBuffer;
    294.             StructuredBuffer<float4> objectRotationsBuffer;
    295.             StructuredBuffer<float3> textureCoordinatesBuffer;
    296. #endif
    297.            
    298.             //@TODO: Use vertex skinning node
    299.  
    300.             struct VertexInputSkinning
    301.             {
    302.                 float4 vertex   : POSITION;
    303.                 half3 normal    : NORMAL;
    304.                 float2 uv0      : TEXCOORD0;
    305.                 float2 boneIds  : TEXCOORD1;
    306.                 float2 boneInfluences : TEXCOORD2;
    307.  
    308.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    309.             };
    310.  
    311.             struct v2f
    312.             {
    313.                 V2F_SHADOW_CASTER;
    314.                 UNITY_VERTEX_OUTPUT_STEREO
    315.             };
    316.            
    317.             //@TODO: use 4x3 matrix
    318.             inline float4x4 CreateMatrix(float texturePosition, float boneId)
    319.             {
    320.                 float4 row0 = tex2Dlod(_AnimationTexture0, float4(texturePosition, boneId, 0, 0));
    321.                 float4 row1 = tex2Dlod(_AnimationTexture1, float4(texturePosition, boneId, 0, 0));
    322.                 float4 row2 = tex2Dlod(_AnimationTexture2, float4(texturePosition, boneId, 0, 0));
    323.            
    324.                 float4x4 reconstructedMatrix = float4x4(row0, row1, row2, float4(0, 0, 0, 1));
    325.            
    326.                 return reconstructedMatrix;
    327.             }
    328.            
    329.             inline float4x4 CalculateSkinMatrix(float3 animationTextureCoords, float2 boneIds, float2 boneInfluences)
    330.             {
    331.                 // We interpolate between two matrices
    332.                 float4x4 frame0_BoneMatrix0 = CreateMatrix(animationTextureCoords.x, boneIds.x);
    333.                 float4x4 frame0_BoneMatrix1 = CreateMatrix(animationTextureCoords.y, boneIds.x);
    334.                 float4x4 frame0_BoneMatrix = frame0_BoneMatrix0 * (1 - animationTextureCoords.z) + frame0_BoneMatrix1 * animationTextureCoords.z;
    335.            
    336.                 float4x4 frame1_BoneMatrix0 = CreateMatrix(animationTextureCoords.x, boneIds.y);
    337.                 float4x4 frame1_BoneMatrix1 = CreateMatrix(animationTextureCoords.y, boneIds.y);
    338.                 float4x4 frame1_BoneMatrix = frame1_BoneMatrix0 * (1 - animationTextureCoords.z) + frame1_BoneMatrix1 * animationTextureCoords.z;
    339.            
    340.                 return frame0_BoneMatrix * boneInfluences.x + frame1_BoneMatrix * boneInfluences.y;
    341.             }
    342.  
    343.  
    344.             void setup()
    345.             {
    346.     #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    347.                 //unity_ObjectToWorld = objectToWorldBuffer[unity_InstanceID];
    348.                 //unity_WorldToObject = unity_ObjectToWorld;
    349.  
    350.                 // Construct an identity matrix
    351.                 unity_ObjectToWorld = float4x4(1, 0, 0, 0,
    352.                     0, 1, 0, 0,
    353.                     0, 0, 1, 0,
    354.                     0, 0, 0, 1);
    355.                 unity_WorldToObject = unity_ObjectToWorld;
    356.  
    357.                 unity_WorldToObject._14_24_34 *= -1;
    358.                 unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33;
    359.     #endif
    360.             }
    361.  
    362.  
    363.             inline float4 QuaternionMul(float4 v, float4 q)
    364.             {
    365.                 v = float4(v + 2 * cross(q.xyz, cross(q.xyz, v.xyz) + q.w * v), v.w);
    366.                 return v;
    367.             }
    368.  
    369.             v2f vertDeferredSkinning(VertexInputSkinning v)
    370.             {
    371.                 UNITY_SETUP_INSTANCE_ID(v);
    372.                 v2f o;
    373.                 ////UNITY_INITIALIZE_OUTPUT(v2f, o);
    374.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    375.  
    376.     #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    377.                 //unity_InstanceID  is the acutal Instance ID after UNITY_SETUP_INSTANCE_ID is called
    378.                 float3 animationTextureCoords = textureCoordinatesBuffer[unity_InstanceID];
    379.  
    380.                 float4x4 firstBoneMatrix0 = CreateMatrix(animationTextureCoords.x, v.boneIds.x);
    381.                 float4x4 firstBoneMatrix1 = CreateMatrix(animationTextureCoords.y, v.boneIds.x);
    382.                 float4x4 firstBoneMatrix = firstBoneMatrix0 * (1 - animationTextureCoords.z) + firstBoneMatrix1 * animationTextureCoords.z;
    383.  
    384.                 float4x4 secondBoneMatrix0 = CreateMatrix(animationTextureCoords.x, v.boneIds.y);
    385.                 float4x4 secondBoneMatrix1 = CreateMatrix(animationTextureCoords.y, v.boneIds.y);
    386.                 float4x4 secondBoneMatrix = secondBoneMatrix0 * (1 - animationTextureCoords.z) + secondBoneMatrix1 * animationTextureCoords.z;
    387.  
    388.                 float4x4 combinedMatrix = firstBoneMatrix * v.boneInfluences.x + secondBoneMatrix * v.boneInfluences.y;
    389.                                 float4 skinnedVertex = mul(combinedMatrix, v.vertex);
    390.                    
    391.                 skinnedVertex *= objectPositionsBuffer[unity_InstanceID].w;
    392.                 float4 posWorld = QuaternionMul(skinnedVertex, objectRotationsBuffer[unity_InstanceID]);
    393.                 posWorld.xyz = posWorld + objectPositionsBuffer[unity_InstanceID].xyz;
    394.  
    395.                 v.vertex = UnityObjectToClipPos(posWorld);
    396.  
    397.                 ////o.tex = TexCoordsSkin(v);
    398.                 ////o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
    399.  
    400.                 float3 normalSkinningRotated = mul(combinedMatrix, float4(v.normal.xyz, 0));
    401.  
    402.                 v.normal = QuaternionMul(float4(normalSkinningRotated, 1), objectRotationsBuffer[unity_InstanceID]);
    403.     #else
    404.  
    405.                 float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
    406.                 v.vertex = UnityObjectToClipPos(v.vertex);
    407.  
    408.                 ////o.tex = TexCoordsSkin(v);
    409.                 ////o.eyeVec = NormalizePerVertexNormal(posWorld.xyz - _WorldSpaceCameraPos);
    410.                 v.normal = UnityObjectToWorldNormal(v.normal);
    411.  
    412.     #endif
    413.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    414.                 return o;
    415.             }
    416.  
    417.             fixed4 frag(v2f i) : SV_Target
    418.             {
    419.                 SHADOW_CASTER_FRAGMENT(i)
    420.             }
    421.             ENDCG
    422.         }
    423.     }
    424.  
    425.  
    426.  
    427.     ////FallBack "VertexLit"
    428.     ////CustomEditor "StandardShaderGUI"
    429. }
    430.