Lux URP Particles Simple Lit Forward Pass.hlsl 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. #ifndef LUXLWRP_SIMPLE_LIT_PASS_INCLUDED
  2. #define LUXLWRP_SIMPLE_LIT_PASS_INCLUDED
  3. #if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  4. #define ADDITIONAL_LIGHT_CALCULATE_SHADOWS
  5. #endif
  6. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  7. // Not needed here - and errors on M1?
  8. //#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Particles.hlsl"
  9. struct AttributesParticleLux
  10. {
  11. float4 vertex : POSITION;
  12. float3 normal : NORMAL;
  13. half4 color : COLOR;
  14. #if defined(_FLIPBOOKBLENDING_ON) && !defined(UNITY_PARTICLE_INSTANCING_ENABLED)
  15. float4 texcoords : TEXCOORD0;
  16. #if defined (_PERVERTEX_SAMPLEOFFSET)
  17. float4 texcoordBlend : TEXCOORD1;
  18. #else
  19. float texcoordBlend : TEXCOORD1;
  20. #endif
  21. #else
  22. #if defined (_PERVERTEX_SAMPLEOFFSET)
  23. float4 texcoords : TEXCOORD0;
  24. float texcoordBlend : TEXCOORD1;
  25. #else
  26. float2 texcoords : TEXCOORD0;
  27. #endif
  28. #endif
  29. #if defined(_NORMALMAP)
  30. float4 tangentOS : TANGENT;
  31. #endif
  32. UNITY_VERTEX_INPUT_INSTANCE_ID
  33. };
  34. struct VaryingsParticleLux
  35. {
  36. half4 color : COLOR;
  37. float2 texcoord : TEXCOORD0;
  38. float4 positionWS : TEXCOORD1;
  39. float3 normalWS : TEXCOORD2;
  40. #ifdef _NORMALMAP
  41. float4 tangentWS : TEXCOORD3; // xyz: tangent, w: viewDir.y
  42. #endif
  43. float3 viewDirWS : TEXCOORD4;
  44. #if defined(_FLIPBOOKBLENDING_ON)
  45. float3 texcoord2AndBlend : TEXCOORD5;
  46. #endif
  47. #if defined(_SOFTPARTICLES_ON) || defined(_FADING_ON) || defined(_DISTORTION_ON)
  48. float4 projectedPosition : TEXCOORD6;
  49. #endif
  50. // Passing shadowCoord from vertex to fragment produced too many artifacts
  51. //#if (defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF)) || defined(_PERVERTEX_SHADOWS)
  52. // float4 shadowCoord : TEXCOORD7;
  53. //#endif
  54. // So we split the work between vertex and fragment and only calculate the cascade in the vertex shader
  55. // Ok on metal but still not perfect on dx11
  56. // uint cascade : TEXCOORD7;
  57. float3 vertexSH : TEXCOORD7; // SH Lighting
  58. half4 lighting : TEXCOORD8; // Per vertex sampled shadows
  59. #if defined _ADDITIONAL_LIGHTS_VERTEX
  60. half3 vertexLighting : TEXCOORD9;
  61. #endif
  62. float4 clipPos : SV_POSITION;
  63. UNITY_VERTEX_INPUT_INSTANCE_ID
  64. UNITY_VERTEX_OUTPUT_STEREO
  65. };
  66. void InitializeInputData(VaryingsParticleLux input, half3 normalTS, out InputData output) {
  67. output = (InputData)0;
  68. output.positionWS = input.positionWS.xyz;
  69. half3 viewDirWS = SafeNormalize(input.viewDirWS);
  70. #ifdef _NORMALMAP
  71. float sgn = input.tangentWS.w; // should be either +1 or -1
  72. float3 bitangent = sgn * cross(input.normalWS.xyz, input.tangentWS.xyz);
  73. output.normalWS = TransformTangentToWorld(normalTS,
  74. half3x3(input.tangentWS.xyz, bitangent.xyz, input.normalWS.xyz));
  75. #else
  76. output.normalWS = input.normalWS;
  77. #endif
  78. output.normalWS = NormalizeNormalPerPixel(output.normalWS);
  79. output.viewDirectionWS = viewDirWS;
  80. //#if (defined(_MAIN_LIGHT_SHADOWS) && !defined(_RECEIVE_SHADOWS_OFF)) || defined(_PERVERTEX_SHADOWS)
  81. //output.shadowCoord = input.shadowCoord;
  82. // #else
  83. output.shadowCoord = float4(1, 1, 1, 1);
  84. // #endif
  85. output.fogCoord = (half)input.positionWS.w;
  86. #if defined _ADDITIONAL_LIGHTS_VERTEX
  87. output.vertexLighting = input.vertexLighting;
  88. #else
  89. output.vertexLighting = half3(0.0h, 0.0h, 0.0h);
  90. #endif
  91. output.bakedGI = SampleSHPixel(input.vertexSH, output.normalWS);
  92. }
  93. ///////////////////////////////////////////////////////////////////////////////
  94. // Vertex and Fragment functions //
  95. ///////////////////////////////////////////////////////////////////////////////
  96. // Because of: ADDITIONAL_LIGHT_CALCULATE_SHADOWS we have to include our own here (copy paste from shadows)
  97. real LuxSampleShadowmap(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData, half4 shadowParams, bool isPerspectiveProjection = true)
  98. {
  99. // Compiler will optimize this branch away as long as isPerspectiveProjection is known at compile time
  100. if (isPerspectiveProjection)
  101. shadowCoord.xyz /= shadowCoord.w;
  102. real attenuation;
  103. real shadowStrength = shadowParams.x;
  104. // 1-tap hardware comparison
  105. attenuation = SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz);
  106. attenuation = LerpWhiteTo(attenuation, shadowStrength);
  107. // Shadow coords that fall out of the light frustum volume must always return attenuation 1.0
  108. // TODO: We could use branch here to save some perf on some platforms.
  109. return BEYOND_SHADOW_FAR(shadowCoord) ? 1.0 : attenuation;
  110. }
  111. half LuxAdditionalLightRealtimeShadow(int lightIndex, float3 positionWS, ShadowSamplingData shadowSamplingData)
  112. {
  113. #if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
  114. return 1.0h;
  115. #endif
  116. //ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData();
  117. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
  118. lightIndex = _AdditionalShadowsIndices[lightIndex];
  119. // We have to branch here as otherwise we would sample buffer with lightIndex == -1.
  120. // However this should be ok for platforms that store light in SSBO.
  121. UNITY_BRANCH
  122. if (lightIndex < 0)
  123. return 1.0;
  124. float4 shadowCoord = mul(_AdditionalShadowsBuffer[lightIndex].worldToShadowMatrix, float4(positionWS, 1.0));
  125. #else
  126. float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[lightIndex], float4(positionWS, 1.0));
  127. #endif
  128. half4 shadowParams = GetAdditionalLightShadowParams(lightIndex);
  129. return LuxSampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_AdditionalLightsShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, true);
  130. }
  131. VaryingsParticleLux ParticlesLitVertex(AttributesParticleLux input)
  132. {
  133. VaryingsParticleLux output;
  134. UNITY_SETUP_INSTANCE_ID(input);
  135. UNITY_TRANSFER_INSTANCE_ID(input, output);
  136. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  137. VertexPositionInputs vertexInput = GetVertexPositionInputs(input.vertex.xyz);
  138. // In order to get rid of the tangent we have to add and #if here.
  139. VertexNormalInputs normalInput = GetVertexNormalInputs(input.normal,
  140. #if defined(_NORMALMAP)
  141. input.tangentOS
  142. #else
  143. float4 (0,0,0,0)
  144. #endif
  145. );
  146. half3 viewDirWS = GetWorldSpaceViewDir(vertexInput.positionWS);
  147. output.normalWS = normalInput.normalWS;
  148. output.viewDirWS = viewDirWS;
  149. #ifdef _NORMALMAP
  150. real sign = input.tangentOS.w * GetOddNegativeScale();
  151. output.tangentWS = half4(normalInput.tangentWS.xyz, sign);
  152. #endif
  153. OUTPUT_SH(output.normalWS.xyz, output.vertexSH);
  154. output.positionWS.xyz = vertexInput.positionWS.xyz;
  155. // NOTE: output.positionWS.w contains fog!
  156. output.positionWS.w = ComputeFogFactor(vertexInput.positionCS.z);
  157. output.clipPos = vertexInput.positionCS;
  158. output.color = input.color;
  159. output.texcoord = input.texcoords.xy;
  160. #ifdef _FLIPBOOKBLENDING_ON
  161. output.texcoord2AndBlend.xy = input.texcoords.zw;
  162. output.texcoord2AndBlend.z = input.texcoordBlend.x;
  163. #endif
  164. #if defined(_SOFTPARTICLES_ON) || defined(_FADING_ON) || defined(_DISTORTION_ON)
  165. output.projectedPosition = ComputeScreenPos(vertexInput.positionCS);
  166. #endif
  167. #if defined _ADDITIONAL_LIGHTS_VERTEX
  168. output.vertexLighting = VertexLighting(vertexInput.positionWS, normalInput.normalWS);
  169. #endif
  170. output.lighting = half4(1,1,1,1);
  171. #if defined(_PERVERTEX_SHADOWS)
  172. // Main Light shadows - we do not sample the screen space shadowmap but the cascaded map
  173. #ifdef _MAIN_LIGHT_SHADOWS_CASCADE
  174. half cascade = ComputeCascadeIndex(output.positionWS.xyz);
  175. #else
  176. half cascade = 0;
  177. #endif
  178. float4 shadowCoord = mul(_MainLightWorldToShadow[cascade], float4(output.positionWS.xyz, 1.0));
  179. shadowCoord.w = cascade;
  180. ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
  181. half shadowStrength = GetMainLightShadowStrength();
  182. output.lighting.a = SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
  183. // Multi sample and blend directional shadows. Offset is derived from velocity.
  184. #if defined(_PERVERTEX_SAMPLEOFFSET)
  185. #ifdef _FLIPBOOKBLENDING_ON
  186. float3 vel = normalize(input.texcoordBlend.yzw) * _SampleOffset;
  187. #else
  188. float3 vel = normalize( float3(input.texcoords.zw, input.texcoordBlend.x)) * _SampleOffset;
  189. #endif
  190. float4 sc = TransformWorldToShadowCoord(output.positionWS.xyz + vel);
  191. output.lighting.a += SampleShadowmap(sc, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
  192. sc = TransformWorldToShadowCoord(output.positionWS.xyz - vel);
  193. output.lighting.a += SampleShadowmap(sc, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
  194. output.lighting.a /= 3;
  195. #endif
  196. #if defined (_ADDITIONALLIGHT_SHADOWS)
  197. uint pixelLightCount = GetAdditionalLightsCount();
  198. // Limit pixelLightCount to 3 as we only have 4 entries ( last one used by the directional light)
  199. pixelLightCount = min(3, pixelLightCount);
  200. float shadow[3] = {(1), (1), (1)};
  201. ShadowSamplingData shadowSamplingDataAdd = GetAdditionalLightShadowSamplingData();
  202. for (uint i = 0u; i < pixelLightCount; ++i) {
  203. int PerObjectLightIndex = GetPerObjectLightIndex(i);
  204. // DX11 does not like this
  205. //output.lighting[i] = AdditionalLightRealtimeShadow(PerObjectLightIndex, output.positionWS.xyz);
  206. // URP 10: we have to call custom fuction
  207. shadow[i] = LuxAdditionalLightRealtimeShadow(PerObjectLightIndex, output.positionWS.xyz, shadowSamplingDataAdd);
  208. #if defined(_PERVERTEX_SAMPLEOFFSET)
  209. shadow[i] += LuxAdditionalLightRealtimeShadow(PerObjectLightIndex, output.positionWS.xyz + vel, shadowSamplingDataAdd);
  210. shadow[i] += LuxAdditionalLightRealtimeShadow(PerObjectLightIndex, output.positionWS.xyz - vel, shadowSamplingDataAdd);
  211. shadow[i] /= 3;
  212. #endif
  213. }
  214. output.lighting.xyz = half3(shadow[0], shadow[1], shadow[2]);
  215. #endif
  216. #endif
  217. return output;
  218. }
  219. // Lighting
  220. half3 LuxLightingLambertTransmission(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half strength)
  221. {
  222. half NdotL = saturate(dot(normal, lightDir));
  223. #if defined(_TRANSMISSION)
  224. return lightColor * saturate(NdotL) + lightColor * saturate(dot(-viewDir, lightDir + normal * _TransmissionDistortion)) * strength;
  225. #else
  226. return lightColor * NdotL;
  227. #endif
  228. }
  229. half4 LuxBlinnPhong(InputData inputData, half3 diffuse, half4 specularGloss, half smoothness, half3 emission, half alpha, float4 inputLighting, half transmission, uint cascade)
  230. {
  231. #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
  232. half4 shadowMask = inputData.shadowMask;
  233. #elif !defined (LIGHTMAP_ON)
  234. half4 shadowMask = unity_ProbesOcclusion;
  235. #else
  236. half4 shadowMask = half4(1, 1, 1, 1);
  237. #endif
  238. shadowMask = half4(1, 1, 1, 1);
  239. Light mainLight = GetMainLight(inputData.shadowCoord);
  240. MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
  241. //transmission *= 1.0h - alpha;
  242. #if defined(_PERVERTEX_SHADOWS)
  243. // Here shadowAttenuation never gets used so it should be stripped by the compiler...
  244. half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation);
  245. attenuatedLightColor *= inputLighting.w;
  246. #else
  247. half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation); // * mainLight.shadowAttenuation);
  248. // Main Light shadows - We do not sample the screen space shadowmap but the cascaded map
  249. ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
  250. // Vertex to fragment interpolation procudes too many errors?
  251. // inputData.shadowCoord = TransformWorldToShadowCoord(inputData.positionWS.xyz); // - inputData.normalWS*0.5);
  252. // Using uint cascade actually looks fine on Metal but not dx11, so we actually do all the calculation per pixel
  253. /* #ifdef _MAIN_LIGHT_SHADOWS_CASCADE
  254. float4 shadowCoord = mul(_MainLightWorldToShadow[cascade], float4(inputData.positionWS, 1.0));
  255. #else
  256. float4 shadowCoord = mul(_MainLightWorldToShadow[0], float4(inputData.positionWS, 1.0));
  257. #endif
  258. */
  259. float4 shadowCoord = TransformWorldToShadowCoord(inputData.positionWS);
  260. half shadowStrength = GetMainLightShadowStrength();
  261. attenuatedLightColor *= SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
  262. #endif
  263. half3 diffuseColor = inputData.bakedGI + LuxLightingLambertTransmission(attenuatedLightColor, mainLight.direction, inputData.normalWS, inputData.viewDirectionWS, transmission);
  264. half3 specularColor = LightingSpecular(attenuatedLightColor, mainLight.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
  265. #ifdef _ADDITIONAL_LIGHTS
  266. uint pixelLightCount = GetAdditionalLightsCount();
  267. #if defined(_PERVERTEX_SHADOWS) && defined(_ADDITIONALLIGHT_SHADOWS)
  268. // Metal does not like to access the components using indices?! So we chose another way.
  269. half shadow[4] = {(inputLighting.x), (inputLighting.y), (inputLighting.z), (inputLighting.w)};
  270. #endif
  271. for (uint i = 0u; i < pixelLightCount; ++i) {
  272. // URP 10: shadowMask needed!
  273. Light light = GetAdditionalLight(i, inputData.positionWS, shadowMask);
  274. #if defined(_PERVERTEX_SHADOWS)
  275. // Here shadowAttenuation never gets used so it should be stripped by the compiler...
  276. half3 attenuatedLightColor = light.color * light.distanceAttenuation;
  277. #if defined(_ADDITIONALLIGHT_SHADOWS)
  278. // make sure we use the same LightIndex and do not sample more than we have.
  279. attenuatedLightColor *= (i < 3u) ? shadow[i] : 1.0h;
  280. #endif
  281. #else
  282. half3 attenuatedLightColor = light.color * (light.distanceAttenuation
  283. #if defined(_ADDITIONALLIGHT_SHADOWS)
  284. * light.shadowAttenuation
  285. #endif
  286. );
  287. #endif
  288. diffuseColor += LuxLightingLambertTransmission(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, transmission);
  289. specularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
  290. }
  291. #endif
  292. #ifdef _ADDITIONAL_LIGHTS_VERTEX
  293. diffuseColor += inputData.vertexLighting;
  294. #endif
  295. half3 finalColor = diffuseColor * diffuse + emission;
  296. #if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
  297. #if !defined(_SPECULARHIGHLIGHTS_OFF)
  298. finalColor += specularColor;
  299. #endif
  300. #endif
  301. #ifdef _ADDITIONAL_LIGHTS
  302. #if defined(_PERVERTEX_SHADOWS) && defined(_ADDITIONALLIGHT_SHADOWS)
  303. //finalColor = half3(shadow[0], shadow[1], shadow[2]);
  304. #endif
  305. #endif
  306. return half4(finalColor, alpha);
  307. }
  308. half4 ParticlesLitFragment(VaryingsParticleLux input) : SV_Target
  309. {
  310. UNITY_SETUP_INSTANCE_ID(input);
  311. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  312. float2 uv = input.texcoord;
  313. float3 blendUv = float3(0, 0, 0);
  314. #if defined(_FLIPBOOKBLENDING_ON)
  315. blendUv = input.texcoord2AndBlend;
  316. #endif
  317. float4 projectedPosition = float4(0,0,0,0);
  318. #if defined(_SOFTPARTICLES_ON) || defined(_FADING_ON) || defined(_DISTORTION_ON)
  319. projectedPosition = input.projectedPosition;
  320. #endif
  321. // Fix screenUV for Single Pass Stereo Rendering
  322. #if defined(UNITY_SINGLE_PASS_STEREO)
  323. projectedPosition.xy /= projectedPosition.w;
  324. projectedPosition.w = 1.0f; // Reset
  325. //projectedPosition.x = projectedPosition.x * 0.5f + (float)unity_StereoEyeIndex * 0.5f;
  326. projectedPosition.xy = UnityStereoTransformScreenSpaceTex(projectedPosition.xy);
  327. #endif
  328. half4 albedo = Lux_SampleAlbedo(uv, blendUv, _BaseColor, input.color, projectedPosition, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap));
  329. // Early out
  330. clip(albedo.a - 0.001h);
  331. half3 normalTS = SampleNormalTS(uv, blendUv, TEXTURE2D_ARGS(_BumpMap, sampler_BumpMap));
  332. // We do not use the macro here
  333. half3 diffuse = albedo.rgb; //AlphaModulate(albedo.rgb, albedo.a);
  334. half alpha = albedo.a;
  335. #if defined(_EMISSION)
  336. half3 emission = BlendTexture(TEXTURE2D_ARGS(_EmissionMap, sampler_EmissionMap), uv, blendUv).rgb * _EmissionColor.rgb;
  337. #else
  338. half3 emission = half3(0, 0, 0);
  339. #endif
  340. //_SpecColor.a *= _Smoothness;
  341. half4 specularGloss = SampleSpecularSmoothness(uv, blendUv, albedo.a, _SpecColor, TEXTURE2D_ARGS(_SpecGlossMap, sampler_SpecGlossMap));
  342. half shininess = specularGloss.a;
  343. #if defined(_DISTORTION_ON)
  344. diffuse = Distortion(half4(diffuse, alpha), normalTS, _DistortionStrengthScaled, _DistortionBlend, projectedPosition);
  345. #endif
  346. InputData inputData;
  347. InitializeInputData(input, normalTS, inputData);
  348. half4 color = LuxBlinnPhong(inputData, diffuse, specularGloss, shininess, emission, alpha, input.lighting, _Transmission, 0 /*input.cascade*/);
  349. #if defined(_ADDITIVE)
  350. // Add fog
  351. color.rgb = MixFogColor(color.rgb, half3(0,0,0), inputData.fogCoord);
  352. #else
  353. // Add fog
  354. color.rgb = MixFog(color.rgb, inputData.fogCoord);
  355. #endif
  356. #if defined(_ALPHAPREMULTIPLY_ON)
  357. color.rgb = color.rgb * color.a;
  358. #endif
  359. return color;
  360. }
  361. ///////////////////////////////////////////////////////////////////////////////
  362. // Tesellation functions //
  363. ///////////////////////////////////////////////////////////////////////////////
  364. #if defined(_USESTESSELLATION)
  365. real3 GetDistanceBasedTessFactor(real3 p0, real3 p1, real3 p2, real3 cameraPosWS, real tessMinDist, real tessMaxDist)
  366. {
  367. real3 edgePosition0 = 0.5 * (p1 + p2);
  368. real3 edgePosition1 = 0.5 * (p0 + p2);
  369. real3 edgePosition2 = 0.5 * (p0 + p1);
  370. // In case camera-relative rendering is enabled, 'cameraPosWS' is statically known to be 0,
  371. // so the compiler will be able to optimize distance() to length().
  372. real dist0 = distance(edgePosition0, cameraPosWS);
  373. real dist1 = distance(edgePosition1, cameraPosWS);
  374. real dist2 = distance(edgePosition2, cameraPosWS);
  375. // The saturate will handle the produced NaN in case min == max
  376. real fadeDist = tessMaxDist - tessMinDist;
  377. real3 tessFactor;
  378. tessFactor.x = saturate(1.0 - (dist0 - tessMinDist) / fadeDist);
  379. tessFactor.y = saturate(1.0 - (dist1 - tessMinDist) / fadeDist);
  380. tessFactor.z = saturate(1.0 - (dist2 - tessMinDist) / fadeDist);
  381. return tessFactor;
  382. }
  383. // More or less the same as AttributesParticleLux
  384. struct TessVertex {
  385. float4 vertex : INTERNALTESSPOS;
  386. float3 normal : NORMAL;
  387. half4 color : COLOR;
  388. #if defined(_FLIPBOOKBLENDING_ON) && !defined(UNITY_PARTICLE_INSTANCING_ENABLED)
  389. float4 texcoords : TEXCOORD0;
  390. #if defined (_PERVERTEX_SAMPLEOFFSET)
  391. float4 texcoordBlend : TEXCOORD1;
  392. #else
  393. float texcoordBlend : TEXCOORD1;
  394. #endif
  395. #else
  396. #if defined (_PERVERTEX_SAMPLEOFFSET)
  397. float4 texcoords : TEXCOORD0;
  398. #else
  399. float2 texcoords : TEXCOORD0;
  400. #endif
  401. #endif
  402. #if defined(_NORMALMAP)
  403. float4 tangentOS : TANGENT;
  404. #endif
  405. UNITY_VERTEX_INPUT_INSTANCE_ID
  406. };
  407. struct OutputPatchConstant {
  408. float edge[3] : SV_TessFactor;
  409. float inside : SV_InsideTessFactor;
  410. };
  411. // The Vertex Shader - simply copies the inputs
  412. TessVertex ParticlesLitTessVertex (AttributesParticleLux input) {
  413. TessVertex o;
  414. UNITY_SETUP_INSTANCE_ID(input);
  415. UNITY_TRANSFER_INSTANCE_ID(input, o); // Fine, now the vertex shader outputs the id
  416. o.vertex = input.vertex;
  417. o.normal = input.normal;
  418. o.color = input.color;
  419. #if defined(_FLIPBOOKBLENDING_ON) && !defined(UNITY_PARTICLE_INSTANCING_ENABLED)
  420. o.texcoords = input.texcoords;
  421. o.texcoordBlend = input.texcoordBlend;
  422. #else
  423. o.texcoords = input.texcoords;
  424. #endif
  425. #if defined(_NORMALMAP)
  426. o.tangentOS = input.tangentOS;
  427. #endif
  428. return o;
  429. }
  430. float4 Tessellation(TessVertex v, TessVertex v1, TessVertex v2) {
  431. real4 tess;
  432. tess.xyz = _Tess * clamp(GetDistanceBasedTessFactor (v.vertex.xyz, v1.vertex.xyz, v2.vertex.xyz, _WorldSpaceCameraPos, _TessRange.x, _TessRange.y ), 0.01, 1 );
  433. tess.w = (tess.x + tess.y + tess.z) / 3.0;
  434. return tess;
  435. }
  436. OutputPatchConstant hullconst (InputPatch<TessVertex,3> v) {
  437. OutputPatchConstant o;
  438. float4 ts = Tessellation( v[0], v[1], v[2]);
  439. o.edge[0] = ts.x;
  440. o.edge[1] = ts.y;
  441. o.edge[2] = ts.z;
  442. o.inside = ts.w;
  443. return o;
  444. }
  445. [domain("tri")]
  446. [partitioning("fractional_odd")]
  447. [outputtopology("triangle_cw")]
  448. [patchconstantfunc("hullconst")]
  449. [outputcontrolpoints(3)]
  450. TessVertex ParticlesLitHull (InputPatch<TessVertex,3> v, uint id : SV_OutputControlPointID) {
  451. return v[id];
  452. }
  453. [domain("tri")]
  454. VaryingsParticleLux ParticlesLitDomain (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3> vi, float3 bary : SV_DomainLocation) {
  455. AttributesParticleLux v = (AttributesParticleLux)0;
  456. v.vertex = vi[0].vertex*bary.x + vi[1].vertex*bary.y + vi[2].vertex*bary.z;
  457. v.normal = vi[0].normal*bary.x + vi[1].normal*bary.y + vi[2].normal*bary.z;
  458. v.color = vi[0].color*bary.x + vi[1].color*bary.y + vi[2].color*bary.z;
  459. #if defined(_FLIPBOOKBLENDING_ON) && !defined(UNITY_PARTICLE_INSTANCING_ENABLED)
  460. v.texcoords = vi[0].texcoords*bary.x + vi[1].texcoords*bary.y + vi[2].texcoords*bary.z;
  461. v.texcoordBlend = vi[0].texcoordBlend*bary.x + vi[1].texcoordBlend*bary.y + vi[2].texcoordBlend*bary.z;
  462. #else
  463. v.texcoords = vi[0].texcoords*bary.x + vi[1].texcoords*bary.y + vi[2].texcoords*bary.z;
  464. #endif
  465. #if defined(_NORMALMAP)
  466. v.tangentOS = vi[0].tangentOS*bary.x + vi[1].tangentOS*bary.y + vi[2].tangentOS*bary.z;
  467. #endif
  468. // UNITY_SETUP_INSTANCE_ID(vi[0]);
  469. // This is all we need?
  470. UNITY_TRANSFER_INSTANCE_ID(vi[0], v);
  471. // Now call the regular vertex function
  472. VaryingsParticleLux o = ParticlesLitVertex(v);
  473. return o;
  474. }
  475. #endif
  476. // ---------------------------
  477. #endif // LUXLWRP_SIMPLE_LIT_PASS_INCLUDED