Lux_Procedural_Texturing_Simple_NoBranching.hlsl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // https://github.com/UnityLabs/procedural-stochastic-texturing/blob/master/Editor/ProceduralTexture2D/SampleProceduralTexture2DNode.cs
  2. // Unity 2019.1. needs a float version
  3. // https://www.shadertoy.com/view/4djSRW
  4. float2 hash22(float2 p) {
  5. float3 p3 = frac(float3(p.xyx) * float3(.1031, .1030, .0973));
  6. p3 += dot(p3, p3.yzx+33.33);
  7. return frac((p3.xx+p3.yz)*p3.zy);
  8. }
  9. void StochasticSampleSimple_half (
  10. SamplerState samplerTex,
  11. // Base inputs
  12. half Blend,
  13. float2 uv,
  14. float stochasticScale,
  15. // Albedo
  16. Texture2D textureAlbedo,
  17. // Normal
  18. Texture2D textureNormal,
  19. half normalScale,
  20. // MetallicSpecular
  21. Texture2D textureMetallicSpec,
  22. // MaskMap
  23. Texture2D textureMask,
  24. // Output
  25. out half3 FinalAlbedo,
  26. out half FinalAlpha,
  27. out half3 FinalNormal,
  28. out half4 FinalMetallicSpecular,
  29. out half4 FinalMask
  30. )
  31. {
  32. float2 uvScaled = uv * 3.464 * stochasticScale; // 2 * sqrt(3)
  33. const float2x2 gridToSkewedGrid = float2x2(1.0, 0.0, -0.57735027, 1.15470054);
  34. float2 skewedCoord = mul(gridToSkewedGrid, uvScaled);
  35. int2 baseId = int2(floor(skewedCoord));
  36. float3 temp = float3(frac(skewedCoord), 0);
  37. temp.z = 1.0 - temp.x - temp.y;
  38. half w1, w2, w3;
  39. int2 vertex1, vertex2, vertex3;
  40. if (temp.z > 0.0) {
  41. w1 = temp.z;
  42. w2 = temp.y;
  43. w3 = temp.x;
  44. vertex1 = baseId;
  45. vertex2 = baseId + int2(0, 1);
  46. vertex3 = baseId + int2(1, 0);
  47. }
  48. else {
  49. w1 = -temp.z;
  50. w2 = 1.0 - temp.y;
  51. w3 = 1.0 - temp.x;
  52. vertex1 = baseId + int2(1, 1);
  53. vertex2 = baseId + int2(1, 0);
  54. vertex3 = baseId + int2(0, 1);
  55. }
  56. const float2x2 hashMatrix = float2x2(127.1, 311.7, 269.5, 183.3);
  57. const float hashFactor = 3758.5453;
  58. float2 uv1 = uv + frac(sin(mul(hashMatrix, (float2)vertex1)) * hashFactor);
  59. float2 uv2 = uv + frac(sin(mul(hashMatrix, (float2)vertex2)) * hashFactor);
  60. float2 uv3 = uv + frac(sin(mul(hashMatrix, (float2)vertex3)) * hashFactor);
  61. // Use a hash function which does not include sin
  62. // Adds a little bit visible tiling...
  63. // float2 uv1 = uv + hash22( (float2)vertex1 );
  64. // float2 uv2 = uv + hash22( (float2)vertex2 );
  65. // float2 uv3 = uv + hash22( (float2)vertex3 );
  66. float2 duvdx = ddx(uv);
  67. float2 duvdy = ddy(uv);
  68. // Here we have to sample first as we want to calculate the wights based on luminance
  69. // Albedo – Sample Gaussion values from transformed input
  70. half4 G1 = SAMPLE_TEXTURE2D_GRAD(textureAlbedo, samplerTex, uv1, duvdx, duvdy);
  71. half4 G2 = SAMPLE_TEXTURE2D_GRAD(textureAlbedo, samplerTex, uv2, duvdx, duvdy);
  72. half4 G3 = SAMPLE_TEXTURE2D_GRAD(textureAlbedo, samplerTex, uv3, duvdx, duvdy);
  73. w1 *= Luminance(G1.rgb);
  74. w2 *= Luminance(G2.rgb);
  75. w3 *= Luminance(G3.rgb);
  76. // Get weights
  77. #pragma warning (disable : 3571)
  78. half exponent = 1.0h + Blend * 15.0h;
  79. w1 = pow(w1, exponent);
  80. w2 = pow(w2, exponent);
  81. w3 = pow(w3, exponent);
  82. #pragma warning (enable : 3571)
  83. // Lets help the compiler here:
  84. half sum = rcp(w1 + w2 + w3);
  85. w1 = w1 * sum;
  86. w2 = w2 * sum;
  87. w3 = w3 * sum;
  88. // Albedo
  89. half4 G = w1 * G1 + w2 * G2 + w3 * G3;
  90. FinalAlbedo = G.rgb;
  91. FinalAlpha = G.a;
  92. // Normal
  93. half4 N1 = SAMPLE_TEXTURE2D_GRAD(textureNormal, samplerTex, uv1, duvdx, duvdy);
  94. half4 N2 = SAMPLE_TEXTURE2D_GRAD(textureNormal, samplerTex, uv2, duvdx, duvdy);
  95. half4 N3 = SAMPLE_TEXTURE2D_GRAD(textureNormal, samplerTex, uv3, duvdx, duvdy);
  96. half4 N = w1 * N1 + w2 * N2 + w3 * N3;
  97. // Normal is either BC5 or DXT5nm – what is about mobile?
  98. #if defined(UNITY_NO_DXT5nm)
  99. FinalNormal = UnpackNormalRGBNoScale(N);
  100. #else
  101. FinalNormal = UnpackNormalmapRGorAG(N, normalScale);
  102. #endif
  103. // MetallicSpecular
  104. half4 MS1 = SAMPLE_TEXTURE2D_GRAD(textureMetallicSpec, samplerTex, uv1, duvdx, duvdy);
  105. half4 MS2 = SAMPLE_TEXTURE2D_GRAD(textureMetallicSpec, samplerTex, uv2, duvdx, duvdy);
  106. half4 MS3 = SAMPLE_TEXTURE2D_GRAD(textureMetallicSpec, samplerTex, uv3, duvdx, duvdy);
  107. FinalMetallicSpecular = w1 * MS1 + w2 * MS2 + w3 * MS3;
  108. // Mask
  109. half4 M1 = SAMPLE_TEXTURE2D_GRAD(textureMask, samplerTex, uv1, duvdx, duvdy);
  110. half4 M2 = SAMPLE_TEXTURE2D_GRAD(textureMask, samplerTex, uv2, duvdx, duvdy);
  111. half4 M3 = SAMPLE_TEXTURE2D_GRAD(textureMask, samplerTex, uv3, duvdx, duvdy);
  112. FinalMask = w1 * M1 + w2 * M2 + w3 * M3;
  113. }
  114. void StochasticSampleSimple_float(
  115. SamplerState samplerTex,
  116. // Base inputs
  117. half Blend,
  118. float2 uv,
  119. float stochasticScale,
  120. // Albedo
  121. Texture2D textureAlbedo,
  122. // Normal
  123. Texture2D textureNormal,
  124. half normalScale,
  125. // MetallicSpecular
  126. Texture2D textureMetallicSpec,
  127. // MaskMap
  128. Texture2D textureMask,
  129. // Output
  130. out half3 FinalAlbedo,
  131. out half FinalAlpha,
  132. out half3 FinalNormal,
  133. out half4 FinalMetallicSpecular,
  134. out half4 FinalMask
  135. )
  136. {
  137. StochasticSampleSimple_half (
  138. samplerTex, Blend, uv, stochasticScale,
  139. textureAlbedo,
  140. textureNormal, normalScale,
  141. textureMetallicSpec,
  142. textureMask,
  143. FinalAlbedo, FinalAlpha, FinalNormal, FinalMetallicSpecular, FinalMask
  144. );
  145. }