Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
8.2 KiB

  1. //
  2. // OvrAvatar Mobile combined mesh shader
  3. // For use on non-expressive face meshes and other components
  4. // Texture array approach for rendering a combined mesh avatar
  5. // Coupled with OvrAvatarMaterialManager to populate the texture arrays
  6. //
  7. // Unity vertex-fragnment implementation
  8. // Simplified lighting model recommended for use on mobile supporting one directional light
  9. // Surface shader recommended on PC
  10. //
  11. // Uses transparent queue for fade effects
  12. //
  13. // Simple mouth animation with speech done with vertex perturbation
  14. //
  15. // Shader keywords:
  16. // - SECONDARY_LIGHT_ON SECONDARY_LIGHT_OFF
  17. // Enable SECONDARY_LIGHT_ON for a second "light" comprised of _SecondaryLightDirection and
  18. // _SecondaryLightColor This will influence the rim effect providing a lit contour to the avatar
  19. //
  20. Shader "OvrAvatar/Avatar_Mobile_CombinedMesh"
  21. {
  22. Properties
  23. {
  24. [NoScaleOffset] _MainTex("Main Texture Array", 2DArray) = "white" {}
  25. [NoScaleOffset] _NormalMap("Normal Map Array", 2DArray) = "bump" {}
  26. [NoScaleOffset] _RoughnessMap("Roughness Map Array", 2DArray) = "black" {}
  27. _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0
  28. _Alpha("Alpha", Range(0.0,1.0)) = 1.0
  29. // Index into the texture array needs an offset for precision
  30. _Slices("Texture Array Slices", int) = 4.97
  31. _Voice("Voice", Range(0.0,1.0)) = 0.0
  32. [HideInInspector] _MouthPosition("Mouth position", Vector) = (0,0,0,1)
  33. [HideInInspector] _MouthDirection("Mouth direction", Vector) = (0,0,0,1)
  34. [HideInInspector] _MouthEffectDistance("Mouth Effect Distance", Float) = 0.03
  35. [HideInInspector] _MouthEffectScale("Mouth Effect Scaler", Float) = 1
  36. [HideInInspector] _SrcBlend("", Float) = 1
  37. [HideInInspector] _DstBlend("", Float) = 0
  38. }
  39. SubShader
  40. {
  41. Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"}
  42. Pass
  43. {
  44. Blend [_SrcBlend] [_DstBlend]
  45. Cull Back
  46. CGPROGRAM
  47. #pragma vertex vert
  48. #pragma fragment frag
  49. #pragma target 3.5
  50. #pragma fragmentoption ARB_precision_hint_fastest
  51. #pragma multi_compile SECONDARY_LIGHT_OFF SECONDARY_LIGHT_ON
  52. #include "UnityCG.cginc"
  53. #include "UnityLightingCommon.cginc"
  54. UNITY_DECLARE_TEX2DARRAY(_MainTex);
  55. UNITY_DECLARE_TEX2DARRAY(_NormalMap);
  56. float4 _NormalMap_ST;
  57. UNITY_DECLARE_TEX2DARRAY(_RoughnessMap);
  58. int _Slices;
  59. half _Dimmer;
  60. half _Alpha;
  61. half4 _BaseColor[5];
  62. half _DiffuseIntensity[5];
  63. half _RimIntensity[5];
  64. half _ReflectionIntensity[5];
  65. half3 _SecondaryLightDirection;
  66. half4 _SecondaryLightColor;
  67. half _Voice;
  68. half4 _MouthPosition;
  69. half4 _MouthDirection;
  70. half _MouthEffectDistance;
  71. half _MouthEffectScale;
  72. static const fixed MOUTH_ZSCALE = 0.5f;
  73. static const fixed MOUTH_DROPOFF = 0.01f;
  74. struct appdata
  75. {
  76. float4 vertex: POSITION;
  77. float3 normal: NORMAL;
  78. float4 tangent: TANGENT;
  79. float2 texcoord: TEXCOORD0;
  80. float4 vertexColor : COLOR0;
  81. };
  82. struct v2f
  83. {
  84. float4 pos : SV_POSITION;
  85. float3 uv : TEXCOORD0;
  86. float4 posWorld: TEXCOORD1;
  87. float3 normalDir: TEXCOORD2;
  88. float3 tangentDir: TEXCOORD3;
  89. float3 bitangentDir: TEXCOORD4;
  90. };
  91. v2f vert(appdata v)
  92. {
  93. v2f o;
  94. // Mouth vertex animation with voice
  95. float4 worldVert = mul(unity_ObjectToWorld, v.vertex);
  96. float3 delta = _MouthPosition - worldVert;
  97. delta.z *= MOUTH_ZSCALE;
  98. half dist = length(delta);
  99. half scaledMouthDropoff = _MouthEffectScale * MOUTH_DROPOFF;
  100. half scaledMouthEffect = _MouthEffectScale * _MouthEffectDistance;
  101. half displacement = _Voice * smoothstep(scaledMouthEffect + scaledMouthDropoff, scaledMouthEffect, dist);
  102. worldVert.xyz -= _MouthDirection * displacement;
  103. v.vertex = mul(unity_WorldToObject, worldVert);
  104. // Calculate tangents for normal mapping
  105. o.normalDir = normalize(UnityObjectToWorldNormal(v.normal));
  106. o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz);
  107. o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w);
  108. o.posWorld = worldVert;
  109. o.pos = UnityObjectToClipPos(v.vertex);
  110. o.uv.xy = v.texcoord;
  111. o.uv.z = v.vertexColor.x * _Slices;
  112. return o;
  113. }
  114. fixed4 frag(v2f i) : COLOR
  115. {
  116. // Diffuse texture sample
  117. float4 albedoColor = UNITY_SAMPLE_TEX2DARRAY(_MainTex, i.uv);
  118. // Process normal map
  119. float3 transformedNormalUV = i.uv;
  120. transformedNormalUV.xy = float2(TRANSFORM_TEX(i.uv.xy, _NormalMap));
  121. float3 normalMap = UNITY_SAMPLE_TEX2DARRAY(_NormalMap, transformedNormalUV) * 2.0 - 1.0;
  122. float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir);
  123. float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform));
  124. // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g
  125. half4 roughnessTex = UNITY_SAMPLE_TEX2DARRAY(_RoughnessMap, i.uv);
  126. // Normal/Light/View calculations
  127. half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
  128. half VdotN = saturate(dot(viewDirection, normalDirection));
  129. half NdotL = saturate(dot(normalDirection, _WorldSpaceLightPos0.xyz));
  130. // Sample the default reflection cubemap using the reflection vector
  131. float3 worldReflection = reflect(-viewDirection, normalDirection);
  132. half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldReflection);
  133. // Decode cubemap data into actual color
  134. half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR);
  135. // Get index into texture array
  136. int componentIndex = floor(i.uv.z + 0.5);
  137. // Base color from array
  138. float4 baseColor = _BaseColor[componentIndex];
  139. // Diffuse intensity from array
  140. half diffuseIntensity = _DiffuseIntensity[componentIndex];
  141. // Multiply in base color
  142. albedoColor.rgb *= baseColor.rgb;
  143. // Lerp diffuseIntensity with roughness map
  144. diffuseIntensity = lerp(diffuseIntensity, 1.0, roughnessTex.a);
  145. // Apply main light with a lerp between DiffuseIntensity and 1 based on the roughness
  146. albedoColor.rgb += diffuseIntensity * NdotL * _LightColor0;
  147. // Reflection from cubemap
  148. albedoColor.rgb += reflectionColor * (roughnessTex.a * _ReflectionIntensity[componentIndex]) * NdotL;
  149. // Rim term
  150. #ifdef SECONDARY_LIGHT_ON
  151. // Secondary light proxy (direction and color) passed into the rim term
  152. NdotL = saturate(dot(normalDirection, _SecondaryLightDirection));
  153. albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity[componentIndex]) * NdotL * _SecondaryLightColor;
  154. #else
  155. albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity[componentIndex]) * NdotL;
  156. #endif
  157. // Global dimmer
  158. albedoColor.rgb *= _Dimmer;
  159. #if !defined(UNITY_COLORSPACE_GAMMA)
  160. albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb);
  161. #endif
  162. albedoColor.rgb = saturate(albedoColor.rgb);
  163. // Set alpha, with special case for lashes
  164. albedoColor.a *= _Alpha;
  165. // Return clamped final color
  166. return albedoColor;
  167. }
  168. ENDCG
  169. }
  170. }
  171. }