FXVVolumeFog.cginc 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  1. #ifndef FXV_VOLUME_FOG_INCLUDED
  2. #define FXV_VOLUME_FOG_INCLUDED
  3. #define FXV_VOLUMETRIC_FOG_APPDATA float3 positionOS : POSITION; \
  4. UNITY_VERTEX_INPUT_INSTANCE_ID
  5. #define FXV_VOLUMETRIC_FOG_LIT_APPDATA float4 positionOS : POSITION; \
  6. float4 tangent : TANGENT; \
  7. float3 normal : NORMAL; \
  8. float4 texcoord : TEXCOORD0; \
  9. UNITY_VERTEX_INPUT_INSTANCE_ID
  10. #if defined(FXV_VOLUMEFOG_URP)
  11. #define FXV_VOLUMETRIC_FOG_V2F_COORDS float4 positionCS : SV_POSITION; \
  12. float depth : TEXCOORD0; \
  13. float4 screenPosition : TEXCOORD1; \
  14. float3 positionOS : TEXCOORD2; \
  15. float3 positionWS : TEXCOORD3; \
  16. UNITY_VERTEX_INPUT_INSTANCE_ID \
  17. UNITY_VERTEX_OUTPUT_STEREO
  18. #else
  19. #define FXV_VOLUMETRIC_FOG_V2F_COORDS float4 positionCS : SV_POSITION; \
  20. float depth : TEXCOORD0; \
  21. float4 screenPosition : TEXCOORD1; \
  22. float3 positionOS : TEXCOORD2; \
  23. float3 positionWS : TEXCOORD3; \
  24. UNITY_VERTEX_INPUT_INSTANCE_ID \
  25. UNITY_VERTEX_OUTPUT_STEREO
  26. #endif
  27. #define FXV_VOLUMETRIC_FOG_PARTICLE_COORDS float depth : TEXCOORD2; \
  28. float4 vertexPos : TEXCOORD3; \
  29. float3 positionWS : TEXCOORD4; \
  30. float4 projPos : TEXCOORD5;
  31. #if defined(FXV_VOLUMEFOG_URP)
  32. #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT(v, o) UNITY_SETUP_INSTANCE_ID(v); \
  33. UNITY_TRANSFER_INSTANCE_ID(v, o); \
  34. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); \
  35. half isOrtho = unity_OrthoParams.w; \
  36. VertexPositionInputs vertInputs = GetVertexPositionInputs (v.positionOS.xyz); \
  37. o.positionCS = vertInputs.positionCS; \
  38. o.screenPosition = vertInputs.positionNDC; \
  39. o.positionOS = v.positionOS; \
  40. o.positionWS = _FXV_ObjectToWorldPos(v.positionOS); \
  41. o.depth = _FXV_ComputeVertexDepth(o.positionWS);
  42. #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT_LIT(v, o) half isOrtho = unity_OrthoParams.w; \
  43. VertexPositionInputs vertInputs = GetVertexPositionInputs (v.positionOS.xyz); \
  44. o.positionCS = vertInputs.positionCS; \
  45. o.screenPosition = vertInputs.positionNDC; \
  46. o.positionOS = v.positionOS; \
  47. o.positionWS = _FXV_ObjectToWorldPos(v.positionOS); \
  48. o.depth = _FXV_ComputeVertexDepth(o.positionWS);
  49. #else
  50. #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT(v, o) UNITY_SETUP_INSTANCE_ID(v); \
  51. UNITY_TRANSFER_INSTANCE_ID(v, o); \
  52. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); \
  53. half isOrtho = unity_OrthoParams.w; \
  54. o.positionCS = UnityObjectToClipPos(v.positionOS.xyz); \
  55. o.screenPosition = ComputeScreenPos(o.positionCS); \
  56. float3 p = UnityObjectToViewPos(v.positionOS); \
  57. o.positionOS = v.positionOS; \
  58. o.positionWS = _FXV_ObjectToWorldPos(v.positionOS); \
  59. o.depth = _FXV_ComputeVertexDepth(o.positionWS); \
  60. #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT_LIT(v, o) half isOrtho = unity_OrthoParams.w; \
  61. appdata vv = (appdata)v; \
  62. o.positionCS = UnityObjectToClipPos(vv.positionOS.xyz); \
  63. o.screenPosition = ComputeScreenPos(o.positionCS); \
  64. float3 p = UnityObjectToViewPos(vv.positionOS); \
  65. o.positionOS = vv.positionOS; \
  66. o.positionWS = _FXV_ObjectToWorldPos(vv.positionOS); \
  67. o.depth = _FXV_ComputeVertexDepth(o.positionWS);
  68. #endif
  69. float4x4 _fxv_ObjectToWorldCustom;
  70. #define FXV_VOLUMETRIC_FOG_FRAGMENT_DEFAULT(i) UNITY_SETUP_INSTANCE_ID(i) \
  71. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
  72. #if !defined(FXV_VOLUMEFOG_HDRP)
  73. #ifdef FXV_VOLUMEFOG_URP
  74. TEXTURE2D_X_FLOAT(_CameraDepthTexture);
  75. SAMPLER(sampler_CameraDepthTexture);
  76. #else
  77. UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
  78. #endif
  79. #endif
  80. UNITY_INSTANCING_BUFFER_START(Props)
  81. UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
  82. UNITY_DEFINE_INSTANCED_PROP(float4, _WorldSize)
  83. #if defined(FXV_FOG_CUSTOM_MESH)
  84. UNITY_DEFINE_INSTANCED_PROP(float4, _LocalSize)
  85. UNITY_DEFINE_INSTANCED_PROP(float4, _LocalOffset)
  86. #endif
  87. UNITY_DEFINE_INSTANCED_PROP(half, _FogMin)
  88. UNITY_DEFINE_INSTANCED_PROP(half, _FogMax)
  89. UNITY_DEFINE_INSTANCED_PROP(half, _FogFalloff)
  90. UNITY_DEFINE_INSTANCED_PROP(half, _InAirSmooth)
  91. UNITY_DEFINE_INSTANCED_PROP(half, _LightScatteringFactor)
  92. UNITY_DEFINE_INSTANCED_PROP(half, _LightReflectivity)
  93. UNITY_DEFINE_INSTANCED_PROP(half, _LightTransmission)
  94. #if defined(FXV_FOGTYPE_HEIGHTXBOX) || defined(FXV_FOGTYPE_HEIGHTXVIEW) || defined(FXV_FOGTYPE_BOXXVIEW) || defined(FXV_FOGTYPE_INVERTEDSPHERICALXHEIGHT)
  95. UNITY_DEFINE_INSTANCED_PROP(half, _SecFogMin)
  96. UNITY_DEFINE_INSTANCED_PROP(half, _SecFogMax)
  97. #endif
  98. UNITY_INSTANCING_BUFFER_END(Props)
  99. inline float3 _FXV_WorldToViewPos(in float3 pos)
  100. {
  101. #if defined(FXV_VOLUMEFOG_URP)
  102. return TransformWorldToView(pos);
  103. #else
  104. return mul(UNITY_MATRIX_V, float4(pos, 1.0)).xyz;
  105. #endif
  106. }
  107. inline float3 _FXV_WorldToViewPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
  108. {
  109. return _FXV_WorldToViewPos(pos.xyz);
  110. }
  111. inline float3 _FXV_WorldToObjectPos(in float3 pos)
  112. {
  113. #if defined(FXV_VOLUMEFOG_URP)
  114. return TransformWorldToObject(pos);
  115. #else
  116. return mul(unity_WorldToObject, float4(pos, 1)).xyz;
  117. #endif
  118. }
  119. inline float3 _FXV_WorldToObjectPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
  120. {
  121. return _FXV_WorldToObjectPos(pos.xyz);
  122. }
  123. inline float3 _FXV_WorldToObjectDir(in float3 dir)
  124. {
  125. #if defined(FXV_VOLUMEFOG_URP)
  126. return mul(GetWorldToObjectMatrix(), float4(dir, 0)).xyz;
  127. #else
  128. return mul(unity_WorldToObject, float4(dir, 0)).xyz;
  129. #endif
  130. }
  131. inline float3 _FXV_WorldToObjectDir(float4 dir) // overload for float4; avoids "implicit truncation" warning for existing shaders
  132. {
  133. return _FXV_WorldToObjectDir(dir.xyz);
  134. }
  135. inline float3 _FXV_ObjectToWorldPos(in float3 pos)
  136. {
  137. #if defined(FXV_VOLUMEFOG_URP)
  138. return TransformObjectToWorld(pos);
  139. #else
  140. return mul(unity_ObjectToWorld, float4(pos, 1)).xyz;
  141. #endif
  142. }
  143. inline float3 _FXV_ObjectToWorldPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
  144. {
  145. return _FXV_ObjectToWorldPos(pos.xyz);
  146. }
  147. inline float3 _FXV_ObjectToWorldDir(in float3 dir)
  148. {
  149. #if defined(FXV_VOLUMEFOG_URP)
  150. return mul(GetObjectToWorldMatrix(), float4(dir, 0)).xyz;
  151. #else
  152. return mul(unity_ObjectToWorld, float4(dir, 0)).xyz;
  153. #endif
  154. }
  155. inline float3 _FXV_ObjectToWorldDir(float4 dir) // overload for float4; avoids "implicit truncation" warning for existing shaders
  156. {
  157. return _FXV_ObjectToWorldDir(dir.xyz);
  158. }
  159. inline float3 _FXV_ObjectToViewPos(in float3 pos)
  160. {
  161. #if defined(FXV_VOLUMEFOG_URP)
  162. return TransformWorldToView(TransformObjectToWorld(pos));
  163. #else
  164. return mul(UNITY_MATRIX_V, mul(unity_ObjectToWorld, float4(pos, 1.0))).xyz;
  165. #endif
  166. }
  167. inline float3 _FXV_ObjectToViewPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
  168. {
  169. return _FXV_ObjectToViewPos(pos.xyz);
  170. }
  171. // Z buffer to linear depth.
  172. // Works in all cases.
  173. // Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
  174. // Assumes that the 'positionWS' is in front of the camera.
  175. float _FXV_ComputeVertexDepth(float3 positionWS)
  176. {
  177. #if defined(FXV_VOLUMEFOG_URP)
  178. return LinearEyeDepth(positionWS, GetWorldToViewMatrix());
  179. #elif defined(FXV_VOLUMEFOG_HDRP)
  180. return LinearEyeDepth(positionWS, GetWorldToViewMatrix());
  181. #else
  182. // calculated as in Library\PackageCache\com.unity.render-pipelines.core@14.0.11\ShaderLibrary\Common.hlsl
  183. float viewSpaceZ = mul(UNITY_MATRIX_V, float4(positionWS, 1.0)).z;
  184. // If the matrix is right-handed, we have to flip the Z axis to get a positive value.
  185. return abs(viewSpaceZ);
  186. #endif
  187. }
  188. half _FXV_GetRawDepth(half4 screenPos)
  189. {
  190. #if defined(FXV_VOLUMEFOG_URP)
  191. float z = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(screenPos.xy / screenPos.w)).r;
  192. #elif defined(FXV_VOLUMEFOG_HDRP)
  193. float z = SampleCameraDepth( screenPos.xy / screenPos.w );
  194. #else
  195. float z = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(screenPos));
  196. #endif
  197. return z;
  198. }
  199. half _FXV_GetLinearEyeDepth(float z)
  200. {
  201. if (unity_OrthoParams.w == 0) // perspective
  202. {
  203. // Perspective linear depth
  204. #if defined(FXV_VOLUMEFOG_URP)
  205. return LinearEyeDepth(z, _ZBufferParams);
  206. #elif defined(FXV_VOLUMEFOG_HDRP)
  207. return LinearEyeDepth(z, _ZBufferParams);
  208. #else
  209. return LinearEyeDepth(z);
  210. #endif
  211. }
  212. else
  213. {
  214. // Orthographic linear depth
  215. // near = _ProjectionParams.y;
  216. // far = _ProjectionParams.z;
  217. // calculated as in Library\PackageCache\com.unity.render-pipelines.universal@14.0.11\ShaderLibrary\ShaderVariablesFunctions.hlsl
  218. #if UNITY_REVERSED_Z
  219. return _ProjectionParams.z - (_ProjectionParams.z - _ProjectionParams.y) * z;
  220. #else
  221. return _ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) * z;
  222. #endif
  223. }
  224. }
  225. /*float3 _FXV_CalcWorldRay(float3 viewPos)
  226. {
  227. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  228. // Perspective camera: View space normalized ray directing vertex
  229. float3 rayPers = normalize(viewPos.xyz);
  230. // This line is equivalent to:
  231. // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
  232. rayPers /= -rayPers.z;
  233. // Orthographic camera: view space vertex position
  234. float3 rayOrtho = float3(viewPos.xy, 0.0);
  235. return lerp(mul(UNITY_MATRIX_I_V, rayPers), rayOrtho, isOrtho);
  236. }*/
  237. float3 _FXV_GetViewForwardDir()
  238. {
  239. #if defined(FXV_VOLUMEFOG_URP)
  240. float4x4 viewMat = GetWorldToViewMatrix();
  241. #else
  242. float4x4 viewMat = UNITY_MATRIX_V;
  243. #endif
  244. return -viewMat[2].xyz;
  245. }
  246. float3 _FXV_GetViewRayOriginWS_fromPositionOS(float3 positionOS)
  247. {
  248. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  249. if (isOrtho == 0)
  250. {
  251. return _WorldSpaceCameraPos;
  252. }
  253. else
  254. {
  255. float3 p = _FXV_ObjectToViewPos(positionOS);
  256. return mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
  257. }
  258. }
  259. float3 _FXV_GetViewRayOriginWS_fromPositionWS(float3 positionWS)
  260. {
  261. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  262. if (isOrtho == 0)
  263. {
  264. return _WorldSpaceCameraPos;
  265. }
  266. else
  267. {
  268. float3 p = _FXV_WorldToViewPos(positionWS);
  269. return mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
  270. }
  271. }
  272. float3 _FXV_GetViewRayDirWS_fromPositionOS(float3 positionOS)
  273. {
  274. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  275. if (isOrtho == 0)
  276. {
  277. float3 p = _FXV_ObjectToViewPos(positionOS);
  278. // Perspective camera: View space normalized ray directing vertex
  279. float3 rayPers = normalize(p.xyz);
  280. // This line is equivalent to:
  281. // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
  282. rayPers /= -rayPers.z;
  283. return mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
  284. }
  285. else
  286. {
  287. return _FXV_GetViewForwardDir();
  288. }
  289. }
  290. float3 _FXV_GetViewRayDirWS_fromPositionWS(float3 positionWS)
  291. {
  292. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  293. if (isOrtho == 0)
  294. {
  295. float3 p = _FXV_WorldToViewPos(positionWS);
  296. // Perspective camera: View space normalized ray directing vertex
  297. float3 rayPers = normalize(p.xyz);
  298. // This line is equivalent to:
  299. // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
  300. rayPers /= -rayPers.z;
  301. return mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
  302. }
  303. else
  304. {
  305. return _FXV_GetViewForwardDir();
  306. }
  307. }
  308. void _FXV_GetViewRayOriginAndDirWS_fromPositionOS(float3 positionOS, out float3 rayOriginWS, out float3 rayDirWS)
  309. {
  310. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  311. float3 p = _FXV_ObjectToViewPos(positionOS);
  312. if (isOrtho == 0)
  313. {
  314. // Perspective camera: View space normalized ray directing vertex
  315. float3 rayPers = normalize(p.xyz);
  316. // This line is equivalent to:
  317. // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
  318. rayPers /= -rayPers.z;
  319. rayDirWS = mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
  320. rayOriginWS = _WorldSpaceCameraPos;
  321. }
  322. else
  323. {
  324. rayDirWS = _FXV_GetViewForwardDir();
  325. rayOriginWS = mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
  326. }
  327. }
  328. void _FXV_GetViewRayOriginAndDirWS_fromPositionWS(float3 positionWS, out float3 rayOriginWS, out float3 rayDirWS)
  329. {
  330. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  331. float3 p = _FXV_WorldToViewPos(positionWS);
  332. if (isOrtho == 0)
  333. {
  334. // Perspective camera: View space normalized ray directing vertex
  335. float3 rayPers = normalize(p.xyz);
  336. // This line is equivalent to:
  337. // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
  338. rayPers /= -rayPers.z;
  339. rayDirWS = mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
  340. rayOriginWS = _WorldSpaceCameraPos;
  341. }
  342. else
  343. {
  344. rayDirWS = _FXV_GetViewForwardDir();
  345. rayOriginWS = mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
  346. }
  347. }
  348. struct fxvFogData
  349. {
  350. float fogT;
  351. float fogDist;
  352. float tNear;
  353. float tFar;
  354. float3 pNear;
  355. float3 pFar;
  356. float3 debugRGB;
  357. };
  358. struct fxvIntersection
  359. {
  360. float tNear;
  361. float tFar;
  362. float3 pNear;
  363. float3 pFar;
  364. float isIntersection;
  365. };
  366. struct fxvRay
  367. {
  368. float3 rayOrigin;
  369. float3 rayDir;
  370. float3 invRayDir;
  371. };
  372. float _FXV_FogT_Default(float fogDist, float fogMin, float fogMax)
  373. {
  374. return saturate((fogDist - fogMin) / (fogMax - fogMin));
  375. }
  376. fxvRay _FXV_GetWSRay(float3 rayOriginWS, float3 rayDirWS)
  377. {
  378. fxvRay r = (fxvRay)0;
  379. r.rayOrigin = rayOriginWS;
  380. r.rayDir = rayDirWS;
  381. return r;
  382. }
  383. fxvRay _FXV_GetOSRay(float3 rayOriginWS, float3 rayDirWS)
  384. {
  385. fxvRay r = (fxvRay)0;
  386. r.rayOrigin = _FXV_WorldToObjectPos(rayOriginWS);
  387. r.rayDir = normalize(_FXV_WorldToObjectDir(rayDirWS));
  388. return r;
  389. }
  390. fxvRay _FXV_GetOSRay_I(float3 rayOriginWS, float3 rayDirWS)
  391. {
  392. fxvRay r = (fxvRay)0;
  393. r.rayOrigin = _FXV_WorldToObjectPos(rayOriginWS);
  394. r.rayDir = normalize(_FXV_WorldToObjectDir(rayDirWS));
  395. r.invRayDir = 1.0 / r.rayDir;
  396. return r;
  397. }
  398. fxvIntersection _FXV_BoxIntersectionOS_T(fxvRay rayOS)
  399. {
  400. fxvIntersection i = (fxvIntersection)0;
  401. #if defined(FXV_FOG_CUSTOM_MESH)
  402. float3 boxSizeHalfOS = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalSize).xyz * 0.5;
  403. float3 boundsOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
  404. #else
  405. float3 boxSizeHalfOS = float3(0.5, 0.5, 0.5);
  406. float3 boundsOffset = float3(0.0, 0.0, 0.0);
  407. #endif
  408. float3 tMin = (-boxSizeHalfOS - rayOS.rayOrigin + boundsOffset) * rayOS.invRayDir;
  409. float3 tMax = (boxSizeHalfOS - rayOS.rayOrigin + boundsOffset) * rayOS.invRayDir;
  410. float3 t1 = min(tMin, tMax);
  411. float3 t2 = max(tMin, tMax);
  412. i.tNear = max(max(max(t1.x, t1.y), t1.z), 0.0);
  413. i.tFar = min(min(t2.x, t2.y), t2.z);
  414. i.isIntersection = step(i.tNear, i.tFar);
  415. return i;
  416. }
  417. fxvIntersection _FXV_BoxIntersectionOS_TP(fxvRay rayOS)
  418. {
  419. fxvIntersection i = _FXV_BoxIntersectionOS_T(rayOS);
  420. i.pNear = rayOS.rayOrigin + rayOS.rayDir * i.tNear;
  421. i.pFar = rayOS.rayOrigin + rayOS.rayDir * i.tFar;
  422. return i;
  423. }
  424. fxvIntersection _FXV_SphereIntersectionWS_T(fxvRay rayWS, float3 spherePosWS, float sphereRadius)
  425. {
  426. fxvIntersection i = (fxvIntersection)0;
  427. // dist to edge inside of sphere calculation
  428. // https://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/
  429. float3 p = rayWS.rayOrigin;
  430. float3 c = spherePosWS;
  431. float3 vpc = spherePosWS - rayWS.rayOrigin;
  432. float3 d = rayWS.rayDir;
  433. float3 pc = -vpc - d * dot(d, -vpc); // projected c onto d
  434. float3 pcc = pc + c; // the same projected but worldspace
  435. float pc2 = dot(pc, pc); //squared length
  436. float pcit = sqrt(sphereRadius * sphereRadius - pc2); //dist from pc to intersection
  437. float3 pccp = pcc - p; // vector from projected to camera position
  438. float tp = dot(pccp, d);
  439. i.tNear = max(0.0, tp - pcit); // dist from p to the near intersection point
  440. i.tFar = tp + pcit; // dist from p to the far intersection point
  441. i.isIntersection = step(i.tNear, i.tFar);
  442. return i;
  443. }
  444. fxvIntersection _FXV_SphereIntersectionWS_TP(fxvRay rayWS, float3 spherePosWS, float sphereRadius)
  445. {
  446. fxvIntersection i = _FXV_SphereIntersectionWS_T(rayWS, spherePosWS, sphereRadius);
  447. i.pNear = rayWS.rayOrigin + rayWS.rayDir * i.tNear;
  448. i.pFar = rayWS.rayOrigin + rayWS.rayDir * i.tFar;
  449. return i;
  450. }
  451. fxvFogData _FXV_ViewAlignedFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  452. {
  453. float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to reconstruct position from depth
  454. float3 depthPoint = viewDirWS * depth;
  455. float tDepthWS = dot(viewDirNormWS, viewDirWS * depth);
  456. float3 boxSizeHalfWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
  457. float tNearWS = 0.0;//dot(viewDirNormWS, worldObjectPos - viewDirOriginWS);
  458. float3 boxSizeHalfOS = float3(0.5,0.5,0.5);
  459. float dist = tDepthWS - tNearWS;
  460. fxvFogData fogData = (fxvFogData)0;
  461. fogData.tNear = tNearWS;
  462. #ifdef FXV_IN_AIR_FOG
  463. fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
  464. fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
  465. float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
  466. float tFarWS = dot(viewDirNormWS, pFarWS - viewDirOriginWS);
  467. fogData.tFar = tFarWS;
  468. dist = min(dist, tFarWS - tNearWS);
  469. #endif
  470. fogData.fogDist = dist;
  471. fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
  472. #ifdef FXV_IN_AIR_FOG
  473. fogData.fogT *= i.isIntersection;
  474. fogData.tNear = i.tNear;
  475. fogData.tFar = i.tFar;
  476. fogData.pNear = _FXV_ObjectToWorldPos(i.pNear);
  477. fogData.pFar = pFarWS;
  478. #endif
  479. return fogData;
  480. }
  481. fxvFogData _FXV_SphericalFog_RayDist(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  482. {
  483. float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruc position from depth
  484. float distToDepth = dot(viewDirNormWS, viewDirWS * depth); //reconstruct position from depth and get it's distance from view origin
  485. float3 pNear = worldPosition;
  486. #ifdef FXV_IN_AIR_FOG
  487. fxvRay rayWS = _FXV_GetWSRay(viewDirOriginWS, viewDirNormWS);
  488. fxvIntersection i = _FXV_SphereIntersectionWS_TP(rayWS, worldObjectPos, fogMax);
  489. pNear = i.pNear;
  490. distToDepth = min(distToDepth, i.tFar); //select what is closer - dist to reconstructed depth, or dist to far intersection with sphere
  491. #endif
  492. float fogIntersectionDepth = distToDepth - dot(viewDirNormWS, pNear - viewDirOriginWS); //distance ray is travelling inside fog
  493. fxvFogData fogData = (fxvFogData)0;
  494. fogData.fogDist = fogMax - 0.5 * fogIntersectionDepth;
  495. fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
  496. fogData.fogT = 1.0 - fogData.fogT;
  497. #ifdef FXV_IN_AIR_FOG
  498. fogData.fogT *= i.isIntersection;
  499. #endif
  500. #ifdef FXV_IN_AIR_FOG
  501. fogData.tNear = i.tNear;
  502. fogData.tFar = i.tFar;
  503. fogData.pNear = i.pNear;
  504. fogData.pFar = i.pFar;
  505. #endif
  506. return fogData;
  507. }
  508. fxvFogData _FXV_SphericalFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  509. {
  510. float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruc position from depth
  511. float distToDepth = dot(viewDirNormWS, viewDirWS * depth); //reconstruct position from depth and get it's distance from view origin
  512. #ifdef FXV_IN_AIR_FOG
  513. float airZ;
  514. if (isOrtho == 1)
  515. {
  516. airZ = -_FXV_WorldToViewPos(worldObjectPos).z;
  517. }
  518. else
  519. {
  520. float3 pointDiff = worldPosition - worldObjectPos;
  521. float3 camToObj = worldObjectPos - viewDirOriginWS;
  522. float3 camDirToObj = normalize(camToObj);
  523. float3 camDirToPoint = normalize(viewDirWS);
  524. float3 viewPerp = pointDiff - camDirToObj * dot(camDirToObj, pointDiff);
  525. float3 viewPerpLocal = _FXV_WorldToObjectDir(viewPerp);
  526. float3 pv = _FXV_ObjectToViewPos(viewPerpLocal);
  527. float dd = dot(camDirToObj, camDirToPoint);
  528. airZ = length(pv) * dd * dd;
  529. }
  530. distToDepth = min(distToDepth, airZ);
  531. #endif
  532. float3 worldspace = viewDirOriginWS + viewDirNormWS * distToDepth;
  533. float3 diff = worldObjectPos - worldspace;
  534. float dist = length(diff);
  535. fxvFogData fogData = (fxvFogData)0;
  536. fogData.fogDist = dist;
  537. fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
  538. fogData.fogT = 1.0 - fogData.fogT;
  539. return fogData;
  540. }
  541. fxvFogData _FXV_BoxFog_RayDist(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  542. {
  543. #if defined(FXV_FOG_CUSTOM_MESH)
  544. float3 boxLocalOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
  545. worldObjectPos += _FXV_ObjectToWorldDir(boxLocalOffset);
  546. #endif
  547. float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruct position from depth
  548. float3 depthPoint = viewDirWS * depth;
  549. float tDepth = dot(viewDirNormWS, viewDirWS * depth);
  550. float tNearWS = dot(viewDirNormWS, worldPosition - viewDirOriginWS); // this will not work if camera view plane is partialy intersecting box
  551. float dist = tDepth;
  552. fxvFogData fogData = (fxvFogData)0;
  553. fogData.tNear = tNearWS;
  554. #ifdef FXV_IN_AIR_FOG
  555. fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
  556. fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
  557. float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
  558. float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
  559. tNearWS = dot(viewDirNormWS, pNearWS - viewDirOriginWS);
  560. float tFarWS = dot(viewDirNormWS, pFarWS - viewDirOriginWS);
  561. fogData.tNear = tNearWS;
  562. fogData.tFar = tFarWS;
  563. dist = min(dist, tFarWS);
  564. #endif
  565. fogData.fogDist = dist - tNearWS;
  566. fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
  567. #ifdef FXV_IN_AIR_FOG
  568. fogData.tNear = i.tNear;
  569. fogData.tFar = i.tFar;
  570. fogData.pNear = pNearWS;
  571. fogData.pFar = pFarWS;
  572. #endif
  573. return fogData;
  574. }
  575. fxvFogData _FXV_BoxFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  576. {
  577. #if defined(FXV_FOG_CUSTOM_MESH)
  578. float3 boxLocalOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
  579. worldObjectPos += _FXV_ObjectToWorldDir(boxLocalOffset);
  580. #endif
  581. float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruct position from depth
  582. float3 depthPoint = viewDirWS * depth;
  583. float3 worldspaceDepthPoint = viewDirOriginWS + depthPoint;
  584. float3 localDepthPoint = _FXV_WorldToObjectPos(worldspaceDepthPoint);
  585. float3 boxSizeWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz;
  586. float3 boxSizeHalfWS = boxSizeWS * 0.5;
  587. float minScaling = min(min(boxSizeWS.x, boxSizeWS.y), boxSizeWS.z);
  588. float maxScaling = max(max(boxSizeWS.x, boxSizeWS.y), boxSizeWS.z);
  589. float3 scaling = boxSizeWS / maxScaling;
  590. float3 diffTestDepth = localDepthPoint * boxSizeHalfWS;
  591. float dist = max(max(abs(diffTestDepth.x), abs(diffTestDepth.y)), abs(diffTestDepth.z));
  592. #ifdef FXV_IN_AIR_FOG
  593. fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
  594. fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
  595. float tDepth = dot(rayOS.rayDir, localDepthPoint - rayOS.rayOrigin);
  596. float tLimit = min(i.tFar, tDepth);
  597. float3 currentPos = i.pNear;
  598. float stepT = i.tNear;
  599. float3 diffTest = currentPos;
  600. float distTest = max(max(abs(diffTest.x), abs(diffTest.y)), abs(diffTest.z));
  601. for (int s = 0; s < 255; s++)
  602. {
  603. float3 diffTestNew = currentPos;
  604. float distTestNew = max(max(abs(diffTestNew.x), abs(diffTestNew.y)), abs(diffTestNew.z));
  605. distTest = min(distTestNew, distTest);
  606. stepT += 1.0/255.0;
  607. stepT = min(stepT, tLimit);
  608. currentPos = rayOS.rayOrigin + rayOS.rayDir * stepT;
  609. }
  610. dist = distTest;
  611. #endif
  612. float fogMin2 = (0.5 - fogMax);
  613. float fogMax2 = (0.5 - fogMin);
  614. fxvFogData fogData = (fxvFogData)0;
  615. fogData.fogDist = dist;
  616. fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin2, fogMax2);
  617. fogData.fogT = 1.0 - fogData.fogT;
  618. #ifdef FXV_IN_AIR_FOG
  619. float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
  620. float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
  621. fogData.tNear = i.tNear;
  622. fogData.tFar = i.tFar;
  623. fogData.pNear = pNearWS;
  624. fogData.pFar = pFarWS;
  625. #endif
  626. return fogData;
  627. }
  628. fxvFogData _FXV_HeightFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho, float3 axis)
  629. {
  630. #if defined(FXV_FOG_CUSTOM_MESH)
  631. float3 boxLocalOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
  632. worldObjectPos += _FXV_ObjectToWorldDir(boxLocalOffset);
  633. #endif
  634. float3 worldspace = viewDirOriginWS + viewDirWS * depth;
  635. float3 diff = worldObjectPos - worldspace;
  636. //axis = float3(0, 1, 0);
  637. float3 worldAxis = normalize(_FXV_ObjectToWorldDir(axis));
  638. //diff = _FXV_WorldToObjectDir(diff); //rotation support
  639. float3 boxSizeHalfWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
  640. float3 boxSizeHalfOS = float3(0.5, 0.5, 0.5);
  641. float axisBoxSize = abs(dot(axis, boxSizeHalfWS));
  642. float dist = dot(worldAxis, diff) + axisBoxSize;
  643. #ifdef FXV_IN_AIR_FOG
  644. fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
  645. fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
  646. float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
  647. float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
  648. float3 diff2 = worldObjectPos - pFarWS;
  649. float dist2 = dot(worldAxis, diff2) + axisBoxSize;
  650. dist = lerp(dist, dist2, step(0, dot(viewDirWS, worldspace - pFarWS))); //equivalent of if (dot(viewDirWS, worldspace - pFarWS) > 0.0) dist = dist2;
  651. //pNearWS = worldPosition; //we can use worldPosition instead of calculationg pNear, but not when plane is mid intersecting with box
  652. float3 diff3 = worldObjectPos - pNearWS;
  653. float dist3 = dot(worldAxis, diff3) + axisBoxSize;
  654. dist = max(dist, dist3);
  655. #endif
  656. fxvFogData fogData = (fxvFogData)0;
  657. fogData.fogDist = dist;
  658. fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
  659. #ifdef FXV_IN_AIR_FOG
  660. float3 pNearVS = _FXV_ObjectToViewPos(i.pNear); //TODO calc only when plane intersection
  661. i.isIntersection *= step(0, depth + pNearVS.z);
  662. fogData.fogT *= i.isIntersection;
  663. fogData.tNear = i.tNear;
  664. fogData.tFar = i.tFar;
  665. fogData.pNear = pNearWS;
  666. fogData.pFar = pFarWS;
  667. #endif
  668. return fogData;
  669. }
  670. fxvFogData _FXV_InverseSpherical(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  671. {
  672. float3 pDepth = viewDirOriginWS + viewDirWS * depth;
  673. float3 diff = worldObjectPos - pDepth;
  674. float3 boxSizeHalfWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
  675. float3 boxSizeHalfOS = float3(0.5, 0.5, 0.5);
  676. float fade = 1.0;
  677. float dist = length(diff);
  678. #ifdef FXV_IN_AIR_FOG
  679. fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
  680. fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
  681. fxvRay rayWS = _FXV_GetWSRay(viewDirOriginWS, normalize(viewDirWS));
  682. fxvIntersection is = _FXV_SphereIntersectionWS_TP(rayWS, worldObjectPos, fogMax);
  683. float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
  684. float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
  685. i.tNear = dot(rayWS.rayDir, pNearWS - viewDirOriginWS);
  686. i.tFar = dot(rayWS.rayDir, pFarWS - viewDirOriginWS);
  687. float tDepth = dot(rayWS.rayDir, pDepth - viewDirOriginWS);
  688. dist = lerp(dist, length(worldObjectPos - pFarWS), step(0, dot(viewDirWS, pDepth - pFarWS))); //equivalent of if (dot(viewDirWS, pDepth - pFarWS) > 0.0) dist = length(worldObjectPos - pFarWS);
  689. if (is.isIntersection == 1)
  690. {
  691. fade = clamp(max(0.0, (is.tNear - i.tNear)) / 1, 0, 1);
  692. fade = max(fade, clamp(max(0.0, (min(i.tFar, tDepth) - is.tFar)) / 1, 0, 1));
  693. }
  694. #endif
  695. fxvFogData fogData = (fxvFogData)0;
  696. fogData.fogDist = dist;
  697. fogData.fogT = saturate(_FXV_FogT_Default(fogData.fogDist, fogMin, fogMax) + fade);
  698. #ifdef FXV_IN_AIR_FOG
  699. fogData.fogT *= i.isIntersection;
  700. fogData.tNear = i.tNear;
  701. fogData.tFar = i.tFar;
  702. fogData.pNear = pNearWS;
  703. fogData.pFar = pFarWS;
  704. #endif
  705. return fogData;
  706. }
  707. #define _fxv_PI 3.14159265359
  708. #define _fxv_HALF_PI 1.57079632679
  709. #define _fxv_SMOOTH 2.88539 // 2.0 / log(2.0)
  710. float smoothestStep(float x, float s)
  711. {
  712. s *= _fxv_SMOOTH;
  713. return 1.0 / (1.0 + exp2(tan(x * _fxv_PI - _fxv_HALF_PI) * -s)) + 0.5;
  714. }
  715. fxvFogData _FXV_CalcPrimaryFogData(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
  716. {
  717. fxvFogData fogData = (fxvFogData)0;
  718. #ifdef FXV_FOGTYPE_VIEWALIGNED
  719. fogData = _FXV_ViewAlignedFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  720. #elif FXV_FOGTYPE_SPHERICALPOS
  721. fogData = _FXV_SphericalFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  722. #elif FXV_FOGTYPE_SPHERICALDIST
  723. fogData = _FXV_SphericalFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  724. #elif FXV_FOGTYPE_INVERTEDSPHERICAL
  725. fogData = _FXV_InverseSpherical(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  726. #elif FXV_FOGTYPE_INVERTEDSPHERICALXHEIGHT
  727. fogData = _FXV_InverseSpherical(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  728. float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
  729. float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
  730. fxvFogData fogData2 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho, float3(0, 1, 0));
  731. fogData.fogT = fogData.fogT * fogData2.fogT;
  732. #elif FXV_FOGTYPE_BOXDIST
  733. fogData = _FXV_BoxFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  734. #elif FXV_FOGTYPE_BOXPOS
  735. fogData = _FXV_BoxFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  736. #elif FXV_FOGTYPE_BOXEXPERIMENTAL
  737. fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(1, 0, 0));
  738. fxvFogData fogData1 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(-1, 0, 0));
  739. fxvFogData fogData2 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 0, 1));
  740. fxvFogData fogData3 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 0, -1));
  741. fxvFogData fogData4 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 1, 0));
  742. fxvFogData fogData5 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, -1, 0));
  743. fogData.fogT = smoothstep(0.0, 1.0, fogData.fogT) * smoothstep(0.0, 1.0, fogData1.fogT) * smoothstep(0.0, 1.0, fogData2.fogT) * smoothstep(0.0, 1.0, fogData3.fogT) * smoothstep(0.0, 1.0, fogData4.fogT) * smoothstep(0.0, 1.0, fogData5.fogT);
  744. #elif FXV_FOGTYPE_HEIGHT
  745. fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0,1,0));
  746. #elif FXV_FOGTYPE_HEIGHTXBOX
  747. fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 1, 0));
  748. float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
  749. float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
  750. fxvFogData fogData2 = _FXV_BoxFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho);
  751. fogData.fogT = fogData.fogT * fogData2.fogT;
  752. #elif FXV_FOGTYPE_HEIGHTXVIEW
  753. fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 1, 0));
  754. float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
  755. float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
  756. fxvFogData fogData2 = _FXV_ViewAlignedFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho);
  757. fogData.fogT = fogData.fogT * fogData2.fogT;
  758. #elif FXV_FOGTYPE_BOXXVIEW
  759. fogData = _FXV_BoxFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  760. float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
  761. float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
  762. fxvFogData fogData2 = _FXV_ViewAlignedFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho);
  763. fogData.fogT = fogData.fogT * fogData2.fogT;
  764. #endif
  765. return fogData;
  766. }
  767. fxvFogData _FXV_CalcVolumetricFog(float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float inputDepth, float4 screenPos)
  768. {
  769. float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
  770. float fogMin = UNITY_ACCESS_INSTANCED_PROP(Props, _FogMin);
  771. float fogMax = UNITY_ACCESS_INSTANCED_PROP(Props, _FogMax);
  772. float z = _FXV_GetRawDepth(screenPos);
  773. #if FXV_FOG_CLIP_SKYBOX
  774. if (z <= 0.0)
  775. discard;
  776. #endif
  777. float depth = _FXV_GetLinearEyeDepth(z);
  778. #if FXV_FOG_CLIP_BOUNDS
  779. float3 pDepth = viewDirOriginWS + viewDirWS * depth;
  780. float3 localDepthPoint = _FXV_WorldToObjectPos(pDepth);
  781. #if FXV_FOGTYPE_SPHERICALPOS ||FXV_FOGTYPE_SPHERICALDIST
  782. clip(0.5 - length(localDepthPoint));
  783. #else
  784. clip(float3(0.5, 0.5, 0.5) - abs(localDepthPoint));
  785. #endif
  786. #endif
  787. float3 worldObjectPos = _FXV_ObjectToWorldPos(float3(0,0,0));
  788. fxvFogData fogData = _FXV_CalcPrimaryFogData(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
  789. float falloff = UNITY_ACCESS_INSTANCED_PROP(Props, _FogFalloff);
  790. #ifdef FXV_SMOOTHED_FALLOFF
  791. fogData.fogT = smoothstep(0.0, 1.0, fogData.fogT);
  792. #elif FXV_EXP_FALLOFF
  793. fogData.fogT = exp(fogData.fogT) - 1.0;
  794. #elif FXV_EXP2_FALLOFF
  795. fogData.fogT = exp2(fogData.fogT) - 1.0;
  796. #endif
  797. fogData.fogT = pow(fogData.fogT, falloff);
  798. return fogData;
  799. }
  800. struct fxvLightingData
  801. {
  802. float3 objectPositionWS;
  803. float3 pixelPositionWS;
  804. float4 lightPositionWS;
  805. float3 lightDirectionWS;
  806. float3 lightColor;
  807. float3 viewDirectionOriginWS;
  808. float3 viewDirectionWS;
  809. float3 normalWS;
  810. float2 lightRangeAttenuation; // x - oneOverLightRangeSqr (oneOverFadeRangeSqr on mobile/switch), y - lightRangeSqrOverFadeRangeSqr, linear fade start at 80% light range
  811. float3 albedo;
  812. float alpha;
  813. };
  814. float3 _FXV_FogLightingFunction(fxvLightingData fxvData, fxvFogData fogData)
  815. {
  816. float4 c;
  817. float NdotL = 1.0;
  818. half fogMax = UNITY_ACCESS_INSTANCED_PROP(Props, _FogMax);
  819. half _scatteringFactor = UNITY_ACCESS_INSTANCED_PROP(Props, _LightScatteringFactor);
  820. half _invScatteringFactor = 1.0 / _scatteringFactor;
  821. half _lightReflectivity = UNITY_ACCESS_INSTANCED_PROP(Props, _LightReflectivity);
  822. half _lightTransmission = UNITY_ACCESS_INSTANCED_PROP(Props, _LightTransmission);
  823. float3 L = fxvData.lightDirectionWS;
  824. float3 V = fxvData.viewDirectionWS;
  825. //float3 N = fxvData.normalWS;
  826. float invLightRangeSqr = fxvData.lightRangeAttenuation.x;
  827. float rangeFade = 1.0;
  828. float lightAtten = 1.0;
  829. if (fxvData.lightPositionWS.w == 1)
  830. {
  831. float3 viewPoint = fxvData.viewDirectionOriginWS - V * length(fxvData.lightPositionWS.xyz - fxvData.viewDirectionOriginWS);
  832. //float3 viewPoint = _WorldSpaceCameraPos.xyz + V * dot(fxvData.lightPositionWS.xyz - _WorldSpaceCameraPos.xyz, V);//length(fxvData.lightPositionWS.xyz - _WorldSpaceCameraPos.xyz);
  833. float3 diffToLight = (viewPoint - fxvData.lightPositionWS.xyz);
  834. float distToViewPointSqr = dot(diffToLight, diffToLight);
  835. float factor = distToViewPointSqr * invLightRangeSqr;
  836. rangeFade = saturate(1.0 - factor);
  837. float3 pixelPosWS = fxvData.pixelPositionWS;
  838. #if FXV_FOGTYPE_VIEWALIGNED || FXV_FOGTYPE_BOXPOS || FXV_FOGTYPE_BOXDIST || FXV_FOGTYPE_BOXEXPERIMENTAL || FXV_FOGTYPE_HEIGHT || FXV_FOGTYPE_HEIGHTXBOX || FXV_FOGTYPE_INVERTEDSPHERICAL || FXV_FOGTYPE_INVERTEDSPHERICALXHEIGHT || FXV_FOGTYPE_HEIGHTXVIEW || FXV_FOGTYPE_BOXXVIEW
  839. #if FXV_IN_AIR_FOG
  840. pixelPosWS = fogData.pNear;
  841. #endif
  842. #endif
  843. diffToLight = (pixelPosWS - fxvData.lightPositionWS.xyz);
  844. float distanceSqr = dot(diffToLight, diffToLight);
  845. #if FXV_FOGTYPE_SPHERICAL
  846. factor = distanceSqr * invLightRangeSqr; //TODO handle SHADER_HINT_NICE_QUALITY and mobile as DistanceAttenuation RealtimeLights.hlsl
  847. #else
  848. float side = dot(V, normalize(diffToLight));
  849. factor = lerp(distanceSqr, distToViewPointSqr, side) * invLightRangeSqr; //TODO handle SHADER_HINT_NICE_QUALITY and mobile as DistanceAttenuation RealtimeLights.hlsl
  850. #endif
  851. float attenuationFade = saturate(1.0 - factor);
  852. lightAtten = pow(attenuationFade, _invScatteringFactor * _invScatteringFactor);
  853. #if FXV_FOGTYPE_VIEWALIGNED || FXV_FOGTYPE_BOXPOS || FXV_FOGTYPE_BOXDIST || FXV_FOGTYPE_BOXEXPERIMENTAL || FXV_FOGTYPE_HEIGHT || FXV_FOGTYPE_HEIGHTXBOX || FXV_FOGTYPE_INVERTEDSPHERICAL || FXV_FOGTYPE_INVERTEDSPHERICALXHEIGHT || FXV_FOGTYPE_HEIGHTXVIEW || FXV_FOGTYPE_BOXXVIEW
  854. #if FXV_IN_AIR_FOG
  855. L = -normalize(diffToLight); //calculate light dir to box - this is required when we use camera plane that is close to box edge - TODO - optimize so this is only calculated in described situation
  856. #endif
  857. #endif
  858. }
  859. else
  860. {
  861. rangeFade = saturate(dot(fxvData.lightDirectionWS, float3(0,1,0)));
  862. }
  863. c.rgb = fxvData.albedo * fxvData.lightColor.rgb * lightAtten * rangeFade * lerp(fxvData.alpha * min(1.0, _lightReflectivity * 2.0), 1, _lightReflectivity);
  864. float powFactor = (_invScatteringFactor);
  865. float VdotH = pow(saturate(dot(V, -L)), powFactor * powFactor);
  866. /*
  867. #if FXV_FOGTYPE_SPHERICAL
  868. diffToLight = (fxvData.objectPositionWS - fxvData.lightPositionWS.xyz);
  869. float l = length(diffToLight);
  870. diffToLight = (diffToLight / l) * (max(0.0, l-fogMax));
  871. factor = dot(diffToLight, diffToLight) * invLightRangeSqr;
  872. #else
  873. float3 boxSizeHalf = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
  874. diffToLight = (fxvData.objectPositionWS - fxvData.lightPositionWS.xyz);
  875. float dist = max(max(abs(diffToLight.x) - boxSizeHalf.x, abs(diffToLight.y) - boxSizeHalf.y), abs(diffToLight.z) - boxSizeHalf.z);
  876. factor = dist * dist * invLightRangeSqr;
  877. #endif
  878. float rangeFade3 = saturate(1.0 - factor);
  879. */
  880. c.rgb += ((fxvData.albedo * fxvData.lightColor.rgb * VdotH)) * rangeFade * lerp(fxvData.alpha * min(1.0, _lightTransmission * 2.0), 1, _lightTransmission); // * rangeFade3
  881. return c.rgb;
  882. }
  883. #endif