| [ |
| { |
| "op":"mod", |
| "return_type":"float", |
| "args":[ |
| "float x", |
| "float y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"mod", |
| "return_type":"float2", |
| "args":[ |
| "float2 x", |
| "float2 y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"mod", |
| "return_type":"float2", |
| "args":[ |
| "float2 x", |
| "float y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"mod", |
| "return_type":"float3", |
| "args":[ |
| "float3 x", |
| "float3 y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"mod", |
| "return_type":"float3", |
| "args":[ |
| "float3 x", |
| "float y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"mod", |
| "return_type":"float4", |
| "args":[ |
| "float4 x", |
| "float4 y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"mod", |
| "return_type":"float4", |
| "args":[ |
| "float4 x", |
| "float y" |
| ], |
| "body":[ |
| "return x - y * floor(x / y);" |
| ] |
| }, |
| { |
| "op":"frexp", |
| "return_type":"float", |
| "args":[ |
| "float x", |
| "out int exp" |
| ], |
| "body":[ |
| "float fexp;", |
| "float mantissa = frexp(abs(x), fexp) * sign(x);", |
| "exp = int(fexp);", |
| "return mantissa;" |
| ] |
| }, |
| { |
| "op":"frexp", |
| "return_type":"float2", |
| "args":[ |
| "float2 x", |
| "out int2 exp" |
| ], |
| "body":[ |
| "float2 fexp;", |
| "float2 mantissa = frexp(abs(x), fexp) * sign(x);", |
| "exp = int2(fexp);", |
| "return mantissa;" |
| ] |
| }, |
| { |
| "op":"frexp", |
| "return_type":"float3", |
| "args":[ |
| "float3 x", |
| "out int3 exp" |
| ], |
| "body":[ |
| "float3 fexp;", |
| "float3 mantissa = frexp(abs(x), fexp) * sign(x);", |
| "exp = int3(fexp);", |
| "return mantissa;" |
| ] |
| }, |
| { |
| "op":"frexp", |
| "return_type":"float4", |
| "args":[ |
| "float4 x", |
| "out int4 exp" |
| ], |
| "body":[ |
| "float4 fexp;", |
| "float4 mantissa = frexp(abs(x), fexp) * sign(x);", |
| "exp = int4(fexp);", |
| "return mantissa;" |
| ] |
| }, |
| { |
| "op":"ldexp", |
| "return_type":"float", |
| "args":[ |
| "float x", |
| "int exp" |
| ], |
| "body":[ |
| "return ldexp(x, float(exp));" |
| ] |
| }, |
| { |
| "op":"ldexp", |
| "return_type":"float2", |
| "args":[ |
| "float2 x", |
| "int2 exp" |
| ], |
| "body":[ |
| "return ldexp(x, float2(exp));" |
| ] |
| }, |
| { |
| "op":"ldexp", |
| "return_type":"float3", |
| "args":[ |
| "float3 x", |
| "int3 exp" |
| ], |
| "body":[ |
| "return ldexp(x, float3(exp));" |
| ] |
| }, |
| { |
| "op":"ldexp", |
| "return_type":"float4", |
| "args":[ |
| "float4 x", |
| "int4 exp" |
| ], |
| "body":[ |
| "return ldexp(x, float4(exp));" |
| ] |
| }, |
| { |
| "op":"faceforward", |
| "return_type":"float", |
| "args":[ |
| "float N", |
| "float I", |
| "float Nref" |
| ], |
| "body":[ |
| "if(dot(Nref, I) >= 0)", |
| "{", |
| " return -N;", |
| "}", |
| "else", |
| "{", |
| " return N;", |
| "}" |
| ] |
| }, |
| { |
| "op":"faceforward", |
| "return_type":"float2", |
| "args":[ |
| "float2 N", |
| "float2 I", |
| "float2 Nref" |
| ], |
| "body":[ |
| "if(dot(Nref, I) >= 0)", |
| "{", |
| " return -N;", |
| "}", |
| "else", |
| "{", |
| " return N;", |
| "}" |
| ] |
| }, |
| { |
| "op":"faceforward", |
| "return_type":"float3", |
| "args":[ |
| "float3 N", |
| "float3 I", |
| "float3 Nref" |
| ], |
| "body":[ |
| "if(dot(Nref, I) >= 0)", |
| "{", |
| " return -N;", |
| "}", |
| "else", |
| "{", |
| " return N;", |
| "}" |
| ] |
| }, |
| { |
| "op":"faceforward", |
| "return_type":"float4", |
| "args":[ |
| "float4 N", |
| "float4 I", |
| "float4 Nref" |
| ], |
| "body":[ |
| "if(dot(Nref, I) >= 0)", |
| "{", |
| " return -N;", |
| "}", |
| "else", |
| "{", |
| " return N;", |
| "}" |
| ] |
| }, |
| { |
| "op":"atan", |
| "return_type":"float", |
| "args":[ |
| "float y", |
| "float x" |
| ], |
| "body":[ |
| "if(x == 0 && y == 0) x = 1;", |
| "return atan2(y, x);" |
| ] |
| }, |
| { |
| "op":"atan", |
| "return_type":"float2", |
| "args":[ |
| "float2 y", |
| "float2 x" |
| ], |
| "body":[ |
| "if(x[0] == 0 && y[0] == 0) x[0] = 1;", |
| "if(x[1] == 0 && y[1] == 0) x[1] = 1;", |
| "return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));" |
| ] |
| }, |
| { |
| "op":"atan", |
| "return_type":"float3", |
| "args":[ |
| "float3 y", |
| "float3 x" |
| ], |
| "body":[ |
| "if(x[0] == 0 && y[0] == 0) x[0] = 1;", |
| "if(x[1] == 0 && y[1] == 0) x[1] = 1;", |
| "if(x[2] == 0 && y[2] == 0) x[2] = 1;", |
| "return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));" |
| ] |
| }, |
| { |
| "op":"atan", |
| "return_type":"float4", |
| "args":[ |
| "float4 y", |
| "float4 x" |
| ], |
| "body":[ |
| "if(x[0] == 0 && y[0] == 0) x[0] = 1;", |
| "if(x[1] == 0 && y[1] == 0) x[1] = 1;", |
| "if(x[2] == 0 && y[2] == 0) x[2] = 1;", |
| "if(x[3] == 0 && y[3] == 0) x[3] = 1;", |
| "return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], ", |
| "x[2]), atan2(y[3], x[3]));" |
| ] |
| }, |
| { |
| "op":"asinh", |
| "return_type":"float", |
| "args":[ |
| "in float x" |
| ], |
| "body":[ |
| "return log(x + sqrt(pow(x, 2.0) + 1.0));" |
| ] |
| }, |
| { |
| "op":"asinh", |
| "return_type":"float2", |
| "args":[ |
| "in float2 x" |
| ], |
| "body":[ |
| "return log(x + sqrt(pow(x, 2.0) + 1.0));" |
| ] |
| }, |
| { |
| "op":"asinh", |
| "return_type":"float3", |
| "args":[ |
| "in float3 x" |
| ], |
| "body":[ |
| "return log(x + sqrt(pow(x, 2.0) + 1.0));" |
| ] |
| }, |
| { |
| "op":"asinh", |
| "return_type":"float4", |
| "args":[ |
| "in float4 x" |
| ], |
| "body":[ |
| "return log(x + sqrt(pow(x, 2.0) + 1.0));" |
| ] |
| }, |
| { |
| "op":"acosh", |
| "return_type":"float", |
| "args":[ |
| "in float x" |
| ], |
| "body":[ |
| "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" |
| ] |
| }, |
| { |
| "op":"acosh", |
| "return_type":"float2", |
| "args":[ |
| "in float2 x" |
| ], |
| "body":[ |
| "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" |
| ] |
| }, |
| { |
| "op":"acosh", |
| "return_type":"float3", |
| "args":[ |
| "in float3 x" |
| ], |
| "body":[ |
| "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" |
| ] |
| }, |
| { |
| "op":"acosh", |
| "return_type":"float4", |
| "args":[ |
| "in float4 x" |
| ], |
| "body":[ |
| "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));" |
| ] |
| }, |
| { |
| "op":"atanh", |
| "return_type":"float", |
| "args":[ |
| "in float x" |
| ], |
| "body":[ |
| "return 0.5 * log((1.0 + x) / (1.0 - x));" |
| ] |
| }, |
| { |
| "op":"atanh", |
| "return_type":"float2", |
| "args":[ |
| "in float2 x" |
| ], |
| "body":[ |
| "return 0.5 * log((1.0 + x) / (1.0 - x));" |
| ] |
| }, |
| { |
| "op":"atanh", |
| "return_type":"float3", |
| "args":[ |
| "in float3 x" |
| ], |
| "body":[ |
| "return 0.5 * log((1.0 + x) / (1.0 - x));" |
| ] |
| }, |
| { |
| "op":"atanh", |
| "return_type":"float4", |
| "args":[ |
| "in float4 x" |
| ], |
| "body":[ |
| "return 0.5 * log((1.0 + x) / (1.0 - x));" |
| ] |
| }, |
| { |
| "op":"roundEven", |
| "return_type":"float", |
| "args":[ |
| "in float x" |
| ], |
| "body":[ |
| "return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);" |
| ] |
| }, |
| { |
| "op":"roundEven", |
| "return_type":"float2", |
| "args":[ |
| "in float2 x" |
| ], |
| "body":[ |
| "float2 v;", |
| "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", |
| "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", |
| "return v;" |
| ] |
| }, |
| { |
| "op":"roundEven", |
| "return_type":"float3", |
| "args":[ |
| "in float3 x" |
| ], |
| "body":[ |
| "float3 v;", |
| "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", |
| "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", |
| "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);", |
| "return v;" |
| ] |
| }, |
| { |
| "op":"roundEven", |
| "return_type":"float4", |
| "args":[ |
| "in float4 x" |
| ], |
| "body":[ |
| "float4 v;", |
| "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);", |
| "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);", |
| "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);", |
| "v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);", |
| "return v;" |
| ] |
| }, |
| { |
| "op":"packSnorm2x16", |
| "return_type":"uint", |
| "args":[ |
| "in float2 v" |
| ], |
| "helper":[ |
| "int webgl_toSnorm16(in float x) {", |
| " return int(round(clamp(x, -1.0, 1.0) * 32767.0));", |
| "}" |
| ], |
| "body":[ |
| "int x = webgl_toSnorm16(v.x);", |
| "int y = webgl_toSnorm16(v.y);", |
| "return (asuint(y) << 16) | (asuint(x) & 0xffffu);" |
| ] |
| }, |
| { |
| "op":"packUnorm2x16", |
| "return_type":"uint", |
| "args":[ |
| "in float2 v" |
| ], |
| "helper":[ |
| "uint webgl_toUnorm16(in float x) {", |
| " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));", |
| "}" |
| ], |
| "body":[ |
| "uint x = webgl_toUnorm16(v.x);", |
| "uint y = webgl_toUnorm16(v.y);", |
| "return (y << 16) | x;" |
| ] |
| }, |
| { |
| "op":"packHalf2x16", |
| "return_type":"uint", |
| "args":[ |
| "in float2 v" |
| ], |
| "body":[ |
| "uint x = f32tof16(v.x);", |
| "uint y = f32tof16(v.y);", |
| "return (y << 16) | x;" |
| ] |
| }, |
| { |
| "op":"unpackSnorm2x16", |
| "return_type":"float2", |
| "args":[ |
| "in uint u" |
| ], |
| "helper":[ |
| "float webgl_fromSnorm16(in uint x) {", |
| " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);", |
| " return clamp(float(xi) / 32767.0, -1.0, 1.0);", |
| "}" |
| ], |
| "body":[ |
| "uint y = (u >> 16);", |
| "uint x = u;", |
| "return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));" |
| ] |
| }, |
| { |
| "op":"unpackUnorm2x16", |
| "return_type":"float2", |
| "args":[ |
| "in uint u" |
| ], |
| "helper":[ |
| "float webgl_fromUnorm16(in uint x) {", |
| " return float(x) / 65535.0;", |
| "}" |
| ], |
| "body":[ |
| "uint y = (u >> 16);", |
| "uint x = u & 0xffffu;", |
| "return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));" |
| ] |
| }, |
| { |
| "op":"unpackHalf2x16", |
| "return_type":"float2", |
| "args":[ |
| "in uint u" |
| ], |
| "body":[ |
| "uint y = (u >> 16);", |
| "uint x = u & 0xffffu;", |
| "return float2(f16tof32(x), f16tof32(y));" |
| ] |
| }, |
| { |
| "op":"packSnorm4x8", |
| "return_type":"uint", |
| "args":[ |
| "in float4 v" |
| ], |
| "helper":[ |
| "int webgl_toSnorm8(in float x) {", |
| " return int(round(clamp(x, -1.0, 1.0) * 127.0));", |
| "}" |
| ], |
| "body":[ |
| "int x = webgl_toSnorm8(v.x);", |
| "int y = webgl_toSnorm8(v.y);", |
| "int z = webgl_toSnorm8(v.z);", |
| "int w = webgl_toSnorm8(v.w);", |
| "return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) ", |
| "| ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);" |
| ] |
| }, |
| { |
| "op":"packUnorm4x8", |
| "return_type":"uint", |
| "args":[ |
| "in float4 v" |
| ], |
| "helper":[ |
| "uint webgl_toUnorm8(in float x) {", |
| " return uint(round(clamp(x, 0.0, 1.0) * 255.0));", |
| "}" |
| ], |
| "body":[ |
| "uint x = webgl_toUnorm8(v.x);", |
| "uint y = webgl_toUnorm8(v.y);", |
| "uint z = webgl_toUnorm8(v.z);", |
| "uint w = webgl_toUnorm8(v.w);", |
| "return (w << 24) | (z << 16) | (y << 8) | x;" |
| ] |
| }, |
| { |
| "op":"unpackSnorm4x8", |
| "return_type":"float4", |
| "args":[ |
| "in uint u" |
| ], |
| "helper":[ |
| "float webgl_fromSnorm8(in uint x) {", |
| " int xi = asint(x & 0x7fu) - asint(x & 0x80u);", |
| " return clamp(float(xi) / 127.0, -1.0, 1.0);", |
| "}" |
| ], |
| "body":[ |
| "uint w = (u >> 24);", |
| "uint z = (u >> 16);", |
| "uint y = (u >> 8);", |
| "uint x = u;", |
| "return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), ", |
| "webgl_fromSnorm8(z), webgl_fromSnorm8(w));" |
| ] |
| }, |
| { |
| "op":"unpackUnorm4x8", |
| "return_type":"float4", |
| "args":[ |
| "in uint u" |
| ], |
| "helper":[ |
| "float webgl_fromUnorm8(in uint x) {", |
| " return float(x) / 255.0;", |
| "}" |
| ], |
| "body":[ |
| "uint w = (u >> 24) & 0xffu;", |
| "uint z = (u >> 16) & 0xffu;", |
| "uint y = (u >> 8) & 0xffu;", |
| "uint x = u & 0xffu;", |
| "return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), ", |
| "webgl_fromUnorm8(z), webgl_fromUnorm8(w));" |
| ] |
| }, |
| { |
| "comment":[ |
| "The matrix resulting from outer product needs to be transposed", |
| "(matrices are stored as transposed to simplify element access in HLSL).", |
| "So the function should return transpose(c * r) where c is a column vector", |
| "and r is a row vector. This can be simplified by using the following", |
| "formula:", |
| "transpose(c * r) = transpose(r) * transpose(c)", |
| "transpose(r) and transpose(c) are in a sense free, since to get the", |
| "transpose of r, we simply can build a column matrix out of the original", |
| "vector instead of a row matrix." |
| ], |
| "op":"outerProduct", |
| "return_type":"float2x2", |
| "args":[ |
| "in float2 c", |
| "in float2 r" |
| ], |
| "body":[ |
| "return mul(float2x1(r), float1x2(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float3x3", |
| "args":[ |
| "in float3 c", |
| "in float3 r" |
| ], |
| "body":[ |
| "return mul(float3x1(r), float1x3(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float4x4", |
| "args":[ |
| "in float4 c", |
| "in float4 r" |
| ], |
| "body":[ |
| "return mul(float4x1(r), float1x4(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float2x3", |
| "args":[ |
| "in float3 c", |
| "in float2 r" |
| ], |
| "body":[ |
| "return mul(float2x1(r), float1x3(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float3x2", |
| "args":[ |
| "in float2 c", |
| "in float3 r" |
| ], |
| "body":[ |
| "return mul(float3x1(r), float1x2(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float2x4", |
| "args":[ |
| "in float4 c", |
| "in float2 r" |
| ], |
| "body":[ |
| "return mul(float2x1(r), float1x4(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float4x2", |
| "args":[ |
| "in float2 c", |
| "in float4 r" |
| ], |
| "body":[ |
| "return mul(float4x1(r), float1x2(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float3x4", |
| "args":[ |
| "in float4 c", |
| "in float3 r" |
| ], |
| "body":[ |
| "return mul(float3x1(r), float1x4(c));" |
| ] |
| }, |
| { |
| "op":"outerProduct", |
| "return_type":"float4x3", |
| "args":[ |
| "in float3 c", |
| "in float4 r" |
| ], |
| "body":[ |
| "return mul(float4x1(r), float1x3(c));" |
| ] |
| }, |
| { |
| "comment":[ |
| "Remember here that the parameter matrix is actually the transpose", |
| "of the matrix that we're trying to invert, and the resulting matrix", |
| "should also be the transpose of the inverse.", |
| "When accessing the parameter matrix with m[a][b] it can be thought of so", |
| "that a is the column and b is the row of the matrix that we're inverting.", |
| "We calculate the inverse as the adjugate matrix divided by the", |
| "determinant of the matrix being inverted. However, as the result needs", |
| "to be transposed, we actually use of the transpose of the adjugate matrix", |
| "which happens to be the cofactor matrix. That's stored in 'cof'.", |
| "We don't need to care about divide-by-zero since results are undefined", |
| "for singular or poorly-conditioned matrices." |
| ], |
| "op":"inverse", |
| "return_type":"float2x2", |
| "args":[ |
| "in float2x2 m" |
| ], |
| "body":[ |
| "float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };", |
| "return cof / determinant(transpose(m));" |
| ] |
| }, |
| { |
| "comment":[ |
| "cofAB is the cofactor for column A and row B." |
| ], |
| "op":"inverse", |
| "return_type":"float3x3", |
| "args":[ |
| "in float3x3 m" |
| ], |
| "body":[ |
| "float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];", |
| "float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);", |
| "float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];", |
| "float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);", |
| "float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];", |
| "float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);", |
| "float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];", |
| "float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);", |
| "float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];", |
| "float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };", |
| "return cof / determinant(transpose(m));" |
| ] |
| }, |
| { |
| "op":"inverse", |
| "return_type":"float4x4", |
| "args":[ |
| "in float4x4 m" |
| ], |
| "body":[ |
| "float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * ", |
| "m[1][2] * m[2][3]", |
| " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * ", |
| "m[1][3];", |
| "float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * ", |
| "m[1][2] * m[2][3]", |
| " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * ", |
| "m[1][3]);", |
| "float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * ", |
| "m[1][1] * m[2][3]", |
| " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * ", |
| "m[1][3];", |
| "float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * ", |
| "m[1][1] * m[2][2]", |
| " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * ", |
| "m[1][2]);", |
| "float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * ", |
| "m[0][2] * m[2][3]", |
| " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * ", |
| "m[0][3]);", |
| "float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * ", |
| "m[0][2] * m[2][3]", |
| " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * ", |
| "m[0][3];", |
| "float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * ", |
| "m[0][1] * m[2][3]", |
| " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * ", |
| "m[0][3]);", |
| "float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * ", |
| "m[0][1] * m[2][2]", |
| " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * ", |
| "m[0][2];", |
| "float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * ", |
| "m[0][2] * m[1][3]", |
| " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * ", |
| "m[0][3];", |
| "float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * ", |
| "m[0][2] * m[1][3]", |
| " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * ", |
| "m[0][3]);", |
| "float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * ", |
| "m[0][1] * m[1][3]", |
| " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * ", |
| "m[0][3];", |
| "float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * ", |
| "m[0][1] * m[1][2]", |
| " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * ", |
| "m[0][2]);", |
| "float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * ", |
| "m[0][2] * m[1][3]", |
| " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * ", |
| "m[0][3]);", |
| "float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * ", |
| "m[0][2] * m[1][3]", |
| " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * ", |
| "m[0][3];", |
| "float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * ", |
| "m[0][1] * m[1][3]", |
| " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * ", |
| "m[0][3]);", |
| "float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * ", |
| "m[0][1] * m[1][2]", |
| " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * ", |
| "m[0][2];", |
| "float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,", |
| " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };", |
| "return cof / determinant(transpose(m));" |
| ] |
| }, |
| { |
| "comment":[ |
| "Emulate ESSL3 variant of mix that takes last argument as boolean vector.", |
| "genType mix(genType x, genType y, genBType a): Selects which vector each returned component", |
| "comes from. For a component of 'a' that is false, the corresponding component of 'x' is", |
| "returned. For a component of 'a' that is true, the corresponding component of 'y' is returned." |
| ], |
| "op":"mix", |
| "return_type":"float", |
| "args":[ |
| "float x", |
| "float y", |
| "bool a" |
| ], |
| "body":[ |
| "return a ? y : x;" |
| ] |
| }, |
| { |
| "op":"mix", |
| "return_type":"float2", |
| "args":[ |
| "float2 x", |
| "float2 y", |
| "bool2 a" |
| ], |
| "body":[ |
| "return a ? y : x;" |
| ] |
| }, |
| { |
| "op":"mix", |
| "return_type":"float3", |
| "args":[ |
| "float3 x", |
| "float3 y", |
| "bool3 a" |
| ], |
| "body":[ |
| "return a ? y : x;" |
| ] |
| }, |
| { |
| "op":"mix", |
| "return_type":"float4", |
| "args":[ |
| "float4 x", |
| "float4 y", |
| "bool4 a" |
| ], |
| "body":[ |
| "return a ? y : x;" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"uint", |
| "args":[ |
| "uint value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return 0u;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "return (value & mask) >> offset;" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"uint2", |
| "args":[ |
| "uint2 value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return uint2(0u, 0u);", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "return (value & mask) >> offset;" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"uint3", |
| "args":[ |
| "uint3 value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return uint3(0u, 0u, 0u);", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "return (value & mask) >> offset;" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"uint4", |
| "args":[ |
| "uint4 value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return uint4(0u, 0u, 0u, 0u);", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "return (value & mask) >> offset;" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"int", |
| "args":[ |
| "int value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return 0;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint resultUnsigned = (asuint(value) & mask) >> offset;", |
| "if (bits != 32 && (resultUnsigned & maskMsb) != 0)", |
| "{", |
| " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", |
| " resultUnsigned |= higherBitsMask;", |
| "}", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"int2", |
| "args":[ |
| "int2 value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return int2(0, 0);", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint2 resultUnsigned = (asuint(value) & mask) >> offset;", |
| "if (bits != 32)", |
| "{", |
| " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", |
| " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", |
| "}", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"int3", |
| "args":[ |
| "int3 value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return int3(0, 0, 0);", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint3 resultUnsigned = (asuint(value) & mask) >> offset;", |
| "if (bits != 32)", |
| "{", |
| " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", |
| " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", |
| "}", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldExtract", |
| "return_type":"int4", |
| "args":[ |
| "int4 value", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return int4(0, 0, 0, 0);", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint mask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint4 resultUnsigned = (asuint(value) & mask) >> offset;", |
| "if (bits != 32)", |
| "{", |
| " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;", |
| " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;", |
| "}", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"uint", |
| "args":[ |
| "uint base", |
| "uint insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "return (base & baseMask) | ((insert << offset) & insertMask);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"uint2", |
| "args":[ |
| "uint2 base", |
| "uint2 insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "return (base & baseMask) | ((insert << offset) & insertMask);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"uint3", |
| "args":[ |
| "uint3 base", |
| "uint3 insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "return (base & baseMask) | ((insert << offset) & insertMask);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"uint4", |
| "args":[ |
| "uint4 base", |
| "uint4 insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "return (base & baseMask) | ((insert << offset) & insertMask);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"int", |
| "args":[ |
| "int base", |
| "int insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", |
| " insertMask);", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"int2", |
| "args":[ |
| "int2 base", |
| "int2 insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", |
| " insertMask);", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"int3", |
| "args":[ |
| "int3 base", |
| "int3 insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", |
| " insertMask);", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"bitfieldInsert", |
| "return_type":"int4", |
| "args":[ |
| "int4 base", |
| "int4 insert", |
| "int offset", |
| "int bits" |
| ], |
| "body":[ |
| "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)", |
| "{", |
| " return base;", |
| "}", |
| "uint maskMsb = (1u << (bits - 1));", |
| "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;", |
| "uint baseMask = ~insertMask;", |
| "uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ", |
| "insertMask);", |
| "return asint(resultUnsigned);" |
| ] |
| }, |
| { |
| "op":"uaddCarry", |
| "return_type":"uint", |
| "args":[ |
| "uint x", |
| "uint y", |
| "out uint carry" |
| ], |
| "body":[ |
| "carry = uint(x > (0xffffffffu - y));", |
| "return x + y;" |
| ] |
| }, |
| { |
| "op":"uaddCarry", |
| "return_type":"uint2", |
| "args":[ |
| "uint2 x", |
| "uint2 y", |
| "out uint2 carry" |
| ], |
| "body":[ |
| "carry = uint2(x > (0xffffffffu - y));", |
| "return x + y;" |
| ] |
| }, |
| { |
| "op":"uaddCarry", |
| "return_type":"uint3", |
| "args":[ |
| "uint3 x", |
| "uint3 y", |
| "out uint3 carry" |
| ], |
| "body":[ |
| "carry = uint3(x > (0xffffffffu - y));", |
| "return x + y;" |
| ] |
| }, |
| { |
| "op":"uaddCarry", |
| "return_type":"uint4", |
| "args":[ |
| "uint4 x", |
| "uint4 y", |
| "out uint4 carry" |
| ], |
| "body":[ |
| "carry = uint4(x > (0xffffffffu - y));", |
| "return x + y;" |
| ] |
| }, |
| { |
| "op":"usubBorrow", |
| "return_type":"uint", |
| "args":[ |
| "uint x", |
| "uint y", |
| "out uint borrow" |
| ], |
| "body":[ |
| "borrow = uint(x < y);", |
| "return x - y;" |
| ] |
| }, |
| { |
| "op":"usubBorrow", |
| "return_type":"uint2", |
| "args":[ |
| "uint2 x", |
| "uint2 y", |
| "out uint2 borrow" |
| ], |
| "body":[ |
| "borrow = uint2(x < y);", |
| "return x - y;" |
| ] |
| }, |
| { |
| "op":"usubBorrow", |
| "return_type":"uint3", |
| "args":[ |
| "uint3 x", |
| "uint3 y", |
| "out uint3 borrow" |
| ], |
| "body":[ |
| "borrow = uint3(x < y);", |
| "return x - y;" |
| ] |
| }, |
| { |
| "op":"usubBorrow", |
| "return_type":"uint4", |
| "args":[ |
| "uint4 x", |
| "uint4 y", |
| "out uint4 borrow" |
| ], |
| "body":[ |
| "borrow = uint4(x < y);", |
| "return x - y;" |
| ] |
| }, |
| { |
| "comment":[ |
| "We emulate tanh just to avoid overflow on large arguments." |
| ], |
| "op":"tanh", |
| "return_type":"float", |
| "args":[ |
| "float x" |
| ], |
| "body":[ |
| "return (abs(x) > 15.0) ? sign(x) : tanh(x);" |
| ] |
| }, |
| { |
| "op":"tanh", |
| "return_type":"float2", |
| "args":[ |
| "float2 x" |
| ], |
| "body":[ |
| "return (abs(x) > 15.0) ? sign(x) : tanh(x);" |
| ] |
| }, |
| { |
| "op":"tanh", |
| "return_type":"float3", |
| "args":[ |
| "float3 x" |
| ], |
| "body":[ |
| "return (abs(x) > 15.0) ? sign(x) : tanh(x);" |
| ] |
| }, |
| { |
| "op":"tanh", |
| "return_type":"float4", |
| "args":[ |
| "float4 x" |
| ], |
| "body":[ |
| "return (abs(x) > 15.0) ? sign(x) : tanh(x);" |
| ] |
| } |
| ] |