GPU: Math: Add safe_rcp and safe_normalize to math libs

This commit is contained in:
Clément Foucault
2023-06-22 22:51:07 +02:00
parent b1f7c87b99
commit 8d2d2d4620
3 changed files with 99 additions and 1 deletions

View File

@@ -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)
{

View File

@@ -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.
*/

View File

@@ -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);