//------------------------------------------------------------------------------ // Common math //------------------------------------------------------------------------------ /** @public-api */ #define PI 3.14159265359 /** @public-api */ #define HALF_PI 1.570796327 #define MEDIUMP_FLT_MAX 65504.0 #define MEDIUMP_FLT_MIN 0.00006103515625 #ifdef TARGET_MOBILE #define FLT_EPS MEDIUMP_FLT_MIN #define saturateMediump(x) min(x, MEDIUMP_FLT_MAX) #else #define FLT_EPS 1e-5 #define saturateMediump(x) x #endif #define saturate(x) clamp(x, 0.0, 1.0) #define atan2(x, y) atan(y, x) //------------------------------------------------------------------------------ // Scalar operations //------------------------------------------------------------------------------ /** * Computes x^5 using only multiply operations. * * @public-api */ float pow5(float x) { float x2 = x * x; return x2 * x2 * x; } /** * Computes x^2 as a single multiplication. * * @public-api */ float sq(float x) { return x * x; } //------------------------------------------------------------------------------ // Vector operations //------------------------------------------------------------------------------ /** * Returns the maximum component of the specified vector. * * @public-api */ float max3(const vec3 v) { return max(v.x, max(v.y, v.z)); } /** * Returns the minimum component of the specified vector. * * @public-api */ float min3(const vec3 v) { return min(v.x, min(v.y, v.z)); } //------------------------------------------------------------------------------ // Trigonometry //------------------------------------------------------------------------------ /** * Approximates acos(x) with a max absolute error of 9.0x10^-3. * Valid in the range -1..1. */ float acosFast(float x) { // Lagarde 2014, "Inverse trigonometric functions GPU optimization for AMD GCN architecture" // This is the approximation of degree 1, with a max absolute error of 9.0x10^-3 float y = abs(x); float p = -0.1565827 * y + 1.570796; p *= sqrt(1.0 - y); return x >= 0.0 ? p : PI - p; } /** * Approximates acos(x) with a max absolute error of 9.0x10^-3. * Valid only in the range 0..1. */ float acosFastPositive(float x) { float p = -0.1565827 * x + 1.570796; return p * sqrt(1.0 - x); } //------------------------------------------------------------------------------ // Matrix and quaternion operations //------------------------------------------------------------------------------ /** * Multiplies the specified 3-component vector by the 4x4 matrix (m * v) in * high precision. * * @public-api */ vec4 mulMat4x4Float3(const highp mat4 m, const highp vec3 v) { return v.x * m[0] + (v.y * m[1] + (v.z * m[2] + m[3])); } /** * Multiplies the specified 3-component vector by the 3x3 matrix (m * v) in * high precision. * * @public-api */ vec3 mulMat3x3Float3(const highp mat4 m, const highp vec3 v) { return v.x * m[0].xyz + (v.y * m[1].xyz + (v.z * m[2].xyz)); } /** * Extracts the normal vector of the tangent frame encoded in the specified quaternion. */ void toTangentFrame(const highp vec4 q, out highp vec3 n) { n = vec3( 0.0, 0.0, 1.0) + vec3( 2.0, -2.0, -2.0) * q.x * q.zwx + vec3( 2.0, 2.0, -2.0) * q.y * q.wzy; } /** * Extracts the normal and tangent vectors of the tangent frame encoded in the * specified quaternion. */ void toTangentFrame(const highp vec4 q, out highp vec3 n, out highp vec3 t) { toTangentFrame(q, n); t = vec3( 1.0, 0.0, 0.0) + vec3(-2.0, 2.0, -2.0) * q.y * q.yxw + vec3(-2.0, 2.0, 2.0) * q.z * q.zwx; }