import ShadersBase from '../shaders.base';
/**
* Set of methods to unpack values from [r][b][g][a] -> float
*/
class Unpack extends ShadersBase {
/**
* Constructor
*/
constructor() {
super();
this.name = 'unpack';
// default properties names
this._packedData = 'packedData';
this._offset = 'offset';
this._unpackedData = 'unpackedData';
this._base._uniforms = {
uNumberOfChannels: {
value: 1,
},
uBitsAllocated: {
value: 16,
},
uPixelType: {
value: 0,
},
};
}
api(
baseFragment = this._base,
packedData = this._packedData,
offset = this._offset,
unpackedData = this._unpackedData
) {
this._base = baseFragment;
return this.compute(packedData, offset, unpackedData);
}
compute(packedData, offset, unpackedData) {
this.computeDefinition();
this._base._functions[this._name] = this._definition;
return `${this._name}(${packedData}, ${offset}, ${unpackedData});`;
}
computeDefinition() {
// fun stuff
let content = '';
if (this._base._uniforms.uNumberOfChannels.value === 1) {
switch (this._base._uniforms.uBitsAllocated.value) {
case 1:
case 8:
content = this.upack8();
break;
case 16:
content = this.upack16();
break;
case 32:
content = this.upack32();
break;
default:
content = this.upackIdentity();
break;
}
} else {
content = this.upackIdentity();
}
this._definition = `
void ${this._name}(in vec4 packedData, in int offset, out vec4 unpackedData){
${content}
}
`;
}
upack8() {
this._base._functions['uInt8'] = this.uInt8();
return `
float floatedOffset = float(offset);
float floatedOffsetSquared = floatedOffset * floatedOffset;
uInt8(
step( floatedOffsetSquared , 0.0 ) * packedData.r +
step( floatedOffsetSquared - 2. * floatedOffset + 1., 0.0 ) * packedData.g +
step( floatedOffsetSquared - 2. * 2. * floatedOffset + 4., 0.0 ) * packedData.b +
step( floatedOffsetSquared - 2. * 3. * floatedOffset + 9., 0.0 ) * packedData.a
,
unpackedData.x);
`;
}
upack16() {
this._base._functions['uInt16'] = this.uInt16();
return `
float floatedOffset = float(offset);
uInt16(
packedData.r * (1. - floatedOffset) + packedData.b * floatedOffset,
packedData.g * (1. - floatedOffset) + packedData.a * floatedOffset,
unpackedData.x);
`;
}
upack32() {
if (this._base._uniforms.uPixelType.value === 0) {
this._base._functions['uInt32'] = this.uInt32();
return `
uInt32(
packedData.r,
packedData.g,
packedData.b,
packedData.a,
unpackedData.x);
`;
} else {
this._base._functions['uFloat32'] = this.uFloat32();
return `
uFloat32(
packedData.r,
packedData.g,
packedData.b,
packedData.a,
unpackedData.x);
`;
}
}
upackIdentity() {
return `
unpackedData = packedData;
`;
}
uInt8() {
return `
void uInt8(in float r, out float value){
value = r * 255.;
}
`;
}
uInt16() {
return `
void uInt16(in float r, in float a, out float value){
value = r * 255. + a * 255. * 256.;
}
`;
}
uInt32() {
return `
void uInt32(in float r, in float g, in float b, in float a, out float value){
value = r * 255. + g * 255. * 256. + b * 255. * 256. * 256. + a * 255. * 256. * 256. * 256.;
// value = r * 255. + g * 65025. + b * 16581375. + a * 4228250625.;
}
`;
}
uFloat32() {
return `
void uFloat32(in float r, in float g, in float b, in float a, out float value){
// create arrays containing bits for rgba values
// value between 0 and 255
value = r * 255.;
int bytemeR[8];
bytemeR[0] = int(floor(value / 128.));
value -= float(bytemeR[0] * 128);
bytemeR[1] = int(floor(value / 64.));
value -= float(bytemeR[1] * 64);
bytemeR[2] = int(floor(value / 32.));
value -= float(bytemeR[2] * 32);
bytemeR[3] = int(floor(value / 16.));
value -= float(bytemeR[3] * 16);
bytemeR[4] = int(floor(value / 8.));
value -= float(bytemeR[4] * 8);
bytemeR[5] = int(floor(value / 4.));
value -= float(bytemeR[5] * 4);
bytemeR[6] = int(floor(value / 2.));
value -= float(bytemeR[6] * 2);
bytemeR[7] = int(floor(value));
value = g * 255.;
int bytemeG[8];
bytemeG[0] = int(floor(value / 128.));
value -= float(bytemeG[0] * 128);
bytemeG[1] = int(floor(value / 64.));
value -= float(bytemeG[1] * 64);
bytemeG[2] = int(floor(value / 32.));
value -= float(bytemeG[2] * 32);
bytemeG[3] = int(floor(value / 16.));
value -= float(bytemeG[3] * 16);
bytemeG[4] = int(floor(value / 8.));
value -= float(bytemeG[4] * 8);
bytemeG[5] = int(floor(value / 4.));
value -= float(bytemeG[5] * 4);
bytemeG[6] = int(floor(value / 2.));
value -= float(bytemeG[6] * 2);
bytemeG[7] = int(floor(value));
value = b * 255.;
int bytemeB[8];
bytemeB[0] = int(floor(value / 128.));
value -= float(bytemeB[0] * 128);
bytemeB[1] = int(floor(value / 64.));
value -= float(bytemeB[1] * 64);
bytemeB[2] = int(floor(value / 32.));
value -= float(bytemeB[2] * 32);
bytemeB[3] = int(floor(value / 16.));
value -= float(bytemeB[3] * 16);
bytemeB[4] = int(floor(value / 8.));
value -= float(bytemeB[4] * 8);
bytemeB[5] = int(floor(value / 4.));
value -= float(bytemeB[5] * 4);
bytemeB[6] = int(floor(value / 2.));
value -= float(bytemeB[6] * 2);
bytemeB[7] = int(floor(value));
value = a * 255.;
int bytemeA[8];
bytemeA[0] = int(floor(value / 128.));
value -= float(bytemeA[0] * 128);
bytemeA[1] = int(floor(value / 64.));
value -= float(bytemeA[1] * 64);
bytemeA[2] = int(floor(value / 32.));
value -= float(bytemeA[2] * 32);
bytemeA[3] = int(floor(value / 16.));
value -= float(bytemeA[3] * 16);
bytemeA[4] = int(floor(value / 8.));
value -= float(bytemeA[4] * 8);
bytemeA[5] = int(floor(value / 4.));
value -= float(bytemeA[5] * 4);
bytemeA[6] = int(floor(value / 2.));
value -= float(bytemeA[6] * 2);
bytemeA[7] = int(floor(value));
// compute float32 value from bit arrays
// sign
int issigned = 1 - 2 * bytemeR[0];
// issigned = int(pow(-1., float(bytemeR[0])));
// exponent
int exponent = 0;
exponent += bytemeR[1] * int(pow(2., 7.));
exponent += bytemeR[2] * int(pow(2., 6.));
exponent += bytemeR[3] * int(pow(2., 5.));
exponent += bytemeR[4] * int(pow(2., 4.));
exponent += bytemeR[5] * int(pow(2., 3.));
exponent += bytemeR[6] * int(pow(2., 2.));
exponent += bytemeR[7] * int(pow(2., 1.));
exponent += bytemeG[0];
// fraction
float fraction = 0.;
fraction = float(bytemeG[1]) * pow(2., -1.);
fraction += float(bytemeG[2]) * pow(2., -2.);
fraction += float(bytemeG[3]) * pow(2., -3.);
fraction += float(bytemeG[4]) * pow(2., -4.);
fraction += float(bytemeG[5]) * pow(2., -5.);
fraction += float(bytemeG[6]) * pow(2., -6.);
fraction += float(bytemeG[7]) * pow(2., -7.);
fraction += float(bytemeB[0]) * pow(2., -8.);
fraction += float(bytemeB[1]) * pow(2., -9.);
fraction += float(bytemeB[2]) * pow(2., -10.);
fraction += float(bytemeB[3]) * pow(2., -11.);
fraction += float(bytemeB[4]) * pow(2., -12.);
fraction += float(bytemeB[5]) * pow(2., -13.);
fraction += float(bytemeB[6]) * pow(2., -14.);
fraction += float(bytemeB[7]) * pow(2., -15.);
fraction += float(bytemeA[0]) * pow(2., -16.);
fraction += float(bytemeA[1]) * pow(2., -17.);
fraction += float(bytemeA[2]) * pow(2., -18.);
fraction += float(bytemeA[3]) * pow(2., -19.);
fraction += float(bytemeA[4]) * pow(2., -20.);
fraction += float(bytemeA[5]) * pow(2., -21.);
fraction += float(bytemeA[6]) * pow(2., -22.);
fraction += float(bytemeA[7]) * pow(2., -23.);
value = float(issigned) * pow( 2., float(exponent - 127)) * (1. + fraction);
}
`;
}
}
export default new Unpack();