UNPKG

react-native-filament

Version:

A real-time physically based 3D rendering engine for React Native

107 lines (99 loc) 3.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BackgroundImage = BackgroundImage; var _useBuffer = require("../hooks/useBuffer"); var _useDisposableResource = require("../hooks/useDisposableResource"); var _useEntityInScene = require("../hooks/useEntityInScene"); var _useWorkletCallback = require("../hooks/useWorkletCallback"); var _useWorkletMemo = require("../hooks/useWorkletMemo"); var _useFilamentContext = require("../hooks/useFilamentContext"); function BackgroundImage({ source, materialSource, resizeMode = 'contain' }) { const { engine, renderableManager, scene, view } = (0, _useFilamentContext.useFilamentContext)(); // Create the material which will be used to render the image const imageMaterialBuffer = (0, _useBuffer.useBuffer)({ source: materialSource }); const imageBuffer = (0, _useBuffer.useBuffer)({ source: source }); const material = (0, _useDisposableResource.useDisposableResource)((0, _useWorkletCallback.useWorkletCallback)(() => { 'worklet'; if (imageMaterialBuffer == null || imageBuffer == null) return undefined; const newMaterial = engine.createMaterial(imageMaterialBuffer); const textureInfo = newMaterial.setDefaultTextureParameter(renderableManager, 'image', imageBuffer, 'sRGB'); newMaterial.setDefaultIntParameter('showImage', 1); // Transform calculation const srcWidth = textureInfo.width; const srcHeight = textureInfo.height; const viewport = view.getViewport(); const dstWidth = viewport.width; const dstHeight = viewport.height; const srcRatio = srcWidth / srcHeight; const dstRatio = dstWidth / dstHeight; let sx; let sy; let tx; let ty; const xMajor = dstWidth / srcWidth > dstHeight / srcHeight; if (resizeMode === 'scale') { sx = 1.0; sy = 1.0; tx = 0.0; ty = 0.0; } else if (resizeMode === 'contain') { if (xMajor) { sx = srcRatio / dstRatio; sy = 1.0; tx = (1.0 - sx) * 0.5 / sx; ty = 0.0; } else { sx = 1.0; sy = dstRatio / srcRatio; tx = 0.0; ty = (1.0 - sy) * 0.5 / sy; } } else if (resizeMode === 'cover') { /** * Scale the image uniformly (maintain the image’s aspect ratio) so that * both dimensions (width and height) of the image will be equal to or larger than * the corresponding dimension of the view (minus padding). */ tx = 0.0; ty = 0.0; const widthScale = dstWidth / srcWidth; const heightScale = dstHeight / srcHeight; const scale = Math.max(widthScale, heightScale); const scaledWidth = srcWidth * scale; const scaledHeight = srcHeight * scale; sx = scaledWidth / dstWidth; sy = scaledHeight / dstHeight; } else { throw new Error(`Invalid resizeMode: ${resizeMode}`); } // eslint-disable-next-line prettier/prettier const transform = [1.0 / sx, 0.0, 0.0, 0.0, 1.0 / sy, 0.0, -tx, -ty, 1.0]; newMaterial.setDefaultMat3fParameter('transform', transform); newMaterial.setDefaultFloat3Parameter('backgroundColor', [0.0, 0.0, 0.0]); return newMaterial; }), [engine, imageMaterialBuffer, imageBuffer]); // Create the geometric shape (a plane) const entity = (0, _useWorkletMemo.useWorkletMemo)(() => { 'worklet'; if (material == null) return; return renderableManager.createImageBackgroundShape(material); }, [material, renderableManager]); (0, _useEntityInScene.useEntityInScene)(scene, entity); return null; } //# sourceMappingURL=BackgroundImage.js.map