Common.hlsl 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130
  1. #ifndef UNITY_COMMON_INCLUDED
  2. #define UNITY_COMMON_INCLUDED
  3. // Convention:
  4. // Unity is Y up and left handed in world space
  5. // Caution: When going from world space to view space, unity is right handed in view space and the determinant of the matrix is negative
  6. // For cubemap capture (reflection probe) view space is still left handed (cubemap convention) and the determinant is positive.
  7. // The lighting code assume that 1 Unity unit (1uu) == 1 meters. This is very important regarding physically based light unit and inverse square attenuation
  8. // space at the end of the variable name
  9. // WS: world space
  10. // RWS: Camera-Relative world space. A space where the translation of the camera have already been substract in order to improve precision
  11. // VS: view space
  12. // OS: object space
  13. // CS: Homogenous clip spaces
  14. // TS: tangent space
  15. // TXS: texture space
  16. // Example: NormalWS
  17. // normalized / unormalized vector
  18. // normalized direction are almost everywhere, we tag unormalized vector with un.
  19. // Example: unL for unormalized light vector
  20. // use capital letter for regular vector, vector are always pointing outward the current pixel position (ready for lighting equation)
  21. // capital letter mean the vector is normalize, unless we put 'un' in front of it.
  22. // V: View vector (no eye vector)
  23. // L: Light vector
  24. // N: Normal vector
  25. // H: Half vector
  26. // Input/Outputs structs in PascalCase and prefixed by entry type
  27. // struct AttributesDefault
  28. // struct VaryingsDefault
  29. // use input/output as variable name when using these structures
  30. // Entry program name
  31. // VertDefault
  32. // FragDefault / FragForward / FragDeferred
  33. // constant floating number written as 1.0 (not 1, not 1.0f, not 1.0h)
  34. // uniform have _ as prefix + uppercase _LowercaseThenCamelCase
  35. // Do not use "in", only "out" or "inout" as califier, no "inline" keyword either, useless.
  36. // When declaring "out" argument of function, they are always last
  37. // headers from ShaderLibrary do not include "common.hlsl", this should be included in the .shader using it (or Material.hlsl)
  38. // All uniforms should be in contant buffer (nothing in the global namespace).
  39. // The reason is that for compute shader we need to guarantee that the layout of CBs is consistent across kernels. Something that we can't control with the global namespace (uniforms get optimized out if not used, modifying the global CBuffer layout per kernel)
  40. // Structure definition that are share between C# and hlsl.
  41. // These structures need to be align on float4 to respect various packing rules from shader language. This mean that these structure need to be padded.
  42. // Rules: When doing an array for constant buffer variables, we always use float4 to avoid any packing issue, particularly between compute shader and pixel shaders
  43. // i.e don't use SetGlobalFloatArray or SetComputeFloatParams
  44. // The array can be alias in hlsl. Exemple:
  45. // uniform float4 packedArray[3];
  46. // static float unpackedArray[12] = (float[12])packedArray;
  47. // The function of the shader library are stateless, no uniform declare in it.
  48. // Any function that require an explicit precision, use float or half qualifier, when the function can support both, it use real (see below)
  49. // If a function require to have both a half and a float version, then both need to be explicitly define
  50. #ifndef real
  51. // The including shader should define whether half
  52. // precision is suitable for its needs. The shader
  53. // API (for now) can indicate whether half is possible.
  54. #if defined(SHADER_API_MOBILE) || defined(SHADER_API_SWITCH)
  55. #define HAS_HALF 1
  56. #else
  57. #define HAS_HALF 0
  58. #endif
  59. #ifndef PREFER_HALF
  60. #define PREFER_HALF 1
  61. #endif
  62. #if HAS_HALF && PREFER_HALF
  63. #define REAL_IS_HALF 1
  64. #else
  65. #define REAL_IS_HALF 0
  66. #endif // Do we have half?
  67. #if REAL_IS_HALF
  68. #define real half
  69. #define real2 half2
  70. #define real3 half3
  71. #define real4 half4
  72. #define real2x2 half2x2
  73. #define real2x3 half2x3
  74. #define real3x2 half3x2
  75. #define real3x3 half3x3
  76. #define real3x4 half3x4
  77. #define real4x3 half4x3
  78. #define real4x4 half4x4
  79. #define half min16float
  80. #define half2 min16float2
  81. #define half3 min16float3
  82. #define half4 min16float4
  83. #define half2x2 min16float2x2
  84. #define half2x3 min16float2x3
  85. #define half3x2 min16float3x2
  86. #define half3x3 min16float3x3
  87. #define half3x4 min16float3x4
  88. #define half4x3 min16float4x3
  89. #define half4x4 min16float4x4
  90. #define REAL_MIN HALF_MIN
  91. #define REAL_MAX HALF_MAX
  92. #define REAL_EPS HALF_EPS
  93. #define TEMPLATE_1_REAL TEMPLATE_1_HALF
  94. #define TEMPLATE_2_REAL TEMPLATE_2_HALF
  95. #define TEMPLATE_3_REAL TEMPLATE_3_HALF
  96. #else
  97. #define real float
  98. #define real2 float2
  99. #define real3 float3
  100. #define real4 float4
  101. #define real2x2 float2x2
  102. #define real2x3 float2x3
  103. #define real3x2 float3x2
  104. #define real3x3 float3x3
  105. #define real3x4 float3x4
  106. #define real4x3 float4x3
  107. #define real4x4 float4x4
  108. #define REAL_MIN FLT_MIN
  109. #define REAL_MAX FLT_MAX
  110. #define REAL_EPS FLT_EPS
  111. #define TEMPLATE_1_REAL TEMPLATE_1_FLT
  112. #define TEMPLATE_2_REAL TEMPLATE_2_FLT
  113. #define TEMPLATE_3_REAL TEMPLATE_3_FLT
  114. #endif // REAL_IS_HALF
  115. #endif // #ifndef real
  116. // Target in compute shader are supported in 2018.2, for now define ours
  117. // (Note only 45 and above support compute shader)
  118. #ifdef SHADER_STAGE_COMPUTE
  119. # ifndef SHADER_TARGET
  120. # if defined(SHADER_API_METAL)
  121. # define SHADER_TARGET 45
  122. # else
  123. # define SHADER_TARGET 50
  124. # endif
  125. # endif
  126. #endif
  127. // Include language header
  128. #if defined(SHADER_API_XBOXONE)
  129. #include "Packages/com.unity.render-pipelines.xboxone/ShaderLibrary/API/XBoxOne.hlsl"
  130. #elif defined(SHADER_API_PSSL)
  131. #include "Packages/com.unity.render-pipelines.ps4/ShaderLibrary/API/PSSL.hlsl"
  132. #elif defined(SHADER_API_D3D11)
  133. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/D3D11.hlsl"
  134. #elif defined(SHADER_API_METAL)
  135. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/Metal.hlsl"
  136. #elif defined(SHADER_API_VULKAN)
  137. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/Vulkan.hlsl"
  138. #elif defined(SHADER_API_SWITCH)
  139. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/Switch.hlsl"
  140. #elif defined(SHADER_API_GLCORE)
  141. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/GLCore.hlsl"
  142. #elif defined(SHADER_API_GLES3)
  143. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/GLES3.hlsl"
  144. #elif defined(SHADER_API_GLES)
  145. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/GLES2.hlsl"
  146. #else
  147. #error unsupported shader api
  148. #endif
  149. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/Validate.hlsl"
  150. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl"
  151. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Random.hlsl"
  152. // ----------------------------------------------------------------------------
  153. // Common intrinsic (general implementation of intrinsic available on some platform)
  154. // ----------------------------------------------------------------------------
  155. // Error on GLES2 undefined functions
  156. #ifdef SHADER_API_GLES
  157. #define BitFieldExtract ERROR_ON_UNSUPPORTED_FUNCTION(BitFieldExtract)
  158. #define IsBitSet ERROR_ON_UNSUPPORTED_FUNCTION(IsBitSet)
  159. #define SetBit ERROR_ON_UNSUPPORTED_FUNCTION(SetBit)
  160. #define ClearBit ERROR_ON_UNSUPPORTED_FUNCTION(ClearBit)
  161. #define ToggleBit ERROR_ON_UNSUPPORTED_FUNCTION(ToggleBit)
  162. #define FastMulBySignOfNegZero ERROR_ON_UNSUPPORTED_FUNCTION(FastMulBySignOfNegZero)
  163. #define LODDitheringTransition ERROR_ON_UNSUPPORTED_FUNCTION(LODDitheringTransition)
  164. #endif
  165. // On everything but GCN consoles we error on cross-lane operations
  166. #ifndef PLATFORM_SUPPORTS_WAVE_INTRINSICS
  167. #define WaveActiveAllTrue ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveAllTrue)
  168. #define WaveActiveAnyTrue ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveAnyTrue)
  169. #define WaveGetLaneIndex ERROR_ON_UNSUPPORTED_FUNCTION(WaveGetLaneIndex)
  170. #define WaveIsFirstLane ERROR_ON_UNSUPPORTED_FUNCTION(WaveIsFirstLane)
  171. #define GetWaveID ERROR_ON_UNSUPPORTED_FUNCTION(GetWaveID)
  172. #define WaveActiveMin ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveMin)
  173. #define WaveActiveMax ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveMax)
  174. #define WaveActiveBallot ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveBallot)
  175. #define WaveActiveSum ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveSum)
  176. #define WaveActiveBitAnd ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveBitAnd)
  177. #define WaveActiveBitOr ERROR_ON_UNSUPPORTED_FUNCTION(WaveActiveBitOr)
  178. #define WaveGetLaneCount ERROR_ON_UNSUPPORTED_FUNCTION(WaveGetLaneCount)
  179. #endif
  180. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonDeprecated.hlsl"
  181. #if !defined(SHADER_API_GLES)
  182. #ifndef INTRINSIC_BITFIELD_EXTRACT
  183. // Unsigned integer bit field extraction.
  184. // Note that the intrinsic itself generates a vector instruction.
  185. // Wrap this function with WaveReadLaneFirst() to get scalar output.
  186. uint BitFieldExtract(uint data, uint offset, uint numBits)
  187. {
  188. uint mask = (1u << numBits) - 1u;
  189. return (data >> offset) & mask;
  190. }
  191. #endif // INTRINSIC_BITFIELD_EXTRACT
  192. #ifndef INTRINSIC_BITFIELD_EXTRACT_SIGN_EXTEND
  193. // Integer bit field extraction with sign extension.
  194. // Note that the intrinsic itself generates a vector instruction.
  195. // Wrap this function with WaveReadLaneFirst() to get scalar output.
  196. int BitFieldExtractSignExtend(int data, uint offset, uint numBits)
  197. {
  198. int shifted = data >> offset; // Sign-extending (arithmetic) shift
  199. int signBit = shifted & (1u << (numBits - 1u));
  200. uint mask = (1u << numBits) - 1u;
  201. return -signBit | (shifted & mask); // Use 2-complement for negation to replicate the sign bit
  202. }
  203. #endif // INTRINSIC_BITFIELD_EXTRACT_SIGN_EXTEND
  204. #ifndef INTRINSIC_BITFIELD_INSERT
  205. // Inserts the bits indicated by 'mask' from 'src' into 'dst'.
  206. uint BitFieldInsert(uint mask, uint src, uint dst)
  207. {
  208. return (src & mask) | (dst & ~mask);
  209. }
  210. #endif // INTRINSIC_BITFIELD_INSERT
  211. bool IsBitSet(uint data, uint offset)
  212. {
  213. return BitFieldExtract(data, offset, 1u) != 0;
  214. }
  215. void SetBit(inout uint data, uint offset)
  216. {
  217. data |= 1u << offset;
  218. }
  219. void ClearBit(inout uint data, uint offset)
  220. {
  221. data &= ~(1u << offset);
  222. }
  223. void ToggleBit(inout uint data, uint offset)
  224. {
  225. data ^= 1u << offset;
  226. }
  227. #endif
  228. #ifndef INTRINSIC_WAVEREADFIRSTLANE
  229. // Warning: for correctness, the argument's value must be the same across all lanes of the wave.
  230. TEMPLATE_1_REAL(WaveReadLaneFirst, scalarValue, return scalarValue)
  231. TEMPLATE_1_INT(WaveReadLaneFirst, scalarValue, return scalarValue)
  232. #endif
  233. #ifndef INTRINSIC_MUL24
  234. TEMPLATE_2_INT(Mul24, a, b, return a * b)
  235. #endif // INTRINSIC_MUL24
  236. #ifndef INTRINSIC_MAD24
  237. TEMPLATE_3_INT(Mad24, a, b, c, return a * b + c)
  238. #endif // INTRINSIC_MAD24
  239. #ifndef INTRINSIC_MINMAX3
  240. TEMPLATE_3_REAL(Min3, a, b, c, return min(min(a, b), c))
  241. TEMPLATE_3_INT(Min3, a, b, c, return min(min(a, b), c))
  242. TEMPLATE_3_REAL(Max3, a, b, c, return max(max(a, b), c))
  243. TEMPLATE_3_INT(Max3, a, b, c, return max(max(a, b), c))
  244. #endif // INTRINSIC_MINMAX3
  245. TEMPLATE_3_REAL(Avg3, a, b, c, return (a + b + c) * 0.33333333)
  246. #ifndef INTRINSIC_QUAD_SHUFFLE
  247. // Important! Only valid in pixel shaders!
  248. float QuadReadAcrossX(float value, int2 screenPos)
  249. {
  250. return value - (ddx_fine(value) * (float(screenPos.x & 1) * 2.0 - 1.0));
  251. }
  252. float QuadReadAcrossY(float value, int2 screenPos)
  253. {
  254. return value - (ddy_fine(value) * (float(screenPos.y & 1) * 2.0 - 1.0));
  255. }
  256. float QuadReadAcrossDiagonal(float value, int2 screenPos)
  257. {
  258. float dX = ddx_fine(value);
  259. float dY = ddy_fine(value);
  260. float2 quadDir = float2(float(screenPos.x & 1) * 2.0 - 1.0, float(screenPos.y & 1) * 2.0 - 1.0);
  261. float X = value - (dX * quadDir.x);
  262. return X - (ddy_fine(value) * quadDir.y);
  263. }
  264. #endif
  265. TEMPLATE_SWAP(Swap) // Define a Swap(a, b) function for all types
  266. #define CUBEMAPFACE_POSITIVE_X 0
  267. #define CUBEMAPFACE_NEGATIVE_X 1
  268. #define CUBEMAPFACE_POSITIVE_Y 2
  269. #define CUBEMAPFACE_NEGATIVE_Y 3
  270. #define CUBEMAPFACE_POSITIVE_Z 4
  271. #define CUBEMAPFACE_NEGATIVE_Z 5
  272. #ifndef INTRINSIC_CUBEMAP_FACE_ID
  273. float CubeMapFaceID(float3 dir)
  274. {
  275. float faceID;
  276. if (abs(dir.z) >= abs(dir.x) && abs(dir.z) >= abs(dir.y))
  277. {
  278. faceID = (dir.z < 0.0) ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
  279. }
  280. else if (abs(dir.y) >= abs(dir.x))
  281. {
  282. faceID = (dir.y < 0.0) ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
  283. }
  284. else
  285. {
  286. faceID = (dir.x < 0.0) ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
  287. }
  288. return faceID;
  289. }
  290. #endif // INTRINSIC_CUBEMAP_FACE_ID
  291. #if !defined(SHADER_API_GLES)
  292. // Intrinsic isnan can't be used because it require /Gic to be enabled on fxc that we can't do. So use AnyIsNan instead
  293. bool IsNaN(float x)
  294. {
  295. return (asuint(x) & 0x7FFFFFFF) > 0x7F800000;
  296. }
  297. bool AnyIsNaN(float2 v)
  298. {
  299. return (IsNaN(v.x) || IsNaN(v.y));
  300. }
  301. bool AnyIsNaN(float3 v)
  302. {
  303. return (IsNaN(v.x) || IsNaN(v.y) || IsNaN(v.z));
  304. }
  305. bool AnyIsNaN(float4 v)
  306. {
  307. return (IsNaN(v.x) || IsNaN(v.y) || IsNaN(v.z) || IsNaN(v.w));
  308. }
  309. bool IsInf(float x)
  310. {
  311. return (asuint(x) & 0x7FFFFFFF) == 0x7F800000;
  312. }
  313. bool AnyIsInf(float2 v)
  314. {
  315. return (IsInf(v.x) || IsInf(v.y));
  316. }
  317. bool AnyIsInf(float3 v)
  318. {
  319. return (IsInf(v.x) || IsInf(v.y) || IsInf(v.z));
  320. }
  321. bool AnyIsInf(float4 v)
  322. {
  323. return (IsInf(v.x) || IsInf(v.y) || IsInf(v.z) || IsInf(v.w));
  324. }
  325. bool IsFinite(float x)
  326. {
  327. return (asuint(x) & 0x7F800000) != 0x7F800000;
  328. }
  329. float SanitizeFinite(float x)
  330. {
  331. return IsFinite(x) ? x : 0;
  332. }
  333. bool IsPositiveFinite(float x)
  334. {
  335. return asuint(x) < 0x7F800000;
  336. }
  337. float SanitizePositiveFinite(float x)
  338. {
  339. return IsPositiveFinite(x) ? x : 0;
  340. }
  341. #endif
  342. // ----------------------------------------------------------------------------
  343. // Common math functions
  344. // ----------------------------------------------------------------------------
  345. real DegToRad(real deg)
  346. {
  347. return deg * (PI / 180.0);
  348. }
  349. real RadToDeg(real rad)
  350. {
  351. return rad * (180.0 / PI);
  352. }
  353. // Square functions for cleaner code
  354. TEMPLATE_1_REAL(Sq, x, return (x) * (x))
  355. TEMPLATE_1_INT(Sq, x, return (x) * (x))
  356. bool IsPower2(uint x)
  357. {
  358. return (x & (x - 1)) == 0;
  359. }
  360. // Input [0, 1] and output [0, PI/2]
  361. // 9 VALU
  362. real FastACosPos(real inX)
  363. {
  364. real x = abs(inX);
  365. real res = (0.0468878 * x + -0.203471) * x + 1.570796; // p(x)
  366. res *= sqrt(1.0 - x);
  367. return res;
  368. }
  369. // Ref: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/
  370. // Input [-1, 1] and output [0, PI]
  371. // 12 VALU
  372. real FastACos(real inX)
  373. {
  374. real res = FastACosPos(inX);
  375. return (inX >= 0) ? res : PI - res; // Undo range reduction
  376. }
  377. // Same cost as Acos + 1 FR
  378. // Same error
  379. // input [-1, 1] and output [-PI/2, PI/2]
  380. real FastASin(real x)
  381. {
  382. return HALF_PI - FastACos(x);
  383. }
  384. // max absolute error 1.3x10^-3
  385. // Eberly's odd polynomial degree 5 - respect bounds
  386. // 4 VGPR, 14 FR (10 FR, 1 QR), 2 scalar
  387. // input [0, infinity] and output [0, PI/2]
  388. real FastATanPos(real x)
  389. {
  390. real t0 = (x < 1.0) ? x : 1.0 / x;
  391. real t1 = t0 * t0;
  392. real poly = 0.0872929;
  393. poly = -0.301895 + poly * t1;
  394. poly = 1.0 + poly * t1;
  395. poly = poly * t0;
  396. return (x < 1.0) ? poly : HALF_PI - poly;
  397. }
  398. // 4 VGPR, 16 FR (12 FR, 1 QR), 2 scalar
  399. // input [-infinity, infinity] and output [-PI/2, PI/2]
  400. real FastATan(real x)
  401. {
  402. real t0 = FastATanPos(abs(x));
  403. return (x < 0.0) ? -t0 : t0;
  404. }
  405. #if (SHADER_TARGET >= 45)
  406. uint FastLog2(uint x)
  407. {
  408. return firstbithigh(x);
  409. }
  410. #endif
  411. // Using pow often result to a warning like this
  412. // "pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them"
  413. // PositivePow remove this warning when you know the value is positive or 0 and avoid inf/NAN.
  414. // Note: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509636(v=vs.85).aspx pow(0, >0) == 0
  415. TEMPLATE_2_REAL(PositivePow, base, power, return pow(abs(base), power))
  416. // Composes a floating point value with the magnitude of 'x' and the sign of 's'.
  417. // See the comment about FastSign() below.
  418. float CopySign(float x, float s, bool ignoreNegZero = true)
  419. {
  420. #if !defined(SHADER_API_GLES)
  421. if (ignoreNegZero)
  422. {
  423. return (s >= 0) ? abs(x) : -abs(x);
  424. }
  425. else
  426. {
  427. uint negZero = 0x80000000u;
  428. uint signBit = negZero & asuint(s);
  429. return asfloat(BitFieldInsert(negZero, signBit, asuint(x)));
  430. }
  431. #else
  432. return (s >= 0) ? abs(x) : -abs(x);
  433. #endif
  434. }
  435. // Returns -1 for negative numbers and 1 for positive numbers.
  436. // 0 can be handled in 2 different ways.
  437. // The IEEE floating point standard defines 0 as signed: +0 and -0.
  438. // However, mathematics typically treats 0 as unsigned.
  439. // Therefore, we treat -0 as +0 by default: FastSign(+0) = FastSign(-0) = 1.
  440. // If (ignoreNegZero = false), FastSign(-0, false) = -1.
  441. // Note that the sign() function in HLSL implements signum, which returns 0 for 0.
  442. float FastSign(float s, bool ignoreNegZero = true)
  443. {
  444. return CopySign(1.0, s, ignoreNegZero);
  445. }
  446. // Orthonormalizes the tangent frame using the Gram-Schmidt process.
  447. // We assume that the normal is normalized and that the two vectors
  448. // aren't collinear.
  449. // Returns the new tangent (the normal is unaffected).
  450. real3 Orthonormalize(real3 tangent, real3 normal)
  451. {
  452. // TODO: use SafeNormalize()?
  453. return normalize(tangent - dot(tangent, normal) * normal);
  454. }
  455. // [start, end] -> [0, 1] : (x - start) / (end - start) = x * rcpLength - (start * rcpLength)
  456. TEMPLATE_3_REAL(Remap01, x, rcpLength, startTimesRcpLength, return saturate(x * rcpLength - startTimesRcpLength))
  457. // [start, end] -> [1, 0] : (end - x) / (end - start) = (end * rcpLength) - x * rcpLength
  458. TEMPLATE_3_REAL(Remap10, x, rcpLength, endTimesRcpLength, return saturate(endTimesRcpLength - x * rcpLength))
  459. // Remap: [0.5 / size, 1 - 0.5 / size] -> [0, 1]
  460. real2 RemapHalfTexelCoordTo01(real2 coord, real2 size)
  461. {
  462. const real2 rcpLen = size * rcp(size - 1);
  463. const real2 startTimesRcpLength = 0.5 * rcp(size - 1);
  464. return Remap01(coord, rcpLen, startTimesRcpLength);
  465. }
  466. // Remap: [0, 1] -> [0.5 / size, 1 - 0.5 / size]
  467. real2 Remap01ToHalfTexelCoord(real2 coord, real2 size)
  468. {
  469. const real2 start = 0.5 * rcp(size);
  470. const real2 len = 1 - rcp(size);
  471. return coord * len + start;
  472. }
  473. // smoothstep that assumes that 'x' lies within the [0, 1] interval.
  474. real Smoothstep01(real x)
  475. {
  476. return x * x * (3 - (2 * x));
  477. }
  478. real Smootherstep01(real x)
  479. {
  480. return x * x * x * (x * (x * 6 - 15) + 10);
  481. }
  482. real Smootherstep(real a, real b, real t)
  483. {
  484. real r = rcp(b - a);
  485. real x = Remap01(t, r, a * r);
  486. return Smootherstep01(x);
  487. }
  488. float3 NLerp(float3 A, float3 B, float t)
  489. {
  490. return normalize(lerp(A, B, t));
  491. }
  492. float Length2(float3 v)
  493. {
  494. return dot(v, v);
  495. }
  496. real Pow4(real x)
  497. {
  498. return (x * x) * (x * x);
  499. }
  500. TEMPLATE_3_FLT(RangeRemap, min, max, t, return saturate((t - min) / (max - min)))
  501. // ----------------------------------------------------------------------------
  502. // Texture utilities
  503. // ----------------------------------------------------------------------------
  504. float ComputeTextureLOD(float2 uvdx, float2 uvdy, float2 scale)
  505. {
  506. float2 ddx_ = scale * uvdx;
  507. float2 ddy_ = scale * uvdy;
  508. float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
  509. return max(0.5 * log2(d), 0.0);
  510. }
  511. float ComputeTextureLOD(float2 uv)
  512. {
  513. float2 ddx_ = ddx(uv);
  514. float2 ddy_ = ddy(uv);
  515. return ComputeTextureLOD(ddx_, ddy_, 1.0);
  516. }
  517. // x contains width, w contains height
  518. float ComputeTextureLOD(float2 uv, float2 texelSize)
  519. {
  520. uv *= texelSize;
  521. return ComputeTextureLOD(uv);
  522. }
  523. // LOD clamp is optional and happens outside the function.
  524. float ComputeTextureLOD(float3 duvw_dx, float3 duvw_dy, float3 duvw_dz, float scale)
  525. {
  526. float d = Max3(dot(duvw_dx, duvw_dx), dot(duvw_dy, duvw_dy), dot(duvw_dz, duvw_dz));
  527. return 0.5 * log2(d * (scale * scale));
  528. }
  529. uint GetMipCount(Texture2D tex)
  530. {
  531. #if defined(SHADER_API_D3D11) || defined(SHADER_API_D3D12) || defined(SHADER_API_D3D11_9X) || defined(SHADER_API_XBOXONE) || defined(SHADER_API_PSSL)
  532. #define MIP_COUNT_SUPPORTED 1
  533. #endif
  534. #if (defined(SHADER_API_OPENGL) || defined(SHADER_API_VULKAN)) && !defined(SHADER_STAGE_COMPUTE)
  535. // OpenGL only supports textureSize for width, height, depth
  536. // textureQueryLevels (GL_ARB_texture_query_levels) needs OpenGL 4.3 or above and doesn't compile in compute shaders
  537. // tex.GetDimensions converted to textureQueryLevels
  538. #define MIP_COUNT_SUPPORTED 1
  539. #endif
  540. // Metal doesn't support high enough OpenGL version
  541. #if defined(MIP_COUNT_SUPPORTED)
  542. uint mipLevel, width, height, mipCount;
  543. mipLevel = width = height = mipCount = 0;
  544. tex.GetDimensions(mipLevel, width, height, mipCount);
  545. return mipCount;
  546. #else
  547. return 0;
  548. #endif
  549. }
  550. // ----------------------------------------------------------------------------
  551. // Texture format sampling
  552. // ----------------------------------------------------------------------------
  553. float2 DirectionToLatLongCoordinate(float3 unDir)
  554. {
  555. float3 dir = normalize(unDir);
  556. // coordinate frame is (-Z, X) meaning negative Z is primary axis and X is secondary axis.
  557. return float2(1.0 - 0.5 * INV_PI * atan2(dir.x, -dir.z), asin(dir.y) * INV_PI + 0.5);
  558. }
  559. float3 LatlongToDirectionCoordinate(float2 coord)
  560. {
  561. float theta = coord.y * PI;
  562. float phi = (coord.x * 2.f * PI - PI*0.5f);
  563. float cosTheta = cos(theta);
  564. float sinTheta = sqrt(1.0 - min(1.0, cosTheta*cosTheta));
  565. float cosPhi = cos(phi);
  566. float sinPhi = sin(phi);
  567. float3 direction = float3(sinTheta*cosPhi, cosTheta, sinTheta*sinPhi);
  568. direction.xy *= -1.0;
  569. return direction;
  570. }
  571. // ----------------------------------------------------------------------------
  572. // Depth encoding/decoding
  573. // ----------------------------------------------------------------------------
  574. // Z buffer to linear 0..1 depth (0 at near plane, 1 at far plane).
  575. // Does NOT correctly handle oblique view frustums.
  576. // Does NOT work with orthographic projection.
  577. // zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
  578. float Linear01DepthFromNear(float depth, float4 zBufferParam)
  579. {
  580. return 1.0 / (zBufferParam.x + zBufferParam.y / depth);
  581. }
  582. // Z buffer to linear 0..1 depth (0 at camera position, 1 at far plane).
  583. // Does NOT work with orthographic projections.
  584. // Does NOT correctly handle oblique view frustums.
  585. // zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
  586. float Linear01Depth(float depth, float4 zBufferParam)
  587. {
  588. return 1.0 / (zBufferParam.x * depth + zBufferParam.y);
  589. }
  590. // Z buffer to linear depth.
  591. // Does NOT correctly handle oblique view frustums.
  592. // Does NOT work with orthographic projection.
  593. // zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
  594. float LinearEyeDepth(float depth, float4 zBufferParam)
  595. {
  596. return 1.0 / (zBufferParam.z * depth + zBufferParam.w);
  597. }
  598. // Z buffer to linear depth.
  599. // Correctly handles oblique view frustums.
  600. // Does NOT work with orthographic projection.
  601. // Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.
  602. float LinearEyeDepth(float2 positionNDC, float deviceDepth, float4 invProjParam)
  603. {
  604. float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
  605. float viewSpaceZ = rcp(dot(positionCS, invProjParam));
  606. // If the matrix is right-handed, we have to flip the Z axis to get a positive value.
  607. return abs(viewSpaceZ);
  608. }
  609. // Z buffer to linear depth.
  610. // Works in all cases.
  611. // Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
  612. // Assumes that the 'positionWS' is in front of the camera.
  613. float LinearEyeDepth(float3 positionWS, float4x4 viewMatrix)
  614. {
  615. float viewSpaceZ = mul(viewMatrix, float4(positionWS, 1.0)).z;
  616. // If the matrix is right-handed, we have to flip the Z axis to get a positive value.
  617. return abs(viewSpaceZ);
  618. }
  619. // 'z' is the view space Z position (linear depth).
  620. // saturate(z) the output of the function to clamp them to the [0, 1] range.
  621. // d = log2(c * (z - n) + 1) / log2(c * (f - n) + 1)
  622. // = log2(c * (z - n + 1/c)) / log2(c * (f - n) + 1)
  623. // = log2(c) / log2(c * (f - n) + 1) + log2(z - (n - 1/c)) / log2(c * (f - n) + 1)
  624. // = E + F * log2(z - G)
  625. // encodingParams = { E, F, G, 0 }
  626. float EncodeLogarithmicDepthGeneralized(float z, float4 encodingParams)
  627. {
  628. // Use max() to avoid NaNs.
  629. return encodingParams.x + encodingParams.y * log2(max(0, z - encodingParams.z));
  630. }
  631. // 'd' is the logarithmically encoded depth value.
  632. // saturate(d) to clamp the output of the function to the [n, f] range.
  633. // z = 1/c * (pow(c * (f - n) + 1, d) - 1) + n
  634. // = 1/c * pow(c * (f - n) + 1, d) + n - 1/c
  635. // = 1/c * exp2(d * log2(c * (f - n) + 1)) + (n - 1/c)
  636. // = L * exp2(d * M) + N
  637. // decodingParams = { L, M, N, 0 }
  638. // Graph: https://www.desmos.com/calculator/qrtatrlrba
  639. float DecodeLogarithmicDepthGeneralized(float d, float4 decodingParams)
  640. {
  641. return decodingParams.x * exp2(d * decodingParams.y) + decodingParams.z;
  642. }
  643. // 'z' is the view-space Z position (linear depth).
  644. // saturate(z) the output of the function to clamp them to the [0, 1] range.
  645. // encodingParams = { n, log2(f/n), 1/n, 1/log2(f/n) }
  646. // This is an optimized version of EncodeLogarithmicDepthGeneralized() for (c = 2).
  647. float EncodeLogarithmicDepth(float z, float4 encodingParams)
  648. {
  649. // Use max() to avoid NaNs.
  650. // TODO: optimize to (log2(z) - log2(n)) / (log2(f) - log2(n)).
  651. return log2(max(0, z * encodingParams.z)) * encodingParams.w;
  652. }
  653. // 'd' is the logarithmically encoded depth value.
  654. // saturate(d) to clamp the output of the function to the [n, f] range.
  655. // encodingParams = { n, log2(f/n), 1/n, 1/log2(f/n) }
  656. // This is an optimized version of DecodeLogarithmicDepthGeneralized() for (c = 2).
  657. // Graph: https://www.desmos.com/calculator/qrtatrlrba
  658. float DecodeLogarithmicDepth(float d, float4 encodingParams)
  659. {
  660. // TODO: optimize to exp2(d * y + log2(x)).
  661. return encodingParams.x * exp2(d * encodingParams.y);
  662. }
  663. real4 CompositeOver(real4 front, real4 back)
  664. {
  665. return front + (1 - front.a) * back;
  666. }
  667. void CompositeOver(real3 colorFront, real3 alphaFront,
  668. real3 colorBack, real3 alphaBack,
  669. out real3 color, out real3 alpha)
  670. {
  671. color = colorFront + (1 - alphaFront) * colorBack;
  672. alpha = alphaFront + (1 - alphaFront) * alphaBack;
  673. }
  674. // ----------------------------------------------------------------------------
  675. // Space transformations
  676. // ----------------------------------------------------------------------------
  677. static const float3x3 k_identity3x3 = {1, 0, 0,
  678. 0, 1, 0,
  679. 0, 0, 1};
  680. static const float4x4 k_identity4x4 = {1, 0, 0, 0,
  681. 0, 1, 0, 0,
  682. 0, 0, 1, 0,
  683. 0, 0, 0, 1};
  684. float4 ComputeClipSpacePosition(float2 positionNDC, float deviceDepth)
  685. {
  686. float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
  687. #if UNITY_UV_STARTS_AT_TOP
  688. // Our world space, view space, screen space and NDC space are Y-up.
  689. // Our clip space is flipped upside-down due to poor legacy Unity design.
  690. // The flip is baked into the projection matrix, so we only have to flip
  691. // manually when going from CS to NDC and back.
  692. positionCS.y = -positionCS.y;
  693. #endif
  694. return positionCS;
  695. }
  696. // Use case examples:
  697. // (position = positionCS) => (clipSpaceTransform = use default)
  698. // (position = positionVS) => (clipSpaceTransform = UNITY_MATRIX_P)
  699. // (position = positionWS) => (clipSpaceTransform = UNITY_MATRIX_VP)
  700. float4 ComputeClipSpacePosition(float3 position, float4x4 clipSpaceTransform = k_identity4x4)
  701. {
  702. return mul(clipSpaceTransform, float4(position, 1.0));
  703. }
  704. // The returned Z value is the depth buffer value (and NOT linear view space Z value).
  705. // Use case examples:
  706. // (position = positionCS) => (clipSpaceTransform = use default)
  707. // (position = positionVS) => (clipSpaceTransform = UNITY_MATRIX_P)
  708. // (position = positionWS) => (clipSpaceTransform = UNITY_MATRIX_VP)
  709. float3 ComputeNormalizedDeviceCoordinatesWithZ(float3 position, float4x4 clipSpaceTransform = k_identity4x4)
  710. {
  711. float4 positionCS = ComputeClipSpacePosition(position, clipSpaceTransform);
  712. #if UNITY_UV_STARTS_AT_TOP
  713. // Our world space, view space, screen space and NDC space are Y-up.
  714. // Our clip space is flipped upside-down due to poor legacy Unity design.
  715. // The flip is baked into the projection matrix, so we only have to flip
  716. // manually when going from CS to NDC and back.
  717. positionCS.y = -positionCS.y;
  718. #endif
  719. positionCS *= rcp(positionCS.w);
  720. positionCS.xy = positionCS.xy * 0.5 + 0.5;
  721. return positionCS.xyz;
  722. }
  723. // Use case examples:
  724. // (position = positionCS) => (clipSpaceTransform = use default)
  725. // (position = positionVS) => (clipSpaceTransform = UNITY_MATRIX_P)
  726. // (position = positionWS) => (clipSpaceTransform = UNITY_MATRIX_VP)
  727. float2 ComputeNormalizedDeviceCoordinates(float3 position, float4x4 clipSpaceTransform = k_identity4x4)
  728. {
  729. return ComputeNormalizedDeviceCoordinatesWithZ(position, clipSpaceTransform).xy;
  730. }
  731. float3 ComputeViewSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invProjMatrix)
  732. {
  733. float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
  734. float4 positionVS = mul(invProjMatrix, positionCS);
  735. // The view space uses a right-handed coordinate system.
  736. positionVS.z = -positionVS.z;
  737. return positionVS.xyz / positionVS.w;
  738. }
  739. float3 ComputeWorldSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invViewProjMatrix)
  740. {
  741. float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
  742. float4 hpositionWS = mul(invViewProjMatrix, positionCS);
  743. return hpositionWS.xyz / hpositionWS.w;
  744. }
  745. // ----------------------------------------------------------------------------
  746. // PositionInputs
  747. // ----------------------------------------------------------------------------
  748. // Note: if you modify this struct, be sure to update the CustomPassFullscreenShader.template
  749. struct PositionInputs
  750. {
  751. float3 positionWS; // World space position (could be camera-relative)
  752. float2 positionNDC; // Normalized screen coordinates within the viewport : [0, 1) (with the half-pixel offset)
  753. uint2 positionSS; // Screen space pixel coordinates : [0, NumPixels)
  754. uint2 tileCoord; // Screen tile coordinates : [0, NumTiles)
  755. float deviceDepth; // Depth from the depth buffer : [0, 1] (typically reversed)
  756. float linearDepth; // View space Z coordinate : [Near, Far]
  757. };
  758. // This function is use to provide an easy way to sample into a screen texture, either from a pixel or a compute shaders.
  759. // This allow to easily share code.
  760. // If a compute shader call this function positionSS is an integer usually calculate like: uint2 positionSS = groupId.xy * BLOCK_SIZE + groupThreadId.xy
  761. // else it is current unormalized screen coordinate like return by SV_Position
  762. PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, uint2 tileCoord) // Specify explicit tile coordinates so that we can easily make it lane invariant for compute evaluation.
  763. {
  764. PositionInputs posInput;
  765. ZERO_INITIALIZE(PositionInputs, posInput);
  766. posInput.positionNDC = positionSS;
  767. #if defined(SHADER_STAGE_COMPUTE) || defined(SHADER_STAGE_RAY_TRACING)
  768. // In case of compute shader an extra half offset is added to the screenPos to shift the integer position to pixel center.
  769. posInput.positionNDC.xy += float2(0.5, 0.5);
  770. #endif
  771. posInput.positionNDC *= invScreenSize;
  772. posInput.positionSS = uint2(positionSS);
  773. posInput.tileCoord = tileCoord;
  774. return posInput;
  775. }
  776. PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize)
  777. {
  778. return GetPositionInput(positionSS, invScreenSize, uint2(0, 0));
  779. }
  780. // From forward
  781. // deviceDepth and linearDepth come directly from .zw of SV_Position
  782. PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float linearDepth, float3 positionWS, uint2 tileCoord)
  783. {
  784. PositionInputs posInput = GetPositionInput(positionSS, invScreenSize, tileCoord);
  785. posInput.positionWS = positionWS;
  786. posInput.deviceDepth = deviceDepth;
  787. posInput.linearDepth = linearDepth;
  788. return posInput;
  789. }
  790. PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float linearDepth, float3 positionWS)
  791. {
  792. return GetPositionInput(positionSS, invScreenSize, deviceDepth, linearDepth, positionWS, uint2(0, 0));
  793. }
  794. // From deferred or compute shader
  795. // depth must be the depth from the raw depth buffer. This allow to handle all kind of depth automatically with the inverse view projection matrix.
  796. // For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed.
  797. PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth,
  798. float4x4 invViewProjMatrix, float4x4 viewMatrix,
  799. uint2 tileCoord)
  800. {
  801. PositionInputs posInput = GetPositionInput(positionSS, invScreenSize, tileCoord);
  802. posInput.positionWS = ComputeWorldSpacePosition(posInput.positionNDC, deviceDepth, invViewProjMatrix);
  803. posInput.deviceDepth = deviceDepth;
  804. posInput.linearDepth = LinearEyeDepth(posInput.positionWS, viewMatrix);
  805. return posInput;
  806. }
  807. PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth,
  808. float4x4 invViewProjMatrix, float4x4 viewMatrix)
  809. {
  810. return GetPositionInput(positionSS, invScreenSize, deviceDepth, invViewProjMatrix, viewMatrix, uint2(0, 0));
  811. }
  812. // The view direction 'V' points towards the camera.
  813. // 'depthOffsetVS' is always applied in the opposite direction (-V).
  814. void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float3 viewForwardDir, float4x4 viewProjMatrix, inout PositionInputs posInput)
  815. {
  816. posInput.positionWS += depthOffsetVS * (-V);
  817. posInput.deviceDepth = ComputeNormalizedDeviceCoordinatesWithZ(posInput.positionWS, viewProjMatrix).z;
  818. // Transform the displacement along the view vector to the displacement along the forward vector.
  819. // Use abs() to make sure we get the sign right.
  820. // 'depthOffsetVS' applies in the direction away from the camera.
  821. posInput.linearDepth += depthOffsetVS * abs(dot(V, viewForwardDir));
  822. }
  823. // ----------------------------------------------------------------------------
  824. // Terrain/Brush heightmap encoding/decoding
  825. // ----------------------------------------------------------------------------
  826. #if defined(SHADER_API_VULKAN) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3)
  827. real4 PackHeightmap(real height)
  828. {
  829. uint a = (uint)(65535.0 * height);
  830. return real4((a >> 0) & 0xFF, (a >> 8) & 0xFF, 0, 0) / 255.0;
  831. }
  832. real UnpackHeightmap(real4 height)
  833. {
  834. return (height.r + height.g * 256.0) / 257.0; // (255.0 * height.r + 255.0 * 256.0 * height.g) / 65535.0
  835. }
  836. #else
  837. real4 PackHeightmap(real height)
  838. {
  839. return real4(height, 0, 0, 0);
  840. }
  841. real UnpackHeightmap(real4 height)
  842. {
  843. return height.r;
  844. }
  845. #endif
  846. // ----------------------------------------------------------------------------
  847. // Misc utilities
  848. // ----------------------------------------------------------------------------
  849. // Simple function to test a bitfield
  850. bool HasFlag(uint bitfield, uint flag)
  851. {
  852. return (bitfield & flag) != 0;
  853. }
  854. // Normalize that account for vectors with zero length
  855. real3 SafeNormalize(float3 inVec)
  856. {
  857. float dp3 = max(FLT_MIN, dot(inVec, inVec));
  858. return inVec * rsqrt(dp3);
  859. }
  860. // Division which returns 1 for (inf/inf) and (0/0).
  861. // If any of the input parameters are NaNs, the result is a NaN.
  862. real SafeDiv(real numer, real denom)
  863. {
  864. return (numer != denom) ? numer / denom : 1;
  865. }
  866. // Assumes that (0 <= x <= Pi).
  867. real SinFromCos(real cosX)
  868. {
  869. return sqrt(saturate(1 - cosX * cosX));
  870. }
  871. // Dot product in spherical coordinates.
  872. real SphericalDot(real cosTheta1, real phi1, real cosTheta2, real phi2)
  873. {
  874. return SinFromCos(cosTheta1) * SinFromCos(cosTheta2) * cos(phi1 - phi2) + cosTheta1 * cosTheta2;
  875. }
  876. // Generates a triangle in homogeneous clip space, s.t.
  877. // v0 = (-1, -1, 1), v1 = (3, -1, 1), v2 = (-1, 3, 1).
  878. float2 GetFullScreenTriangleTexCoord(uint vertexID)
  879. {
  880. #if UNITY_UV_STARTS_AT_TOP
  881. return float2((vertexID << 1) & 2, 1.0 - (vertexID & 2));
  882. #else
  883. return float2((vertexID << 1) & 2, vertexID & 2);
  884. #endif
  885. }
  886. float4 GetFullScreenTriangleVertexPosition(uint vertexID, float z = UNITY_NEAR_CLIP_VALUE)
  887. {
  888. float2 uv = float2((vertexID << 1) & 2, vertexID & 2);
  889. return float4(uv * 2.0 - 1.0, z, 1.0);
  890. }
  891. // draw procedural with 2 triangles has index order (0,1,2) (0,2,3)
  892. // 0 - 0,0
  893. // 1 - 0,1
  894. // 2 - 1,1
  895. // 3 - 1,0
  896. float2 GetQuadTexCoord(uint vertexID)
  897. {
  898. uint topBit = vertexID >> 1;
  899. uint botBit = (vertexID & 1);
  900. float u = topBit;
  901. float v = (topBit + botBit) & 1; // produces 0 for indices 0,3 and 1 for 1,2
  902. #if UNITY_UV_STARTS_AT_TOP
  903. v = 1.0 - v;
  904. #endif
  905. return float2(u, v);
  906. }
  907. // 0 - 0,1
  908. // 1 - 0,0
  909. // 2 - 1,0
  910. // 3 - 1,1
  911. float4 GetQuadVertexPosition(uint vertexID, float z = UNITY_NEAR_CLIP_VALUE)
  912. {
  913. uint topBit = vertexID >> 1;
  914. uint botBit = (vertexID & 1);
  915. float x = topBit;
  916. float y = 1 - (topBit + botBit) & 1; // produces 1 for indices 0,3 and 0 for 1,2
  917. return float4(x, y, z, 1.0);
  918. }
  919. #if !defined(SHADER_API_GLES) && !defined(SHADER_STAGE_RAY_TRACING)
  920. // LOD dithering transition helper
  921. // LOD0 must use this function with ditherFactor 1..0
  922. // LOD1 must use this function with ditherFactor -1..0
  923. // This is what is provided by unity_LODFade
  924. void LODDitheringTransition(uint2 fadeMaskSeed, float ditherFactor)
  925. {
  926. // Generate a spatially varying pattern.
  927. // Unfortunately, varying the pattern with time confuses the TAA, increasing the amount of noise.
  928. float p = GenerateHashedRandomFloat(fadeMaskSeed);
  929. // This preserves the symmetry s.t. if LOD 0 has f = x, LOD 1 has f = -x.
  930. float f = ditherFactor - CopySign(p, ditherFactor);
  931. clip(f);
  932. }
  933. #endif
  934. // The resource that is bound when binding a stencil buffer from the depth buffer is two channel. On D3D11 the stencil value is in the green channel,
  935. // while on other APIs is in the red channel. Note that on some platform, always using the green channel might work, but is not guaranteed.
  936. uint GetStencilValue(uint2 stencilBufferVal)
  937. {
  938. #if defined(SHADER_API_D3D11) || defined(SHADER_API_XBOXONE)
  939. return stencilBufferVal.y;
  940. #else
  941. return stencilBufferVal.x;
  942. #endif
  943. }
  944. #endif // UNITY_COMMON_INCLUDED