1 2#pragma BLENDER_REQUIRE(common_math_lib.glsl) 3 4/* ---------------------------------------------------------------------- */ 5/** \name Math intersection & projection functions. 6 * \{ */ 7 8float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal) 9{ 10 return dot(planenormal, planeorigin - lineorigin); 11} 12 13float line_plane_intersect_dist(vec3 lineorigin, 14 vec3 linedirection, 15 vec3 planeorigin, 16 vec3 planenormal) 17{ 18 return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection); 19} 20 21float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane) 22{ 23 vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz)); 24 vec3 h = lineorigin - plane_co; 25 return -dot(plane.xyz, h) / dot(plane.xyz, linedirection); 26} 27 28vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) 29{ 30 float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal); 31 return lineorigin + linedirection * dist; 32} 33 34vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane) 35{ 36 float dist = line_plane_intersect_dist(lineorigin, linedirection, plane); 37 return lineorigin + linedirection * dist; 38} 39 40float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) 41{ 42 /* aligned plane normal */ 43 vec3 L = planeorigin - lineorigin; 44 float diskdist = length(L); 45 vec3 planenormal = -normalize(L); 46 return -diskdist / dot(planenormal, linedirection); 47} 48 49vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) 50{ 51 float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin); 52 if (dist < 0) { 53 /* if intersection is behind we fake the intersection to be 54 * really far and (hopefully) not inside the radius of interest */ 55 dist = 1e16; 56 } 57 return lineorigin + linedirection * dist; 58} 59 60float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) 61{ 62 float a = dot(linedirection, linedirection); 63 float b = dot(linedirection, lineorigin); 64 float c = dot(lineorigin, lineorigin) - 1; 65 66 float dist = 1e15; 67 float determinant = b * b - a * c; 68 if (determinant >= 0) { 69 dist = (sqrt(determinant) - b) / a; 70 } 71 72 return dist; 73} 74 75float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) 76{ 77 /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ 78 */ 79 vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; 80 vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; 81 vec3 furthestplane = max(firstplane, secondplane); 82 83 return min_v3(furthestplane); 84} 85 86/** \} */ 87 88/* ---------------------------------------------------------------------- */ 89/** \name Other useful functions. 90 * \{ */ 91 92void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) 93{ 94 vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); 95 T = normalize(cross(UpVector, N)); 96 B = cross(N, T); 97} 98 99/* ---- Encode / Decode Normal buffer data ---- */ 100/* From http://aras-p.info/texts/CompactNormalStorage.html 101 * Using Method #4: Spheremap Transform */ 102vec2 normal_encode(vec3 n, vec3 view) 103{ 104 float p = sqrt(n.z * 8.0 + 8.0); 105 return n.xy / p + 0.5; 106} 107 108vec3 normal_decode(vec2 enc, vec3 view) 109{ 110 vec2 fenc = enc * 4.0 - 2.0; 111 float f = dot(fenc, fenc); 112 float g = sqrt(1.0 - f / 4.0); 113 vec3 n; 114 n.xy = fenc * g; 115 n.z = 1 - f / 2; 116 return n; 117} 118 119/** \} */ 120