functions.chunk 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // helper functions for lighting model-functions
  2. // return unnormalized vector, support oppo-side
  3. // V from pixel to camera
  4. vec3 CalculateRefractDirection(vec3 N, vec3 V, float NoV, float ior)
  5. {
  6. // two sided
  7. float sideSign = NoV < 0.0 ? -1.0 : 1.0;
  8. N *= sideSign;
  9. // A: NV B:NR
  10. float cosA = abs(NoV);
  11. float sinA = sqrt(1.0 - cosA * cosA);
  12. float sinB = saturate(sinA / ior);
  13. float cosB = sqrt(1.0 - sinB * sinB);
  14. vec3 edgeA = -V + N * cosA;
  15. vec3 edgeB = normalize(edgeA) * sinB;
  16. vec3 R = edgeB - N * cosB;
  17. return R;
  18. }
  19. vec3 CalculateRefractDirectionFast(vec3 N, vec3 V, float NoV, float ior)
  20. {
  21. // two sided
  22. float sideSign = NoV < 0.0 ? -1.0 : 1.0;
  23. N *= sideSign;
  24. float w = ior * NoV;
  25. float k = sqrt(1.0 + (w - ior) * (w + ior)); // 1 + ior2 * (NoV2 - 1)
  26. vec3 R = (w - k) * N - ior * V;
  27. return -R;
  28. }
  29. vec3 CalculateReflectDirection(vec3 N, vec3 V, float NoV)
  30. {
  31. // two sided
  32. float sideSign = NoV < 0.0 ? -1.0 : 1.0;
  33. N *= sideSign;
  34. return reflect(-V, N);
  35. }
  36. // for bumped planar reflection
  37. vec3 CalculatePlanarReflectPositionOnPlane(vec3 N, vec3 V, vec3 worldPos, vec4 plane, vec3 cameraPos, float probeReflectedDepth)
  38. {
  39. float distPixelToPlane = -dot(plane, vec4(worldPos, 1.0));
  40. // bring plane to worldPos, avoid artifacts when reflected point away from plane (do not bring worldPos to plane)
  41. plane.w += distPixelToPlane;
  42. float distCameraToPlane = abs(-dot(plane, vec4(cameraPos, 1.0)));
  43. vec3 planeN = plane.xyz;
  44. vec3 virtualCameraPos = cameraPos - 2.0 * distCameraToPlane * planeN;
  45. /*support for two-sided reflections
  46. float sideSignPlaneN = dot(planeN, V) < 0.0 ? -1.0 : 1.0;
  47. float sideSignN = dot(N, V) < 0.0 ? -1.0 : 1.0;
  48. planeN *= sideSignPlaneN;
  49. N *= sideSignN;*/
  50. vec3 bumpedR = normalize(reflect(-V, N)); //R'
  51. // actually reflected pos alone bumpedR direction, avoid tracing by specified a fake depth
  52. vec3 reflectedPointPos = worldPos + probeReflectedDepth * bumpedR;
  53. vec3 virtualCameraToReflectedPoint = normalize(reflectedPointPos - virtualCameraPos);
  54. // the ray from virtual camera to reflected point, will intersect with plane on P'
  55. float y = distCameraToPlane / max(EPSILON_LOWP, dot(planeN, virtualCameraToReflectedPoint));
  56. return virtualCameraPos + y * virtualCameraToReflectedPoint;
  57. }
  58. // fix cubemap direction with box projection
  59. // return unnormalized vector and weight for exceeding
  60. vec4 CalculateBoxProjectedDirection(vec3 R, vec3 worldPos, vec3 cubeCenterPos, vec3 cubeBoxHalfSize)
  61. {
  62. // point W is the worldPos in the space origin align with cube center
  63. vec3 W = worldPos - cubeCenterPos;
  64. // find point P which intersected with cube box border from W alone R
  65. vec3 projectedLength = (sign(R) * cubeBoxHalfSize - W) / (R + vec3(EPSILON));
  66. float len = min(min(projectedLength.x, projectedLength.y), projectedLength.z);
  67. vec3 P = W + len * R;
  68. float weight = len < 0.0 ? 0.0 : 1.0;
  69. return vec4(P, weight);
  70. }
  71. // calculate planar world pos
  72. vec4 CalculatePlanarShadowPos(vec3 meshWorldPos, vec3 cameraPos, vec3 lightDir, vec4 plane) {
  73. vec3 P = meshWorldPos;
  74. vec3 L = lightDir;
  75. vec3 N = plane.xyz;
  76. float d = plane.w + EPSILON_LOWP;
  77. float dist = (-d - dot(P, N)) / (dot(L, N) + EPSILON_LOWP);
  78. vec3 shadowPos = P + L * dist;
  79. return vec4(shadowPos, dist);
  80. }
  81. // calculate planar clip pos from world pos
  82. vec4 CalculatePlanarShadowClipPos(vec4 shadowPos, vec3 cameraPos, mat4 matView, mat4 matProj, vec4 nearFar, float bias) {
  83. vec4 camPos = matView * vec4(shadowPos.xyz, 1.0);
  84. // avoid z-fighting with shadow receive plane, add camera bias with perspective correction
  85. // notice that near plane should not be too small, assume near 1, far 1000
  86. float lerpCoef = saturate((nearFar.z < 0.0 ? -camPos.z : camPos.z) / (nearFar.y - nearFar.x));
  87. camPos.z += mix(nearFar.x * 0.01, nearFar.y * EPSILON_LOWP * bias, lerpCoef);
  88. return matProj * camPos;
  89. }