1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174 |
- #ifndef FXV_VOLUME_FOG_INCLUDED
- #define FXV_VOLUME_FOG_INCLUDED
- #define FXV_VOLUMETRIC_FOG_APPDATA float3 positionOS : POSITION; \
- UNITY_VERTEX_INPUT_INSTANCE_ID
- #define FXV_VOLUMETRIC_FOG_LIT_APPDATA float4 positionOS : POSITION; \
- float4 tangent : TANGENT; \
- float3 normal : NORMAL; \
- float4 texcoord : TEXCOORD0; \
- UNITY_VERTEX_INPUT_INSTANCE_ID
- #if defined(FXV_VOLUMEFOG_URP)
- #define FXV_VOLUMETRIC_FOG_V2F_COORDS float4 positionCS : SV_POSITION; \
- float depth : TEXCOORD0; \
- float4 screenPosition : TEXCOORD1; \
- float3 positionOS : TEXCOORD2; \
- float3 positionWS : TEXCOORD3; \
- UNITY_VERTEX_INPUT_INSTANCE_ID \
- UNITY_VERTEX_OUTPUT_STEREO
- #else
- #define FXV_VOLUMETRIC_FOG_V2F_COORDS float4 positionCS : SV_POSITION; \
- float depth : TEXCOORD0; \
- float4 screenPosition : TEXCOORD1; \
- float3 positionOS : TEXCOORD2; \
- float3 positionWS : TEXCOORD3; \
- UNITY_VERTEX_INPUT_INSTANCE_ID \
- UNITY_VERTEX_OUTPUT_STEREO
- #endif
- #define FXV_VOLUMETRIC_FOG_PARTICLE_COORDS float depth : TEXCOORD2; \
- float4 vertexPos : TEXCOORD3; \
- float3 positionWS : TEXCOORD4; \
- float4 projPos : TEXCOORD5;
- #if defined(FXV_VOLUMEFOG_URP)
- #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT(v, o) UNITY_SETUP_INSTANCE_ID(v); \
- UNITY_TRANSFER_INSTANCE_ID(v, o); \
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); \
- half isOrtho = unity_OrthoParams.w; \
- VertexPositionInputs vertInputs = GetVertexPositionInputs (v.positionOS.xyz); \
- o.positionCS = vertInputs.positionCS; \
- o.screenPosition = vertInputs.positionNDC; \
- o.positionOS = v.positionOS; \
- o.positionWS = _FXV_ObjectToWorldPos(v.positionOS); \
- o.depth = _FXV_ComputeVertexDepth(o.positionWS);
- #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT_LIT(v, o) half isOrtho = unity_OrthoParams.w; \
- VertexPositionInputs vertInputs = GetVertexPositionInputs (v.positionOS.xyz); \
- o.positionCS = vertInputs.positionCS; \
- o.screenPosition = vertInputs.positionNDC; \
- o.positionOS = v.positionOS; \
- o.positionWS = _FXV_ObjectToWorldPos(v.positionOS); \
- o.depth = _FXV_ComputeVertexDepth(o.positionWS);
- #else
- #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT(v, o) UNITY_SETUP_INSTANCE_ID(v); \
- UNITY_TRANSFER_INSTANCE_ID(v, o); \
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); \
- half isOrtho = unity_OrthoParams.w; \
- o.positionCS = UnityObjectToClipPos(v.positionOS.xyz); \
- o.screenPosition = ComputeScreenPos(o.positionCS); \
- float3 p = UnityObjectToViewPos(v.positionOS); \
- o.positionOS = v.positionOS; \
- o.positionWS = _FXV_ObjectToWorldPos(v.positionOS); \
- o.depth = _FXV_ComputeVertexDepth(o.positionWS); \
- #define FXV_VOLUMETRIC_FOG_VERTEX_DEFAULT_LIT(v, o) half isOrtho = unity_OrthoParams.w; \
- appdata vv = (appdata)v; \
- o.positionCS = UnityObjectToClipPos(vv.positionOS.xyz); \
- o.screenPosition = ComputeScreenPos(o.positionCS); \
- float3 p = UnityObjectToViewPos(vv.positionOS); \
- o.positionOS = vv.positionOS; \
- o.positionWS = _FXV_ObjectToWorldPos(vv.positionOS); \
- o.depth = _FXV_ComputeVertexDepth(o.positionWS);
- #endif
-
- float4x4 _fxv_ObjectToWorldCustom;
- #define FXV_VOLUMETRIC_FOG_FRAGMENT_DEFAULT(i) UNITY_SETUP_INSTANCE_ID(i) \
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
- #if !defined(FXV_VOLUMEFOG_HDRP)
- #ifdef FXV_VOLUMEFOG_URP
- TEXTURE2D_X_FLOAT(_CameraDepthTexture);
- SAMPLER(sampler_CameraDepthTexture);
- #else
- UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
- #endif
- #endif
- UNITY_INSTANCING_BUFFER_START(Props)
- UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
- UNITY_DEFINE_INSTANCED_PROP(float4, _WorldSize)
- #if defined(FXV_FOG_CUSTOM_MESH)
- UNITY_DEFINE_INSTANCED_PROP(float4, _LocalSize)
- UNITY_DEFINE_INSTANCED_PROP(float4, _LocalOffset)
- #endif
- UNITY_DEFINE_INSTANCED_PROP(half, _FogMin)
- UNITY_DEFINE_INSTANCED_PROP(half, _FogMax)
- UNITY_DEFINE_INSTANCED_PROP(half, _FogFalloff)
- UNITY_DEFINE_INSTANCED_PROP(half, _InAirSmooth)
- UNITY_DEFINE_INSTANCED_PROP(half, _LightScatteringFactor)
- UNITY_DEFINE_INSTANCED_PROP(half, _LightReflectivity)
- UNITY_DEFINE_INSTANCED_PROP(half, _LightTransmission)
- #if defined(FXV_FOGTYPE_HEIGHTXBOX) || defined(FXV_FOGTYPE_HEIGHTXVIEW) || defined(FXV_FOGTYPE_BOXXVIEW) || defined(FXV_FOGTYPE_INVERTEDSPHERICALXHEIGHT)
- UNITY_DEFINE_INSTANCED_PROP(half, _SecFogMin)
- UNITY_DEFINE_INSTANCED_PROP(half, _SecFogMax)
- #endif
- UNITY_INSTANCING_BUFFER_END(Props)
- inline float3 _FXV_WorldToViewPos(in float3 pos)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return TransformWorldToView(pos);
- #else
- return mul(UNITY_MATRIX_V, float4(pos, 1.0)).xyz;
- #endif
- }
- inline float3 _FXV_WorldToViewPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return _FXV_WorldToViewPos(pos.xyz);
- }
- inline float3 _FXV_WorldToObjectPos(in float3 pos)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return TransformWorldToObject(pos);
- #else
- return mul(unity_WorldToObject, float4(pos, 1)).xyz;
- #endif
- }
- inline float3 _FXV_WorldToObjectPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return _FXV_WorldToObjectPos(pos.xyz);
- }
- inline float3 _FXV_WorldToObjectDir(in float3 dir)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return mul(GetWorldToObjectMatrix(), float4(dir, 0)).xyz;
- #else
- return mul(unity_WorldToObject, float4(dir, 0)).xyz;
- #endif
- }
- inline float3 _FXV_WorldToObjectDir(float4 dir) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return _FXV_WorldToObjectDir(dir.xyz);
- }
- inline float3 _FXV_ObjectToWorldPos(in float3 pos)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return TransformObjectToWorld(pos);
- #else
- return mul(unity_ObjectToWorld, float4(pos, 1)).xyz;
- #endif
- }
- inline float3 _FXV_ObjectToWorldPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return _FXV_ObjectToWorldPos(pos.xyz);
- }
- inline float3 _FXV_ObjectToWorldDir(in float3 dir)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return mul(GetObjectToWorldMatrix(), float4(dir, 0)).xyz;
- #else
- return mul(unity_ObjectToWorld, float4(dir, 0)).xyz;
- #endif
- }
- inline float3 _FXV_ObjectToWorldDir(float4 dir) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return _FXV_ObjectToWorldDir(dir.xyz);
- }
- inline float3 _FXV_ObjectToViewPos(in float3 pos)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return TransformWorldToView(TransformObjectToWorld(pos));
- #else
- return mul(UNITY_MATRIX_V, mul(unity_ObjectToWorld, float4(pos, 1.0))).xyz;
- #endif
- }
- inline float3 _FXV_ObjectToViewPos(float4 pos) // overload for float4; avoids "implicit truncation" warning for existing shaders
- {
- return _FXV_ObjectToViewPos(pos.xyz);
- }
- // Z buffer to linear depth.
- // Works in all cases.
- // Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
- // Assumes that the 'positionWS' is in front of the camera.
- float _FXV_ComputeVertexDepth(float3 positionWS)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- return LinearEyeDepth(positionWS, GetWorldToViewMatrix());
- #elif defined(FXV_VOLUMEFOG_HDRP)
- return LinearEyeDepth(positionWS, GetWorldToViewMatrix());
- #else
- // calculated as in Library\PackageCache\com.unity.render-pipelines.core@14.0.11\ShaderLibrary\Common.hlsl
- float viewSpaceZ = mul(UNITY_MATRIX_V, float4(positionWS, 1.0)).z;
- // If the matrix is right-handed, we have to flip the Z axis to get a positive value.
- return abs(viewSpaceZ);
- #endif
- }
- half _FXV_GetRawDepth(half4 screenPos)
- {
- #if defined(FXV_VOLUMEFOG_URP)
- float z = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(screenPos.xy / screenPos.w)).r;
- #elif defined(FXV_VOLUMEFOG_HDRP)
- float z = SampleCameraDepth( screenPos.xy / screenPos.w );
- #else
- float z = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(screenPos));
- #endif
- return z;
- }
- half _FXV_GetLinearEyeDepth(float z)
- {
- if (unity_OrthoParams.w == 0) // perspective
- {
- // Perspective linear depth
- #if defined(FXV_VOLUMEFOG_URP)
- return LinearEyeDepth(z, _ZBufferParams);
- #elif defined(FXV_VOLUMEFOG_HDRP)
- return LinearEyeDepth(z, _ZBufferParams);
- #else
- return LinearEyeDepth(z);
- #endif
- }
- else
- {
- // Orthographic linear depth
- // near = _ProjectionParams.y;
- // far = _ProjectionParams.z;
- // calculated as in Library\PackageCache\com.unity.render-pipelines.universal@14.0.11\ShaderLibrary\ShaderVariablesFunctions.hlsl
- #if UNITY_REVERSED_Z
- return _ProjectionParams.z - (_ProjectionParams.z - _ProjectionParams.y) * z;
- #else
- return _ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) * z;
- #endif
- }
- }
- /*float3 _FXV_CalcWorldRay(float3 viewPos)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- // Perspective camera: View space normalized ray directing vertex
- float3 rayPers = normalize(viewPos.xyz);
- // This line is equivalent to:
- // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
- rayPers /= -rayPers.z;
- // Orthographic camera: view space vertex position
- float3 rayOrtho = float3(viewPos.xy, 0.0);
- return lerp(mul(UNITY_MATRIX_I_V, rayPers), rayOrtho, isOrtho);
- }*/
- float3 _FXV_GetViewForwardDir()
- {
- #if defined(FXV_VOLUMEFOG_URP)
- float4x4 viewMat = GetWorldToViewMatrix();
- #else
- float4x4 viewMat = UNITY_MATRIX_V;
- #endif
- return -viewMat[2].xyz;
- }
- float3 _FXV_GetViewRayOriginWS_fromPositionOS(float3 positionOS)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- if (isOrtho == 0)
- {
- return _WorldSpaceCameraPos;
- }
- else
- {
- float3 p = _FXV_ObjectToViewPos(positionOS);
- return mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
- }
- }
- float3 _FXV_GetViewRayOriginWS_fromPositionWS(float3 positionWS)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- if (isOrtho == 0)
- {
- return _WorldSpaceCameraPos;
- }
- else
- {
- float3 p = _FXV_WorldToViewPos(positionWS);
- return mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
- }
- }
- float3 _FXV_GetViewRayDirWS_fromPositionOS(float3 positionOS)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- if (isOrtho == 0)
- {
- float3 p = _FXV_ObjectToViewPos(positionOS);
- // Perspective camera: View space normalized ray directing vertex
- float3 rayPers = normalize(p.xyz);
- // This line is equivalent to:
- // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
- rayPers /= -rayPers.z;
- return mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
- }
- else
- {
- return _FXV_GetViewForwardDir();
- }
- }
- float3 _FXV_GetViewRayDirWS_fromPositionWS(float3 positionWS)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- if (isOrtho == 0)
- {
- float3 p = _FXV_WorldToViewPos(positionWS);
- // Perspective camera: View space normalized ray directing vertex
- float3 rayPers = normalize(p.xyz);
- // This line is equivalent to:
- // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
- rayPers /= -rayPers.z;
- return mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
- }
- else
- {
- return _FXV_GetViewForwardDir();
- }
- }
- void _FXV_GetViewRayOriginAndDirWS_fromPositionOS(float3 positionOS, out float3 rayOriginWS, out float3 rayDirWS)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
-
- float3 p = _FXV_ObjectToViewPos(positionOS);
- if (isOrtho == 0)
- {
- // Perspective camera: View space normalized ray directing vertex
- float3 rayPers = normalize(p.xyz);
- // This line is equivalent to:
- // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
- rayPers /= -rayPers.z;
- rayDirWS = mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
- rayOriginWS = _WorldSpaceCameraPos;
- }
- else
- {
- rayDirWS = _FXV_GetViewForwardDir();
- rayOriginWS = mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
- }
- }
- void _FXV_GetViewRayOriginAndDirWS_fromPositionWS(float3 positionWS, out float3 rayOriginWS, out float3 rayDirWS)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- float3 p = _FXV_WorldToViewPos(positionWS);
- if (isOrtho == 0)
- {
- // Perspective camera: View space normalized ray directing vertex
- float3 rayPers = normalize(p.xyz);
- // This line is equivalent to:
- // rayPers /= dot(rayPers, float3(0.0, 0.0, -1.0));
- rayPers /= -rayPers.z;
- rayDirWS = mul(UNITY_MATRIX_I_V, float4(rayPers, 0)).xyz;
- rayOriginWS = _WorldSpaceCameraPos;
- }
- else
- {
- rayDirWS = _FXV_GetViewForwardDir();
- rayOriginWS = mul(UNITY_MATRIX_I_V, float4(p.xy, 0, 0)).xyz + _WorldSpaceCameraPos;
- }
- }
- struct fxvFogData
- {
- float fogT;
- float fogDist;
- float tNear;
- float tFar;
- float3 pNear;
- float3 pFar;
- float3 debugRGB;
- };
- struct fxvIntersection
- {
- float tNear;
- float tFar;
- float3 pNear;
- float3 pFar;
- float isIntersection;
- };
- struct fxvRay
- {
- float3 rayOrigin;
- float3 rayDir;
- float3 invRayDir;
- };
- float _FXV_FogT_Default(float fogDist, float fogMin, float fogMax)
- {
- return saturate((fogDist - fogMin) / (fogMax - fogMin));
- }
- fxvRay _FXV_GetWSRay(float3 rayOriginWS, float3 rayDirWS)
- {
- fxvRay r = (fxvRay)0;
- r.rayOrigin = rayOriginWS;
- r.rayDir = rayDirWS;
- return r;
- }
- fxvRay _FXV_GetOSRay(float3 rayOriginWS, float3 rayDirWS)
- {
- fxvRay r = (fxvRay)0;
- r.rayOrigin = _FXV_WorldToObjectPos(rayOriginWS);
- r.rayDir = normalize(_FXV_WorldToObjectDir(rayDirWS));
- return r;
- }
- fxvRay _FXV_GetOSRay_I(float3 rayOriginWS, float3 rayDirWS)
- {
- fxvRay r = (fxvRay)0;
- r.rayOrigin = _FXV_WorldToObjectPos(rayOriginWS);
- r.rayDir = normalize(_FXV_WorldToObjectDir(rayDirWS));
- r.invRayDir = 1.0 / r.rayDir;
- return r;
- }
- fxvIntersection _FXV_BoxIntersectionOS_T(fxvRay rayOS)
- {
- fxvIntersection i = (fxvIntersection)0;
- #if defined(FXV_FOG_CUSTOM_MESH)
- float3 boxSizeHalfOS = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalSize).xyz * 0.5;
- float3 boundsOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
- #else
- float3 boxSizeHalfOS = float3(0.5, 0.5, 0.5);
- float3 boundsOffset = float3(0.0, 0.0, 0.0);
- #endif
- float3 tMin = (-boxSizeHalfOS - rayOS.rayOrigin + boundsOffset) * rayOS.invRayDir;
- float3 tMax = (boxSizeHalfOS - rayOS.rayOrigin + boundsOffset) * rayOS.invRayDir;
- float3 t1 = min(tMin, tMax);
- float3 t2 = max(tMin, tMax);
- i.tNear = max(max(max(t1.x, t1.y), t1.z), 0.0);
- i.tFar = min(min(t2.x, t2.y), t2.z);
- i.isIntersection = step(i.tNear, i.tFar);
- return i;
- }
- fxvIntersection _FXV_BoxIntersectionOS_TP(fxvRay rayOS)
- {
- fxvIntersection i = _FXV_BoxIntersectionOS_T(rayOS);
- i.pNear = rayOS.rayOrigin + rayOS.rayDir * i.tNear;
- i.pFar = rayOS.rayOrigin + rayOS.rayDir * i.tFar;
- return i;
- }
- fxvIntersection _FXV_SphereIntersectionWS_T(fxvRay rayWS, float3 spherePosWS, float sphereRadius)
- {
- fxvIntersection i = (fxvIntersection)0;
- // dist to edge inside of sphere calculation
- // https://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/
- float3 p = rayWS.rayOrigin;
- float3 c = spherePosWS;
- float3 vpc = spherePosWS - rayWS.rayOrigin;
- float3 d = rayWS.rayDir;
- float3 pc = -vpc - d * dot(d, -vpc); // projected c onto d
- float3 pcc = pc + c; // the same projected but worldspace
- float pc2 = dot(pc, pc); //squared length
- float pcit = sqrt(sphereRadius * sphereRadius - pc2); //dist from pc to intersection
- float3 pccp = pcc - p; // vector from projected to camera position
- float tp = dot(pccp, d);
- i.tNear = max(0.0, tp - pcit); // dist from p to the near intersection point
- i.tFar = tp + pcit; // dist from p to the far intersection point
- i.isIntersection = step(i.tNear, i.tFar);
- return i;
- }
- fxvIntersection _FXV_SphereIntersectionWS_TP(fxvRay rayWS, float3 spherePosWS, float sphereRadius)
- {
- fxvIntersection i = _FXV_SphereIntersectionWS_T(rayWS, spherePosWS, sphereRadius);
- i.pNear = rayWS.rayOrigin + rayWS.rayDir * i.tNear;
- i.pFar = rayWS.rayOrigin + rayWS.rayDir * i.tFar;
- return i;
- }
- fxvFogData _FXV_ViewAlignedFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to reconstruct position from depth
- float3 depthPoint = viewDirWS * depth;
- float tDepthWS = dot(viewDirNormWS, viewDirWS * depth);
- float3 boxSizeHalfWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
- float tNearWS = 0.0;//dot(viewDirNormWS, worldObjectPos - viewDirOriginWS);
- float3 boxSizeHalfOS = float3(0.5,0.5,0.5);
- float dist = tDepthWS - tNearWS;
- fxvFogData fogData = (fxvFogData)0;
- fogData.tNear = tNearWS;
- #ifdef FXV_IN_AIR_FOG
- fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
- fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
- float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
- float tFarWS = dot(viewDirNormWS, pFarWS - viewDirOriginWS);
- fogData.tFar = tFarWS;
- dist = min(dist, tFarWS - tNearWS);
- #endif
- fogData.fogDist = dist;
- fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
- #ifdef FXV_IN_AIR_FOG
- fogData.fogT *= i.isIntersection;
- fogData.tNear = i.tNear;
- fogData.tFar = i.tFar;
- fogData.pNear = _FXV_ObjectToWorldPos(i.pNear);
- fogData.pFar = pFarWS;
- #endif
- return fogData;
- }
- fxvFogData _FXV_SphericalFog_RayDist(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruc position from depth
- float distToDepth = dot(viewDirNormWS, viewDirWS * depth); //reconstruct position from depth and get it's distance from view origin
- float3 pNear = worldPosition;
- #ifdef FXV_IN_AIR_FOG
- fxvRay rayWS = _FXV_GetWSRay(viewDirOriginWS, viewDirNormWS);
- fxvIntersection i = _FXV_SphereIntersectionWS_TP(rayWS, worldObjectPos, fogMax);
- pNear = i.pNear;
- distToDepth = min(distToDepth, i.tFar); //select what is closer - dist to reconstructed depth, or dist to far intersection with sphere
- #endif
- float fogIntersectionDepth = distToDepth - dot(viewDirNormWS, pNear - viewDirOriginWS); //distance ray is travelling inside fog
- fxvFogData fogData = (fxvFogData)0;
- fogData.fogDist = fogMax - 0.5 * fogIntersectionDepth;
- fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
- fogData.fogT = 1.0 - fogData.fogT;
- #ifdef FXV_IN_AIR_FOG
- fogData.fogT *= i.isIntersection;
- #endif
- #ifdef FXV_IN_AIR_FOG
- fogData.tNear = i.tNear;
- fogData.tFar = i.tFar;
- fogData.pNear = i.pNear;
- fogData.pFar = i.pFar;
- #endif
- return fogData;
- }
- fxvFogData _FXV_SphericalFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruc position from depth
- float distToDepth = dot(viewDirNormWS, viewDirWS * depth); //reconstruct position from depth and get it's distance from view origin
- #ifdef FXV_IN_AIR_FOG
- float airZ;
- if (isOrtho == 1)
- {
- airZ = -_FXV_WorldToViewPos(worldObjectPos).z;
- }
- else
- {
- float3 pointDiff = worldPosition - worldObjectPos;
- float3 camToObj = worldObjectPos - viewDirOriginWS;
- float3 camDirToObj = normalize(camToObj);
- float3 camDirToPoint = normalize(viewDirWS);
- float3 viewPerp = pointDiff - camDirToObj * dot(camDirToObj, pointDiff);
- float3 viewPerpLocal = _FXV_WorldToObjectDir(viewPerp);
- float3 pv = _FXV_ObjectToViewPos(viewPerpLocal);
- float dd = dot(camDirToObj, camDirToPoint);
- airZ = length(pv) * dd * dd;
- }
- distToDepth = min(distToDepth, airZ);
- #endif
- float3 worldspace = viewDirOriginWS + viewDirNormWS * distToDepth;
- float3 diff = worldObjectPos - worldspace;
- float dist = length(diff);
- fxvFogData fogData = (fxvFogData)0;
- fogData.fogDist = dist;
- fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
- fogData.fogT = 1.0 - fogData.fogT;
- return fogData;
- }
- fxvFogData _FXV_BoxFog_RayDist(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- #if defined(FXV_FOG_CUSTOM_MESH)
- float3 boxLocalOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
- worldObjectPos += _FXV_ObjectToWorldDir(boxLocalOffset);
- #endif
- float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruct position from depth
- float3 depthPoint = viewDirWS * depth;
- float tDepth = dot(viewDirNormWS, viewDirWS * depth);
- float tNearWS = dot(viewDirNormWS, worldPosition - viewDirOriginWS); // this will not work if camera view plane is partialy intersecting box
- float dist = tDepth;
- fxvFogData fogData = (fxvFogData)0;
- fogData.tNear = tNearWS;
- #ifdef FXV_IN_AIR_FOG
- fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
- fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
- float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
- float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
- tNearWS = dot(viewDirNormWS, pNearWS - viewDirOriginWS);
- float tFarWS = dot(viewDirNormWS, pFarWS - viewDirOriginWS);
- fogData.tNear = tNearWS;
- fogData.tFar = tFarWS;
- dist = min(dist, tFarWS);
- #endif
- fogData.fogDist = dist - tNearWS;
- fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
- #ifdef FXV_IN_AIR_FOG
- fogData.tNear = i.tNear;
- fogData.tFar = i.tFar;
- fogData.pNear = pNearWS;
- fogData.pFar = pFarWS;
- #endif
- return fogData;
- }
- fxvFogData _FXV_BoxFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- #if defined(FXV_FOG_CUSTOM_MESH)
- float3 boxLocalOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
- worldObjectPos += _FXV_ObjectToWorldDir(boxLocalOffset);
- #endif
- float3 viewDirNormWS = normalize(viewDirWS); // viewDirWS is not normalized to recnstruct position from depth
- float3 depthPoint = viewDirWS * depth;
- float3 worldspaceDepthPoint = viewDirOriginWS + depthPoint;
- float3 localDepthPoint = _FXV_WorldToObjectPos(worldspaceDepthPoint);
- float3 boxSizeWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz;
- float3 boxSizeHalfWS = boxSizeWS * 0.5;
- float minScaling = min(min(boxSizeWS.x, boxSizeWS.y), boxSizeWS.z);
- float maxScaling = max(max(boxSizeWS.x, boxSizeWS.y), boxSizeWS.z);
- float3 scaling = boxSizeWS / maxScaling;
- float3 diffTestDepth = localDepthPoint * boxSizeHalfWS;
- float dist = max(max(abs(diffTestDepth.x), abs(diffTestDepth.y)), abs(diffTestDepth.z));
- #ifdef FXV_IN_AIR_FOG
- fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
- fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
- float tDepth = dot(rayOS.rayDir, localDepthPoint - rayOS.rayOrigin);
- float tLimit = min(i.tFar, tDepth);
- float3 currentPos = i.pNear;
- float stepT = i.tNear;
- float3 diffTest = currentPos;
- float distTest = max(max(abs(diffTest.x), abs(diffTest.y)), abs(diffTest.z));
- for (int s = 0; s < 255; s++)
- {
- float3 diffTestNew = currentPos;
- float distTestNew = max(max(abs(diffTestNew.x), abs(diffTestNew.y)), abs(diffTestNew.z));
- distTest = min(distTestNew, distTest);
- stepT += 1.0/255.0;
- stepT = min(stepT, tLimit);
- currentPos = rayOS.rayOrigin + rayOS.rayDir * stepT;
- }
- dist = distTest;
- #endif
- float fogMin2 = (0.5 - fogMax);
- float fogMax2 = (0.5 - fogMin);
- fxvFogData fogData = (fxvFogData)0;
- fogData.fogDist = dist;
- fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin2, fogMax2);
- fogData.fogT = 1.0 - fogData.fogT;
- #ifdef FXV_IN_AIR_FOG
- float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
- float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
- fogData.tNear = i.tNear;
- fogData.tFar = i.tFar;
- fogData.pNear = pNearWS;
- fogData.pFar = pFarWS;
- #endif
- return fogData;
- }
- fxvFogData _FXV_HeightFog(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho, float3 axis)
- {
- #if defined(FXV_FOG_CUSTOM_MESH)
- float3 boxLocalOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _LocalOffset).xyz;
- worldObjectPos += _FXV_ObjectToWorldDir(boxLocalOffset);
- #endif
- float3 worldspace = viewDirOriginWS + viewDirWS * depth;
- float3 diff = worldObjectPos - worldspace;
- //axis = float3(0, 1, 0);
- float3 worldAxis = normalize(_FXV_ObjectToWorldDir(axis));
- //diff = _FXV_WorldToObjectDir(diff); //rotation support
- float3 boxSizeHalfWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
- float3 boxSizeHalfOS = float3(0.5, 0.5, 0.5);
- float axisBoxSize = abs(dot(axis, boxSizeHalfWS));
- float dist = dot(worldAxis, diff) + axisBoxSize;
- #ifdef FXV_IN_AIR_FOG
- fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
- fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
- float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
- float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
- float3 diff2 = worldObjectPos - pFarWS;
- float dist2 = dot(worldAxis, diff2) + axisBoxSize;
- dist = lerp(dist, dist2, step(0, dot(viewDirWS, worldspace - pFarWS))); //equivalent of if (dot(viewDirWS, worldspace - pFarWS) > 0.0) dist = dist2;
- //pNearWS = worldPosition; //we can use worldPosition instead of calculationg pNear, but not when plane is mid intersecting with box
- float3 diff3 = worldObjectPos - pNearWS;
- float dist3 = dot(worldAxis, diff3) + axisBoxSize;
- dist = max(dist, dist3);
- #endif
- fxvFogData fogData = (fxvFogData)0;
- fogData.fogDist = dist;
- fogData.fogT = _FXV_FogT_Default(fogData.fogDist, fogMin, fogMax);
- #ifdef FXV_IN_AIR_FOG
- float3 pNearVS = _FXV_ObjectToViewPos(i.pNear); //TODO calc only when plane intersection
- i.isIntersection *= step(0, depth + pNearVS.z);
- fogData.fogT *= i.isIntersection;
- fogData.tNear = i.tNear;
- fogData.tFar = i.tFar;
- fogData.pNear = pNearWS;
- fogData.pFar = pFarWS;
- #endif
- return fogData;
- }
- fxvFogData _FXV_InverseSpherical(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- float3 pDepth = viewDirOriginWS + viewDirWS * depth;
- float3 diff = worldObjectPos - pDepth;
- float3 boxSizeHalfWS = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
- float3 boxSizeHalfOS = float3(0.5, 0.5, 0.5);
- float fade = 1.0;
- float dist = length(diff);
- #ifdef FXV_IN_AIR_FOG
- fxvRay rayOS = _FXV_GetOSRay_I(viewDirOriginWS, viewDirWS);
- fxvIntersection i = _FXV_BoxIntersectionOS_TP(rayOS);
- fxvRay rayWS = _FXV_GetWSRay(viewDirOriginWS, normalize(viewDirWS));
- fxvIntersection is = _FXV_SphereIntersectionWS_TP(rayWS, worldObjectPos, fogMax);
- float3 pNearWS = _FXV_ObjectToWorldPos(i.pNear);
- float3 pFarWS = _FXV_ObjectToWorldPos(i.pFar);
- i.tNear = dot(rayWS.rayDir, pNearWS - viewDirOriginWS);
- i.tFar = dot(rayWS.rayDir, pFarWS - viewDirOriginWS);
- float tDepth = dot(rayWS.rayDir, pDepth - viewDirOriginWS);
- 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);
- if (is.isIntersection == 1)
- {
- fade = clamp(max(0.0, (is.tNear - i.tNear)) / 1, 0, 1);
- fade = max(fade, clamp(max(0.0, (min(i.tFar, tDepth) - is.tFar)) / 1, 0, 1));
- }
- #endif
- fxvFogData fogData = (fxvFogData)0;
- fogData.fogDist = dist;
- fogData.fogT = saturate(_FXV_FogT_Default(fogData.fogDist, fogMin, fogMax) + fade);
- #ifdef FXV_IN_AIR_FOG
- fogData.fogT *= i.isIntersection;
- fogData.tNear = i.tNear;
- fogData.tFar = i.tFar;
- fogData.pNear = pNearWS;
- fogData.pFar = pFarWS;
- #endif
- return fogData;
- }
- #define _fxv_PI 3.14159265359
- #define _fxv_HALF_PI 1.57079632679
- #define _fxv_SMOOTH 2.88539 // 2.0 / log(2.0)
- float smoothestStep(float x, float s)
- {
- s *= _fxv_SMOOTH;
- return 1.0 / (1.0 + exp2(tan(x * _fxv_PI - _fxv_HALF_PI) * -s)) + 0.5;
- }
- fxvFogData _FXV_CalcPrimaryFogData(float depth, float inputDepth, float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float3 worldObjectPos, float fogMin, float fogMax, float isOrtho)
- {
- fxvFogData fogData = (fxvFogData)0;
- #ifdef FXV_FOGTYPE_VIEWALIGNED
- fogData = _FXV_ViewAlignedFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- #elif FXV_FOGTYPE_SPHERICALPOS
- fogData = _FXV_SphericalFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- #elif FXV_FOGTYPE_SPHERICALDIST
- fogData = _FXV_SphericalFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- #elif FXV_FOGTYPE_INVERTEDSPHERICAL
- fogData = _FXV_InverseSpherical(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- #elif FXV_FOGTYPE_INVERTEDSPHERICALXHEIGHT
- fogData = _FXV_InverseSpherical(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
- float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
- fxvFogData fogData2 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho, float3(0, 1, 0));
- fogData.fogT = fogData.fogT * fogData2.fogT;
- #elif FXV_FOGTYPE_BOXDIST
- fogData = _FXV_BoxFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- #elif FXV_FOGTYPE_BOXPOS
- fogData = _FXV_BoxFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
-
- #elif FXV_FOGTYPE_BOXEXPERIMENTAL
- fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(1, 0, 0));
- fxvFogData fogData1 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(-1, 0, 0));
- fxvFogData fogData2 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 0, 1));
- fxvFogData fogData3 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 0, -1));
- fxvFogData fogData4 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 1, 0));
- fxvFogData fogData5 = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, -1, 0));
- 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);
- #elif FXV_FOGTYPE_HEIGHT
- fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0,1,0));
- #elif FXV_FOGTYPE_HEIGHTXBOX
- fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 1, 0));
- float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
- float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
- fxvFogData fogData2 = _FXV_BoxFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho);
- fogData.fogT = fogData.fogT * fogData2.fogT;
- #elif FXV_FOGTYPE_HEIGHTXVIEW
- fogData = _FXV_HeightFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho, float3(0, 1, 0));
- float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
- float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
- fxvFogData fogData2 = _FXV_ViewAlignedFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho);
- fogData.fogT = fogData.fogT * fogData2.fogT;
- #elif FXV_FOGTYPE_BOXXVIEW
- fogData = _FXV_BoxFog_RayDist(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- float fogMin2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMin);
- float fogMax2 = UNITY_ACCESS_INSTANCED_PROP(Props, _SecFogMax);
- fxvFogData fogData2 = _FXV_ViewAlignedFog(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin2, fogMax2, isOrtho);
- fogData.fogT = fogData.fogT * fogData2.fogT;
- #endif
- return fogData;
- }
- fxvFogData _FXV_CalcVolumetricFog(float3 worldPosition, float3 viewDirOriginWS, float3 viewDirWS, float inputDepth, float4 screenPos)
- {
- float isOrtho = unity_OrthoParams.w; // 0 - perspective, 1 - ortho
- float fogMin = UNITY_ACCESS_INSTANCED_PROP(Props, _FogMin);
- float fogMax = UNITY_ACCESS_INSTANCED_PROP(Props, _FogMax);
- float z = _FXV_GetRawDepth(screenPos);
- #if FXV_FOG_CLIP_SKYBOX
- if (z <= 0.0)
- discard;
- #endif
- float depth = _FXV_GetLinearEyeDepth(z);
- #if FXV_FOG_CLIP_BOUNDS
- float3 pDepth = viewDirOriginWS + viewDirWS * depth;
- float3 localDepthPoint = _FXV_WorldToObjectPos(pDepth);
- #if FXV_FOGTYPE_SPHERICALPOS ||FXV_FOGTYPE_SPHERICALDIST
- clip(0.5 - length(localDepthPoint));
- #else
- clip(float3(0.5, 0.5, 0.5) - abs(localDepthPoint));
- #endif
- #endif
- float3 worldObjectPos = _FXV_ObjectToWorldPos(float3(0,0,0));
- fxvFogData fogData = _FXV_CalcPrimaryFogData(depth, inputDepth, worldPosition, viewDirOriginWS, viewDirWS, worldObjectPos, fogMin, fogMax, isOrtho);
- float falloff = UNITY_ACCESS_INSTANCED_PROP(Props, _FogFalloff);
- #ifdef FXV_SMOOTHED_FALLOFF
- fogData.fogT = smoothstep(0.0, 1.0, fogData.fogT);
- #elif FXV_EXP_FALLOFF
- fogData.fogT = exp(fogData.fogT) - 1.0;
- #elif FXV_EXP2_FALLOFF
- fogData.fogT = exp2(fogData.fogT) - 1.0;
- #endif
- fogData.fogT = pow(fogData.fogT, falloff);
- return fogData;
- }
- struct fxvLightingData
- {
- float3 objectPositionWS;
- float3 pixelPositionWS;
- float4 lightPositionWS;
- float3 lightDirectionWS;
- float3 lightColor;
- float3 viewDirectionOriginWS;
- float3 viewDirectionWS;
- float3 normalWS;
- float2 lightRangeAttenuation; // x - oneOverLightRangeSqr (oneOverFadeRangeSqr on mobile/switch), y - lightRangeSqrOverFadeRangeSqr, linear fade start at 80% light range
- float3 albedo;
- float alpha;
- };
- float3 _FXV_FogLightingFunction(fxvLightingData fxvData, fxvFogData fogData)
- {
- float4 c;
- float NdotL = 1.0;
- half fogMax = UNITY_ACCESS_INSTANCED_PROP(Props, _FogMax);
- half _scatteringFactor = UNITY_ACCESS_INSTANCED_PROP(Props, _LightScatteringFactor);
- half _invScatteringFactor = 1.0 / _scatteringFactor;
- half _lightReflectivity = UNITY_ACCESS_INSTANCED_PROP(Props, _LightReflectivity);
- half _lightTransmission = UNITY_ACCESS_INSTANCED_PROP(Props, _LightTransmission);
- float3 L = fxvData.lightDirectionWS;
- float3 V = fxvData.viewDirectionWS;
- //float3 N = fxvData.normalWS;
- float invLightRangeSqr = fxvData.lightRangeAttenuation.x;
- float rangeFade = 1.0;
- float lightAtten = 1.0;
- if (fxvData.lightPositionWS.w == 1)
- {
- float3 viewPoint = fxvData.viewDirectionOriginWS - V * length(fxvData.lightPositionWS.xyz - fxvData.viewDirectionOriginWS);
- //float3 viewPoint = _WorldSpaceCameraPos.xyz + V * dot(fxvData.lightPositionWS.xyz - _WorldSpaceCameraPos.xyz, V);//length(fxvData.lightPositionWS.xyz - _WorldSpaceCameraPos.xyz);
- float3 diffToLight = (viewPoint - fxvData.lightPositionWS.xyz);
- float distToViewPointSqr = dot(diffToLight, diffToLight);
- float factor = distToViewPointSqr * invLightRangeSqr;
- rangeFade = saturate(1.0 - factor);
- float3 pixelPosWS = fxvData.pixelPositionWS;
- #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
- #if FXV_IN_AIR_FOG
- pixelPosWS = fogData.pNear;
- #endif
- #endif
- diffToLight = (pixelPosWS - fxvData.lightPositionWS.xyz);
- float distanceSqr = dot(diffToLight, diffToLight);
- #if FXV_FOGTYPE_SPHERICAL
- factor = distanceSqr * invLightRangeSqr; //TODO handle SHADER_HINT_NICE_QUALITY and mobile as DistanceAttenuation RealtimeLights.hlsl
- #else
- float side = dot(V, normalize(diffToLight));
- factor = lerp(distanceSqr, distToViewPointSqr, side) * invLightRangeSqr; //TODO handle SHADER_HINT_NICE_QUALITY and mobile as DistanceAttenuation RealtimeLights.hlsl
- #endif
- float attenuationFade = saturate(1.0 - factor);
- lightAtten = pow(attenuationFade, _invScatteringFactor * _invScatteringFactor);
- #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
- #if FXV_IN_AIR_FOG
- 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
- #endif
- #endif
- }
- else
- {
- rangeFade = saturate(dot(fxvData.lightDirectionWS, float3(0,1,0)));
- }
- c.rgb = fxvData.albedo * fxvData.lightColor.rgb * lightAtten * rangeFade * lerp(fxvData.alpha * min(1.0, _lightReflectivity * 2.0), 1, _lightReflectivity);
- float powFactor = (_invScatteringFactor);
- float VdotH = pow(saturate(dot(V, -L)), powFactor * powFactor);
- /*
- #if FXV_FOGTYPE_SPHERICAL
- diffToLight = (fxvData.objectPositionWS - fxvData.lightPositionWS.xyz);
- float l = length(diffToLight);
- diffToLight = (diffToLight / l) * (max(0.0, l-fogMax));
- factor = dot(diffToLight, diffToLight) * invLightRangeSqr;
- #else
- float3 boxSizeHalf = UNITY_ACCESS_INSTANCED_PROP(Props, _WorldSize).xyz * 0.5;
- diffToLight = (fxvData.objectPositionWS - fxvData.lightPositionWS.xyz);
- float dist = max(max(abs(diffToLight.x) - boxSizeHalf.x, abs(diffToLight.y) - boxSizeHalf.y), abs(diffToLight.z) - boxSizeHalf.z);
- factor = dist * dist * invLightRangeSqr;
- #endif
- float rangeFade3 = saturate(1.0 - factor);
- */
- c.rgb += ((fxvData.albedo * fxvData.lightColor.rgb * VdotH)) * rangeFade * lerp(fxvData.alpha * min(1.0, _lightTransmission * 2.0), 1, _lightTransmission); // * rangeFade3
- return c.rgb;
- }
- #endif
|