@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
291 lines (290 loc) • 13.2 kB
JavaScript
import { InternalTexture } from "../../../Materials/Textures/internalTexture.js";
import { Logger } from "../../../Misc/logger.js";
import { ThinWebGPUEngine } from "../../thinWebGPUEngine.js";
ThinWebGPUEngine.prototype.createRawTexture = function (data, width, height, format, generateMipMaps, invertY, samplingMode, compression = null, type = 0, creationFlags = 0, useSRGBBuffer = false) {
const texture = new InternalTexture(this, 3 /* InternalTextureSource.Raw */);
texture.baseWidth = width;
texture.baseHeight = height;
texture.width = width;
texture.height = height;
texture.format = format;
texture.generateMipMaps = generateMipMaps;
texture.samplingMode = samplingMode;
texture.invertY = invertY;
texture._compression = compression;
texture.type = type;
texture._creationFlags = creationFlags;
texture._useSRGBBuffer = useSRGBBuffer;
if (!this._doNotHandleContextLost) {
texture._bufferView = data;
}
this._textureHelper.createGPUTextureForInternalTexture(texture, width, height, undefined, creationFlags);
this.updateRawTexture(texture, data, format, invertY, compression, type, useSRGBBuffer);
this._internalTexturesCache.push(texture);
return texture;
};
ThinWebGPUEngine.prototype.updateRawTexture = function (texture, bufferView, format, invertY, compression = null, type = 0, useSRGBBuffer = false) {
if (!texture) {
return;
}
if (!this._doNotHandleContextLost) {
texture._bufferView = bufferView;
texture.invertY = invertY;
texture._compression = compression;
texture._useSRGBBuffer = useSRGBBuffer;
}
if (bufferView) {
const gpuTextureWrapper = texture._hardwareTexture;
const needConversion = format === 4;
if (needConversion) {
bufferView = ConvertRGBtoRGBATextureData(bufferView, texture.width, texture.height, type);
}
const data = new Uint8Array(bufferView.buffer, bufferView.byteOffset, bufferView.byteLength);
this._textureHelper.updateTexture(data, texture, texture.width, texture.height, texture.depth, gpuTextureWrapper.format, 0, 0, invertY, false, 0, 0);
if (texture.generateMipMaps) {
this._generateMipmaps(texture, this._uploadEncoder);
}
}
texture.isReady = true;
};
ThinWebGPUEngine.prototype.createRawCubeTexture = function (data, size, format, type, generateMipMaps, invertY, samplingMode, compression = null) {
const texture = new InternalTexture(this, 8 /* InternalTextureSource.CubeRaw */);
if (type === 1 && !this._caps.textureFloatLinearFiltering) {
generateMipMaps = false;
samplingMode = 1;
Logger.Warn("Float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
}
else if (type === 2 && !this._caps.textureHalfFloatLinearFiltering) {
generateMipMaps = false;
samplingMode = 1;
Logger.Warn("Half float texture filtering is not supported. Mipmap generation and sampling mode are forced to false and TEXTURE_NEAREST_SAMPLINGMODE, respectively.");
}
else if (type === 1 && !this._caps.textureFloatRender) {
generateMipMaps = false;
Logger.Warn("Render to float textures is not supported. Mipmap generation forced to false.");
}
else if (type === 2 && !this._caps.colorBufferFloat) {
generateMipMaps = false;
Logger.Warn("Render to half float textures is not supported. Mipmap generation forced to false.");
}
texture.isCube = true;
texture._originalFormat = format;
texture.format = format === 4 ? 5 : format;
texture.type = type;
texture.generateMipMaps = generateMipMaps;
texture.width = size;
texture.height = size;
texture.samplingMode = samplingMode;
if (!this._doNotHandleContextLost) {
texture._bufferViewArray = data;
}
texture.invertY = invertY;
texture._compression = compression;
texture._cachedWrapU = 0;
texture._cachedWrapV = 0;
this._textureHelper.createGPUTextureForInternalTexture(texture);
if (format === 4) {
const gpuTextureWrapper = texture._hardwareTexture;
gpuTextureWrapper._originalFormatIsRGB = true;
}
if (data) {
this.updateRawCubeTexture(texture, data, format, type, invertY, compression);
}
texture.isReady = true;
return texture;
};
ThinWebGPUEngine.prototype.updateRawCubeTexture = function (texture, bufferView, _format, type, invertY, compression = null) {
texture._bufferViewArray = bufferView;
texture.invertY = invertY;
texture._compression = compression;
const gpuTextureWrapper = texture._hardwareTexture;
const needConversion = gpuTextureWrapper._originalFormatIsRGB;
const faces = [0, 2, 4, 1, 3, 5];
const data = [];
for (let i = 0; i < bufferView.length; ++i) {
let faceData = bufferView[faces[i]];
if (needConversion) {
faceData = ConvertRGBtoRGBATextureData(faceData, texture.width, texture.height, type);
}
data.push(new Uint8Array(faceData.buffer, faceData.byteOffset, faceData.byteLength));
}
this._textureHelper.updateCubeTextures(data, gpuTextureWrapper.underlyingResource, texture.width, texture.height, gpuTextureWrapper.format, invertY, false, 0, 0);
if (texture.generateMipMaps) {
this._generateMipmaps(texture, this._uploadEncoder);
}
texture.isReady = true;
};
ThinWebGPUEngine.prototype.createRawCubeTextureFromUrl = function (url, scene, size, format, type, noMipmap, callback, mipmapGenerator, onLoad = null, onError = null, samplingMode = 3, invertY = false) {
const texture = this.createRawCubeTexture(null, size, format, type, !noMipmap, invertY, samplingMode, null);
scene?.addPendingData(texture);
texture.url = url;
texture.isReady = false;
this._internalTexturesCache.push(texture);
const onerror = (request, exception) => {
scene?.removePendingData(texture);
if (onError && request) {
onError(request.status + " " + request.statusText, exception);
}
};
const internalCallback = (data) => {
const width = texture.width;
const faceDataArrays = callback(data);
if (!faceDataArrays) {
return;
}
if (mipmapGenerator) {
const needConversion = format === 4;
const mipData = mipmapGenerator(faceDataArrays);
const gpuTextureWrapper = texture._hardwareTexture;
const faces = [0, 1, 2, 3, 4, 5];
for (let level = 0; level < mipData.length; level++) {
const mipSize = width >> level;
const allFaces = [];
for (let faceIndex = 0; faceIndex < 6; faceIndex++) {
let mipFaceData = mipData[level][faces[faceIndex]];
if (needConversion) {
mipFaceData = ConvertRGBtoRGBATextureData(mipFaceData, mipSize, mipSize, type);
}
allFaces.push(new Uint8Array(mipFaceData.buffer, mipFaceData.byteOffset, mipFaceData.byteLength));
}
this._textureHelper.updateCubeTextures(allFaces, gpuTextureWrapper.underlyingResource, mipSize, mipSize, gpuTextureWrapper.format, invertY, false, 0, 0);
}
}
else {
this.updateRawCubeTexture(texture, faceDataArrays, format, type, invertY);
}
texture.isReady = true;
scene?.removePendingData(texture);
if (onLoad) {
onLoad();
}
};
this._loadFile(url, (data) => {
internalCallback(data);
}, undefined, scene?.offlineProvider, true, onerror);
return texture;
};
ThinWebGPUEngine.prototype.createRawTexture3D = function (data, width, height, depth, format, generateMipMaps, invertY, samplingMode, compression = null, textureType = 0, creationFlags = 0) {
const source = 10 /* InternalTextureSource.Raw3D */;
const texture = new InternalTexture(this, source);
texture.baseWidth = width;
texture.baseHeight = height;
texture.baseDepth = depth;
texture.width = width;
texture.height = height;
texture.depth = depth;
texture.format = format;
texture.type = textureType;
texture.generateMipMaps = generateMipMaps;
texture.samplingMode = samplingMode;
texture.is3D = true;
texture._creationFlags = creationFlags;
if (!this._doNotHandleContextLost) {
texture._bufferView = data;
}
this._textureHelper.createGPUTextureForInternalTexture(texture, width, height, undefined, creationFlags);
this.updateRawTexture3D(texture, data, format, invertY, compression, textureType);
this._internalTexturesCache.push(texture);
return texture;
};
ThinWebGPUEngine.prototype.updateRawTexture3D = function (texture, bufferView, format, invertY, compression = null, textureType = 0) {
if (!this._doNotHandleContextLost) {
texture._bufferView = bufferView;
texture.format = format;
texture.invertY = invertY;
texture._compression = compression;
}
if (bufferView) {
const gpuTextureWrapper = texture._hardwareTexture;
const needConversion = format === 4;
if (needConversion) {
bufferView = ConvertRGBtoRGBATextureData(bufferView, texture.width, texture.height, textureType);
}
const data = new Uint8Array(bufferView.buffer, bufferView.byteOffset, bufferView.byteLength);
this._textureHelper.updateTexture(data, texture, texture.width, texture.height, texture.depth, gpuTextureWrapper.format, 0, 0, invertY, false, 0, 0);
if (texture.generateMipMaps) {
this._generateMipmaps(texture, this._uploadEncoder);
}
}
texture.isReady = true;
};
ThinWebGPUEngine.prototype.createRawTexture2DArray = function (data, width, height, depth, format, generateMipMaps, invertY, samplingMode, compression = null, textureType = 0, creationFlags = 0) {
const source = 11 /* InternalTextureSource.Raw2DArray */;
const texture = new InternalTexture(this, source);
texture.baseWidth = width;
texture.baseHeight = height;
texture.baseDepth = depth;
texture.width = width;
texture.height = height;
texture.depth = depth;
texture.format = format;
texture.type = textureType;
texture.generateMipMaps = generateMipMaps;
texture.samplingMode = samplingMode;
texture.is2DArray = true;
texture._creationFlags = creationFlags;
if (!this._doNotHandleContextLost) {
texture._bufferView = data;
}
this._textureHelper.createGPUTextureForInternalTexture(texture, width, height, depth, creationFlags);
this.updateRawTexture2DArray(texture, data, format, invertY, compression, textureType);
this._internalTexturesCache.push(texture);
return texture;
};
ThinWebGPUEngine.prototype.updateRawTexture2DArray = function (texture, bufferView, format, invertY, compression = null, textureType = 0) {
if (!this._doNotHandleContextLost) {
texture._bufferView = bufferView;
texture.format = format;
texture.invertY = invertY;
texture._compression = compression;
}
if (bufferView) {
const gpuTextureWrapper = texture._hardwareTexture;
const needConversion = format === 4;
if (needConversion) {
bufferView = ConvertRGBtoRGBATextureData(bufferView, texture.width, texture.height, textureType);
}
const data = new Uint8Array(bufferView.buffer, bufferView.byteOffset, bufferView.byteLength);
this._textureHelper.updateTexture(data, texture, texture.width, texture.height, texture.depth, gpuTextureWrapper.format, 0, 0, invertY, false, 0, 0);
if (texture.generateMipMaps) {
this._generateMipmaps(texture, this._uploadEncoder);
}
}
texture.isReady = true;
};
/**
* @internal
*/
function ConvertRGBtoRGBATextureData(rgbData, width, height, textureType) {
// Create new RGBA data container.
let rgbaData;
let val1 = 1;
if (textureType === 1) {
rgbaData = new Float32Array(width * height * 4);
}
else if (textureType === 2) {
rgbaData = new Uint16Array(width * height * 4);
val1 = 15360; // 15360 is the encoding of 1 in half float
}
else if (textureType === 7) {
rgbaData = new Uint32Array(width * height * 4);
}
else {
rgbaData = new Uint8Array(width * height * 4);
}
// Convert each pixel.
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const index = (y * width + x) * 3;
const newIndex = (y * width + x) * 4;
// Map Old Value to new value.
rgbaData[newIndex + 0] = rgbData[index + 0];
rgbaData[newIndex + 1] = rgbData[index + 1];
rgbaData[newIndex + 2] = rgbData[index + 2];
// Add fully opaque alpha channel.
rgbaData[newIndex + 3] = val1;
}
}
return rgbaData;
}
//# sourceMappingURL=engine.rawTexture.js.map