ShaderVariablesFunctions.hlsl 8.6 KB

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