1. #ifndef UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
  2. #define UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
  3.  
  4. VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
  5. {
  6. VertexPositionInputs input;
  7. input.positionWS = TransformObjectToWorld(positionOS);
  8. input.positionVS = TransformWorldToView(input.positionWS);
  9. input.positionCS = TransformWorldToHClip(input.positionWS);
  10.  
  11. float4 ndc = input.positionCS * 0.5f;
  12. input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
  13. input.positionNDC.zw = input.positionCS.zw;
  14.  
  15. return input;
  16. }
  17.  
  18. VertexNormalInputs GetVertexNormalInputs(float3 normalOS)
  19. {
  20. VertexNormalInputs tbn;
  21. tbn.tangentWS = real3(1.0, 0.0, 0.0);
  22. tbn.bitangentWS = real3(0.0, 1.0, 0.0);
  23. tbn.normalWS = TransformObjectToWorldNormal(normalOS);
  24. return tbn;
  25. }
  26.  
  27. VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS)
  28. {
  29. VertexNormalInputs tbn;
  30.  
  31. // mikkts space compliant. only normalize when extracting normal at frag.
  32. real sign = tangentOS.w * GetOddNegativeScale();
  33. tbn.normalWS = TransformObjectToWorldNormal(normalOS);
  34. tbn.tangentWS = TransformObjectToWorldDir(tangentOS.xyz);
  35. tbn.bitangentWS = cross(tbn.normalWS, tbn.tangentWS) * sign;
  36. return tbn;
  37. }
  38.  
  39. float4 GetScaledScreenParams()
  40. {
  41. return _ScaledScreenParams;
  42. }
  43.  
  44. // Returns 'true' if the current view performs a perspective projection.
  45. bool IsPerspectiveProjection()
  46. {
  47. return (unity_OrthoParams.w == 0);
  48. }
  49.  
  50. float3 GetCameraPositionWS()
  51. {
  52. // Currently we do not support Camera Relative Rendering so
  53. // we simply return the _WorldSpaceCameraPos until then
  54. return _WorldSpaceCameraPos;
  55.  
  56. // We will replace the code above with this one once
  57. // we start supporting Camera Relative Rendering
  58. //#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
  59. // return float3(0, 0, 0);
  60. //#else
  61. // return _WorldSpaceCameraPos;
  62. //#endif
  63. }
  64.  
  65. // Could be e.g. the position of a primary camera or a shadow-casting light.
  66. float3 GetCurrentViewPosition()
  67. {
  68. // Currently we do not support Camera Relative Rendering so
  69. // we simply return the _WorldSpaceCameraPos until then
  70. return GetCameraPositionWS();
  71.  
  72. // We will replace the code above with this one once
  73. // we start supporting Camera Relative Rendering
  74. //#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS)
  75. // return GetCameraPositionWS();
  76. //#else
  77. // // This is a generic solution.
  78. // // However, for the primary camera, using '_WorldSpaceCameraPos' is better for cache locality,
  79. // // and in case we enable camera-relative rendering, we can statically set the position is 0.
  80. // return UNITY_MATRIX_I_V._14_24_34;
  81. //#endif
  82. }
  83.  
  84. // Returns the forward (central) direction of the current view in the world space.
  85. float3 GetViewForwardDir()
  86. {
  87. float4x4 viewMat = GetWorldToViewMatrix();
  88. return -viewMat[2].xyz;
  89. }
  90.  
  91. // Computes the world space view direction (pointing towards the viewer).
  92. float3 GetWorldSpaceViewDir(float3 positionWS)
  93. {
  94. if (IsPerspectiveProjection())
  95. {
  96. // Perspective
  97. return GetCurrentViewPosition() - positionWS;
  98. }
  99. else
  100. {
  101. // Orthographic
  102. return -GetViewForwardDir();
  103. }
  104. }
  105.  
  106. float3 GetWorldSpaceNormalizeViewDir(float3 positionWS)
  107. {
  108. if (IsPerspectiveProjection())
  109. {
  110. // Perspective
  111. float3 V = GetCurrentViewPosition() - positionWS;
  112. return normalize(V);
  113. }
  114. else
  115. {
  116. // Orthographic
  117. return -GetViewForwardDir();
  118. }
  119. }
  120.  
  121. // UNITY_MATRIX_V defines a right-handed view space with the Z axis pointing towards the viewer.
  122. // This function reverses the direction of the Z axis (so that it points forward),
  123. // making the view space coordinate system left-handed.
  124. void GetLeftHandedViewSpaceMatrices(out float4x4 viewMatrix, out float4x4 projMatrix)
  125. {
  126. viewMatrix = UNITY_MATRIX_V;
  127. viewMatrix._31_32_33_34 = -viewMatrix._31_32_33_34;
  128.  
  129. projMatrix = UNITY_MATRIX_P;
  130. projMatrix._13_23_33_43 = -projMatrix._13_23_33_43;
  131. }
  132.  
  133. void AlphaDiscard(real alpha, real cutoff, real offset = 0.0h)
  134. {
  135. #ifdef _ALPHATEST_ON
  136. clip(alpha - cutoff + offset);
  137. #endif
  138. }
  139.  
  140. half OutputAlpha(half outputAlpha, half surfaceType = 0.0)
  141. {
  142. return surfaceType == 1 ? outputAlpha : 1.0;
  143. }
  144.  
  145. // A word on normalization of normals:
  146. // For better quality normals should be normalized before and after
  147. // interpolation.
  148. // 1) In vertex, skinning or blend shapes might vary significantly the lenght of normal.
  149. // 2) In fragment, because even outputting unit-length normals interpolation can make it non-unit.
  150. // 3) In fragment when using normal map, because mikktspace sets up non orthonormal basis.
  151. // However we will try to balance performance vs quality here as also let users configure that as
  152. // shader quality tiers.
  153. // Low Quality Tier: Normalize either per-vertex or per-pixel depending if normalmap is sampled.
  154. // Medium Quality Tier: Always normalize per-vertex. Normalize per-pixel only if using normal map
  155. // High Quality Tier: Normalize in both vertex and pixel shaders.
  156. real3 NormalizeNormalPerVertex(real3 normalWS)
  157. {
  158. #if defined(SHADER_QUALITY_LOW) && defined(_NORMALMAP)
  159. return normalWS;
  160. #else
  161. return normalize(normalWS);
  162. #endif
  163. }
  164.  
  165. real3 NormalizeNormalPerPixel(real3 normalWS)
  166. {
  167. #if defined(SHADER_QUALITY_HIGH) || defined(_NORMALMAP)
  168. return normalize(normalWS);
  169. #else
  170. return normalWS;
  171. #endif
  172. }
  173.  
  174. // TODO: A similar function should be already available in SRP lib on master. Use that instead
  175. float4 ComputeScreenPos(float4 positionCS)
  176. {
  177. float4 o = positionCS * 0.5f;
  178. o.xy = float2(o.x, o.y * _ProjectionParams.x) + o.w;
  179. o.zw = positionCS.zw;
  180. return o;
  181. }
  182.  
  183. real ComputeFogFactor(float z)
  184. {
  185. float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);
  186.  
  187. #if defined(FOG_LINEAR)
  188. // factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
  189. float fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w);
  190. return real(fogFactor);
  191. #elif defined(FOG_EXP) || defined(FOG_EXP2)
  192. // factor = exp(-(density*z)^2)
  193. // -density * z computed at vertex
  194. return real(unity_FogParams.x * clipZ_01);
  195. #else
  196. return 0.0h;
  197. #endif
  198. }
  199.  
  200. real ComputeFogIntensity(real fogFactor)
  201. {
  202. real fogIntensity = 0.0h;
  203. #if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
  204. #if defined(FOG_EXP)
  205. // factor = exp(-density*z)
  206. // fogFactor = density*z compute at vertex
  207. fogIntensity = saturate(exp2(-fogFactor));
  208. #elif defined(FOG_EXP2)
  209. // factor = exp(-(density*z)^2)
  210. // fogFactor = density*z compute at vertex
  211. fogIntensity = saturate(exp2(-fogFactor * fogFactor));
  212. #elif defined(FOG_LINEAR)
  213. fogIntensity = fogFactor;
  214. #endif
  215. #endif
  216. return fogIntensity;
  217. }
  218.  
  219. half3 MixFogColor(real3 fragColor, real3 fogColor, real fogFactor)
  220. {
  221. #if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
  222. real fogIntensity = ComputeFogIntensity(fogFactor);
  223. fragColor = lerp(fogColor, fragColor, fogIntensity);
  224. #endif
  225. return fragColor;
  226. }
  227.  
  228. half3 MixFog(real3 fragColor, real fogFactor)
  229. {
  230. return MixFogColor(fragColor, unity_FogColor.rgb, fogFactor);
  231. }
  232.  
  233. void TransformScreenUV(inout float2 uv, float screenHeight)
  234. {
  235. #if UNITY_UV_STARTS_AT_TOP
  236. uv.y = screenHeight - (uv.y * _ScaleBiasRt.x + _ScaleBiasRt.y * screenHeight);
  237. #endif
  238. }
  239.  
  240. void TransformScreenUV(inout float2 uv)
  241. {
  242. #if UNITY_UV_STARTS_AT_TOP
  243. TransformScreenUV(uv, GetScaledScreenParams().y);
  244. #endif
  245. }
  246.  
  247. void TransformNormalizedScreenUV(inout float2 uv)
  248. {
  249. #if UNITY_UV_STARTS_AT_TOP
  250. TransformScreenUV(uv, 1.0);
  251. #endif
  252. }
  253.  
  254. float2 GetNormalizedScreenSpaceUV(float2 positionCS)
  255. {
  256. float2 normalizedScreenSpaceUV = positionCS.xy * rcp(GetScaledScreenParams().xy);
  257. TransformNormalizedScreenUV(normalizedScreenSpaceUV);
  258. return normalizedScreenSpaceUV;
  259. }
  260.  
  261. float2 GetNormalizedScreenSpaceUV(float4 positionCS)
  262. {
  263. return GetNormalizedScreenSpaceUV(positionCS.xy);
  264. }
  265.  
  266. #if defined(UNITY_SINGLE_PASS_STEREO)
  267. float2 TransformStereoScreenSpaceTex(float2 uv, float w)
  268. {
  269. // TODO: RVS support can be added here, if Universal decides to support it
  270. float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
  271. return uv.xy * scaleOffset.xy + scaleOffset.zw * w;
  272. }
  273.  
  274. float2 UnityStereoTransformScreenSpaceTex(float2 uv)
  275. {
  276. return TransformStereoScreenSpaceTex(saturate(uv), 1.0);
  277. }
  278. #else
  279. #define UnityStereoTransformScreenSpaceTex(uv) uv
  280. #endif // defined(UNITY_SINGLE_PASS_STEREO)
  281.  
  282. #endif // UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED