120 lines
3.5 KiB
GLSL
120 lines
3.5 KiB
GLSL
|
|
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/** \name Math intersection & projection functions.
|
|
* \{ */
|
|
|
|
float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal)
|
|
{
|
|
return dot(planenormal, planeorigin - lineorigin);
|
|
}
|
|
|
|
float line_plane_intersect_dist(vec3 lineorigin,
|
|
vec3 linedirection,
|
|
vec3 planeorigin,
|
|
vec3 planenormal)
|
|
{
|
|
return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
|
|
}
|
|
|
|
float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane)
|
|
{
|
|
vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz));
|
|
vec3 h = lineorigin - plane_co;
|
|
return -dot(plane.xyz, h) / dot(plane.xyz, linedirection);
|
|
}
|
|
|
|
vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
|
|
{
|
|
float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal);
|
|
return lineorigin + linedirection * dist;
|
|
}
|
|
|
|
vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane)
|
|
{
|
|
float dist = line_plane_intersect_dist(lineorigin, linedirection, plane);
|
|
return lineorigin + linedirection * dist;
|
|
}
|
|
|
|
float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
|
|
{
|
|
/* aligned plane normal */
|
|
vec3 L = planeorigin - lineorigin;
|
|
float diskdist = length(L);
|
|
vec3 planenormal = -normalize(L);
|
|
return -diskdist / dot(planenormal, linedirection);
|
|
}
|
|
|
|
vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
|
|
{
|
|
float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin);
|
|
if (dist < 0) {
|
|
/* if intersection is behind we fake the intersection to be
|
|
* really far and (hopefully) not inside the radius of interest */
|
|
dist = 1e16;
|
|
}
|
|
return lineorigin + linedirection * dist;
|
|
}
|
|
|
|
float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection)
|
|
{
|
|
float a = dot(linedirection, linedirection);
|
|
float b = dot(linedirection, lineorigin);
|
|
float c = dot(lineorigin, lineorigin) - 1;
|
|
|
|
float dist = 1e15;
|
|
float determinant = b * b - a * c;
|
|
if (determinant >= 0) {
|
|
dist = (sqrt(determinant) - b) / a;
|
|
}
|
|
|
|
return dist;
|
|
}
|
|
|
|
float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection)
|
|
{
|
|
/* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
|
*/
|
|
vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection;
|
|
vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection;
|
|
vec3 furthestplane = max(firstplane, secondplane);
|
|
|
|
return min_v3(furthestplane);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
/** \name Other useful functions.
|
|
* \{ */
|
|
|
|
void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
|
|
{
|
|
vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
T = normalize(cross(UpVector, N));
|
|
B = cross(N, T);
|
|
}
|
|
|
|
/* ---- Encode / Decode Normal buffer data ---- */
|
|
/* From http://aras-p.info/texts/CompactNormalStorage.html
|
|
* Using Method #4: Spheremap Transform */
|
|
vec2 normal_encode(vec3 n, vec3 view)
|
|
{
|
|
float p = sqrt(n.z * 8.0 + 8.0);
|
|
return n.xy / p + 0.5;
|
|
}
|
|
|
|
vec3 normal_decode(vec2 enc, vec3 view)
|
|
{
|
|
vec2 fenc = enc * 4.0 - 2.0;
|
|
float f = dot(fenc, fenc);
|
|
float g = sqrt(1.0 - f / 4.0);
|
|
vec3 n;
|
|
n.xy = fenc * g;
|
|
n.z = 1 - f / 2;
|
|
return n;
|
|
}
|
|
|
|
/** \} */
|