NVIDIA CG语言 函数之所有数学类函数(Mathematical Functions)
数学类函数(Mathematical Functions)
abs(x) |
返回标量和向量x的绝对值 如果x是向量,则返回每一个成员的绝对值 |
acos(x) |
返回标量和向量x的反余弦 x的范围是[-1,1],返回值的范围是[0,π], 如果x是向量,则返回每一个成员的反余弦 |
all(x) |
如果一个布尔标量为真,或者布尔向量的所有成员为真,则返回真 |
any(x) |
如果一个布尔标量为真,或者布尔向量成员存在真值,则返回真 |
asin(x) |
返回标量和向量x的反正弦 x的范围是[-1,1],返回值的范围是[-π/2,π/2], 如果x是向量,则返回每一个成员的反正弦 |
atan(x) |
返回标量和向量x的反正切 x的范围不限,返回值的范围是[-π/2,π/2], 如果x是向量,则返回每一个成员的反正切· |
atan2(y, x) |
返回标量和向量y/x的反正切 返回值的范围是[-π,π], |
ceil(x) |
返回不小于x的下一个整数 |
clamp(x, a, b) |
返回一个[a, b]范围内的数 如果x<a则返回a 如果x>b则返回b 否则返回x |
cos(x) |
返回x的cos值 |
cosh(x) |
返回一个x的双曲线cos值 |
cross(a, b) |
返回a, b的叉积 a, b一定含有3个成员 |
degrees(x) |
弧度转化为角度 |
determinant(M) |
返回的正方形矩阵m的行列式 |
dot(a, b) |
返回a与b的点积 |
exp(x) |
返回以e为底的x次幂 |
exp2(x) |
返回以2为底的x次幂 |
floor(x) |
返回不大于x的上一个整数 |
fmod(x, y) |
返回一个x/y的余数, y如果为0,结果不可预料 |
frac(x) |
返回x的小数部分 |
frexp(x, out exp) |
将浮点数x分解为尾数(在[0.5, 1]范围内)和指数(输出为e) 如果x为0,结果的所有部分都为0 |
isfinite(x) |
如果x是有限的则返回true |
isinf(x) |
如果x是无限的则返回true |
isnan(x) |
NaN(not-a-number) 如果x NaN(not-a-number) 则返回true |
ldexp(x, n) |
x * 2的n次方 |
lerp(a, b, w) |
w是比重 当w= 0时返回a,当w= 1时返回b 根据w返回一个[a, b]的值 p.s. w可以为任意值,不用限制在[0, 1]之内 w can be any value (so is not restricted to be between zero and one); |
lit(ndotl, ndoth, m) |
计算环境、漫反射、和高光的光照系数 返回一个4维向量 x,环境光系数,经常值为1.0 y,漫反射系数 如果 dot(n, l) < 0返回0,否则返回dot(n, l) z,高光系数 如果 dot(n, l) < 0或dot(n, h) < 0返回0,否则返回dot(n, h)的m次方 w 固定值为1.0 |
log(x) |
ln(x) |
log2(x) |
以2为底x的对数 |
log10(x) |
以10为底x的对数 |
max(a, b) |
返回a,b中的最大值 |
min(a, b) |
返回a,b中的最小值 |
modf(x, out ip) |
把x分离成整数和小数部分,把x的整数值存在输出参数ip处,并返回x的小数部分 |
mul(M, N) |
矩阵M和N的乘积 如果M是一个AxB的矩阵,N是一个BxC的矩阵,就返回一个AxC的矩阵 |
mul(M, v) |
矩阵M和列矢量v的乘积 如果M是一个AxB的矩阵,v是一个Bx1的矢量,就返回一个Ax1的矢量 |
mul(v, M) |
行矢量v和矩阵M的乘积 如果v是一个1xA的矢量,M是一个AxB的矩阵,就返回一个1xB的矢量 |
noise(x) |
任意一个1维2维或3维的噪波函数取决于x的类型。 返回一个[0, 1]范围内的,总是和输入相同的值 |
pow(x, y) |
返回x的y次方值 |
radians(x) |
角度转化为弧度的值 |
round(x) |
采用四舍五入法,返回把x化为整数值 |
rsqrt(x) |
返回x的平方根的倒数 x必须大于0 |
saturate(x) |
返回一个[0, 1]范围内的数 如果x<0则返回0 如果x>1则返回1 否则返回x |
sign(x) |
如果 x>0返回1 如果 x<0返回-1 否则返回0 |
sin(x) |
返回x的sin值 |
sincos(float x, out s, out c) |
输出参数s 为x的sin值,c为s的cos值 这个函数比分别计算x的sin和cos有效率 此函数无返回值 |
sinh(x) |
返回一个x的双曲线sin值 |
smoothstep(min, max, x) |
x是一个[min, max]范围内的数 如果x=min返回0,如果x=max返回1 否则返回如下公式的计算结果:
|
step(a, x) |
如果 x<a返回0 如果 x≥a返回1 |
sqrt(x) |
返回x的平方根 x必须大于0 |
tan(x) |
返回x的tan值 |
tanh(x) |
返回一个x的双曲线tan值 |
transpose(M) |
返回M的转置矩阵 |
cg函数的内部代码实施
看了他们的函数内部实现代码,感觉他们写的都很巧妙,可以用“微量高效”来形容,值得我们学习
abs(x)
如果x是float值,则内部是这么实施的
float abs(float a)
{
return max(-a, a);
}
操作消耗的非常小,等同于无
acos(x)
如果x是float值,则内部是这么实施的
// Handbook of Mathematical Functions
// M. Abramowitz and I.A. Stegun, Ed.
// Absolute error <= 6.7e-5
float acos(float x) {
float negate = float(x < 0);
x = abs(x);
float ret = -0.0187293;
ret = ret * x;
ret = ret + 0.0742610;
ret = ret * x;
ret = ret - 0.2121144;
ret = ret * x;
ret = ret + 1.5707288;
ret = ret * sqrt(1.0-x);
ret = ret - 2 * negate * ret;
return negate * 3.14159265358979 + ret;
}
all(x)
如果x是float值,则内部是这么实施的
bool all(bool4 a)
{
return a.x && a.y && a.z && a.w;
}
any(x)
如果x是float值,则内部是这么实施的
bool any(bool4 a)
{
return a.x || a.y || a.z || a.w;
}
asin(x)
如果x是float值,则内部是这么实施的
// Handbook of Mathematical Functions
// M. Abramowitz and I.A. Stegun, Ed.
float asin(float x) {
float negate = float(x < 0);
x = abs(x);
float ret = -0.0187293;
ret *= x;
ret += 0.0742610;
ret *= x;
ret -= 0.2121144;
ret *= x;
ret += 1.5707288;
ret = 3.14159265358979*0.5 - sqrt(1.0 - x)*ret;
return ret - 2 * negate * ret;
}
atan(x)
如果x是float值,则内部是这么实施的
float atan(float x) {
return atan2(x, float(1));
}
atan2(y, x)
float2 atan2(float2 y, float2 x)
{
float2 t0, t1, t2, t3, t4;
t3 = abs(x);
t1 = abs(y);
t0 = max(t3, t1);
t1 = min(t3, t1);
t3 = float(1) / t0;
t3 = t1 * t3;
t4 = t3 * t3;
t0 = - float(0.013480470);
t0 = t0 * t4 + float(0.057477314);
t0 = t0 * t4 - float(0.121239071);
t0 = t0 * t4 + float(0.195635925);
t0 = t0 * t4 - float(0.332994597);
t0 = t0 * t4 + float(0.999995630);
t3 = t0 * t3;
t3 = (abs(y) > abs(x)) ? float(1.570796327) - t3 : t3;
t3 = (x < 0) ? float(3.141592654) - t3 : t3;
t3 = (y < 0) ? -t3 : t3;
return t3;
}
ceil(x)
如果x是float值,则内部是这么实施的
float ceil(float v)
{
return -floor(-v);
}
clamp(x)
如果x是float值,则内部是这么实施的
float clamp(float x, float a, float b)
{
return max(a, min(b, x));
}
cos(x)
如果x是float值,则内部是这么实施的
cos(float a)
{
/* C simulation gives a max absolute error of less than 1.8e-7 */
const float4 c0 = float4( 0.0, 0.5,
1.0, 0.0 );
const float4 c1 = float4( 0.25, -9.0,
0.75, 0.159154943091 );
const float4 c2 = float4( 24.9808039603, -24.9808039603,
-60.1458091736, 60.1458091736 );
const float4 c3 = float4( 85.4537887573, -85.4537887573,
-64.9393539429, 64.9393539429 );
const float4 c4 = float4( 19.7392082214, -19.7392082214,
-1.0, 1.0 );
/* r0.x = cos(a) */
float3 r0, r1, r2;
r1.x = c1.w * a; // normalize input
r1.y = frac( r1.x ); // and extract fraction
r2.x = (float) ( r1.y < c1.x ); // range check: 0.0 to 0.25
r2.yz = (float2) ( r1.yy >= c1.yz ); // range check: 0.75 to 1.0
r2.y = dot( r2, c4.zwz ); // range check: 0.25 to 0.75
r0 = c0.xyz - r1.yyy; // range centering
r0 = r0 * r0;
r1 = c2.xyx * r0 + c2.zwz; // start power series
r1 = r1 * r0 + c3.xyx;
r1 = r1 * r0 + c3.zwz;
r1 = r1 * r0 + c4.xyx;
r1 = r1 * r0 + c4.zwz;
r0.x = dot( r1, -r2 ); // range extract
return r0.x;
cosh(x)
如果x是float值,则内部是这么实施的
float cosh(float x)
{
return 0.5 * (exp(x)+exp(-x));
}
degrees(x)
如果x是float值,则内部是这么实施的
float degrees(float a)
{
return 57.29577951 * a;
}
determinant (x)
float determinant(float1x1 A)
{
return A._m00;
}
float determinant(float2x2 A)
{
return A._m00*A._m11 - A._m01*A._m10;
}
float determinant(float3x3 A)
{
return dot(A._m00_m01_m02,
A._m11_m12_m10 * A._m22_m20_m21
- A._m12_m10_m11 * A._m21_m22_m20);
}
float determinant(float4x4 A) {
return dot(float4(1,-1,1,-1) * A._m00_m01_m02_m03,
A._m11_m12_m13_m10*( A._m22_m23_m20_m21*A._m33_m30_m31_m32
- A._m23_m20_m21_m22*A._m32_m33_m30_m31)
+ A._m12_m13_m10_m11*( A._m23_m20_m21_m22*A._m31_m32_m33_m30
- A._m21_m22_m23_m20*A._m33_m30_m31_m32)
+ A._m13_m10_m11_m12*( A._m21_m22_m23_m20*A._m32_m33_m30_m31
- A._m22_m23_m20_m21*A._m31_m32_m33_m30));
}
degrees(x)
如果x是float4值,则内部是这么实施的
float dot(float4 a, float4 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
}
exp(x)
float3 exp(float3 a)
{
float3 rv;
int i;
for (i=0; i<3; i++) {
rv[i] = exp(a[i]); // this is the ANSI C standard library exp()
}
return rv;
}
exp2(x)
float3 exp2(float3 a)
{
float3 rv;
int i;
for (i=0; i<3; i++) {
rv[i] = exp2(a[i]); // this is the ANSI C standard library exp2()
}
return rv;
}
floor(x)
float3 floor(float3 v)
{
float3 rv;
int i;
for (i=0; i<3; i++) {
rv[i] = v[i] - frac(v[i]);
}
return rv;
}
fmod(x)
float2 fmod(float2 a, float2 b)
{
float2 c = frac(abs(a/b))*abs(b);
return (a < 0) ? -c : c; /* if ( a < 0 ) c = 0-c */
}
frac(x)
float frac(float v)
{
return v - floor(v);
}
frexp(x)
float3 frexp(float3 x, out float3 e)
{
float3 rv;
int i;
for (i=0; i<3; i++) {
float eout;
rv[i] = frexp(a[i], &eout); // this is the ANSI C standard library frexp()
e[i] = eout;
}
return rv;
}
isfinite(x)
bool3 isfinite(float3 s)
{
// By IEEE 754 rule, 2*Inf equals Inf
return (s == s) && ((s == 0) || (s != 2*s));
}
isinf(x)
bool3 isinf(float3 s)
{
// By IEEE 754 rule, 2*Inf equals Inf
return (2*s == s) && (s != 0);
}
isnan(x)
bool3 isnan(float3 s)
{
// By IEEE 754 rule, NaN is not equal to NaN
return s != s;
}
lerp(a, b, f)
float3 lerp(float3 a, float3 b, float w)
{
return a + w*(b-a);
}
lit(ndotl, ndoth, m)
float4 lit(float NdotL, float NdotH, float m)
{
float specular = (NdotL > 0) ? pow(max(0.0, NdotH), m);
return float4(1.0, max(0.0, NdotL), specular, 1.0);
}
max(a, b)
float3 max(float3 a, float3 b)
{
return float3(a.x > b.x ? a.x : b.x,
a.y > b.y ? a.y : b.y,
a.z > b.z ? a.z : b.z);
}
min(a, b)
float3 min(float3 a, float3 b)
{
return float3(a.x < b.x ? a.x : b.x,
a.y < b.y ? a.y : b.y,
a.z < b.z ? a.z : b.z);
}
modf(x, out ip)
float4 mul(float4x3 M, float3 v)
{
float4 r;
r.x = dot( M._m00_m01_m02, v );
r.y = dot( M._m10_m11_m12, v );
r.z = dot( M._m20_m21_m22, v );
r.w = dot( M._m30_m31_m32, v );
return r;
}
pow(x, y)
float3 pow(float3 x, float3 y)
{
float3 rv;
for (int i=0; i<3; i++) {
rv[i] = exp(x[i] * log(y[i]));
}
return rv;
}
round(x)
// round-to-nearest even profiles
float round(float a)
{
float x = a + 0.5;
float f = floor(x);
float r;
if (x == f) {
if (a > 0)
r = f - fmod(f, 2);
else
r = f + fmod(f, 2);
} else
r = f;
return r;
}
// round-to-nearest up profiles
float round(float a)
{
return floor(x + 0.5);
}
rsqrt(x)
float3 rsqrt(float3 a)
{
return pow(a, -0.5);
}
saturate(x)
float saturate(float x)
{
return max(0, min(1, x));
}
sign(x)
float3 sign(float x)
{
float3 val = a > 0;
return val - (a < 0);
}
step(a, x)
float3 step(float3 a, float3 x)
{
return x >= a;
}
sqrt(x)
感觉这个有点麻烦了,直接pow就好了。
float3 sqrt(float3 a)
{
return 1.0 / rsqrt(a);
}
transpose(M)
float4x3 transpose(float3x4 A)
{
float4x3 C;
C[0] = A._m00_m10_m20;
C[1] = A._m01_m11_m21;
C[2] = A._m02_m12_m22;
C[3] = A._m03_m13_m23;
return C;
}
------------------------------------by wolf96 http://blog.csdn.net/wolf96