Texture Loading

Texture Loading, Wrapping and Color Space

new BABYLON.Texture(url, scene, noMipmap, invertY, samplingMode) loads asynchronously and returns at once. The defaults follow Textures: mipmaps, trilinear filtering, invertY true, repeat wrapping, and gammaSpace true, marking the image as sRGB so shaders linearize it before lighting (sRGB); set it false for normal, roughness and metallic maps:

Loading a cover texture and changing its wrapping and tilingJavaScript
const cover = new BABYLON.Texture('booknest-cover-3.png', scene);
cover.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;          // 2: flip every other tile
cover.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;           // 0: stretch the edge texels
cover.uScale = 3;                                          // three tiles across
cover.onLoadObservable.addOnce(() => {
  const { width, height } = cover.getSize();
  console.log(`${width} x ${height}, hasAlpha ${cover.hasAlpha}, ` +
    `gammaSpace ${cover.gammaSpace}, sampling ${cover.samplingMode}`);
});
Output
256 x 384, hasAlpha false, gammaSpace true, sampling 3

The PNG has an alpha channel, but hasAlpha stays false until you set it, so a cover never blends by accident. .ktx2 files (Basis Universal 3,114 , Compressed Textures) load through the same constructor and transcode per device.

One cover image loaded as a Texture and tiled three times with repeat, mirror and clamp wrappingHTMLLive
<!doctype html>
<style>
  body { margin: 0; background: #f7f3ec; font: 13px system-ui, sans-serif; color: #333; }
  canvas { width: 100%; max-width: 600px; height: 300px; display: block; touch-action: none; outline: none; }
  #info { max-width: 600px; padding: 4px 8px; font-family: monospace; }
</style>
<canvas id="view"></canvas>
<div id="info">Loading…</div>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babylonjs-gui@9.28.0/babylon.gui.min.js"></script>
<script>
// The book loads 'booknest-cover-3.png'. Here the PNG is drawn on a canvas and handed to
// BABYLON.Texture as a data: URL, so it still goes through the normal asynchronous loader.
const art = document.createElement('canvas');
art.width = 256; art.height = 384;
const c = art.getContext('2d');
c.fillStyle = '#e09a10'; c.fillRect(0, 0, 256, 384);
c.fillStyle = '#7a4a00'; c.fillRect(0, 0, 40, 384);           // a band on the left edge
c.fillStyle = '#fff8e1'; c.textAlign = 'center'; c.font = 'bold 36px Georgia';
c.fillText('Salt and', 148, 150); c.fillText('Saffron', 148, 192);
c.beginPath(); c.arc(148, 280, 40, 0, Math.PI * 2); c.fill();
const url = art.toDataURL('image/png');

const canvas = document.getElementById('view');
const engine = new BABYLON.Engine(canvas, true);
const scene = new BABYLON.Scene(engine);
scene.clearColor = BABYLON.Color4.FromHexString('#f7f3ecff');
const camera = new BABYLON.ArcRotateCamera('cam', -Math.PI / 2, Math.PI / 2, 7, new BABYLON.Vector3(0, 0.1, 0), scene);
camera.attachControl(canvas, true);
new BABYLON.HemisphericLight('sky', new BABYLON.Vector3(0, 0, -1), scene);
const ui = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI('ui');

const MODES = [['WRAP (repeat)', BABYLON.Texture.WRAP_ADDRESSMODE],
  ['MIRROR', BABYLON.Texture.MIRROR_ADDRESSMODE], ['CLAMP', BABYLON.Texture.CLAMP_ADDRESSMODE]];
MODES.forEach(([name, mode], i) => {
  // new BABYLON.Texture(url, scene, noMipmap, invertY, samplingMode) returns at once
  const cover = new BABYLON.Texture(url, scene);
  cover.wrapU = mode;
  cover.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;       // stretch the edge texels vertically
  cover.uScale = 3;                                      // three tiles across
  cover.uOffset = -1;                                    // centered, so clamp shows both edges
  const panel = BABYLON.MeshBuilder.CreatePlane(name, { width: 1.8, height: 1.8 }, scene);
  panel.position.x = (i - 1) * 2;
  panel.material = new BABYLON.StandardMaterial(name, scene);
  panel.material.diffuseTexture = cover;
  panel.material.specularColor = BABYLON.Color3.Black();
  const label = new BABYLON.GUI.TextBlock('', name);
  Object.assign(label, { color: '#333', fontSize: 12, resizeToFit: true });
  ui.addControl(label);
  label.linkWithMesh(panel);
  label.linkOffsetY = 95;
  if (i === 0) cover.onLoadObservable.addOnce(() => {
    const { width, height } = cover.getSize();
    document.getElementById('info').textContent = `${width} x ${height}, hasAlpha ${cover.hasAlpha}, ` +
      `gammaSpace ${cover.gammaSpace}, samplingMode ${cover.samplingMode} (trilinear)`;
  });
});
engine.runRenderLoop(() => scene.render());
addEventListener('resize', () => engine.resize());
</script>