math.glsl 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /* math.glsl -- Contains everything you need for maths
  2. *
  3. * Copyright (c) 2025 Le Juez Victor
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * For conditions of distribution and use, see accompanying LICENSE file.
  7. */
  8. /* === Constants === */
  9. #define M_PI 3.1415926535897931
  10. #define M_HPI 1.5707963267948966
  11. #define M_TAU 6.2831853071795862
  12. #define M_INV_PI 0.3183098861837907
  13. /* === Functions === */
  14. vec3 M_Rotate3D(vec3 v, vec4 q)
  15. {
  16. vec3 t = 2.0 * cross(q.xyz, v);
  17. return v + q.w * t + cross(q.xyz, t);
  18. }
  19. mat3 M_OrthonormalBasis(vec3 n)
  20. {
  21. // Previously we used Frisvad's method to generate a stable orthonormal basis
  22. // SEE: https://backend.orbit.dtu.dk/ws/portalfiles/portal/126824972/onb_frisvad_jgt2012_v2.pdf
  23. // However, it can cause visible artifacts (eg. bright pixels on the -Z face of irradiance cubemaps)
  24. // So now we use the revised method by Duff et al., it's more accurate, though slightly slower
  25. // SEE: https://graphics.pixar.com/library/OrthonormalB/paper.pdf
  26. float sgn = n.z >= 0.0 ? 1.0 : -1.0;
  27. float a = -1.0 / (sgn + n.z);
  28. float b = n.x * n.y * a;
  29. vec3 t = vec3(1.0 + sgn * n.x * n.x * a, sgn * b, -sgn * n.x);
  30. vec3 bt = vec3(b, sgn + n.y * n.y * a, -n.y);
  31. return mat3(t, bt, n);
  32. }
  33. vec2 M_OctahedronWrap(vec2 val)
  34. {
  35. // Reference(s):
  36. // - Octahedron normal vector encoding
  37. // https://web.archive.org/web/20191027010600/https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/comment-page-1/
  38. return (1.0 - abs(val.yx)) * mix(vec2(-1.0), vec2(1.0), vec2(greaterThanEqual(val.xy, vec2(0.0))));
  39. }
  40. vec3 M_DecodeOctahedral(vec2 encoded)
  41. {
  42. encoded = encoded * 2.0 - 1.0;
  43. vec3 normal;
  44. normal.z = 1.0 - abs(encoded.x) - abs(encoded.y);
  45. normal.xy = normal.z >= 0.0 ? encoded.xy : M_OctahedronWrap(encoded.xy);
  46. return normalize(normal);
  47. }
  48. vec2 M_EncodeOctahedral(vec3 normal)
  49. {
  50. normal /= abs(normal.x) + abs(normal.y) + abs(normal.z);
  51. normal.xy = normal.z >= 0.0 ? normal.xy : M_OctahedronWrap(normal.xy);
  52. normal.xy = normal.xy * 0.5 + 0.5;
  53. return normal.xy;
  54. }
  55. vec3 M_NormalScale(vec3 normal, float scale)
  56. {
  57. normal.xy *= scale;
  58. normal.z = sqrt(1.0 - clamp(dot(normal.xy, normal.xy), 0.0, 1.0));
  59. return normal;
  60. }
  61. float M_HashIGN(vec2 pos)
  62. {
  63. // http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
  64. const vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
  65. return fract(magic.z * fract(dot(pos, magic.xy)));
  66. }