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.

271 lines
12 KiB

  1. //
  2. // OvrAvatar Mobile single component expressive face shader
  3. // For use on expressive face meshes
  4. //
  5. // Unity vertex-fragnment implementation
  6. // Simplified lighting model recommended for use on mobile supporting one directional light
  7. // Surface shader recommended on PC
  8. //
  9. // Uses transparent queue for fade effects
  10. //
  11. // Color and appearance of the facial regions controlled via G&B channels in roughness texture
  12. // Pupil size controlled by manipulating UV coordinates
  13. //
  14. // Shader keywords:
  15. // - SECONDARY_LIGHT_ON SECONDARY_LIGHT_OFF
  16. // Enable SECONDARY_LIGHT_ON for a second "light" comprised of _SecondaryLightDirection and
  17. // _SecondaryLightColor This will influence the rim effect providing additional contour to the
  18. // avatar
  19. //
  20. Shader "OvrAvatar/Avatar_Mobile_SingleComponentExpressive"
  21. {
  22. Properties
  23. {
  24. [NoScaleOffset] _MainTex("Main Texture", 2D) = "white" {}
  25. [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {}
  26. [NoScaleOffset] _RoughnessMap("Roughness Map", 2D) = "black" {}
  27. _BaseColor("Color Tint", Color) = (1.0,1.0,1.0,1.0)
  28. _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0
  29. _Alpha("Alpha", Range(0.0,1.0)) = 1.0
  30. _DiffuseIntensity("Diffuse Intensity", Range(0.0,1.0)) = 0.3
  31. _ReflectionIntensity("Reflection Intensity", Range(0.0,1.0)) = 0.0
  32. _RimIntensity("Rim Intensity", Range(0.0,10.0)) = 5.0
  33. _PupilSize("Pupil Size", Range(-1, 2)) = 0
  34. _LipSmoothness("Lip Smoothness", Range(0, 1)) = 0
  35. _MaskColorIris("Iris Color", Color) = (0.0,0.0,0.0,1.0)
  36. _MaskColorLips("Lips Color", Color) = (0.0,0.0,0.0,1.0)
  37. _MaskColorBrows("Brows Color", Color) = (0.0,0.0,0.0,1.0)
  38. _MaskColorLashes("Lashes Color", Color) = (0.0,0.0,0.0,1.0)
  39. _MaskColorSclera("Sclera Color", Color) = (0.0,0.0,0.0,1.0)
  40. _MaskColorGums("Gums Color", Color) = (0.0,0.0,0.0,1.0)
  41. _MaskColorTeeth("Teeth Color", Color) = (0.0,0.0,0.0,1.0)
  42. [HideInInspector] _SrcBlend("", Float) = 1
  43. [HideInInspector] _DstBlend("", Float) = 0
  44. }
  45. SubShader
  46. {
  47. Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"}
  48. Pass
  49. {
  50. Blend [_SrcBlend] [_DstBlend]
  51. Cull Back
  52. CGPROGRAM
  53. #pragma vertex vert
  54. #pragma fragment frag
  55. #pragma target 3.0
  56. #pragma fragmentoption ARB_precision_hint_fastest
  57. #pragma multi_compile SECONDARY_LIGHT_OFF SECONDARY_LIGHT_ON
  58. #include "UnityCG.cginc"
  59. #include "UnityLightingCommon.cginc"
  60. sampler2D _MainTex;
  61. sampler2D _NormalMap;
  62. float4 _NormalMap_ST;
  63. sampler2D _RoughnessMap;
  64. half4 _BaseColor;
  65. half _Dimmer;
  66. half _Alpha;
  67. half _DiffuseIntensity;
  68. half _RimIntensity;
  69. half _ReflectionIntensity;
  70. half3 _SecondaryLightDirection;
  71. half4 _SecondaryLightColor;
  72. half _PupilSize;
  73. half _LipSmoothness;
  74. fixed4 _MaskColorIris;
  75. fixed4 _MaskColorSclera;
  76. fixed4 _MaskColorBrows;
  77. fixed4 _MaskColorLashes;
  78. fixed4 _MaskColorLashesEnd;
  79. fixed4 _MaskColorLips;
  80. fixed4 _MaskColorGums;
  81. fixed4 _MaskColorTeeth;
  82. static const int ONE = 1;
  83. static const fixed ALPHA_CLIP_THRESHOLD = 0.7;
  84. static const int IRIS_BRIGHTNESS_MODIFIER = 2;
  85. static const fixed SCLERA_BRIGHTNESS_MODIFIER = 1.2;
  86. static const fixed LIP_SMOOTHNESS_MULTIPLIER = 0.5;
  87. static const fixed LIP_SMOOTHNESS_MIN_NDOTL = 0.3;
  88. static const fixed BROWS_LASHES_DIFFUSEINTENSITY = ONE - 0.25;
  89. static const int COLOR_MULTIPLIER = 255;
  90. static const half2 PUPIL_CENTER_UV = half2(0.127, 0.1175);
  91. static const half DILATION_ENVELOPE = 0.024;
  92. static const half2 EYE_REGION_UV = PUPIL_CENTER_UV + DILATION_ENVELOPE;
  93. static const int MASK_SLICE_SIZE = 17;
  94. static const half MASK_SLICE_THRESHOLD = MASK_SLICE_SIZE * 0.5f;
  95. static const int MASK_INDEX_IRIS = 255;
  96. static const int MASK_INDEX_SCLERA = 238;
  97. static const int MASK_INDEX_LASHES = 221;
  98. static const int MASK_INDEX_LIPS = 204;
  99. static const int MASK_INDEX_GUMS = 187;
  100. static const int MASK_INDEX_TEETH = 170;
  101. static const int MASK_INDEX_BROWS = 153;
  102. struct appdata
  103. {
  104. float4 vertex: POSITION;
  105. float3 normal: NORMAL;
  106. float4 tangent: TANGENT;
  107. float4 uv: TEXCOORD0;
  108. };
  109. struct v2f
  110. {
  111. float4 pos : SV_POSITION;
  112. float2 uv : TEXCOORD0;
  113. float4 posWorld: TEXCOORD1;
  114. float3 normalDir: TEXCOORD2;
  115. float3 tangentDir: TEXCOORD3;
  116. float3 bitangentDir: TEXCOORD4;
  117. };
  118. v2f vert(appdata v)
  119. {
  120. v2f o;
  121. // Calculate tangents for normal mapping
  122. o.normalDir = normalize(UnityObjectToWorldNormal(v.normal));
  123. o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz);
  124. o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w);
  125. o.posWorld = mul(unity_ObjectToWorld, v.vertex);
  126. o.pos = UnityObjectToClipPos(v.vertex);
  127. o.uv = v.uv;
  128. return o;
  129. }
  130. fixed4 frag(v2f i) : COLOR
  131. {
  132. // Pupil size offsets uv coords
  133. if (all(i.uv < EYE_REGION_UV))
  134. {
  135. i.uv -= PUPIL_CENTER_UV;
  136. half pupil = saturate(length(i.uv) / DILATION_ENVELOPE);
  137. i.uv *= lerp(1.0, pupil, _PupilSize);
  138. i.uv += PUPIL_CENTER_UV;
  139. }
  140. // Diffuse texture sample
  141. half4 albedoColor = tex2D(_MainTex, i.uv);
  142. // Process normal map
  143. #if (UNITY_VERSION >= 20171)
  144. float3 normalMap = UnpackNormal(tex2D(_NormalMap, i.uv));
  145. #else
  146. float3 normalMap = tex2D(_NormalMap, i.uv) * 2.0 - ONE;
  147. #endif
  148. float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir);
  149. float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform));
  150. // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g
  151. half4 roughnessTex = tex2D(_RoughnessMap, i.uv);
  152. // Normal/Light/View calculations
  153. half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
  154. half VdotN = saturate(dot(viewDirection, normalDirection));
  155. half NdotL = saturate(dot(normalDirection, normalize(_WorldSpaceLightPos0.xyz)));
  156. // Sample the default reflection cubemap using the reflection vector
  157. float3 worldReflection = reflect(-viewDirection, normalDirection);
  158. half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldReflection);
  159. // Decode cubemap data into actual color
  160. half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR);
  161. // Color space conversions if we are in linear
  162. #ifndef UNITY_COLORSPACE_GAMMA
  163. _BaseColor.rgb = LinearToGammaSpace(_BaseColor.rgb);
  164. _MaskColorIris.rgb = LinearToGammaSpace(_MaskColorIris);
  165. _MaskColorLips.rgb = LinearToGammaSpace(_MaskColorLips.rgb);
  166. _MaskColorBrows.rgb = LinearToGammaSpace(_MaskColorBrows.rgb);
  167. _MaskColorLashes.rgb = LinearToGammaSpace(_MaskColorLashes.rgb);
  168. _MaskColorLashesEnd.rgb = LinearToGammaSpace(_MaskColorLashesEnd.rgb);
  169. _MaskColorSclera.rgb = LinearToGammaSpace(_MaskColorSclera.rgb);
  170. _MaskColorGums.rgb = LinearToGammaSpace(_MaskColorGums.rgb);
  171. _MaskColorTeeth.rgb = LinearToGammaSpace(_MaskColorTeeth.rgb);
  172. #endif
  173. // Calculate color masks
  174. half irisScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_IRIS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;
  175. half lipsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LIPS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;
  176. half browsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_BROWS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;;
  177. half lashesScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LASHES) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;
  178. half scleraScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_SCLERA) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;
  179. half teethScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_TEETH) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;;
  180. half gumsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_GUMS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;;
  181. half3 maskIris = irisScalar * (_MaskColorIris * IRIS_BRIGHTNESS_MODIFIER - _BaseColor.rgb);
  182. half3 maskBrows = browsScalar * (_MaskColorBrows - _BaseColor.rgb);
  183. half3 maskLashes = lashesScalar * (_MaskColorLashes - _BaseColor.rgb);
  184. half3 maskSclera = scleraScalar * (_MaskColorSclera * SCLERA_BRIGHTNESS_MODIFIER - _BaseColor.rgb);
  185. half3 maskTeeth = teethScalar * (_MaskColorTeeth - _BaseColor.rgb);
  186. half3 maskGums = gumsScalar * (_MaskColorGums - _BaseColor.rgb);
  187. // Lip tint excluded from color mask as it lerps with texture color
  188. half3 colorMask = maskIris + maskBrows + maskLashes + maskSclera + maskTeeth + maskGums;
  189. // Lerp diffuseIntensity with roughness map
  190. _DiffuseIntensity = lerp(_DiffuseIntensity, ONE, roughnessTex.a);
  191. // Brows and lashes modify DiffuseIntensity
  192. _DiffuseIntensity *= ONE - (saturate(browsScalar + lashesScalar) * BROWS_LASHES_DIFFUSEINTENSITY);
  193. // Add in diffuseIntensity and main lighting to base color
  194. _BaseColor.rgb += _DiffuseIntensity * NdotL * _LightColor0;
  195. // Add in color mask to base color
  196. _BaseColor.rgb += colorMask;
  197. // Multiply texture with base color with special case for lips
  198. albedoColor.rgb = lerp(albedoColor.rgb * _BaseColor.rgb, _MaskColorLips.rgb, lipsScalar * _MaskColorLips.a);
  199. // Smoothness multiplier on lip region
  200. albedoColor.rgb += lipsScalar * reflectionColor * (_LipSmoothness * LIP_SMOOTHNESS_MULTIPLIER) *
  201. lerp(LIP_SMOOTHNESS_MIN_NDOTL, ONE, NdotL);
  202. // Reflection from cubemap
  203. albedoColor.rgb += reflectionColor * (roughnessTex.a * _ReflectionIntensity) * NdotL;
  204. // Rim term
  205. #ifdef SECONDARY_LIGHT_ON
  206. // Secondary light proxy (direction and color) passed into the rim term
  207. NdotL = saturate(dot(normalDirection, _SecondaryLightDirection));
  208. albedoColor.rgb += pow(ONE - VdotN, _RimIntensity) * NdotL * _SecondaryLightColor;
  209. #else
  210. albedoColor.rgb += pow(ONE - VdotN, _RimIntensity) * NdotL;
  211. #endif
  212. // Global dimmer
  213. albedoColor.rgb *= _Dimmer;
  214. // Convert back to linear color space if we are in linear
  215. #if !defined(UNITY_COLORSPACE_GAMMA)
  216. albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb);
  217. #endif
  218. albedoColor.rgb = saturate(albedoColor.rgb);
  219. // Set alpha, with special case for lashes
  220. albedoColor.a = saturate(albedoColor.a * lerp(ONE, _Alpha, ONE - lashesScalar) * _Alpha);
  221. // Clip fragments in the lash region for clean lash transparency
  222. clip(albedoColor.a - lerp(0.0, ALPHA_CLIP_THRESHOLD, lashesScalar));
  223. // Return clamped final color
  224. return albedoColor;
  225. }
  226. ENDCG
  227. }
  228. }
  229. Fallback "Diffuse"
  230. }