UNPKG

@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.

245 lines (244 loc) 8.84 kB
import { Matrix } from "../../Maths/math.vector.js"; import { BaseTexture } from "../../Materials/Textures/baseTexture.js"; import { RegisterClass } from "../../Misc/typeStore.js"; /** * This represents a color grading texture. This acts as a lookup table LUT, useful during post process * It can help converting any input color in a desired output one. This can then be used to create effects * from sepia, black and white to sixties or futuristic rendering... * * The only supported format is currently 3dl. * More information on LUT: https://en.wikipedia.org/wiki/3D_lookup_table */ export class ColorGradingTexture extends BaseTexture { /** * Instantiates a ColorGradingTexture from the following parameters. * * @param url The location of the color grading data (currently only supporting 3dl) * @param sceneOrEngine The scene or engine the texture will be used in * @param onLoad defines a callback triggered when the texture has been loaded */ constructor(url, sceneOrEngine, onLoad = null) { super(sceneOrEngine); if (!url) { return; } this._textureMatrix = Matrix.Identity(); this.name = url; this.url = url; this._onLoad = onLoad; this._texture = this._getFromCache(url, true); if (!this._texture) { const scene = this.getScene(); if (scene) { if (!scene.useDelayedTextureLoading) { this._loadTexture(); } else { this.delayLoadState = 4; } } else { this._loadTexture(); } } else { this._triggerOnLoad(); } } /** * Fires the onload event from the constructor if requested. */ _triggerOnLoad() { if (this._onLoad) { this._onLoad(); } } /** * @returns the texture matrix used in most of the material. * This is not used in color grading but keep for troubleshooting purpose (easily swap diffuse by colorgrading to look in). */ getTextureMatrix() { return this._textureMatrix; } /** * Occurs when the file being loaded is a .3dl LUT file. * @returns the 3D LUT texture */ _load3dlTexture() { const engine = this._getEngine(); let texture; if (!engine._features.support3DTextures) { texture = engine.createRawTexture(null, 1, 1, 5, false, false, 2, null, 0); } else { texture = engine.createRawTexture3D(null, 1, 1, 1, 5, false, false, 2, null, 0); } this._texture = texture; this._texture.isReady = false; this.isCube = false; this.is3D = engine._features.support3DTextures; this.wrapU = 0; this.wrapV = 0; this.wrapR = 0; this.anisotropicFilteringLevel = 1; const callback = (text) => { if (typeof text !== "string") { return; } let data = null; let tempData = null; let line; const lines = text.split("\n"); let size = 0, pixelIndexW = 0, pixelIndexH = 0, pixelIndexSlice = 0; let maxColor = 0; for (let i = 0; i < lines.length; i++) { line = lines[i]; if (!ColorGradingTexture._NoneEmptyLineRegex.test(line)) { continue; } if (line.indexOf("#") === 0) { continue; } const words = line.split(" "); if (size === 0) { // Number of space + one size = words.length; data = new Uint8Array(size * size * size * 4); // volume texture of side size and rgb 8 tempData = new Float32Array(size * size * size * 4); continue; } if (size != 0) { const r = Math.max(parseInt(words[0]), 0); const g = Math.max(parseInt(words[1]), 0); const b = Math.max(parseInt(words[2]), 0); maxColor = Math.max(r, maxColor); maxColor = Math.max(g, maxColor); maxColor = Math.max(b, maxColor); const pixelStorageIndex = (pixelIndexW + pixelIndexSlice * size + pixelIndexH * size * size) * 4; if (tempData) { tempData[pixelStorageIndex + 0] = r; tempData[pixelStorageIndex + 1] = g; tempData[pixelStorageIndex + 2] = b; } // Keep for reference in case of back compat problems. // pixelIndexSlice++; // if (pixelIndexSlice % size == 0) { // pixelIndexH++; // pixelIndexSlice = 0; // if (pixelIndexH % size == 0) { // pixelIndexW++; // pixelIndexH = 0; // } // } pixelIndexH++; if (pixelIndexH % size == 0) { pixelIndexSlice++; pixelIndexH = 0; if (pixelIndexSlice % size == 0) { pixelIndexW++; pixelIndexSlice = 0; } } } } if (tempData && data) { for (let i = 0; i < tempData.length; i++) { if (i > 0 && (i + 1) % 4 === 0) { data[i] = 255; } else { const value = tempData[i]; data[i] = (value / maxColor) * 255; } } } if (texture.is3D) { texture.updateSize(size, size, size); engine.updateRawTexture3D(texture, data, 5, false); } else { texture.updateSize(size * size, size); engine.updateRawTexture(texture, data, 5, false); } texture.isReady = true; this._triggerOnLoad(); }; const scene = this.getScene(); if (scene) { scene._loadFile(this.url, callback); } else { engine._loadFile(this.url, callback); } return this._texture; } /** * Starts the loading process of the texture. */ _loadTexture() { if (this.url) { const url = this.url.toLocaleLowerCase(); if (url.endsWith(".3dl") || url.startsWith("blob:")) { this._load3dlTexture(); } } } /** * Clones the color grading texture. * @returns the cloned texture */ clone() { const newTexture = new ColorGradingTexture(this.url, this.getScene() || this._getEngine()); // Base texture newTexture.level = this.level; return newTexture; } /** * Called during delayed load for textures. */ delayLoad() { if (this.delayLoadState !== 4) { return; } this.delayLoadState = 1; this._texture = this._getFromCache(this.url, true); if (!this._texture) { this._loadTexture(); } } /** * Parses a color grading texture serialized by Babylon. * @param parsedTexture The texture information being parsedTexture * @param scene The scene to load the texture in * @returns A color grading texture */ static Parse(parsedTexture, scene) { let texture = null; if (parsedTexture.name && !parsedTexture.isRenderTarget) { texture = new ColorGradingTexture(parsedTexture.name, scene); texture.name = parsedTexture.name; texture.level = parsedTexture.level; } return texture; } /** * Serializes the LUT texture to json format. * @returns The JSON representation of the texture */ serialize() { if (!this.name) { return null; } const serializationObject = {}; serializationObject.name = this.name; serializationObject.level = this.level; serializationObject.customType = "BABYLON.ColorGradingTexture"; return serializationObject; } } /** * Empty line regex stored for GC. */ ColorGradingTexture._NoneEmptyLineRegex = /\S+/; RegisterClass("BABYLON.ColorGradingTexture", ColorGradingTexture); //# sourceMappingURL=colorGradingTexture.js.map