From cd8f3c9ee7abb60457384779d8a2c00405402046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 15 Jul 2020 16:38:44 +0200 Subject: DRW: Add glsl math libraries Copied from eevee bsdf_common_lib.glsl --- .../draw/intern/shaders/common_math_geom_lib.glsl | 119 +++++++++++++++++++ .../draw/intern/shaders/common_math_lib.glsl | 130 +++++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 source/blender/draw/intern/shaders/common_math_geom_lib.glsl create mode 100644 source/blender/draw/intern/shaders/common_math_lib.glsl diff --git a/source/blender/draw/intern/shaders/common_math_geom_lib.glsl b/source/blender/draw/intern/shaders/common_math_geom_lib.glsl new file mode 100644 index 00000000000..e337376d7c4 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_math_geom_lib.glsl @@ -0,0 +1,119 @@ + +#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; +} + +/** \} */ \ No newline at end of file diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl new file mode 100644 index 00000000000..a82e0b5a5e9 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_math_lib.glsl @@ -0,0 +1,130 @@ + +/* ---------------------------------------------------------------------- */ +/** \name Common Math Utilities + * \{ */ + +#define M_PI 3.14159265358979323846 /* pi */ +#define M_2PI 6.28318530717958647692 /* 2*pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_1_PI 0.318309886183790671538 /* 1/pi */ +#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */ +#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */ +#define FLT_MAX 3.402823e+38 + +vec3 mul(mat3 m, vec3 v) +{ + return m * v; +} +mat3 mul(mat3 m1, mat3 m2) +{ + return m1 * m2; +} +vec3 transform_direction(mat4 m, vec3 v) +{ + return mat3(m) * v; +} +vec3 transform_point(mat4 m, vec3 v) +{ + return (m * vec4(v, 1.0)).xyz; +} +vec3 project_point(mat4 m, vec3 v) +{ + vec4 tmp = m * vec4(v, 1.0); + return tmp.xyz / tmp.w; +} + +#define min3(a, b, c) min(a, min(b, c)) +#define min4(a, b, c, d) min(a, min3(b, c, d)) +#define min5(a, b, c, d, e) min(a, min4(b, c, d, e)) +#define min6(a, b, c, d, e, f) min(a, min5(b, c, d, e, f)) +#define min7(a, b, c, d, e, f, g) min(a, min6(b, c, d, e, f, g)) +#define min8(a, b, c, d, e, f, g, h) min(a, min7(b, c, d, e, f, g, h)) +#define min9(a, b, c, d, e, f, g, h, i) min(a, min8(b, c, d, e, f, g, h, i)) + +#define max3(a, b, c) max(a, max(b, c)) +#define max4(a, b, c, d) max(a, max3(b, c, d)) +#define max5(a, b, c, d, e) max(a, max4(b, c, d, e)) +#define max6(a, b, c, d, e, f) max(a, max5(b, c, d, e, f)) +#define max7(a, b, c, d, e, f, g) max(a, max6(b, c, d, e, f, g)) +#define max8(a, b, c, d, e, f, g, h) max(a, max7(b, c, d, e, f, g, h)) +#define max9(a, b, c, d, e, f, g, h, i) max(a, max8(b, c, d, e, f, g, h, i)) + +#define avg3(a, b, c) (a + b + c) * (1.0 / 3.0) +#define avg4(a, b, c, d) (a + b + c + d) * (1.0 / 4.0) +#define avg5(a, b, c, d, e) (a + b + c + d + e) * (1.0 / 5.0) +#define avg6(a, b, c, d, e, f) (a + b + c + d + e + f) * (1.0 / 6.0) +#define avg7(a, b, c, d, e, f, g) (a + b + c + d + e + f + g) * (1.0 / 7.0) +#define avg8(a, b, c, d, e, f, g, h) (a + b + c + d + e + f + g + h) * (1.0 / 8.0) +#define avg9(a, b, c, d, e, f, g, h, i) (a + b + c + d + e + f + g + h + i) * (1.0 / 9.0) + +/* clang-format off */ +float min_v2(vec2 v) { return min(v.x, v.y); } +float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); } +float min_v4(vec4 v) { return min(min(v.x, v.y), min(v.z, v.w)); } +float max_v2(vec2 v) { return max(v.x, v.y); } +float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); } +float max_v4(vec4 v) { return max(max(v.x, v.y), max(v.z, v.w)); } + +float sum(vec2 v) { return dot(vec2(1.0), v); } +float sum(vec3 v) { return dot(vec3(1.0), v); } +float sum(vec4 v) { return dot(vec4(1.0), v); } + +float avg(vec2 v) { return dot(vec2(1.0 / 2.0), v); } +float avg(vec3 v) { return dot(vec3(1.0 / 3.0), v); } +float avg(vec4 v) { return dot(vec4(1.0 / 4.0), v); } +/* clang-format on */ + +#define saturate(a) clamp(a, 0.0, 1.0) + +float distance_squared(vec2 a, vec2 b) +{ + a -= b; + return dot(a, a); +} + +float distance_squared(vec3 a, vec3 b) +{ + a -= b; + return dot(a, a); +} + +float len_squared(vec3 a) +{ + return dot(a, a); +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Fast Math + * \{ */ + +/* [Drobot2014a] Low Level Optimizations for GCN */ +float fast_sqrt(float v) +{ + return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); +} + +vec2 fast_sqrt(vec2 v) +{ + return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); +} + +/* [Eberly2014] GPGPU Programming for Games and Science */ +float fast_acos(float v) +{ + float res = -0.156583 * abs(v) + M_PI_2; + res *= fast_sqrt(1.0 - abs(v)); + return (v >= 0) ? res : M_PI - res; +} + +vec2 fast_acos(vec2 v) +{ + vec2 res = -0.156583 * abs(v) + M_PI_2; + res *= fast_sqrt(1.0 - abs(v)); + v.x = (v.x >= 0) ? res.x : M_PI - res.x; + v.y = (v.y >= 0) ? res.y : M_PI - res.y; + return v; +} + +/** \} */ -- cgit v1.2.3