@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
169 lines (130 loc) • 4.76 kB
JavaScript
import { assert } from "../../../../core/assert.js";
import ImageFilter from "../../filter/ImageFilter.js";
import { sampler2d_flipY_in_place } from "../../filter/sampler2d_flipY_in_place.js";
import CopyShader from "../../postprocess/threejs/shaders/CopyShader.js";
import { WebGLRendererPool } from "../../render/RendererPool.js";
import { canvasDataToSampler } from "../canvasDataToSampler.js";
import { formatToChannelCount } from "../formatToChannelCount.js";
import { sampler2d_scale } from "./resize/sampler2d_scale.js";
import { Sampler2D } from "./Sampler2D.js";
import { sampler2d_ensure_uint8_RGBA } from "./sampler2d_ensure_uint8_RGBA.js";
const DEFAULT_TEXTURE_WIDTH = 512;
const DEFAULT_TEXTURE_HEIGHT = 512;
/**
*
* @param {THREE.DataTexture} texture
* @param {number} channel_count
* @param {number} _width
* @param {number} _height
* @returns {Sampler2D}
*/
function data_texture_to_sampler(texture, channel_count, _width, _height) {
const source = new Sampler2D(texture.image.data, channel_count, texture.image.width, texture.image.height);
let converted = sampler2d_ensure_uint8_RGBA(source);
if (converted.width !== _width || converted.height !== _height) {
const target = Sampler2D.uint8(4, _width, _height);
sampler2d_scale(converted, target);
converted = target;
}
return converted;
}
/**
*
* @param {THREE.Texture} texture
* @param {number} channel_count
* @param {number} _width
* @param {number} _height
* @returns {Sampler2D}
*/
function html_image_texture_to_sampler(texture, channel_count, _width, _height) {
/**
*
* @type {Image}
*/
const img = texture.image;
assert.isInstanceOf(img, Image, 'texture.image', 'Image');
const canvas = document.createElement('canvas');
canvas.width = _width;
canvas.height = _height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, _width, _height);
const result = Sampler2D.uint8(4, _width, _height);
canvasDataToSampler(result, ctx);
return result;
}
/**
*
* @param {Texture} texture
* @param {number} [width]
* @param {number} [height]
* @param {boolean} [flipY]
* @return {Sampler2D}
*/
export function convertTexture2Sampler2D(
texture,
width,
height,
flipY = true
) {
let _height = height;
let _width = width;
const channel_count = formatToChannelCount(texture.format);
if (_width === undefined || _height === undefined) {
//figure out texture size
const image = texture.image;
if (image !== undefined && image !== null) {
if (_width === undefined) {
if (typeof image.width === "number") {
_width = image.width;
} else {
_width = DEFAULT_TEXTURE_WIDTH;
}
}
if (_height === undefined) {
if (typeof image.height === "number") {
_height = image.height;
} else {
_height = DEFAULT_TEXTURE_HEIGHT;
}
}
} else {
if (_width === undefined) {
_width = DEFAULT_TEXTURE_WIDTH;
}
if (_height === undefined) {
_height = DEFAULT_TEXTURE_HEIGHT;
}
}
}
let data;
if (texture.isDataTexture === true) {
// special case
const converted = data_texture_to_sampler(texture, channel_count, _width, _height);
data = converted.data;
} else if (texture.image instanceof Image) {
const converted = html_image_texture_to_sampler(texture, channel_count, _width, _height);
data = converted.data;
} else {
const built = WebGLRendererPool.global.use(renderer => {
const ctx = renderer.getContext();
//support for compressed textures
ctx.getExtension("WEBGL_compressed_texture_s3tc");
return ImageFilter(renderer, _width, _height, {
vertexShader: CopyShader.vertexShader,
fragmentShader: CopyShader.fragmentShader,
uniforms: {
tDiffuse: {
value: texture,
type: 't'
},
opacity: { value: 1.0 }
}
});
});
data = built.array;
}
if (flipY) {
sampler2d_flipY_in_place(data, _width, _height);
}
return new Sampler2D(data, 4, _width, _height);
}