TEXTURE2D_ARRAY(_ClusterDiffuse2); TEXTURE2D_ARRAY(_ClusterNormal2); #if _PACKINGHQ TEXTURE2D_ARRAY(_ClusterSmoothAO2); #endif #if _USEEMISSIVEMETAL TEXTURE2D_ARRAY(_ClusterEmissiveMetal2); #endif #if _TEXTURECLUSTER3 TEXTURE2D_ARRAY(_ClusterDiffuse3); TEXTURE2D_ARRAY(_ClusterNormal3); #if _PACKINGHQ TEXTURE2D_ARRAY(_ClusterSmoothAO3); #endif #if _USEEMISSIVEMETAL TEXTURE2D_ARRAY(_ClusterEmissiveMetal3); #endif #endif TEXTURE2D(_ClusterNoise); #if _TEXTURECLUSTERNOISE2 TEXTURE2D(_ClusterNoise2); #endif half3 ClusterWeights2(half4 iWeights, half h0, half h1) { half2 blend = iWeights.xy / dot(iWeights.xy, half2(1,1)); float2 heights = float2(h0, h1) + (blend * 3.0); half height_start = max(heights.x, heights.y) - iWeights.w; half2 h = max(heights - height_start.xx, half2(0,0)); blend = h / dot(h, half2(1,1)); return half3(blend, 0); } half3 ClusterWeights3(half4 iWeights, half h0, half h1, half h2) { half3 blend = iWeights.xyz / dot(iWeights.xyz, half3(1,1,1)); float3 heights = float3(h0, h1, h2) + (blend * 3.0); half height_start = max(max(heights.x, heights.y), heights.z) - iWeights.w; half3 h = max(heights - height_start.xxx, half3(0,0,0)); blend = h / dot(h, half3(1,1,1)); return blend; } half4 ClusterSampleDiffuse(float3 uv, inout half4 cluster, MIPFROMATRAW mipLevel) { half4 a0 = MICROSPLAT_SAMPLE_SAMPLER(_Diffuse, sampler_Diffuse, uv, mipLevel); COUNTSAMPLE half4 a1 = MICROSPLAT_SAMPLE_SAMPLER(_ClusterDiffuse2, sampler_Diffuse, float3(uv.xy * (1 + _ClusterScaleVar), uv.z), mipLevel); COUNTSAMPLE #if _TEXTURECLUSTER3 half4 a2 = MICROSPLAT_SAMPLE_SAMPLER(_ClusterDiffuse3, sampler_Diffuse, float3(uv.xy * (1 - _ClusterScaleVar), uv.z), mipLevel); COUNTSAMPLE cluster.rgb = ClusterWeights3(cluster, a0.a, a1.a, a2.a); return a0 * cluster.x + a1 * cluster.y + a2 * cluster.z; #else cluster.rgb = ClusterWeights2(cluster, a0.a, a1.a); return a0 * cluster.x + a1 * cluster.y; #endif } half4 ClusterSampleEmis(float3 uv, inout half4 cluster, MIPFROMATRAW mipLevel) { #if _USEEMISSIVEMETAL half4 a0 = half4(0, 0, 0, 0); half4 a1 = half4(0, 0, 0, 0); half4 a2 = half4(0, 0, 0, 0); MSBRANCHCLUSTER(cluster.x) { a0 = MICROSPLAT_SAMPLE_SAMPLER(_EmissiveMetal, sampler_Diffuse, uv, mipLevel); COUNTSAMPLE } MSBRANCHCLUSTER(cluster.y) { a1 = MICROSPLAT_SAMPLE_SAMPLER(_ClusterEmissiveMetal2, sampler_Diffuse, float3(uv.xy * (1 + _ClusterScaleVar), uv.z), mipLevel); COUNTSAMPLE } #if _TEXTURECLUSTER3 MSBRANCHCLUSTER(cluster.z) { a2 = MICROSPLAT_SAMPLE_SAMPLER(_ClusterEmissiveMetal3, sampler_Diffuse, float3(uv.xy * (1 - _ClusterScaleVar), uv.z), mipLevel); COUNTSAMPLE } return a0 * cluster.x + a1 * cluster.y + a2 * cluster.z; #else return a0 * cluster.x + a1 * cluster.y; #endif #endif return 0; } half4 ClusterSampleDiffuseLOD(float3 uv, inout half4 cluster, float mipLevel) { half4 a0 = SAMPLE_TEXTURE2D_ARRAY_LOD(_Diffuse, sampler_Diffuse, uv.xy, uv.z, mipLevel); half4 a1 = SAMPLE_TEXTURE2D_ARRAY_LOD(_ClusterDiffuse2, sampler_Diffuse, uv.xy * (1 + _ClusterScaleVar), uv.z, mipLevel); #if _TEXTURECLUSTER3 half4 a2 = SAMPLE_TEXTURE2D_ARRAY_LOD(_ClusterDiffuse3, sampler_Diffuse, uv.xy * (1 - _ClusterScaleVar), uv.z, mipLevel); cluster.rgb = ClusterWeights3(cluster, a0.a, a1.a, a2.a); return a0 * cluster.x + a1 * cluster.y + a2 * cluster.z; #else cluster.rgb = ClusterWeights2(cluster, a0.a, a1.a); return a0 * cluster.x + a1 * cluster.y; #endif } half4 ClusterSampleNormal(float3 uv, half4 cluster, MIPFROMATRAW mipLevel) { #ifdef UNITY_COLORSPACE_GAMMA cluster.rgb *= cluster.rgb; #endif half4 a0 = half4(0.5, 0.5, 0, 1); half4 a1 = half4(0.5, 0.5, 0, 1); half4 a2 = half4(0.5, 0.5, 0, 1); #if _PACKINGHQ MSBRANCHCLUSTER(cluster.x) { a0 = half4(MICROSPLAT_SAMPLE_SAMPLER(_NormalSAO, sampler_NormalSAO, uv, mipLevel).ga, MICROSPLAT_SAMPLE_SAMPLER(_SmoothAO, sampler_SmoothAO, uv, mipLevel).ga).brag; COUNTSAMPLE } #else MSBRANCHCLUSTER(cluster.x) { a0 = MICROSPLAT_SAMPLE_SAMPLER(_NormalSAO, sampler_NormalSAO, uv, mipLevel); COUNTSAMPLE } #endif a0.ga *= 2; a0.ga -= 1; float3 uv2 = float3(uv.xy * (1 + _ClusterScaleVar), uv.z); #if _PACKINGHQ MSBRANCHCLUSTER(cluster.y) { a1 = half4(MICROSPLAT_SAMPLE_SAMPLER(_ClusterNormal2, sampler_NormalSAO, uv2, mipLevel).ga, MICROSPLAT_SAMPLE_SAMPLER(_ClusterSmoothAO2, sampler_SmoothAO, uv2, mipLevel).ga).brag; COUNTSAMPLE } #else MSBRANCHCLUSTER(cluster.y) { a1 = MICROSPLAT_SAMPLE_SAMPLER(_ClusterNormal2, sampler_NormalSAO, uv2, mipLevel); COUNTSAMPLE } #endif a1.ga *= 2; a1.ga -= 1; #if _TEXTURECLUSTER3 float3 uv3 = float3(uv.xy * (1 - _ClusterScaleVar), uv.z); #if _PACKINGHQ MSBRANCHCLUSTER(cluster.z) { a2 = half4(MICROSPLAT_SAMPLE_SAMPLER(_ClusterNormal3, sampler_NormalSAO, uv3, mipLevel).ga, MICROSPLAT_SAMPLE_SAMPLER(_ClusterSmoothAO3, sampler_SmoothAO, uv3, mipLevel).ga).brag; COUNTSAMPLE COUNTSAMPLE } #else MSBRANCHCLUSTER(cluster.z) { a2 = MICROSPLAT_SAMPLE_SAMPLER(_ClusterNormal3, sampler_NormalSAO, uv3, mipLevel); COUNTSAMPLE } #endif a2.ga *= 2; a2.ga -= 1; half4 ret = a0 * cluster.x + a1 * cluster.y + a2 * cluster.z; ret.ga *= 0.5; ret.ga += 0.5; return ret; #else half4 ret = a0 * cluster.x + a1 * cluster.y; ret.ga *= 0.5; ret.ga += 0.5; return ret; #endif } #undef MICROSPLAT_SAMPLE_DIFFUSE #undef MICROSPLAT_SAMPLE_NORMAL #undef MICROSPLAT_SAMPLE_DIFFUSE_LOD #undef MICROSPLAT_SAMPLE_EMIS #define MICROSPLAT_SAMPLE_DIFFUSE(u, cl, l) ClusterSampleDiffuse(u, cl, l) #define MICROSPLAT_SAMPLE_NORMAL(u, cl, l) ClusterSampleNormal(u, cl, l) #define MICROSPLAT_SAMPLE_DIFFUSE_LOD(u, cl, l) ClusterSampleDiffuseLOD(u, cl, l) #define MICROSPLAT_SAMPLE_EMIS(u, cl, l) ClusterSampleEmis(u, cl, l) void PrepClusterData(half4 noise, inout Config c) { noise.a = _ClusterContrast; #if _PERTEXCLUSTERBOOST || _PERTEXCLUSTERCONTRAST SAMPLE_PER_TEX(pt, 10.5, c, 0.5); #endif #if _PERTEXCLUSTERBOOST c.cluster0 = noise; c.cluster1 = noise; c.cluster2 = noise; c.cluster3 = noise; c.cluster0.rgb = pow(c.cluster0.rgb, abs(pt0.g)); c.cluster1.rgb = pow(c.cluster1.rgb, abs(pt1.g)); #if !_MAX2LAYER c.cluster2.rgb = pow(c.cluster2.rgb, abs(pt2.g)); #endif #if !_MAX3LAYER || !_MAX2LAYER c.cluster3.rgb = pow(c.cluster3.rgb, abs(pt3.g)); #endif #if _TEXTURECLUSTER3 c.cluster0.rgb = TotalOne(c.cluster0.rgb); c.cluster1.rgb = TotalOne(c.cluster1.rgb); c.cluster2.rgb = TotalOne(c.cluster2.rgb); c.cluster3.rgb = TotalOne(c.cluster3.rgb); #else c.cluster0.rg = TotalOne(c.cluster0.rg); c.cluster1.rg = TotalOne(c.cluster1.rg); c.cluster2.rg = TotalOne(c.cluster2.rg); c.cluster3.rg = TotalOne(c.cluster3.rg); #endif #else noise.rgb = pow(noise.rgb, abs(_ClusterBoost)); #if _TEXTURECLUSTER3 noise.rgb = TotalOne(noise.rgb); #else noise.rg = TotalOne(noise.rg); #endif c.cluster0 = noise; c.cluster1 = noise; c.cluster2 = noise; c.cluster3 = noise; #endif #if _PERTEXCLUSTERCONTRAST c.cluster0.a = max(pt0.r, 0.01); c.cluster1.a = max(pt1.r, 0.01);; #if !_MAX2LAYER c.cluster2.a = max(pt2.r, 0.01); #endif #if !_MAX3LAYER || !_MAX2LAYER c.cluster3.a = max(pt3.r, 0.01); #endif #endif } void PrepClusters(float2 uv, inout Config c, float3 worldPos, float3 normal) { #if _TEXTURECLUSTERTRIPLANARNOISE float3 pn = pow(abs(normal), 0.7); pn = pn / (pn.x + pn.y + pn.z); half3 axisSign = sign(normal); float2 uv0 = (worldPos.zy * _ClusterParams.xy + _ClusterParams.zw) * axisSign.x; float2 uv1 = (worldPos.xz * _ClusterParams.xy + _ClusterParams.zw) * axisSign.y; float2 uv2 = (worldPos.xy * _ClusterParams.xy + _ClusterParams.zw) * axisSign.z; half4 n0 = SAMPLE_TEXTURE2D(_ClusterNoise, sampler_Diffuse, uv0); half4 n1 = SAMPLE_TEXTURE2D(_ClusterNoise, sampler_Diffuse, uv1); half4 n2 = SAMPLE_TEXTURE2D(_ClusterNoise, sampler_Diffuse, uv2); half4 noise = n0 * pn.x + n1 * pn.y + n2 * pn.z; #if _TEXTURECLUSTERNOISE2 uv0 = (worldPos.zy * _ClusterParams2.xy + _ClusterParams2.zw) * axisSign.x; uv1 = (worldPos.xz * _ClusterParams2.xy + _ClusterParams2.zw) * axisSign.y; uv2 = (worldPos.xy * _ClusterParams2.xy + _ClusterParams2.zw) * axisSign.z; n0 = SAMPLE_TEXTURE2D(_ClusterNoise2, sampler_Diffuse, uv0); n1 = SAMPLE_TEXTURE2D(_ClusterNoise2, sampler_Diffuse, uv1); n2 = SAMPLE_TEXTURE2D(_ClusterNoise2, sampler_Diffuse, uv2); half4 noise2 = n0 * pn.x + n1 * pn.y + n2 * pn.z; noise += noise2; noise *= 0.5; #endif #else float2 nuv = uv * _ClusterParams.xy + _ClusterParams.zw; half4 noise = SAMPLE_TEXTURE2D(_ClusterNoise, sampler_Diffuse, nuv); #if _TEXTURECLUSTERNOISE2 nuv = uv * _ClusterParams2.xy + _ClusterParams2.zw; half4 noise2 = SAMPLE_TEXTURE2D(_ClusterNoise2, sampler_Diffuse, nuv); noise += noise2; noise *= 0.5; #endif #endif PrepClusterData(noise, c); } void PrepClustersDisplace(float2 uv, inout Config c, float3 worldPos, float3 normal) { #if _TRIPLANAR float3 pn = pow(abs(normal), 0.7); pn = pn / (pn.x + pn.y + pn.z); half3 axisSign = sign(normal); float2 uv0 = (worldPos.zy * _ClusterParams.xy + _ClusterParams.zw) * axisSign.x; float2 uv1 = (worldPos.xz * _ClusterParams.xy + _ClusterParams.zw) * axisSign.y; float2 uv2 = (worldPos.xy * _ClusterParams.xy + _ClusterParams.zw) * axisSign.z; half4 n0 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise, sampler_Diffuse, uv0, 0); half4 n1 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise, sampler_Diffuse, uv1, 0); half4 n2 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise, sampler_Diffuse, uv2, 0); half4 noise = n0 * pn.x + n1 * pn.y + n2 * pn.z; #if _TEXTURECLUSTERNOISE2 uv0 = (worldPos.zy * _ClusterParams2.xy + _ClusterParams2.zw) * axisSign.x; uv1 = (worldPos.xz * _ClusterParams2.xy + _ClusterParams2.zw) * axisSign.y; uv2 = (worldPos.xy * _ClusterParams2.xy + _ClusterParams2.zw) * axisSign.z; n0 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise2, sampler_Diffuse, uv0, 0); n1 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise2, sampler_Diffuse, uv1, 0); n2 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise2, sampler_Diffuse, uv2, 0); half4 noise2 = n0 * pn.x + n1 * pn.y + n2 * pn.z; noise += noise2; noise *= 0.5; #endif #else float2 nuv = uv * _ClusterParams.xy + _ClusterParams.zw; uv = uv * _ClusterParams.xy + _ClusterParams.zw; half4 noise = SAMPLE_TEXTURE2D_LOD(_ClusterNoise, sampler_Diffuse, nuv, 0); #if _TEXTURECLUSTERNOISE2 nuv = uv * _ClusterParams2.xy + _ClusterParams2.zw; half4 noise2 = SAMPLE_TEXTURE2D_LOD(_ClusterNoise2, sampler_Diffuse, nuv, 0); noise += noise2; noise *= 0.5; #endif #endif PrepClusterData(noise, c); }