VolumetricLightBeamShared.cginc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. // The following comment prevents Unity from auto upgrading the shader. Please keep it to keep backward compatibility
  2. // UNITY_SHADER_NO_UPGRADE
  3. #ifndef _VOLUMETRIC_LIGHT_BEAM_SHARED_INCLUDED_
  4. #define _VOLUMETRIC_LIGHT_BEAM_SHARED_INCLUDED_
  5. /// ****************************************
  6. /// SHADER INPUT / OUTPUT STRUCT
  7. /// ****************************************
  8. struct vlb_appdata
  9. {
  10. float4 vertex : POSITION;
  11. float4 texcoord : TEXCOORD0;
  12. #if VLB_INSTANCING_API_AVAILABLE && (VLB_STEREO_INSTANCING || VLB_GPU_INSTANCING)
  13. UNITY_VERTEX_INPUT_INSTANCE_ID // for GPU Instancing and Single Pass Instanced rendering
  14. #endif
  15. };
  16. struct v2f
  17. {
  18. float4 posClipSpace : SV_POSITION;
  19. float3 posObjectSpace : TEXCOORD0;
  20. float3 posObjectSpaceNonSkewed : TEXCOORD8;
  21. float4 posWorldSpace : TEXCOORD1;
  22. float4 posViewSpace_extraData : TEXCOORD2;
  23. float4 cameraPosObjectSpace_outsideBeam : TEXCOORD3;
  24. #if OPTIM_VS
  25. half4 color : TEXCOORD4;
  26. #endif
  27. #if VLB_NOISE_3D || OPTIM_VS
  28. float4 uvwNoise_intensity : TEXCOORD5;
  29. #endif
  30. #if VLB_DEPTH_BLEND || VLB_DITHERING
  31. float4 projPos : TEXCOORD6;
  32. #endif
  33. #ifdef VLB_FOG_UNITY_BUILTIN_COORDS
  34. UNITY_FOG_COORDS(7)
  35. #endif
  36. #if VLB_INSTANCING_API_AVAILABLE
  37. #if VLB_GPU_INSTANCING
  38. UNITY_VERTEX_INPUT_INSTANCE_ID // not sure this one is useful
  39. #endif
  40. #if VLB_STEREO_INSTANCING
  41. UNITY_VERTEX_OUTPUT_STEREO // for Single Pass Instanced rendering
  42. #endif
  43. #endif // VLB_INSTANCING_API_AVAILABLE
  44. };
  45. #include "ShaderUtils.cginc"
  46. inline float ComputeBoostFactor(float pixDistFromSource, float outsideBeam, float isCap)
  47. {
  48. pixDistFromSource = max(pixDistFromSource, 0.001); // prevent 1st segment from being boosted when boostFactor is 0
  49. float glareFrontal = VLB_GET_PROP(_GlareFrontal);
  50. float insideBoostDistance = glareFrontal * VLB_GET_PROP(_DistanceFallOff).y;
  51. float boostFactor = 1 - smoothstep(0, 0 + insideBoostDistance + 0.001, pixDistFromSource); // 0 = no boost ; 1 = max boost
  52. boostFactor = lerp(boostFactor, 0, outsideBeam); // no boost for outside pass
  53. float4 cameraParams = VLB_GET_PROP(_CameraParams);
  54. float cameraIsInsideBeamFactor = saturate(cameraParams.w); // _CameraParams.w is (-1 ; 1)
  55. boostFactor = cameraIsInsideBeamFactor * boostFactor; // no boost for outside pass
  56. boostFactor = lerp(boostFactor, 1, isCap); // cap is always at max boost
  57. return boostFactor;
  58. }
  59. // boostFactor is normalized
  60. float ComputeFresnel(float3 posObjectSpace, float3 vecCamToPixOSN, float outsideBeam, float boostFactor)
  61. {
  62. // Compute normal
  63. float2 cosSinFlat = normalize(posObjectSpace.xy);
  64. float2 coneSlopeCosSin = VLB_GET_PROP(_ConeSlopeCosSin);
  65. float3 normalObjectSpace = (float3(cosSinFlat.x * coneSlopeCosSin.x, cosSinFlat.y * coneSlopeCosSin.x, -coneSlopeCosSin.y));
  66. normalObjectSpace *= (outsideBeam * 2 - 1); // = outsideBeam ? 1 : -1;
  67. // real fresnel factor
  68. float fresnelReal = dot(normalObjectSpace, -vecCamToPixOSN);
  69. // compute a fresnel factor to support long beams by projecting the viewDir vector
  70. // on the virtual plane formed by the normal and tangent
  71. float coneApexOffsetZ = VLB_GET_PROP(_ConeApexOffsetZ);
  72. float3 tangentPlaneNormal = normalize(posObjectSpace.xyz + float3(0, 0, coneApexOffsetZ));
  73. float distToPlane = dot(-vecCamToPixOSN, tangentPlaneNormal);
  74. float3 vec2D = normalize(-vecCamToPixOSN - distToPlane * tangentPlaneNormal);
  75. float fresnelProjOnTangentPlane = dot(normalObjectSpace, vec2D);
  76. // blend between the 2 fresnels
  77. float3 localForwardDirN = VLB_GET_PROP(_LocalForwardDirection);
  78. float vecCamToPixDotZ = dot(vecCamToPixOSN, localForwardDirN);
  79. float factorNearAxisZ = abs(vecCamToPixDotZ); // factorNearAxisZ is normalized
  80. float fresnel = lerp(fresnelProjOnTangentPlane, fresnelReal, factorNearAxisZ);
  81. float fresnelPow = VLB_GET_PROP(_FresnelPow);
  82. // Lerp the fresnel pow to the glare factor according to how far we are from the axis Z
  83. const float kMaxGlarePow = 1.5;
  84. float glareFrontal = VLB_GET_PROP(_GlareFrontal);
  85. float glareBehind = VLB_GET_PROP(_GlareBehind);
  86. float glareFactor = kMaxGlarePow * (1 - lerp(glareFrontal, glareBehind, outsideBeam));
  87. fresnelPow = lerp(fresnelPow, min(fresnelPow, glareFactor), factorNearAxisZ);
  88. // Pow the fresnel
  89. fresnel = smoothstep(0, 1, fresnel);
  90. fresnel = (1 - isEqualOrGreater(-fresnel, 0)) * // fix edges artefacts on android ES2
  91. (pow(fresnel, fresnelPow));
  92. // Boost distance inside
  93. float boostFresnel = lerp(fresnel, 1 + 0.001, boostFactor);
  94. fresnel = lerp(boostFresnel, fresnel, outsideBeam); // no boosted fresnel if outside
  95. // We do not have to treat cap a special way, since boostFactor is already set to 1 for cap via ComputeBoostFactor
  96. return fresnel;
  97. }
  98. inline float ComputeFadeWithCamera(float3 posViewSpace, float enabled)
  99. {
  100. float distCamToPixWS = abs(posViewSpace.z); // only check Z axis (instead of length(posViewSpace.xyz)) to have smoother transition with near plane (which is not curved)
  101. float camFadeDistStart = _ProjectionParams.y; // cam near place
  102. float camFadeDistEnd = camFadeDistStart + VLB_GET_PROP(_DistanceCamClipping);
  103. float fadeWhenTooClose = smoothstep(0, 1, invLerpClamped(camFadeDistStart, camFadeDistEnd, distCamToPixWS));
  104. // fade out according to camera's near plane
  105. return lerp(1, fadeWhenTooClose, enabled);
  106. }
  107. half4 ComputeColor(float pixDistFromSource, float outsideBeam)
  108. {
  109. #if VLB_COLOR_GRADIENT_MATRIX_HIGH || VLB_COLOR_GRADIENT_MATRIX_LOW
  110. float distanceFadeEnd = VLB_GET_PROP(_DistanceFallOff).y;
  111. float4x4 colorGradientMatrix = VLB_GET_PROP(_ColorGradientMatrix);
  112. float distFromSourceNormalized = invLerpClamped(0, distanceFadeEnd, pixDistFromSource);
  113. half4 color = DecodeGradient(distFromSourceNormalized, colorGradientMatrix);
  114. #else
  115. half4 color = VLB_GET_PROP(_ColorFlat);
  116. #endif
  117. half alphaInside = VLB_GET_PROP(_AlphaInside);
  118. half alphaOutside = VLB_GET_PROP(_AlphaOutside);
  119. half alpha = lerp(alphaInside, alphaOutside, outsideBeam);
  120. #if VLB_ALPHA_AS_BLACK
  121. color.rgb *= color.a;
  122. color.rgb *= alpha;
  123. #else
  124. color.a *= alpha;
  125. #endif
  126. return color;
  127. }
  128. inline float ComputeInOutBlending(float vecCamToPixDotZ, float outsideBeam)
  129. {
  130. // smooth blend between inside and outside geometry depending of View Direction
  131. const float kFaceLightSmoothingLimit = 1;
  132. float factorFaceLightSourcePerPixN = saturate(smoothstep(kFaceLightSmoothingLimit, -kFaceLightSmoothingLimit, vecCamToPixDotZ)); // smoother transition
  133. return lerp(factorFaceLightSourcePerPixN, 1 - factorFaceLightSourcePerPixN, outsideBeam);
  134. }
  135. #if VLB_MESH_SKEWING
  136. inline float4 SkewVectorOS(float4 vec, float3 scaleObjectSpace)
  137. {
  138. float3 localForwardDirN = VLB_GET_PROP(_LocalForwardDirection);
  139. vec.xy += vec.z * localForwardDirN.xy * scaleObjectSpace.z / (scaleObjectSpace.xy * localForwardDirN.z);
  140. return vec;
  141. }
  142. inline float3 UnskewVectorOS(float3 vec)
  143. {
  144. float3 localForwardDirN = VLB_GET_PROP(_LocalForwardDirection);
  145. vec.xy -= localForwardDirN.xy * (vec.z / localForwardDirN.z);
  146. return vec;
  147. }
  148. #endif // VLB_MESH_SKEWING
  149. // Vector Camera to current Pixel, in object space and normalized
  150. inline float3 ComputeVectorCamToPixOSN(float3 pixPosOS, float3 cameraPosOS)
  151. {
  152. float3 vecCamToPixOSN = normalize(pixPosOS - cameraPosOS);
  153. // Deal with ortho camera:
  154. // With ortho camera, we don't want to change the fresnel according to camera position.
  155. // So instead of computing the proper vector "Camera to Pixel", we take account of the "Camera Forward" vector (which is not dependant on the pixel position)
  156. float4 cameraParams = VLB_GET_PROP(_CameraParams);
  157. float3 vecCamForwardOSN = cameraParams.xyz;
  158. #if VLB_MESH_SKEWING
  159. vecCamForwardOSN = normalize(UnskewVectorOS(vecCamForwardOSN));
  160. #endif // VLB_MESH_SKEWING
  161. return lerp(vecCamToPixOSN, vecCamForwardOSN, VLB_CAMERA_ORTHO);
  162. }
  163. inline float GetTiltDistanceFactor(float3 posObjectSpace)
  164. {
  165. float2 tiltVector = VLB_GET_PROP(_TiltVector);
  166. float pixDistFromSource = abs(posObjectSpace.z);
  167. return pixDistFromSource + posObjectSpace.x * tiltVector.x + posObjectSpace.y * tiltVector.y;
  168. }
  169. v2f vertShared(vlb_appdata v, float outsideBeam)
  170. {
  171. v2f o;
  172. #if VLB_INSTANCING_API_AVAILABLE && (VLB_STEREO_INSTANCING || VLB_GPU_INSTANCING)
  173. UNITY_SETUP_INSTANCE_ID(v);
  174. #if VLB_STEREO_INSTANCING
  175. #ifndef VLB_SRP_API // TODO CHECK THAT WE DON'T NEED THIS WITH SRP
  176. UNITY_INITIALIZE_OUTPUT(v2f, o);
  177. #endif
  178. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  179. #endif
  180. #if VLB_GPU_INSTANCING
  181. UNITY_TRANSFER_INSTANCE_ID(v, o);
  182. #endif
  183. #endif
  184. #if VLB_NOISE_3D || OPTIM_VS
  185. o.uvwNoise_intensity = 1;
  186. #endif
  187. // compute the proper cone shape, so the whole beam fits into a 2x2x1 box
  188. // The model matrix (computed via the localScale from BeamGeometry.)
  189. float4 vertexOS = v.vertex;
  190. vertexOS.z *= vertexOS.z; // make segment tessellation denser near the source, since beam is usually more visible at start
  191. float2 coneRadius = VLB_GET_PROP(_ConeRadius);
  192. float maxRadius = max(coneRadius.x, coneRadius.y);
  193. float normalizedRadiusStart = coneRadius.x / maxRadius;
  194. float normalizedRadiusEnd = coneRadius.y / maxRadius;
  195. vertexOS.xy *= lerp(normalizedRadiusStart, normalizedRadiusEnd, vertexOS.z);
  196. float3 scaleObjectSpace = float3(maxRadius, maxRadius, VLB_GET_PROP(_DistanceFallOff).z); // maxGeometryDistance
  197. o.posObjectSpaceNonSkewed = vertexOS.xyz * scaleObjectSpace;
  198. #if VLB_MESH_SKEWING
  199. // skew the real vertex position
  200. vertexOS = SkewVectorOS(vertexOS, scaleObjectSpace);
  201. #endif
  202. o.posWorldSpace = VLBObjectToWorldPos(vertexOS);
  203. o.posClipSpace = VLBObjectToClipPos(vertexOS.xyz);
  204. // TODO Should create and use VLBWorldToClipPos instead
  205. //o.posClipSpace = VLBWorldToClipPos(o.posWorldSpace.xyz);
  206. #if defined(VLBWorldToViewPos)
  207. float3 posViewSpace = VLBWorldToViewPos(o.posWorldSpace.xyz);
  208. #elif defined(VLBObjectToViewPos)
  209. float3 posViewSpace = VLBObjectToViewPos(vertexOS);
  210. #else
  211. You_should_define_either_VLBWorldToViewPos_or_VLBObjectToViewPos
  212. #endif
  213. // apply the same scaling than we do through the localScale in BeamGeometry.ComputeLocalMatrix
  214. // to get the proper transformed vertex position in object space
  215. o.posObjectSpace = vertexOS.xyz * scaleObjectSpace;
  216. #if VLB_DEPTH_BLEND || VLB_DITHERING
  217. o.projPos = DepthFade_VS_ComputeProjPos(posViewSpace, o.posClipSpace);
  218. #endif
  219. float isCap = v.texcoord.x;
  220. #if VLB_NOISE_3D
  221. o.uvwNoise_intensity.rgb = Noise3D_GetUVW(o.posWorldSpace.xyz, o.posObjectSpace);
  222. #endif
  223. float3 cameraPosObjectSpace = VLBGetCameraPositionObjectSpace(scaleObjectSpace);
  224. #if VLB_MESH_SKEWING
  225. cameraPosObjectSpace = UnskewVectorOS(cameraPosObjectSpace); // unskew the camera position of object space
  226. #endif // VLB_MESH_SKEWING
  227. o.cameraPosObjectSpace_outsideBeam = float4(
  228. cameraPosObjectSpace,
  229. outsideBeam);
  230. #if OPTIM_VS
  231. // Treat Cap a special way: cap is only visible from inside
  232. float intensity = 1 - outsideBeam * isCap; // AKA if (outsideBeam == 1 && isCap == 1) intensity = 0
  233. float pixDistFromSource = length(o.posObjectSpace.z);
  234. float pixDistFromSourceTilted = GetTiltDistanceFactor(o.posObjectSpace);
  235. float3 distancesFallOff = VLB_GET_PROP(_DistanceFallOff);
  236. float attenuationLerpLinearQuad = VLB_GET_PROP(_AttenuationLerpLinearQuad);
  237. intensity *= ComputeAttenuation(pixDistFromSourceTilted, distancesFallOff.x, distancesFallOff.y, attenuationLerpLinearQuad);
  238. float boostFactor = ComputeBoostFactor(pixDistFromSource, outsideBeam, isCap);
  239. // Vector Camera to current Pixel, in object space and normalized
  240. float3 vecCamToPixOSN = ComputeVectorCamToPixOSN(o.posObjectSpaceNonSkewed.xyz, cameraPosObjectSpace);
  241. float vecCamToPixDotZ = dot(vecCamToPixOSN, float3(0, 0, 1));
  242. #if OPTIM_VS_FRESNEL_VS
  243. // Pass data needed to compute fresnel in fragment shader
  244. // Computing fresnel on vertex shader give imprecise results
  245. intensity *= ComputeFresnel(o.posObjectSpaceNonSkewed, vecCamToPixOSN, outsideBeam, boostFactor);
  246. #endif
  247. // fade out
  248. intensity *= VLB_GET_PROP(_FadeOutFactor);
  249. // smooth blend between inside and outside geometry depending of View Direction
  250. intensity *= ComputeInOutBlending(vecCamToPixDotZ, outsideBeam);
  251. // no intensity for cap if _DrawCap = 0
  252. float drawCap = VLB_GET_PROP(_DrawCap);
  253. intensity *= isEqualOrGreater(drawCap, isCap);
  254. o.uvwNoise_intensity.a = intensity;
  255. o.color = ComputeColor(pixDistFromSourceTilted, outsideBeam);
  256. float extraData = boostFactor;
  257. #else
  258. float extraData = isCap;
  259. #endif // OPTIM_VS
  260. o.posViewSpace_extraData = float4(posViewSpace, extraData);
  261. #ifdef VLB_FOG_UNITY_BUILTIN_COORDS
  262. UNITY_TRANSFER_FOG(o, o.posClipSpace);
  263. #endif
  264. return o;
  265. }
  266. half4 fragShared(v2f i, float outsideBeam)
  267. {
  268. #if VLB_INSTANCING_API_AVAILABLE && VLB_GPU_INSTANCING
  269. UNITY_SETUP_INSTANCE_ID(i);
  270. #endif
  271. #if VLB_INSTANCING_API_AVAILABLE && VLB_STEREO_INSTANCING
  272. // This fix access to depth map on the right eye when using single pass (aka Stereo Rendering Mode Multiview) on Gear VR or Oculus Go/Quest
  273. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i); // https://docs.unity3d.com/Manual/SinglePassInstancing.html
  274. #endif
  275. {
  276. float4 cameraParams = VLB_GET_PROP(_CameraParams);
  277. float cameraIsInsideBeamFactor = saturate(cameraParams.w); // _CameraParams.w is (-1 ; 1)
  278. }
  279. #if OPTIM_VS
  280. float intensity = i.uvwNoise_intensity.a;
  281. #else
  282. float intensity = 1;
  283. #endif
  284. float pixDistFromSource = length(i.posObjectSpace.z);
  285. // additional clipping plane
  286. {
  287. float4 addClippingPlaneWS = VLB_GET_PROP(_AdditionalClippingPlaneWS);
  288. clip(DistanceToPlane(i.posWorldSpace.xyz, addClippingPlaneWS.xyz, addClippingPlaneWS.w));
  289. }
  290. // DYNAMIC OCCLUSION
  291. #if VLB_OCCLUSION_CLIPPING_PLANE
  292. {
  293. float4 clippingPlaneWS = VLB_GET_PROP(_DynamicOcclusionClippingPlaneWS);
  294. float distToClipPlane = DistanceToPlane(i.posWorldSpace.xyz, clippingPlaneWS.xyz, clippingPlaneWS.w);
  295. clip(distToClipPlane);
  296. float fadeDistance = VLB_GET_PROP(_DynamicOcclusionClippingPlaneProps);
  297. intensity *= smoothstep(0, fadeDistance, distToClipPlane);
  298. }
  299. #elif VLB_OCCLUSION_DEPTH_TEXTURE
  300. {
  301. #if VLB_GPU_INSTANCING
  302. // Dynamic Occlusion Depth Texture is not supported with GPU Instancing because instanced cbuffers cannot hold samplers
  303. return float4(1, 0, 0, 1);
  304. #endif
  305. const float kMinNearClipPlane = 0.1f; // should be the same than in DynamicOcclusion.cs
  306. float apexDist = VLB_GET_PROP(_ConeApexOffsetZ);
  307. float2 uv = normalize(i.posObjectSpace.xy) * 0.5 + 0.5;
  308. float dynamicOcclusionDepthRaw = tex2D(_DynamicOcclusionDepthTexture, uv).r;
  309. #if defined(UNITY_REVERSED_Z)
  310. dynamicOcclusionDepthRaw = 1.0f - dynamicOcclusionDepthRaw;
  311. #endif
  312. float fallOffEnd = VLB_GET_PROP(_DistanceFallOff).z; // maxGeometryDistance
  313. float near = max(apexDist, kMinNearClipPlane);
  314. float far = near + fallOffEnd;
  315. float dynamicOcclusionDepthLinear = VLB_ZBufferToLinear(dynamicOcclusionDepthRaw, near, far);
  316. dynamicOcclusionDepthLinear -= apexDist;
  317. float fadeDistance = VLB_GET_PROP(_DynamicOcclusionDepthProps);
  318. float factor = smoothstep(0, fadeDistance, dynamicOcclusionDepthLinear - pixDistFromSource);
  319. intensity *= lerp(factor, 1, isEqualOrGreater(dynamicOcclusionDepthRaw, 1)); // only apply factor if(dynamicOcclusionDepthRaw < 1), meaning there is an occlusion
  320. }
  321. #endif
  322. #if DEBUG_SHOW_NOISE3D
  323. return Noise3D_GetFactorFromUVW(i.uvwNoise_intensity.xyz);
  324. #endif
  325. float3 cameraPosObjectSpace = i.cameraPosObjectSpace_outsideBeam.xyz;
  326. // Vector Camera to current Pixel, in object space and normalized
  327. float3 vecCamToPixOSN = ComputeVectorCamToPixOSN(i.posObjectSpaceNonSkewed.xyz, cameraPosObjectSpace);
  328. #if VLB_NOISE_3D || !OPTIM_VS
  329. // Blend inside and outside
  330. float vecCamToPixDotZ = dot(vecCamToPixOSN, float3(0, 0, 1));
  331. float factorNearAxisZ = abs(vecCamToPixDotZ);
  332. #endif
  333. // 3D NOISE
  334. #if VLB_NOISE_3D
  335. {
  336. float noise3DFactor = Noise3D_GetFactorFromUVW(i.uvwNoise_intensity.rgb);
  337. // disable noise 3D when looking from behind or from inside because it makes the cone shape too much visible
  338. noise3DFactor = lerp(noise3DFactor, 1, pow(factorNearAxisZ, 10));
  339. intensity *= noise3DFactor;
  340. }
  341. #endif // VLB_NOISE_3D
  342. // DEPTH BLEND
  343. #if VLB_DEPTH_BLEND
  344. {
  345. float depthBlendDistance = VLB_GET_PROP(_DepthBlendDistance);
  346. #if FIX_DISABLE_DEPTH_BLEND_WITH_OBLIQUE_PROJ
  347. // disable depth sampling with oblique projection
  348. float3 nearPlaneWS = VLBFrustumPlanes[4].xyz;
  349. float3 farPlaneWS = VLBFrustumPlanes[5].xyz;
  350. float dotNearFar = abs(dot(nearPlaneWS, farPlaneWS)); // abs needed on 5.2, but not needed on 2018
  351. depthBlendDistance *= isEqualOrGreater(dotNearFar, 0.99);
  352. #endif // FIX_DISABLE_DEPTH_BLEND_WITH_OBLIQUE_PROJ
  353. // we disable blend factor when the pixel is near the light source,
  354. // to prevent from blending with the light source model geometry (like the flashlight model).
  355. float depthBlendStartDistFromSource = depthBlendDistance;
  356. float pixDistFromSourceNormalized = invLerpClamped(0, depthBlendStartDistFromSource, pixDistFromSource);
  357. float depthBlendDist = depthBlendDistance * pixDistFromSourceNormalized;
  358. float depthBlendFactor = DepthFade_PS_BlendDistance(i.projPos, depthBlendDist);
  359. depthBlendFactor = lerp(depthBlendFactor, 1, isEqualOrGreater(0, depthBlendDistance));
  360. depthBlendFactor = lerpClamped(1, depthBlendFactor, pixDistFromSourceNormalized * 100); // prevent artifacts when cap geometry is too close from some geometry
  361. intensity *= depthBlendFactor;
  362. #if DEBUG_DEPTH_MODE == DEBUG_VALUE_DEPTHBUFFER
  363. return SampleSceneZ_Eye(i.projPos) * _ProjectionParams.w;
  364. #elif DEBUG_DEPTH_MODE == DEBUG_VALUE_DEPTHSTEREOEYE
  365. float depthValue = SampleSceneZ_Eye(i.projPos) * _ProjectionParams.w;
  366. #if defined(USING_STEREO_MATRICES) && defined(UNITY_STEREO_MULTIVIEW_ENABLED) // used with single pass / multiview on android VR (Oculus Go/Quest, Gear VR)
  367. return depthValue * lerp(float4(1, 0, 0, 1), float4(0, 1, 0, 1), unity_StereoEyeIndex);
  368. #elif defined(UNITY_SINGLE_PASS_STEREO)
  369. return depthValue * lerp(float4(1, 0, 0, 1), float4(0, 0, 1, 1), unity_StereoEyeIndex);
  370. #elif defined(UNITY_STEREO_INSTANCING_ENABLED)
  371. return depthValue * lerp(float4(0, 1, 0, 1), float4(0, 0, 1, 1), unity_StereoEyeIndex);
  372. #elif defined(UNITY_STEREO_MULTIVIEW_ENABLED)
  373. return depthValue * lerp(float4(1, 1, 0, 1), float4(0, 1, 1, 1), unity_StereoEyeIndex);
  374. #else
  375. return depthValue;
  376. #endif
  377. #elif DEBUG_DEPTH_MODE == DEBUG_VALUE_DEPTHBLEND
  378. return depthBlendFactor;
  379. #endif
  380. }
  381. #endif // VLB_DEPTH_BLEND
  382. float3 posViewSpace = i.posViewSpace_extraData.xyz;
  383. #if !OPTIM_VS
  384. float pixDistFromSourceTilted = GetTiltDistanceFactor(i.posObjectSpace);
  385. {
  386. float isCap = i.posViewSpace_extraData.w;
  387. // no intensity for cap if _DrawCap = 0
  388. intensity *= isEqualOrGreater(VLB_GET_PROP(_DrawCap), isCap - 0.00001);
  389. // Treat Cap a special way: cap is only visible from inside
  390. intensity *= 1 - outsideBeam * isCap; // AKA if (outsideBeam == 1 && isCap == 1) intensity = 0
  391. // boost factor
  392. float boostFactor = ComputeBoostFactor(pixDistFromSource, outsideBeam, isCap);
  393. // fresnel
  394. intensity *= ComputeFresnel(i.posObjectSpaceNonSkewed, vecCamToPixOSN, outsideBeam, boostFactor);
  395. // fade out
  396. intensity *= VLB_GET_PROP(_FadeOutFactor);
  397. // attenuation
  398. float3 distancesFallOff = VLB_GET_PROP(_DistanceFallOff);
  399. intensity *= ComputeAttenuation(pixDistFromSourceTilted, distancesFallOff.x, distancesFallOff.y, VLB_GET_PROP(_AttenuationLerpLinearQuad));
  400. // smooth blend between inside and outside geometry depending of View Direction
  401. intensity *= ComputeInOutBlending(vecCamToPixDotZ, outsideBeam);
  402. }
  403. #elif !OPTIM_VS_FRESNEL_VS // && OPTIM_VS
  404. {
  405. float boostFactor = i.posViewSpace_extraData.w;
  406. // compute fresnel in fragment shader to keep good quality even with low tessellation
  407. intensity *= ComputeFresnel(i.posObjectSpaceNonSkewed, vecCamToPixOSN, outsideBeam, boostFactor);
  408. }
  409. #endif // !OPTIM_VS_FRESNEL_VS && OPTIM_VS
  410. // fade when too close to camera factor
  411. {
  412. float fadeWithCameraEnabled = 1 - VLB_CAMERA_ORTHO; // fading according to camera eye position doesn't make sense with ortho camera
  413. intensity *= ComputeFadeWithCamera(posViewSpace, fadeWithCameraEnabled);
  414. }
  415. #if DEBUG_BLEND_INSIDE_OUTSIDE
  416. float DBGvecCamToPixDotZ = dot(vecCamToPixOSN, float3(0, 0, 1));
  417. return lerp(float4(1, 0, 0, 1), float4(0, 1, 0, 1), ComputeInOutBlending(DBGvecCamToPixDotZ, outsideBeam));
  418. #endif // DEBUG_BLEND_INSIDE_OUTSIDE
  419. // Do not fill color.rgb only, because of performance drops on android
  420. #if !OPTIM_VS
  421. half4 color = ComputeColor(pixDistFromSourceTilted, outsideBeam);
  422. #else
  423. half4 color = i.color;
  424. #endif
  425. #if VLB_DITHERING
  426. float2 screenPos = i.projPos.xy / i.projPos.w;
  427. float2 ditherCoord = screenPos * _ScreenParams.xy * _VLB_DitheringNoiseTex_TexelSize.xy;
  428. float dither = tex2D(_VLB_DitheringNoiseTex, ditherCoord).r - 0.5;
  429. color += (1 - saturate(intensity)) * _VLB_DitheringFactor * dither;
  430. #endif
  431. #if VLB_ALPHA_AS_BLACK
  432. color *= intensity;
  433. #else
  434. color.a *= intensity;
  435. #endif
  436. #ifdef VLB_FOG_APPLY
  437. VLB_FOG_APPLY(color);
  438. #endif
  439. return color;
  440. }
  441. #endif