@luma.gl/shadertools
Version:
Shader module system for luma.gl
161 lines (132 loc) • 3.4 kB
JavaScript
/** @typedef {import('../../types').ShaderModule} ShaderModule */
const fp32shader = `\
#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND
// All these functions are for substituting tan() function from Intel GPU only
const float TWO_PI = 6.2831854820251465;
const float PI_2 = 1.5707963705062866;
const float PI_16 = 0.1963495463132858;
const float SIN_TABLE_0 = 0.19509032368659973;
const float SIN_TABLE_1 = 0.3826834261417389;
const float SIN_TABLE_2 = 0.5555702447891235;
const float SIN_TABLE_3 = 0.7071067690849304;
const float COS_TABLE_0 = 0.9807852506637573;
const float COS_TABLE_1 = 0.9238795042037964;
const float COS_TABLE_2 = 0.8314695954322815;
const float COS_TABLE_3 = 0.7071067690849304;
const float INVERSE_FACTORIAL_3 = 1.666666716337204e-01; // 1/3!
const float INVERSE_FACTORIAL_5 = 8.333333767950535e-03; // 1/5!
const float INVERSE_FACTORIAL_7 = 1.9841270113829523e-04; // 1/7!
const float INVERSE_FACTORIAL_9 = 2.75573188446287533e-06; // 1/9!
float sin_taylor_fp32(float a) {
float r, s, t, x;
if (a == 0.0) {
return 0.0;
}
x = -a * a;
s = a;
r = a;
r = r * x;
t = r * INVERSE_FACTORIAL_3;
s = s + t;
r = r * x;
t = r * INVERSE_FACTORIAL_5;
s = s + t;
r = r * x;
t = r * INVERSE_FACTORIAL_7;
s = s + t;
r = r * x;
t = r * INVERSE_FACTORIAL_9;
s = s + t;
return s;
}
void sincos_taylor_fp32(float a, out float sin_t, out float cos_t) {
if (a == 0.0) {
sin_t = 0.0;
cos_t = 1.0;
}
sin_t = sin_taylor_fp32(a);
cos_t = sqrt(1.0 - sin_t * sin_t);
}
float tan_taylor_fp32(float a) {
float sin_a;
float cos_a;
if (a == 0.0) {
return 0.0;
}
// 2pi range reduction
float z = floor(a / TWO_PI);
float r = a - TWO_PI * z;
float t;
float q = floor(r / PI_2 + 0.5);
int j = int(q);
if (j < -2 || j > 2) {
return 1.0 / 0.0;
}
t = r - PI_2 * q;
q = floor(t / PI_16 + 0.5);
int k = int(q);
int abs_k = int(abs(float(k)));
if (abs_k > 4) {
return 1.0 / 0.0;
} else {
t = t - PI_16 * q;
}
float u = 0.0;
float v = 0.0;
float sin_t, cos_t;
float s, c;
sincos_taylor_fp32(t, sin_t, cos_t);
if (k == 0) {
s = sin_t;
c = cos_t;
} else {
if (abs(float(abs_k) - 1.0) < 0.5) {
u = COS_TABLE_0;
v = SIN_TABLE_0;
} else if (abs(float(abs_k) - 2.0) < 0.5) {
u = COS_TABLE_1;
v = SIN_TABLE_1;
} else if (abs(float(abs_k) - 3.0) < 0.5) {
u = COS_TABLE_2;
v = SIN_TABLE_2;
} else if (abs(float(abs_k) - 4.0) < 0.5) {
u = COS_TABLE_3;
v = SIN_TABLE_3;
}
if (k > 0) {
s = u * sin_t + v * cos_t;
c = u * cos_t - v * sin_t;
} else {
s = u * sin_t - v * cos_t;
c = u * cos_t + v * sin_t;
}
}
if (j == 0) {
sin_a = s;
cos_a = c;
} else if (j == 1) {
sin_a = c;
cos_a = -s;
} else if (j == -1) {
sin_a = -c;
cos_a = s;
} else {
sin_a = -s;
cos_a = -c;
}
return sin_a / cos_a;
}
#endif
float tan_fp32(float a) {
#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND
return tan_taylor_fp32(a);
#else
return tan(a);
#endif
}
`;
export const fp32 = {
name: 'fp32',
vs: fp32shader,
fs: null
};