ltc.glsl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Linearly Transformed Cosines
  2. // https://eheitzresearch.wordpress.com/415-2/
  3. #ifndef _LTC_GLSL_
  4. #define _LTC_GLSL_
  5. const float LUT_SIZE = 64.0;
  6. const float LUT_SCALE = (LUT_SIZE - 1.0) / LUT_SIZE;
  7. const float LUT_BIAS = 0.5 / LUT_SIZE;
  8. float integrateEdge(vec3 v1, vec3 v2) {
  9. float cosTheta = dot(v1, v2);
  10. float theta = acos(cosTheta);
  11. float res = cross(v1, v2).z * ((theta > 0.001) ? theta / sin(theta) : 1.0);
  12. return res;
  13. }
  14. float ltcEvaluate(vec3 N, vec3 V, float dotNV, vec3 P, mat3 Minv, vec3 points0, vec3 points1, vec3 points2, vec3 points3) {
  15. // Construct orthonormal basis around N
  16. vec3 T1, T2;
  17. T1 = normalize(V - N * dotNV);
  18. T2 = cross(N, T1);
  19. // Rotate area light in (T1, T2, R) basis
  20. Minv = Minv * transpose(mat3(T1, T2, N));
  21. // Polygon (allocate 5 vertices for clipping)
  22. vec3 L0 = Minv * (points0 - P);
  23. vec3 L1 = Minv * (points1 - P);
  24. vec3 L2 = Minv * (points2 - P);
  25. vec3 L3 = Minv * (points3 - P);
  26. vec3 L4 = vec3(0.0);
  27. int n = 0;
  28. // Detect clipping config
  29. int config = 0;
  30. if (L0.z > 0.0) config += 1;
  31. if (L1.z > 0.0) config += 2;
  32. if (L2.z > 0.0) config += 4;
  33. if (L3.z > 0.0) config += 8;
  34. // Clip
  35. if (config == 0) {
  36. // Clip all
  37. }
  38. else if (config == 1) { // V1 clip V2 V3 V4
  39. n = 3;
  40. L1 = -L1.z * L0 + L0.z * L1;
  41. L2 = -L3.z * L0 + L0.z * L3;
  42. }
  43. else if (config == 2) { // V2 clip V1 V3 V4
  44. n = 3;
  45. L0 = -L0.z * L1 + L1.z * L0;
  46. L2 = -L2.z * L1 + L1.z * L2;
  47. }
  48. else if (config == 3) { // V1 V2 clip V3 V4
  49. n = 4;
  50. L2 = -L2.z * L1 + L1.z * L2;
  51. L3 = -L3.z * L0 + L0.z * L3;
  52. }
  53. else if (config == 4) { // V3 clip V1 V2 V4
  54. n = 3;
  55. L0 = -L3.z * L2 + L2.z * L3;
  56. L1 = -L1.z * L2 + L2.z * L1;
  57. }
  58. else if (config == 5) { // V1 V3 clip V2 V4) impossible
  59. n = 0;
  60. }
  61. else if (config == 6) { // V2 V3 clip V1 V4
  62. n = 4;
  63. L0 = -L0.z * L1 + L1.z * L0;
  64. L3 = -L3.z * L2 + L2.z * L3;
  65. }
  66. else if (config == 7) { // V1 V2 V3 clip V4
  67. n = 5;
  68. L4 = -L3.z * L0 + L0.z * L3;
  69. L3 = -L3.z * L2 + L2.z * L3;
  70. }
  71. else if (config == 8) { // V4 clip V1 V2 V3
  72. n = 3;
  73. L0 = -L0.z * L3 + L3.z * L0;
  74. L1 = -L2.z * L3 + L3.z * L2;
  75. L2 = L3;
  76. }
  77. else if (config == 9) { // V1 V4 clip V2 V3
  78. n = 4;
  79. L1 = -L1.z * L0 + L0.z * L1;
  80. L2 = -L2.z * L3 + L3.z * L2;
  81. }
  82. else if (config == 10) { // V2 V4 clip V1 V3) impossible
  83. n = 0;
  84. }
  85. else if (config == 11) { // V1 V2 V4 clip V3
  86. n = 5;
  87. L4 = L3;
  88. L3 = -L2.z * L3 + L3.z * L2;
  89. L2 = -L2.z * L1 + L1.z * L2;
  90. }
  91. else if (config == 12) { // V3 V4 clip V1 V2
  92. n = 4;
  93. L1 = -L1.z * L2 + L2.z * L1;
  94. L0 = -L0.z * L3 + L3.z * L0;
  95. }
  96. else if (config == 13) { // V1 V3 V4 clip V2
  97. n = 5;
  98. L4 = L3;
  99. L3 = L2;
  100. L2 = -L1.z * L2 + L2.z * L1;
  101. L1 = -L1.z * L0 + L0.z * L1;
  102. }
  103. else if (config == 14) { // V2 V3 V4 clip V1
  104. n = 5;
  105. L4 = -L0.z * L3 + L3.z * L0;
  106. L0 = -L0.z * L1 + L1.z * L0;
  107. }
  108. else if (config == 15) { // V1 V2 V3 V4
  109. n = 4;
  110. }
  111. if (n == 0) return 0.0;
  112. if (n == 3) L3 = L0;
  113. if (n == 4) L4 = L0;
  114. // Project onto sphere
  115. L0 = normalize(L0);
  116. L1 = normalize(L1);
  117. L2 = normalize(L2);
  118. L3 = normalize(L3);
  119. L4 = normalize(L4);
  120. // Integrate
  121. float sum = 0.0;
  122. sum += integrateEdge(L0, L1);
  123. sum += integrateEdge(L1, L2);
  124. sum += integrateEdge(L2, L3);
  125. if (n >= 4) sum += integrateEdge(L3, L4);
  126. if (n == 5) sum += integrateEdge(L4, L0);
  127. return max(0.0, -sum);
  128. }
  129. #endif