Functions.glsl 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #ifndef ANKI_SHADERS_FUNCTIONS_GLSL
  6. #define ANKI_SHADERS_FUNCTIONS_GLSL
  7. #include "shaders/Common.glsl"
  8. #if defined(ANKI_FRAGMENT_SHADER)
  9. vec3 dither(in vec3 col, in float C)
  10. {
  11. vec3 vDither = vec3(dot(vec2(171.0, 231.0), gl_FragCoord.xy));
  12. vDither.rgb = fract(vDither.rgb / vec3(103.0, 71.0, 97.0));
  13. col = col * (255.0 / C) + vDither.rgb;
  14. col = floor(col) / 255.0;
  15. col *= C;
  16. return col;
  17. }
  18. float dither(in float col, in float C)
  19. {
  20. float vDither = dot(vec2(171.0, 231.0), gl_FragCoord.xy);
  21. vDither = fract(vDither / 103.0);
  22. col = col * (255.0 / C) + vDither;
  23. col = floor(col) / 255.0;
  24. col *= C;
  25. return col;
  26. }
  27. #endif
  28. // Convert to linear depth
  29. float linearizeDepth(in float depth, in float zNear, in float zFar)
  30. {
  31. return zNear / ((zNear - zFar) + zFar / depth);
  32. }
  33. // This is the optimal linearizeDepth where a=(n-f)/n and b=f/n
  34. float linearizeDepthOptimal(in float depth, in float a, in float b)
  35. {
  36. return 1.0 / (a + b / depth);
  37. }
  38. // Project a vector by knowing only the non zero values of a perspective matrix
  39. vec4 projectPerspective(in vec4 vec, in float m00, in float m11, in float m22, in float m23)
  40. {
  41. vec4 o;
  42. o.x = vec.x * m00;
  43. o.y = vec.y * m11;
  44. o.z = vec.z * m22 + vec.w * m23;
  45. o.w = -vec.z;
  46. return o;
  47. }
  48. // Stolen from shadertoy.com/view/4tyGDD
  49. vec4 textureCatmullRom4Samples(sampler2D tex, vec2 uv, vec2 texSize)
  50. {
  51. vec2 halff = 2.0 * fract(0.5 * uv * texSize - 0.25) - 1.0;
  52. vec2 f = fract(halff);
  53. vec2 sum0 = (2.0 * f - 3.5) * f + 0.5;
  54. vec2 sum1 = (2.0 * f - 2.5) * f - 0.5;
  55. vec4 w = vec4(f * sum0 + 1.0, f * sum1);
  56. vec4 pos = vec4((((-2.0 * f + 3.0) * f + 0.5) * f - 1.5) * f / (w.xy * texSize) + uv,
  57. (((-2.0 * f + 5.0) * f - 2.5) * f - 0.5) / (sum1 * texSize) + uv);
  58. w.xz *= halff.x * halff.y > 0.0 ? 1.0 : -1.0;
  59. return (texture(tex, pos.xy) * w.x + texture(tex, pos.zy) * w.z) * w.y
  60. + (texture(tex, pos.xw) * w.x + texture(tex, pos.zw) * w.z) * w.w;
  61. }
  62. float rand(vec2 n)
  63. {
  64. return 0.5 + 0.5 * fract(sin(dot(n, vec2(12.9898, 78.233))) * 43758.5453);
  65. }
  66. vec3 nearestDepthUpscale(vec2 uv, sampler2D depthFull, sampler2D depthHalf, sampler2D colorTex, float depthThreshold)
  67. {
  68. float fullDepth = texture(depthFull, uv).r;
  69. vec4 halfDepths = textureGather(depthHalf, uv, 0);
  70. vec4 diffs = abs(vec4(fullDepth) - halfDepths);
  71. vec3 color;
  72. if(all(lessThan(diffs, vec4(depthThreshold))))
  73. {
  74. // No major discontinuites, sample with bilinear
  75. color = texture(colorTex, uv).rgb;
  76. }
  77. else
  78. {
  79. // Some discontinuites, need to use the newUv
  80. vec4 r = textureGather(colorTex, uv, 0);
  81. vec4 g = textureGather(colorTex, uv, 1);
  82. vec4 b = textureGather(colorTex, uv, 2);
  83. float minDiff = diffs.x;
  84. uint comp = 0;
  85. if(diffs.y < minDiff)
  86. {
  87. comp = 1;
  88. minDiff = diffs.y;
  89. }
  90. if(diffs.z < minDiff)
  91. {
  92. comp = 2;
  93. minDiff = diffs.z;
  94. }
  95. if(diffs.w < minDiff)
  96. {
  97. comp = 3;
  98. }
  99. color = vec3(r[comp], g[comp], b[comp]);
  100. }
  101. return color;
  102. }
  103. float _calcDepthWeight(sampler2D depthLow, vec2 uv, float ref, vec2 linearDepthCf)
  104. {
  105. float d = texture(depthLow, uv).r;
  106. float linearD = linearizeDepthOptimal(d, linearDepthCf.x, linearDepthCf.y);
  107. return 1.0 / (EPSILON + abs(ref - linearD));
  108. }
  109. vec4 _sampleAndWeight(sampler2D depthLow,
  110. sampler2D colorLow,
  111. vec2 lowInvSize,
  112. vec2 uv,
  113. vec2 offset,
  114. float ref,
  115. float weight,
  116. vec2 linearDepthCf,
  117. inout float normalize)
  118. {
  119. uv += offset * lowInvSize;
  120. float dw = _calcDepthWeight(depthLow, uv, ref, linearDepthCf);
  121. vec4 v = texture(colorLow, uv);
  122. normalize += weight * dw;
  123. return v * dw * weight;
  124. }
  125. vec4 bilateralUpsample(
  126. sampler2D depthHigh, sampler2D depthLow, sampler2D colorLow, vec2 lowInvSize, vec2 uv, vec2 linearDepthCf)
  127. {
  128. const vec3 WEIGHTS = vec3(0.25, 0.125, 0.0625);
  129. float depthRef = linearizeDepthOptimal(texture(depthHigh, uv).r, linearDepthCf.x, linearDepthCf.y);
  130. float normalize = 0.0;
  131. vec4 sum = _sampleAndWeight(
  132. depthLow, colorLow, lowInvSize, uv, vec2(0.0, 0.0), depthRef, WEIGHTS.x, linearDepthCf, normalize);
  133. sum += _sampleAndWeight(
  134. depthLow, colorLow, lowInvSize, uv, vec2(-1.0, 0.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
  135. sum += _sampleAndWeight(
  136. depthLow, colorLow, lowInvSize, uv, vec2(0.0, -1.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
  137. sum += _sampleAndWeight(
  138. depthLow, colorLow, lowInvSize, uv, vec2(1.0, 0.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
  139. sum += _sampleAndWeight(
  140. depthLow, colorLow, lowInvSize, uv, vec2(0.0, 1.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
  141. sum += _sampleAndWeight(
  142. depthLow, colorLow, lowInvSize, uv, vec2(1.0, 1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
  143. sum += _sampleAndWeight(
  144. depthLow, colorLow, lowInvSize, uv, vec2(1.0, -1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
  145. sum += _sampleAndWeight(
  146. depthLow, colorLow, lowInvSize, uv, vec2(-1.0, 1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
  147. sum += _sampleAndWeight(
  148. depthLow, colorLow, lowInvSize, uv, vec2(-1.0, -1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
  149. return sum / normalize;
  150. }
  151. vec3 getCubemapDirection(vec2 norm, uint faceIdx)
  152. {
  153. vec3 zDir = vec3((faceIdx <= 1u) ? 1 : 0, (faceIdx & 2u) >> 1u, (faceIdx & 4u) >> 2u);
  154. zDir *= (((faceIdx & 1u) == 1u) ? -1.0 : 1.0);
  155. vec3 yDir = (faceIdx == 2u) ? vec3(0.0, 0.0, 1.0) : (faceIdx == 3u) ? vec3(0.0, 0.0, -1.0) : vec3(0.0, -1.0, 0.0);
  156. vec3 xDir = cross(zDir, yDir);
  157. return normalize(norm.x * xDir + norm.y * yDir + zDir);
  158. }
  159. // Convert 3D cubemap coordinates to 2D plus face index. v doesn't need to be normalized.
  160. vec2 convertCubeUvs(vec3 v, out float faceIndex)
  161. {
  162. vec3 absV = abs(v);
  163. float mag;
  164. vec2 uv;
  165. if(all(greaterThanEqual(absV.zz, absV.xy)))
  166. {
  167. faceIndex = (v.z < 0.0) ? 5.0 : 4.0;
  168. uv = vec2((v.z < 0.0) ? -v.x : v.x, -v.y);
  169. mag = absV.z;
  170. }
  171. else if(absV.y >= absV.x)
  172. {
  173. faceIndex = (v.y < 0.0) ? 3.0 : 2.0;
  174. uv = vec2(v.x, (v.y < 0.0) ? -v.z : v.z);
  175. mag = absV.y;
  176. }
  177. else
  178. {
  179. faceIndex = (v.x < 0.0) ? 1.0 : 0.0;
  180. uv = vec2((v.x < 0.0) ? v.z : -v.z, -v.y);
  181. mag = absV.x;
  182. }
  183. return 0.5 / mag * uv + 0.5;
  184. }
  185. // Same as convertCubeUvs but it returns the faceIndex as unsigned int.
  186. vec2 convertCubeUvsu(vec3 v, out uint faceIndex)
  187. {
  188. vec3 absV = abs(v);
  189. float mag;
  190. vec2 uv;
  191. if(all(greaterThanEqual(absV.zz, absV.xy)))
  192. {
  193. faceIndex = (v.z < 0.0) ? 5u : 4u;
  194. uv = vec2((v.z < 0.0) ? -v.x : v.x, -v.y);
  195. mag = absV.z;
  196. }
  197. else if(absV.y >= absV.x)
  198. {
  199. faceIndex = (v.y < 0.0) ? 3u : 2u;
  200. uv = vec2(v.x, (v.y < 0.0) ? -v.z : v.z);
  201. mag = absV.y;
  202. }
  203. else
  204. {
  205. faceIndex = (v.x < 0.0) ? 1u : 0u;
  206. uv = vec2((v.x < 0.0) ? v.z : -v.z, -v.y);
  207. mag = absV.x;
  208. }
  209. return 0.5 / mag * uv + 0.5;
  210. }
  211. vec3 grayScale(vec3 col)
  212. {
  213. float grey = (col.r + col.g + col.b) * (1.0 / 3.0);
  214. return vec3(grey);
  215. }
  216. vec3 saturateColor(vec3 col, float factor)
  217. {
  218. const vec3 LUM_COEFF = vec3(0.2125, 0.7154, 0.0721);
  219. vec3 intensity = vec3(dot(col, LUM_COEFF));
  220. return mix(intensity, col, factor);
  221. }
  222. vec3 gammaCorrection(vec3 gamma, vec3 col)
  223. {
  224. return pow(col, 1.0 / gamma);
  225. }
  226. // Can use 0.15 for sharpenFactor
  227. vec3 readSharpen(sampler2D tex, vec2 uv, float sharpenFactor, bool detailed)
  228. {
  229. vec3 col = textureLod(tex, uv, 0.0).rgb;
  230. vec3 col2 = textureLodOffset(tex, uv, 0.0, ivec2(1, 1)).rgb;
  231. col2 += textureLodOffset(tex, uv, 0.0, ivec2(-1, -1)).rgb;
  232. col2 += textureLodOffset(tex, uv, 0.0, ivec2(1, -1)).rgb;
  233. col2 += textureLodOffset(tex, uv, 0.0, ivec2(-1, 1)).rgb;
  234. float f = 4.0;
  235. if(detailed)
  236. {
  237. col2 += textureLodOffset(tex, uv, 0.0, ivec2(0, 1)).rgb;
  238. col2 += textureLodOffset(tex, uv, 0.0, ivec2(1, 0)).rgb;
  239. col2 += textureLodOffset(tex, uv, 0.0, ivec2(-1, 0)).rgb;
  240. col2 += textureLodOffset(tex, uv, 0.0, ivec2(0, -1)).rgb;
  241. f = 8.0;
  242. }
  243. col = col * (f * sharpenFactor + 1.0) - sharpenFactor * col2;
  244. return max(vec3(0.0), col);
  245. }
  246. vec3 readErosion(sampler2D tex, vec2 uv)
  247. {
  248. vec3 minValue = textureLod(tex, uv, 0.0).rgb;
  249. #define ANKI_EROSION(x, y) \
  250. col2 = textureLodOffset(tex, uv, 0.0, ivec2(x, y)).rgb; \
  251. minValue = min(col2, minValue);
  252. vec3 col2;
  253. ANKI_EROSION(1, 1);
  254. ANKI_EROSION(-1, -1);
  255. ANKI_EROSION(1, -1);
  256. ANKI_EROSION(-1, 1);
  257. ANKI_EROSION(0, 1);
  258. ANKI_EROSION(1, 0);
  259. ANKI_EROSION(-1, 0);
  260. ANKI_EROSION(0, -1);
  261. #undef ANKI_EROSION
  262. return minValue;
  263. }
  264. // 5 color heatmap from a factor.
  265. vec3 heatmap(float factor)
  266. {
  267. float intPart;
  268. float fractional = modf(factor * 4.0, intPart);
  269. if(intPart < 1.0)
  270. {
  271. return mix(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0), fractional);
  272. }
  273. else if(intPart < 2.0)
  274. {
  275. return mix(vec3(0.0, 0.0, 1.0), vec3(0.0, 1.0, 0.0), fractional);
  276. }
  277. else if(intPart < 3.0)
  278. {
  279. return mix(vec3(0.0, 1.0, 0.0), vec3(1.0, 1.0, 0.0), fractional);
  280. }
  281. else
  282. {
  283. return mix(vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 0.0), fractional);
  284. }
  285. }
  286. bool incorrectColor(vec3 c)
  287. {
  288. return isnan(c.x) || isnan(c.y) || isnan(c.z) || isinf(c.x) || isinf(c.y) || isinf(c.z);
  289. }
  290. #endif