LayaPBRUtil.cginc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. inline half3 LayaPreMultiplyAlpha(half3 diffColor, half alpha, half oneMinusReflectivity, out half outModifiedAlpha)
  2. {
  3. #if defined(TRANSPARENTBLEND)
  4. diffColor *= alpha;
  5. #if (SHADER_TARGET < 30)
  6. outModifiedAlpha = alpha;
  7. #else
  8. outModifiedAlpha = 1 - oneMinusReflectivity + alpha * oneMinusReflectivity;
  9. #endif
  10. #else
  11. outModifiedAlpha = alpha;
  12. #endif
  13. return diffColor;
  14. }
  15. float2 LayaTransform_Tex(float2 tex, float4 name)
  16. {
  17. return tex.xy * name.xy + name.zw;
  18. }
  19. float4 layaTexCoords(VertexInput v)
  20. {
  21. float4 texcoord;
  22. texcoord.xy = LayaTransform_Tex(v.uv0, tilingOffset);
  23. texcoord.zw = LayaTransform_Tex(v.uv0,tilingOffset);
  24. return texcoord;
  25. }
  26. half3 LayaNormalizePerVertexNormal(float3 n)
  27. {
  28. #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
  29. return normalize(n);
  30. #else
  31. return n;
  32. #endif
  33. }
  34. float3 LayaNormalizePerPixelNormal(float3 n)
  35. {
  36. #if (SHADER_TARGET < 30) || UNITY_STANDARD_SIMPLE
  37. return n;
  38. #else
  39. return normalize((float3)n);
  40. #endif
  41. }
  42. half3 LayaUnpackScaleNormal(half4 packednormal, half bumpScale)
  43. {
  44. packednormal.x *= packednormal.w;
  45. half3 normal;
  46. normal.xy = (packednormal.xy * 2 - 1);
  47. normal.xy *= bumpScale;
  48. normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
  49. return normal;
  50. }
  51. half3 LayaNormalInTangentSpace(float4 texcoords)
  52. {
  53. half3 normalTangent = LayaUnpackScaleNormal(tex2D(normalTexture, texcoords.xy), normalTextureScale);
  54. return normalTangent;
  55. }
  56. inline float3 LayaPerPixelWorldNormal(float4 i_tex, float4 tangentToWorld[3])
  57. {
  58. #ifdef NORMALTEXTURE
  59. half3 tangent = tangentToWorld[0].xyz;
  60. half3 binormal = tangentToWorld[1].xyz;
  61. half3 normal = tangentToWorld[2].xyz;
  62. half3 normalTangent = LayaNormalInTangentSpace(i_tex);
  63. float3 normalWorld =LayaNormalizePerPixelNormal(tangent * normalTangent.x + binormal * normalTangent.y + normal * normalTangent.z); // @TODO: see if we can squeeze this normalize on SM2.0 as well
  64. #else
  65. float3 normalWorld = normalize(tangentToWorld[2].xyz);
  66. #endif
  67. return normalWorld;
  68. }
  69. half3 LayaEmission(float2 uv)
  70. {
  71. #ifndef _EMISSION
  72. return 0;
  73. #else
  74. return tex2D(_EmissionMap, uv).rgb * _EmissionColor.rgb;
  75. #endif
  76. }
  77. half3 in_ViewDir4Parallax(VertexOutputForwardBase i)
  78. {
  79. half3 viewdir;
  80. #ifdef PARALLAXTEXTURE
  81. viewdir = LayaNormalizePerPixelNormal(half3(i.tangentToWorldAndPackedData[0].w, i.tangentToWorldAndPackedData[1].w, i.tangentToWorldAndPackedData[2].w));
  82. #else
  83. viewdir = half3(0, 0, 0);
  84. #endif
  85. return viewdir;
  86. }
  87. half3 in_ViewDir4Parallax_Fwdadd(VertexOutputForwardAdd i)
  88. {
  89. half3 viewdir;
  90. #ifdef PARALLAXTEXTURE
  91. viewdir = LayaNormalizePerPixelNormal(i.viewDirForParallax.xyz);
  92. #else
  93. viewdir = half3(0, 0, 0);
  94. #endif
  95. return viewdir;
  96. }
  97. half2 LayaParallaxOffset1Step(half h, half height, half3 viewDir)
  98. {
  99. h = h * height - height / 2.0;
  100. half3 v = normalize(viewDir);
  101. v.z += 0.42;
  102. return h * (v.xy / v.z);
  103. }
  104. float4 LayaParallax(float4 texcoords, half3 viewDir)
  105. {
  106. #if !defined(PARALLAXTEXTURE) || (SHADER_TARGET < 30)
  107. return texcoords;
  108. #else
  109. half h = tex2D(parallaxTexture, texcoords.xy).g;
  110. float2 offset = LayaParallaxOffset1Step(h, parallaxTextureScale, viewDir);
  111. return float4(texcoords.xy + offset, texcoords.zw + offset);
  112. #endif
  113. }
  114. half LayaAlpha(float2 uv)
  115. {
  116. #if defined(SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA)
  117. return _Color.a;
  118. #else
  119. return tex2D(albedoTexture, uv).a * _Color.a;
  120. #endif
  121. }
  122. half3 LayaAlbedo(float4 texcoords)
  123. {
  124. half3 albedo = _Color.rgb * tex2D(albedoTexture, texcoords.xy).rgb;
  125. return albedo;
  126. }
  127. half4 LayaSpecularGloss(float2 uv)
  128. {
  129. half4 sg;
  130. #ifdef SPECULARGLOSSTEXTURE
  131. #if defined(SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA)
  132. sg.rgb = tex2D(specularTexture, uv).rgb;
  133. sg.a = tex2D(albedoTexture, uv).a;
  134. #else
  135. sg = tex2D(specularTexture, uv);
  136. #endif
  137. sg.a *= smoothnessTextureScale;
  138. #else
  139. sg.rgb = specularColor.rgb;
  140. #ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA
  141. sg.a = tex2D(albedoTexture, uv).a * smoothness;
  142. #else
  143. sg.a = smoothness;
  144. #endif
  145. #endif
  146. return sg;
  147. }
  148. half2 LayaMetallicGloss(float2 uv)
  149. {
  150. half2 mg;
  151. #ifdef METALLICGLOSSTEXTURE
  152. #ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA
  153. mg.r = tex2D(metallicGlossTexture, uv).r;
  154. mg.g = tex2D(albedoTexture, uv).a;
  155. #else
  156. mg = tex2D(metallicGlossTexture, uv).ra;
  157. #endif
  158. mg.g *= smoothnessTextureScale;
  159. #else
  160. mg.r = metallic;
  161. #ifdef SMOOTHNESSSOURCE_ALBEDOTEXTURE_ALPHA
  162. mg.g = tex2D(albedoTexture, uv).a * smoothness;
  163. #else
  164. mg.g = smoothness;
  165. #endif
  166. #endif
  167. return mg;
  168. }
  169. half LayaSpecularStrength(half3 specular)
  170. {
  171. #if (SHADER_TARGET < 30)
  172. return specular.r;
  173. #else
  174. return max(max(specular.r, specular.g), specular.b);
  175. #endif
  176. }
  177. inline half3 LayaEnergyConservationBetweenDiffuseAndSpecular(half3 albedo, half3 specColor, out half oneMinusReflectivity)
  178. {
  179. oneMinusReflectivity = 1 - LayaSpecularStrength(specColor);
  180. #if !UNITY_CONSERVE_ENERGY
  181. return albedo;
  182. #elif UNITY_CONSERVE_ENERGY_MONOCHROME
  183. return albedo * oneMinusReflectivity;
  184. #else
  185. return albedo * (half3(1, 1, 1) - specColor);
  186. #endif
  187. }
  188. LayaFragmentCommonData LayaSpecularSetup(float4 i_tex)
  189. {
  190. half4 specGloss = LayaSpecularGloss(i_tex.xy);
  191. half3 specColor = specGloss.rgb;
  192. half smoothness = specGloss.a;
  193. half oneMinusReflectivity;
  194. half3 diffColor = LayaEnergyConservationBetweenDiffuseAndSpecular(LayaAlbedo(i_tex), specColor, oneMinusReflectivity);
  195. LayaFragmentCommonData o;
  196. o.diffColor = diffColor;
  197. o.specColor = specColor;
  198. o.oneMinusReflectivity = oneMinusReflectivity;
  199. o.smoothness = smoothness;
  200. return o;
  201. }
  202. inline half LayaOneMinusReflectivityFromMetallic(half metallic)
  203. {
  204. half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
  205. return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
  206. }
  207. inline half3 LayaDiffuseAndSpecularFromMetallic(half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity)
  208. {
  209. specColor = lerp(unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
  210. oneMinusReflectivity = LayaOneMinusReflectivityFromMetallic(metallic);
  211. return albedo * oneMinusReflectivity;
  212. }
  213. LayaFragmentCommonData LayaMetallicSetup(float4 i_tex)
  214. {
  215. half2 metallicGloss = LayaMetallicGloss(i_tex.xy);
  216. half metallic = metallicGloss.x;
  217. half smoothness = metallicGloss.y;
  218. half oneMinusReflectivity;
  219. half3 specColor;
  220. half3 diffColor = LayaDiffuseAndSpecularFromMetallic(LayaAlbedo(i_tex), metallic, /*out*/ specColor, /*out*/ oneMinusReflectivity);
  221. LayaFragmentCommonData o = (LayaFragmentCommonData)0;
  222. o.diffColor = diffColor;
  223. o.specColor = specColor;
  224. o.oneMinusReflectivity = oneMinusReflectivity;
  225. o.smoothness = smoothness;
  226. return o;
  227. }
  228. LayaFragmentCommonData LayaFragmentSetup(inout float4 i_tex, float3 i_eyeVec, half3 i_viewDirForParallax, float4 tangentToWorld[3], float3 i_posWorld)
  229. {
  230. i_tex = LayaParallax(i_tex, i_viewDirForParallax);
  231. half alpha = LayaAlpha(i_tex.xy);
  232. #if defined(ALPHATEST)
  233. clip(alpha - _Cutoff);
  234. #endif
  235. LayaFragmentCommonData o;
  236. o = (LayaFragmentCommonData)0;
  237. #ifdef LayaStandardPBR
  238. o = LayaMetallicSetup(i_tex);
  239. #else
  240. o = LayaSpecularSetup(i_tex);
  241. #endif
  242. o.normalWorld = LayaPerPixelWorldNormal(i_tex, tangentToWorld);
  243. o.eyeVec = LayaNormalizePerPixelNormal(i_eyeVec);
  244. o.posWorld = i_posWorld;
  245. o.diffColor = LayaPreMultiplyAlpha(o.diffColor, alpha, o.oneMinusReflectivity, /*out*/ o.alpha);
  246. return o;
  247. }
  248. float LayaSmoothnessToPerceptualRoughness(float smoothness)
  249. {
  250. return (1 - smoothness);
  251. }
  252. Laya_GlossyEnvironmentData LayaGlossyEnvironmentSetup(half Smoothness, half3 worldViewDir, half3 Normal, half3 fresnel0)
  253. {
  254. Laya_GlossyEnvironmentData g;
  255. g.roughness /* perceptualRoughness */ = LayaSmoothnessToPerceptualRoughness(Smoothness);
  256. g.reflUVW = reflect(-worldViewDir, Normal);
  257. return g;
  258. }
  259. half3 LayaSHEvalLinearL0L1(half4 normal)
  260. {
  261. half3 x;
  262. x.r = dot(unity_SHAr, normal);
  263. x.g = dot(unity_SHAg, normal);
  264. x.b = dot(unity_SHAb, normal);
  265. return x;
  266. }
  267. half3 LayaSHEvalLinearL2(half4 normal)
  268. {
  269. half3 x1, x2;
  270. half4 vB = normal.xyzz * normal.yzzx;
  271. x1.r = dot(unity_SHBr, vB);
  272. x1.g = dot(unity_SHBg, vB);
  273. x1.b = dot(unity_SHBb, vB);
  274. half vC = normal.x*normal.x - normal.y*normal.y;
  275. x2 = unity_SHC.rgb * vC;
  276. return x1 + x2;
  277. }
  278. half3 LayaShadeSHPerPixel(half3 normal, half3 ambient, float3 worldPos)
  279. {
  280. half3 ambient_contrib = 0.0;
  281. #if (SHADER_TARGET >= 30)
  282. ambient_contrib = LayaSHEvalLinearL0L1(half4(normal, 1.0));
  283. ambient_contrib += LayaSHEvalLinearL2(half4(normal, 1.0));
  284. ambient += max(half3(0, 0, 0), ambient_contrib);
  285. #endif
  286. #ifdef UNITY_COLORSPACE_GAMMA
  287. ambient = LinearToGammaSpace(ambient);
  288. #endif
  289. return ambient;
  290. }
  291. half3 LayaShadeSH9(half4 normal)
  292. {
  293. half3 res = LayaSHEvalLinearL0L1(normal);
  294. res += LayaSHEvalLinearL2(normal);
  295. # ifdef UNITY_COLORSPACE_GAMMA
  296. res = LinearToGammaSpace(res);
  297. # endif
  298. return res;
  299. }
  300. half3 LayaShadeSHPerVertex(half3 normal, half3 ambient)
  301. {
  302. #if UNITY_SAMPLE_FULL_SH_PER_PIXEL
  303. #elif (SHADER_TARGET < 30)
  304. ambient += max(half3(0, 0, 0), LayaShadeSH9(half4(normal, 1.0)));
  305. #endif
  306. return ambient;
  307. }
  308. inline LayaGI LayaGI_Base(LayaGIInput data, half occlusion, half3 normalWorld)
  309. {
  310. LayaGI o_gi;
  311. o_gi = (LayaGI)0;
  312. o_gi.light = data.light;
  313. o_gi.light.color *= data.atten;
  314. #if UNITY_SHOULD_SAMPLE_SH
  315. o_gi.indirect.diffuse = LayaShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);
  316. #endif
  317. #if defined(LIGHTMAP_ON)
  318. half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
  319. half3 bakedColor = DecodeLightmap(bakedColorTex);
  320. #ifdef DIRLIGHTMAP_COMBINED
  321. fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
  322. o_gi.indirect.diffuse += DecodeDirectionalLightmap(bakedColor, bakedDirTex, normalWorld);
  323. // #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
  324. // ResetUnityLight(o_gi.light);
  325. // o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
  326. // #endif
  327. #else
  328. o_gi.indirect.diffuse += bakedColor;
  329. #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
  330. ResetUnityLight(o_gi.light);
  331. o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
  332. #endif
  333. #endif
  334. #endif
  335. o_gi.indirect.diffuse *= occlusion;
  336. return o_gi;
  337. }
  338. inline half3 LayaDecodeHDR(half4 data, half4 decodeInstructions)
  339. {
  340. #if defined(UNITY_COLORSPACE_GAMMA)
  341. return (decodeInstructions.x* data.a) * data.rgb;
  342. #else
  343. # if defined(UNITY_USE_NATIVE_HDR)
  344. return decodeInstructions.x * data.rgb;
  345. # else
  346. return (decodeInstructions.x * pow(alpha, decodeInstructions.y)) * data.rgb;
  347. # endif
  348. #endif
  349. }
  350. half3 Laya_GlossyEnvironment(UNITY_ARGS_TEXCUBE(tex), half4 hdr, Laya_GlossyEnvironmentData glossIn)
  351. {
  352. half perceptualRoughness = glossIn.roughness ;
  353. perceptualRoughness = perceptualRoughness * (1.7 - 0.7*perceptualRoughness);
  354. half mip = perceptualRoughness * 6;
  355. half3 R = glossIn.reflUVW;
  356. half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(tex, R, mip);
  357. return LayaDecodeHDR(rgbm, hdr);
  358. }
  359. float3 LayaBoxProjectedCubemapDirection(float3 worldRefl, float3 worldPos, float4 cubemapCenter, float4 boxMin, float4 boxMax)
  360. {
  361. UNITY_BRANCH
  362. if (cubemapCenter.w > 0.0)
  363. {
  364. float3 nrdir = normalize(worldRefl);
  365. #if 1
  366. float3 rbmax = (boxMax.xyz - worldPos) / nrdir;
  367. float3 rbmin = (boxMin.xyz - worldPos) / nrdir;
  368. float3 rbminmax = (nrdir > 0.0f) ? rbmax : rbmin;
  369. #else
  370. float3 rbmax = (boxMax.xyz - worldPos);
  371. float3 rbmin = (boxMin.xyz - worldPos);
  372. float3 select = step(float3(0, 0, 0), nrdir);
  373. float3 rbminmax = lerp(rbmax, rbmin, select);
  374. rbminmax /= nrdir;
  375. #endif
  376. float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
  377. worldPos -= cubemapCenter.xyz;
  378. worldRefl = worldPos + nrdir * fa;
  379. }
  380. return worldRefl;
  381. }
  382. inline half3 LayaGI_IndirectSpecular(LayaGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
  383. {
  384. half3 specular;
  385. #ifdef UNITY_SPECCUBE_BOX_PROJECTION
  386. half3 originalReflUVW = glossIn.reflUVW;
  387. glossIn.reflUVW = LayaBoxProjectedCubemapDirection(originalReflUVW, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
  388. #endif
  389. #ifdef _GLOSSYREFLECTIONS_OFF
  390. specular = unity_IndirectSpecColor.rgb;
  391. #else
  392. half3 env0 = Laya_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
  393. specular = env0;
  394. #endif
  395. return specular * occlusion;
  396. }
  397. LayaGI LayaGlobalIllumination(LayaGIInput data, half occlusion, half3 normalWorld, Laya_GlossyEnvironmentData glossIn)
  398. {
  399. LayaGI o_gi = LayaGI_Base(data, occlusion, normalWorld);
  400. o_gi.indirect.specular = LayaGI_IndirectSpecular(data, occlusion, glossIn);
  401. return o_gi;
  402. }
  403. LayaGI LayaFragmentGI(LayaFragmentCommonData s, half occlusion, half4 i_ambientOrLightmapUV, half atten, UnityLight light)
  404. {
  405. LayaGIInput d;
  406. d.light = light;
  407. d.worldPos = s.posWorld;
  408. d.worldViewDir = -s.eyeVec;
  409. d.atten = atten;
  410. #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
  411. d.ambient = 0;
  412. d.lightmapUV = i_ambientOrLightmapUV;
  413. #else
  414. d.ambient = i_ambientOrLightmapUV.rgb;
  415. d.lightmapUV = 0;
  416. #endif
  417. d.probeHDR[0] = unity_SpecCube0_HDR;
  418. d.probeHDR[1] = unity_SpecCube1_HDR;
  419. #if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
  420. d.boxMin[0] = unity_SpecCube0_BoxMin;
  421. #endif
  422. #ifdef UNITY_SPECCUBE_BOX_PROJECTION
  423. d.boxMax[0] = unity_SpecCube0_BoxMax;
  424. d.probePosition[0] = unity_SpecCube0_ProbePosition;
  425. d.boxMax[1] = unity_SpecCube1_BoxMax;
  426. d.boxMin[1] = unity_SpecCube1_BoxMin;
  427. d.probePosition[1] = unity_SpecCube1_ProbePosition;
  428. #endif
  429. Laya_GlossyEnvironmentData g = LayaGlossyEnvironmentSetup(s.smoothness, -s.eyeVec, s.normalWorld, s.specColor);
  430. return LayaGlobalIllumination(d, occlusion, s.normalWorld, g);
  431. }
  432. half4 LayaVertexGIForward(VertexInput v, float3 posWorld, half3 normalWorld)
  433. {
  434. half4 ambientOrLightmapUV = 0;
  435. #ifdef LIGHTMAP_ON
  436. ambientOrLightmapUV.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
  437. ambientOrLightmapUV.zw = 0;
  438. #elif UNITY_SHOULD_SAMPLE_SH
  439. ambientOrLightmapUV.rgb = LayaShadeSHPerVertex(normalWorld, ambientOrLightmapUV.rgb);
  440. #endif
  441. return ambientOrLightmapUV;
  442. }
  443. half4 LayaOutputForward(half4 output, half alphaFromSurface)
  444. {
  445. output.a = alphaFromSurface;
  446. return output;
  447. }
  448. half LayaLerpOneTo(half b, half t)
  449. {
  450. half oneMinusT = 1 - t;
  451. return oneMinusT + b * t;
  452. }
  453. half LayaOcclusion(float2 uv)
  454. {
  455. #if (SHADER_TARGET < 30)
  456. return tex2D(occlusionTexture, uv).g;
  457. #else
  458. half occ = tex2D(occlusionTexture, uv).g;
  459. return LayaLerpOneTo(occ, occlusionTextureStrength);
  460. #endif
  461. }
  462. half LayaSmoothnessToRoughness(half smoothness)
  463. {
  464. return (1 - smoothness) * (1 - smoothness);
  465. }