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.

194 lines 7.12 kB
import { __decorate } from "../../../../tslib.es6.js"; import { Vector4 } from "../../../../Maths/math.vector.js"; import { RegisterClass } from "../../../../Misc/typeStore.js"; import { NodeGeometryBlockConnectionPointTypes } from "../../Enums/nodeGeometryConnectionPointTypes.js"; import { NodeGeometryBlock } from "../../nodeGeometryBlock.js"; import { editableInPropertyPage } from "../../../../Decorators/nodeDecorator.js"; /** * Block used to fetch a color from texture data */ export class GeometryTextureFetchBlock extends NodeGeometryBlock { /** * Creates a new GeometryTextureFetchBlock * @param name defines the block name */ constructor(name) { super(name); /** * Gets or sets a boolean indicating if coordinates should be clamped between 0 and 1 */ this.clampCoordinates = true; /** * Gets or sets a boolean indicating if coordinates should be clamped between 0 and 1 */ this.interpolation = true; this.registerInput("texture", NodeGeometryBlockConnectionPointTypes.Texture); this.registerInput("coordinates", NodeGeometryBlockConnectionPointTypes.Vector2); this.registerOutput("rgba", NodeGeometryBlockConnectionPointTypes.Vector4); this.registerOutput("rgb", NodeGeometryBlockConnectionPointTypes.Vector3); this.registerOutput("r", NodeGeometryBlockConnectionPointTypes.Float); this.registerOutput("g", NodeGeometryBlockConnectionPointTypes.Float); this.registerOutput("b", NodeGeometryBlockConnectionPointTypes.Float); this.registerOutput("a", NodeGeometryBlockConnectionPointTypes.Float); } /** * Gets the current class name * @returns the class name */ getClassName() { return "GeometryTextureFetchBlock"; } /** * Gets the texture component */ get texture() { return this.inputs[0]; } /** * Gets the coordinates component */ get coordinates() { return this.inputs[1]; } /** * Gets the rgba component */ get rgba() { return this._outputs[0]; } /** * Gets the rgb component */ get rgb() { return this._outputs[1]; } /** * Gets the r component */ get r() { return this._outputs[2]; } /** * Gets the g component */ get g() { return this._outputs[3]; } /** * Gets the b component */ get b() { return this._outputs[4]; } /** * Gets the a component */ get a() { return this._outputs[5]; } _repeatClamp(num) { if (num >= 0) { return num % 1; } else { return 1 - (Math.abs(num) % 1); } } _lerp(a, b, t) { return new Vector4(a.x * (1 - t) + b.x * t, a.y * (1 - t) + b.y * t, a.z * (1 - t) + b.z * t, a.w * (1 - t) + b.w * t); } _getPixel(ix, iy, data, width) { const i = (iy * width + ix) * 4; return new Vector4(data[i], data[i + 1], data[i + 2], data[i + 3]); } _buildBlock() { const func = (state) => { const textureData = this.texture.getConnectedValue(state); if (!textureData || !textureData.data) { return null; } const uv = this.coordinates.getConnectedValue(state); if (!uv) { return null; } const u = this.clampCoordinates ? Math.max(0, Math.min(uv.x, 1.0)) : this._repeatClamp(uv.x); const v = this.clampCoordinates ? Math.max(0, Math.min(uv.y, 1.0)) : this._repeatClamp(uv.y); const width = textureData.width; const height = textureData.height; const data = textureData.data; // Convert UV to texel space const x = u * (width - 1); const y = v * (height - 1); if (this.interpolation) { const x0 = Math.floor(x); const y0 = Math.floor(y); const x1 = Math.min(x0 + 1, width - 1); const y1 = Math.min(y0 + 1, height - 1); const dx = x - x0; const dy = y - y0; const c00 = this._getPixel(x0, y0, data, width); const c10 = this._getPixel(x1, y0, data, width); const c01 = this._getPixel(x0, y1, data, width); const c11 = this._getPixel(x1, y1, data, width); // Interpolate horizontally const top = this._lerp(c00, c10, dx); const bottom = this._lerp(c01, c11, dx); // Interpolate vertically return this._lerp(top, bottom, dy); } return this._getPixel(Math.floor(x), Math.floor(y), data, width); }; this.rgba._storedFunction = (state) => { return func(state); }; this.rgb._storedFunction = (state) => { const color = func(state); return color ? color.toVector3() : null; }; this.r._storedFunction = (state) => { const color = func(state); return color ? color.x : null; }; this.g._storedFunction = (state) => { const color = func(state); return color ? color.y : null; }; this.b._storedFunction = (state) => { const color = func(state); return color ? color.z : null; }; this.a._storedFunction = (state) => { const color = func(state); return color ? color.w : null; }; } _dumpPropertiesCode() { const codeString = super._dumpPropertiesCode() + `${this._codeVariableName}.clampCoordinates = ${this.clampCoordinates};\n`; return codeString; } /** * Serializes this block in a JSON representation * @returns the serialized block object */ serialize() { const serializationObject = super.serialize(); serializationObject.clampCoordinates = this.clampCoordinates; serializationObject.interpolation = this.interpolation; return serializationObject; } _deserialize(serializationObject) { super._deserialize(serializationObject); this.clampCoordinates = serializationObject.clampCoordinates; if (serializationObject.clampCoordinates === undefined) { this.interpolation = serializationObject.interpolation; } } } __decorate([ editableInPropertyPage("Clamp Coordinates", 0 /* PropertyTypeForEdition.Boolean */, "ADVANCED", { embedded: true, notifiers: { rebuild: true } }) ], GeometryTextureFetchBlock.prototype, "clampCoordinates", void 0); __decorate([ editableInPropertyPage("Interpolation", 0 /* PropertyTypeForEdition.Boolean */, "ADVANCED", { embedded: true, notifiers: { rebuild: true } }) ], GeometryTextureFetchBlock.prototype, "interpolation", void 0); RegisterClass("BABYLON.GeometryTextureFetchBlock", GeometryTextureFetchBlock); //# sourceMappingURL=geometryTextureFetchBlock.js.map