@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
75 lines (57 loc) • 2.65 kB
JavaScript
import { saturated_value_by_constructor } from "./saturated_value_by_constructor.js";
/**
* Allows copying data from one sampler to another with unequal number of channels (a.itemSize !== b.itemSize)
* @example convert RGBA to RGB or R to RGB
* @param {Sampler2D} source
* @param {Sampler2D} destination
*/
export function sampler2d_transfer_data(source, destination) {
if (source.width !== destination.width || source.height !== destination.height) {
throw new Error('Source and destination dimensions do not match');
}
const source_item_size = source.itemSize;
const destination_item_size = destination.itemSize;
const pixel_count = source.width * source.height;
const destination_data = destination.data;
const source_data = source.data;
let i=0, j=0;
if (source_item_size === destination_item_size) {
// just copy data chunk
destination_data.set(source_data);
} else if (source_item_size > destination_item_size) {
// more channels in source than in destination
for (i = 0; i < pixel_count; i++) {
const source_sample_offset = i * source_item_size;
const destination_sample_offset = i * destination_item_size;
for (j = 0; j < destination_item_size; j++) {
destination_data[destination_sample_offset + j] = source_data[source_sample_offset + j];
}
}
} else if (source_item_size === 3 && destination_item_size === 4) {
const saturated_channel_value = saturated_value_by_constructor(destination_data.constructor);
// RGB -> RGBA
for (i = 0; i < pixel_count; i++) {
const i3 = i * 3;
const i4 = i * 4;
destination_data[i4] = source_data[i3];
destination_data[i4 + 1] = source_data[i3 + 1];
destination_data[i4 + 2] = source_data[i3 + 2];
destination_data[i4 + 3] = saturated_channel_value; // fill alpha
}
} else if (source_item_size === 2 && destination_item_size === 4) {
//RA -> RGBA
for (i = 0; i < pixel_count; i++) {
const i2 = i * 2;
const i4 = i * 4;
const r = source_data[i2];
destination_data[i4] = r;
destination_data[i4 + 1] = r;
destination_data[i4 + 2] = r;
destination_data[i4 + 3] = source_data[i2 + 1]; // fill alpha
}
} else {
throw new Error('Unsupported channel layout combination');
}
// register data change
destination.version++;
}