GPU: Math: Add safe_rcp and safe_normalize to math libs
This commit is contained in:
@@ -94,10 +94,15 @@ 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); }
|
||||
|
||||
/* WORKAROUND: To be removed once we port all code to use gpu_shader_math_base_lib.glsl. */
|
||||
#ifndef GPU_SHADER_MATH_BASE_LIB_GLSL
|
||||
float safe_rcp(float a) { return (a != 0.0) ? (1.0 / a) : 0.0; }
|
||||
#endif
|
||||
#ifndef GPU_SHADER_MATH_VECTOR_LIB_GLSL
|
||||
vec2 safe_rcp(vec2 a) { return select(vec2(0.0), (1.0 / a), notEqual(a, vec2(0.0))); }
|
||||
vec3 safe_rcp(vec3 a) { return select(vec3(0.0), (1.0 / a), notEqual(a, vec3(0.0))); }
|
||||
vec4 safe_rcp(vec4 a) { return select(vec4(0.0), (1.0 / a), notEqual(a, vec4(0.0))); }
|
||||
#endif
|
||||
|
||||
float safe_sqrt(float a) { return sqrt(max(a, 0.0)); }
|
||||
|
||||
@@ -206,7 +211,6 @@ float distance_squared(vec3 a, vec3 b)
|
||||
a -= b;
|
||||
return dot(a, a);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 safe_normalize(vec3 v)
|
||||
{
|
||||
@@ -216,6 +220,7 @@ vec3 safe_normalize(vec3 v)
|
||||
}
|
||||
return v / len;
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 safe_normalize_len(vec2 v, out float len)
|
||||
{
|
||||
@@ -226,11 +231,14 @@ vec2 safe_normalize_len(vec2 v, out float len)
|
||||
return v / len;
|
||||
}
|
||||
|
||||
/* WORKAROUND: To be removed once we port all code to use gpu_shader_math_base_lib.glsl. */
|
||||
#ifndef GPU_SHADER_MATH_VECTOR_LIB_GLSL
|
||||
vec2 safe_normalize(vec2 v)
|
||||
{
|
||||
float len;
|
||||
return safe_normalize_len(v, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 normalize_len(vec3 v, out float len)
|
||||
{
|
||||
|
||||
@@ -139,6 +139,15 @@ float safe_divide(float a, float b)
|
||||
return (b != 0.0) ? (a / b) : 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe reciprocal function. Returns `1/a`.
|
||||
* If `a` equal 0 the result will be 0.
|
||||
*/
|
||||
float safe_rcp(float a)
|
||||
{
|
||||
return (a != 0.0) ? (1.0 / a) : 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the difference between`a` and `b` is below the `epsilon` value.
|
||||
*/
|
||||
|
||||
@@ -123,6 +123,21 @@ vec2 normalize_and_get_length(vec2 vector, out float out_length);
|
||||
vec3 normalize_and_get_length(vec3 vector, out float out_length);
|
||||
vec4 normalize_and_get_length(vec4 vector, out float out_length);
|
||||
|
||||
/**
|
||||
* Return normalized version of the `vector` or a default normalized vector if `vector` is invalid.
|
||||
*/
|
||||
vec2 safe_normalize(vec2 vector);
|
||||
vec3 safe_normalize(vec3 vector);
|
||||
vec4 safe_normalize(vec4 vector);
|
||||
|
||||
/**
|
||||
* Safe reciprocal function. Returns `1/a`.
|
||||
* If `a` equal 0 the result will be 0.
|
||||
*/
|
||||
vec2 safe_rcp(vec2 a);
|
||||
vec3 safe_rcp(vec3 a);
|
||||
vec4 safe_rcp(vec4 a);
|
||||
|
||||
/**
|
||||
* Per component linear interpolation.
|
||||
*/
|
||||
@@ -443,6 +458,72 @@ vec4 normalize_and_get_length(vec4 vector, out float out_length)
|
||||
return vec4(0.0);
|
||||
}
|
||||
|
||||
vec2 safe_normalize_and_get_length(vec2 vector, out float out_length)
|
||||
{
|
||||
out_length = length_squared(vector);
|
||||
const float threshold = 1e-35f;
|
||||
if (out_length > threshold) {
|
||||
out_length = sqrt(out_length);
|
||||
return vector / out_length;
|
||||
}
|
||||
/* Either the vector is small or one of it's values contained `nan`. */
|
||||
out_length = 1.0;
|
||||
return vec2(1.0, 0.0);
|
||||
}
|
||||
vec3 safe_normalize_and_get_length(vec3 vector, out float out_length)
|
||||
{
|
||||
out_length = length_squared(vector);
|
||||
const float threshold = 1e-35f;
|
||||
if (out_length > threshold) {
|
||||
out_length = sqrt(out_length);
|
||||
return vector / out_length;
|
||||
}
|
||||
/* Either the vector is small or one of it's values contained `nan`. */
|
||||
out_length = 1.0;
|
||||
return vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
vec4 safe_normalize_and_get_length(vec4 vector, out float out_length)
|
||||
{
|
||||
out_length = length_squared(vector);
|
||||
const float threshold = 1e-35f;
|
||||
if (out_length > threshold) {
|
||||
out_length = sqrt(out_length);
|
||||
return vector / out_length;
|
||||
}
|
||||
/* Either the vector is small or one of it's values contained `nan`. */
|
||||
out_length = 1.0;
|
||||
return vec4(1.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
vec2 safe_normalize(vec2 vector)
|
||||
{
|
||||
float unused_length;
|
||||
return safe_normalize_and_get_length(vector, unused_length);
|
||||
}
|
||||
vec3 safe_normalize(vec3 vector)
|
||||
{
|
||||
float unused_length;
|
||||
return safe_normalize_and_get_length(vector, unused_length);
|
||||
}
|
||||
vec4 safe_normalize(vec4 vector)
|
||||
{
|
||||
float unused_length;
|
||||
return safe_normalize_and_get_length(vector, unused_length);
|
||||
}
|
||||
|
||||
vec2 safe_rcp(vec2 a)
|
||||
{
|
||||
return select(vec2(0.0), (1.0 / a), notEqual(a, vec2(0.0)));
|
||||
}
|
||||
vec3 safe_rcp(vec3 a)
|
||||
{
|
||||
return select(vec3(0.0), (1.0 / a), notEqual(a, vec3(0.0)));
|
||||
}
|
||||
vec4 safe_rcp(vec4 a)
|
||||
{
|
||||
return select(vec4(0.0), (1.0 / a), notEqual(a, vec4(0.0)));
|
||||
}
|
||||
|
||||
vec2 interpolate(vec2 a, vec2 b, float t)
|
||||
{
|
||||
return mix(a, b, t);
|
||||
|
||||
Reference in New Issue
Block a user