glm_perlin_vec3 impl

This commit is contained in:
Marcin
2025-01-17 15:46:30 +00:00
parent fbdc46b205
commit 5f241a2daf

View File

@@ -19,6 +19,9 @@
#include "vec4.h"
#include "vec4-ext.h"
#include "vec3.h"
#include "vec3-ext.h"
#include "vec2.h"
#include "vec2-ext.h"
@@ -40,6 +43,20 @@ _glm_vec4_floor(vec4 x, vec4 dest) {
dest[3] = floorf(x[3]);
}
/*!
* @brief floor each element of v, result is written to dest
*
* @param[in] v vector
* @param[out] dest destination vector
*/
CGLM_INLINE
void
_glm_vec3_floor(vec3 x, vec3 dest) {
dest[0] = floorf(x[0]);
dest[1] = floorf(x[1]);
dest[2] = floorf(x[2]);
}
/*!
* @brief mod v by a scalar, result is written to dest (dest = v % s)
*
@@ -56,6 +73,22 @@ _glm_vec4_mods(vec4 x, float y, vec4 dest) {
dest[3] = fmodf(x[3], y);
}
/*!
* @brief mod v by a scalar, result is written to dest (dest = v % s)
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest destination vector
*/
CGLM_INLINE
void
_glm_vec3_mods(vec3 x, float y, vec3 dest) {
dest[0] = fmodf(x[0], y);
dest[1] = fmodf(x[1], y);
dest[2] = fmodf(x[2], y);
}
/*!
* @brief threshold function with scalar
*
@@ -72,6 +105,21 @@ _glm_vec4_steps(vec4 edge, float x, vec4 dest) {
dest[3] = glm_step(edge[3], x);
}
/*!
* @brief threshold function with scalar
*
* @param[in] edge threshold
* @param[in] x value to test against threshold
* @param[out] dest destination
*/
CGLM_INLINE
void
_glm_vec3_steps(vec3 edge, float x, vec3 dest) {
dest[0] = glm_step(edge[0], x);
dest[1] = glm_step(edge[1], x);
dest[2] = glm_step(edge[2], x);
}
/*!
* @brief set all elements of dest to value
*
@@ -87,6 +135,20 @@ _glm_vec4_sets(vec4 v, float x) {
v[3] = x;
}
/*!
* @brief set all elements of dest to value
*
* @param[in] vector threshold
* @param[in] x value
*/
CGLM_INLINE
void
_glm_vec3_sets(vec3 v, float x) {
v[0] = x;
v[1] = x;
v[2] = x;
}
/*!
* @brief mul v by a scalar, result is written to dest (dest = v * s)
*
@@ -103,6 +165,21 @@ _glm_vec4_muls(vec4 x, float y, vec4 dest) {
dest[3] = x[3] * y;
}
/*!
* @brief mul v by a scalar, result is written to dest (dest = v * s)
*
* @param[in] v vector
* @param[in] s scalar
* @param[out] dest destination vector
*/
CGLM_INLINE
void
_glm_vec3_muls(vec3 x, float y, vec3 dest) {
dest[0] = x[0] * y;
dest[1] = x[1] * y;
dest[2] = x[2] * y;
}
//////////////////////////////
// GLM noise detail functions
@@ -124,13 +201,21 @@ _glm_noiseDetail_permute(vec4 x, vec4 dest) {
CGLM_INLINE
void
_glm_noiseDetail_fade(vec4 t, vec4 dest) {
_glm_noiseDetail_fade_vec4(vec4 t, vec4 dest) {
dest[0] = (t[0] * t[0] * t[0]) * (t[0] * (t[0] * 6.0f - 15.0f) + 10.0f);
dest[1] = (t[1] * t[1] * t[1]) * (t[1] * (t[1] * 6.0f - 15.0f) + 10.0f);
dest[2] = (t[2] * t[2] * t[2]) * (t[2] * (t[2] * 6.0f - 15.0f) + 10.0f);
dest[3] = (t[3] * t[3] * t[3]) * (t[3] * (t[3] * 6.0f - 15.0f) + 10.0f);
}
CGLM_INLINE
void
_glm_noiseDetail_fade_vec3(vec3 t, vec3 dest) {
dest[0] = (t[0] * t[0] * t[0]) * (t[0] * (t[0] * 6.0f - 15.0f) + 10.0f);
dest[1] = (t[1] * t[1] * t[1]) * (t[1] * (t[1] * 6.0f - 15.0f) + 10.0f);
dest[2] = (t[2] * t[2] * t[2]) * (t[2] * (t[2] * 6.0f - 15.0f) + 10.0f);
}
CGLM_INLINE
void
_glm_noiseDetail_taylorInvSqrt(vec4 x, vec4 dest) {
@@ -141,7 +226,7 @@ _glm_noiseDetail_taylorInvSqrt(vec4 x, vec4 dest) {
}
/*!
* @brief Normalize gradients inplace
* @brief Normalize 4D gradients inplace
*
* @param[in, out] g00__ gradient from point 00
* @param[in, out] g01__ gradient from point 01
@@ -150,7 +235,7 @@ _glm_noiseDetail_taylorInvSqrt(vec4 x, vec4 dest) {
*/
CGLM_INLINE
void
_glm_noiseDetail_gradNorm(vec4 g00__, vec4 g01__, vec4 g10__, vec4 g11__) {
_glm_noiseDetail_gradNorm_vec4(vec4 g00__, vec4 g01__, vec4 g10__, vec4 g11__) {
// norm = taylorInvSqrt(vec4(
// dot(g00__, g00__),
@@ -171,9 +256,42 @@ _glm_noiseDetail_gradNorm(vec4 g00__, vec4 g01__, vec4 g10__, vec4 g11__) {
_glm_vec4_muls(g11__, norm[3], g11__); // g11__ *= norm.w
}
/*!
* @brief Normalize 3D gradients inplace
*
* @param[in, out] g00__ gradient from point 00
* @param[in, out] g01__ gradient from point 01
* @param[in, out] g10__ gradient from point 10
* @param[in, out] g11__ gradient from point 11
*/
CGLM_INLINE
void
_glm_noiseDetail_xy2g(
_glm_noiseDetail_gradNorm_vec3(vec3 g00_, vec3 g01_, vec3 g10_, vec3 g11_) {
// norm = taylorInvSqrt(vec4(
// dot(g00_, g00_),
// dot(g01_, g01_),
// dot(g10_, g10_),
// dot(g11_, g11_)
// ));
vec4 norm;
norm[0] = glm_vec3_dot(g00_, g00_); // norm.x = dot(g00_, g00_)
norm[1] = glm_vec3_dot(g01_, g01_); // norm.y = dot(g01_, g01_)
norm[2] = glm_vec3_dot(g10_, g10_); // norm.z = dot(g10_, g10_)
norm[3] = glm_vec3_dot(g11_, g11_); // norm.w = dot(g11_, g11_)
_glm_noiseDetail_taylorInvSqrt(norm, norm); // norm = taylorInvSqrt(norm)
_glm_vec3_muls(g00_, norm[0], g00_); // g00_ *= norm.x
_glm_vec3_muls(g01_, norm[1], g01_); // g01_ *= norm.y
_glm_vec3_muls(g10_, norm[2], g10_); // g10_ *= norm.z
_glm_vec3_muls(g11_, norm[3], g11_); // g11_ *= norm.w
}
CGLM_INLINE
void
_glm_noiseDetail_xy2gxyzw(
vec4 ixy,
/* out */
vec4 gx,
@@ -205,11 +323,9 @@ _glm_noiseDetail_xy2g(
glm_vec4_subs(gz, 0.5f, gz); // gz -= 0.5f
// abs(gx), abs(gy), abs(gz)
vec4 gxa;
vec4 gxa, gya, gza;
glm_vec4_abs(gx, gxa); // gxa = abs(gx)
vec4 gya;
glm_vec4_abs(gy, gya); // gya = abs(gy)
vec4 gza;
glm_vec4_abs(gz, gza); // gza = abs(gz)
// gw = 0.75 - abs(gx) - abs(gy) - abs(gz)
@@ -238,6 +354,59 @@ _glm_noiseDetail_xy2g(
}
CGLM_INLINE
void
_glm_noiseDetail_xy2gxyz(
vec4 ixy,
/* out */
vec4 gx,
vec4 gy,
vec4 gz
) {
// gx = ixy / 7.0
glm_vec4_divs(ixy, 7.0f, gx); // gx = ixy / 7.0
// gy = fract(floor(gx0) / 7.0)) - 0.5;
_glm_vec4_floor(gx, gy); // gy = floor(gx)
glm_vec4_divs(gy, 7.0f, gy); // gy /= 7.0
glm_vec4_fract(gy, gy); // gy = fract(gy)
glm_vec4_subs(gy, 0.5f, gy); // gy -= 0.5f
// gx = fract(gx);
glm_vec4_fract(gx, gx); // gx = fract(gx)
// abs(gx), abs(gy)
vec4 gxa, gya;
glm_vec4_abs(gx, gxa); // gxa = abs(gx)
glm_vec4_abs(gy, gya); // gya = abs(gy)
// gz = vec4(0.5) - abs(gx0) - abs(gy0);
_glm_vec4_sets(gz, 0.5f); // gz = 0.5
glm_vec4_sub(gz, gxa, gz); // gz -= gxa
glm_vec4_sub(gz, gya, gz); // gz -= gya
// sz = step(gw, 0.0);
vec4 sz;
_glm_vec4_steps(gz, 0.0f, sz); // sz = step(gz, 0.0)
// gx0 -= sz0 * (step(0.0, gx0) - T(0.5));
vec4 temp = {0.0f}; // temp = 0.0
glm_vec4_step(temp, gx, temp); // temp = step(temp, gx)
glm_vec4_subs(temp, 0.5f, temp); // temp -= 0.5
glm_vec4_mul(sz, temp, temp); // temp *= sz
glm_vec4_sub(gx, temp, gx); // gx -= temp
// gy0 -= sz0 * (step(0.0, gy0) - T(0.5));
glm_vec4_zero(temp); // reset temp
glm_vec4_step(temp, gy, temp); // temp = step(temp, gy)
glm_vec4_subs(temp, 0.5f, temp); // temp -= 0.5
glm_vec4_mul(sz, temp, temp); // temp *= sz
glm_vec4_sub(gy, temp, gy); // gy -= temp
}
//////////////////////////////
// Perlin noise
@@ -315,16 +484,16 @@ glm_perlin_vec4(vec4 point) {
// ------------
vec4 gx00, gy00, gz00, gw00;
_glm_noiseDetail_xy2g(ixy00, gx00, gy00, gz00, gw00);
_glm_noiseDetail_xy2gxyzw(ixy00, gx00, gy00, gz00, gw00);
vec4 gx01, gy01, gz01, gw01;
_glm_noiseDetail_xy2g(ixy01, gx01, gy01, gz01, gw01);
_glm_noiseDetail_xy2gxyzw(ixy01, gx01, gy01, gz01, gw01);
vec4 gx10, gy10, gz10, gw10;
_glm_noiseDetail_xy2g(ixy10, gx10, gy10, gz10, gw10);
_glm_noiseDetail_xy2gxyzw(ixy10, gx10, gy10, gz10, gw10);
vec4 gx11, gy11, gz11, gw11;
_glm_noiseDetail_xy2g(ixy11, gx11, gy11, gz11, gw11);
_glm_noiseDetail_xy2gxyzw(ixy11, gx11, gy11, gz11, gw11);
// ------------
@@ -348,10 +517,10 @@ glm_perlin_vec4(vec4 point) {
vec4 g1011 = {gx11[1], gy11[1], gz11[1], gw11[1]}; // g1011 = vec4(gx11.y, gy11.y, gz11.y, gw11.y);
vec4 g1111 = {gx11[3], gy11[3], gz11[3], gw11[3]}; // g1111 = vec4(gx11.w, gy11.w, gz11.w, gw11.w);
_glm_noiseDetail_gradNorm(g0000, g0100, g1000, g1100);
_glm_noiseDetail_gradNorm(g0001, g0101, g1001, g1101);
_glm_noiseDetail_gradNorm(g0010, g0110, g1010, g1110);
_glm_noiseDetail_gradNorm(g0011, g0111, g1011, g1111);
_glm_noiseDetail_gradNorm_vec4(g0000, g0100, g1000, g1100);
_glm_noiseDetail_gradNorm_vec4(g0001, g0101, g1001, g1101);
_glm_noiseDetail_gradNorm_vec4(g0010, g0110, g1010, g1110);
_glm_noiseDetail_gradNorm_vec4(g0011, g0111, g1011, g1111);
// ------------
@@ -418,7 +587,7 @@ glm_perlin_vec4(vec4 point) {
// ------------
vec4 fade_xyzw;
_glm_noiseDetail_fade(Pf0, fade_xyzw); // fade_xyzw = fade(Pf0)
_glm_noiseDetail_fade_vec4(Pf0, fade_xyzw); // fade_xyzw = fade(Pf0)
// n_0w = lerp(vec4(n0000, n1000, n0100, n1100), vec4(n0001, n1001, n0101, n1101), fade_xyzw.w)
vec4 n_0w1 = {n0000, n1000, n0100, n1100};
@@ -449,4 +618,125 @@ glm_perlin_vec4(vec4 point) {
}
CGLM_INLINE
float
glm_perlin_vec3(vec3 point) {
// Integer part of p for indexing
vec3 Pi0;
_glm_vec3_floor(point, Pi0); // Pi0 = floor(point);
// Integer part + 1
vec3 Pi1;
glm_vec3_adds(Pi0, 1.0f, Pi1); // Pi1 = Pi0 + 1.0f;
_glm_vec3_mods(Pi0, 289.0f, Pi0); // Pi0 = mod(Pi0, 289.0f);
_glm_vec3_mods(Pi1, 289.0f, Pi1); // Pi1 = mod(Pi1, 289.0f);
// Fractional part of p for interpolation
vec3 Pf0;
glm_vec3_fract(point, Pf0);
// Fractional part - 1.0
vec3 Pf1;
glm_vec3_subs(Pf0, 1.0f, Pf1);
vec4 ix = {Pi0[0], Pi1[0], Pi0[0], Pi1[0]};
vec4 iy = {Pi0[1], Pi0[1], Pi1[1], Pi1[1]};
vec4 iz0 = {Pi0[2], Pi0[2], Pi0[2], Pi0[2]}; // iz0 = vec4(Pi0.z);
vec4 iz1 = {Pi1[2], Pi1[2], Pi1[2], Pi1[2]}; // iz1 = vec4(Pi1.z);
// ixy = permute(permute(ix) + iy)
vec4 ixy;
_glm_noiseDetail_permute(ix, ixy); // ixy = permute(ix)
glm_vec4_add(ixy, iy, ixy); // ixy += iy;
_glm_noiseDetail_permute(ixy, ixy); // ixy = permute(ixy)
// ixy0 = permute(ixy + iz0)
vec4 ixy0;
glm_vec4_add(ixy, iz0, ixy0); // ixy0 = ixy + iz0
_glm_noiseDetail_permute(ixy0, ixy0); // ixy0 = permute(ixy0)
// ixy1 = permute(ixy + iz1)
vec4 ixy1;
glm_vec4_add(ixy, iz1, ixy1); // ixy1 = ixy, iz1
_glm_noiseDetail_permute(ixy1, ixy1); // ixy1 = permute(ixy1)
// ------------
vec4 gx0, gy0, gz0;
_glm_noiseDetail_xy2gxyz(ixy0, gx0, gy0, gz0);
vec4 gx1, gy1, gz1;
_glm_noiseDetail_xy2gxyz(ixy1, gx1, gy1, gz1);
// ------------
vec3 g000 = {gx0[0], gy0[0], gz0[0]}; // g000 = vec3(gx0.x, gy0.x, gz0.x);
vec3 g100 = {gx0[1], gy0[1], gz0[1]}; // g100 = vec3(gx0.y, gy0.y, gz0.y);
vec3 g010 = {gx0[2], gy0[2], gz0[2]}; // g010 = vec3(gx0.z, gy0.z, gz0.z);
vec3 g110 = {gx0[3], gy0[3], gz0[3]}; // g110 = vec3(gx0.w, gy0.w, gz0.w);
vec3 g001 = {gx1[0], gy1[0], gz1[0]}; // g001 = vec3(gx1.x, gy1.x, gz1.x);
vec3 g101 = {gx1[1], gy1[1], gz1[1]}; // g101 = vec3(gx1.y, gy1.y, gz1.y);
vec3 g011 = {gx1[2], gy1[2], gz1[2]}; // g011 = vec3(gx1.z, gy1.z, gz1.z);
vec3 g111 = {gx1[3], gy1[3], gz1[3]}; // g111 = vec3(gx1.w, gy1.w, gz1.w);
_glm_noiseDetail_gradNorm_vec3(g000, g100, g010, g110);
_glm_noiseDetail_gradNorm_vec3(g001, g101, g011, g111);
// ------------
float n000 = glm_vec3_dot(g000, Pf0); // n000 = dot(g000, Pf0)
// n100 = dot(g100, vec3(Pf1.x, Pf0.y, Pf0.z))
vec3 n100d = {Pf1[0], Pf0[1], Pf0[2]};
float n100 = glm_vec3_dot(g100, n100d);
// n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z))
vec3 n010d = {Pf0[0], Pf1[1], Pf0[2]};
float n010 = glm_vec3_dot(g010, n010d);
// n110 = dot(g110, vec3(Pf1.x, Pf1.y, Pf0.z))
vec3 n110d = {Pf1[0], Pf1[1], Pf0[2]};
float n110 = glm_vec3_dot(g110, n110d);
// n001 = dot(g001, vec3(Pf0.x, Pf0.y, Pf1.z))
vec3 n001d = {Pf0[0], Pf0[1], Pf1[2]};
float n001 = glm_vec3_dot(g001, n001d);
// n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z))
vec3 n101d = {Pf1[0], Pf0[1], Pf1[2]};
float n101 = glm_vec3_dot(g101, n101d);
// n011 = dot(g011, vec3(Pf0.x, Pf1.y, Pf1.z))
vec3 n011d = {Pf0[0], Pf1[1], Pf1[2]};
float n011 = glm_vec3_dot(g011, n011d);
float n111 = glm_vec3_dot(g111, Pf1); // n111 = dot(g111, Pf1)
// ------------
vec3 fade_xyz;
_glm_noiseDetail_fade_vec3(Pf0, fade_xyz); // fade_xyz = fade(Pf0)
// n_z = lerp(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
vec4 n_z;
vec4 n_z1 = {n000, n100, n010, n110};
vec4 n_z2 = {n001, n101, n011, n111};
glm_vec4_lerp(n_z1, n_z2, fade_xyz[2], n_z);
// vec2 n_yz = lerp(vec2(n_z.x, n_z.y), vec2(n_z.z, n_z.w), fade_xyz.y);
vec2 n_yz;
vec2 n_yz1 = {n_z[0], n_z[1]};
vec2 n_yz2 = {n_z[2], n_z[3]};
glm_vec2_lerp(n_yz1, n_yz2, fade_xyz[1], n_yz);
// n_xyz = lerp(n_yz.x, n_yz.y, fade_xyz.x);
float n_xyz = glm_lerp(n_yz[0], n_yz[1], fade_xyz[0]);
return n_xyz * 2.2f;
}
#endif /* cglm_noise_h */