Textures doesn't work on some versions Safari

The code doesn’t work on some of versions Safari (16.5 for example). What is the reason? Please see screenshots

// Set up the scene
const scene = new THREE.Scene();

// Instantiate a loader for textures
const loader = new THREE.TextureLoader();

// Define the supportsWebP variable
const supportsWebP = document.createElement('canvas').toDataURL('image/webp').startsWith('data:image/webp');

// Load mapTexture
loader.load(
  supportsWebP
    ? 'src/img/textures/map_lines_dots.webp'
    : 'src/img/textures/map_lines_dots.jpg',
  (mapTexture) => {
    // Create the material when the texture is loaded
    const material = new THREE.MeshStandardMaterial({
      map: mapTexture,
      opacity: 0.8, // Set opacity (0 is fully transparent, 1 is fully opaque)
      transparent: true, // Enable transparency
    });

    // Set up the camera
    const camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 3;

    // Set up the renderer
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true; // Enable shadow mapping
    document.getElementById("scene-container").appendChild(renderer.domElement);

    // Set the initial rotation angles of the camera
    camera.rotation.z = Math.PI / -7;

    // Create a sphere geometry
    const geometry = new THREE.SphereGeometry(1, 50, 50);
    const sphere = new THREE.Mesh(geometry, material);
    sphere.position.set(0, 0, 0);

    // Enable shadow casting and receiving for the sphere
    sphere.castShadow = true;
    sphere.receiveShadow = true;

    // Add the sphere to the scene
    scene.add(sphere);

    // Set up a directional light for shadows
    const light = new THREE.DirectionalLight(0xffffff, 2);
    light.position.set(3, 2, 5);
    light.castShadow = true; // Enable shadow casting for the light
    scene.add(light);

    // Set up the animation
    const animate = function () {
      requestAnimationFrame(animate);

      // Rotate the sphere
      sphere.rotation.x = 0.3;
      sphere.rotation.y += 0.0025;

      // Render the scene with the camera
      renderer.render(scene, camera);
    };

    // Call the animate function
    animate();

    // Adjust camera aspect ratio and renderer size when the window is resized
    window.addEventListener('resize', () => {
      const width = window.innerWidth;
      const height = window.innerHeight;

      renderer.setSize(width, height);
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
    });
  },
  undefined,
  (err) => {
    console.error('An error happened when loading mapTexture: ', err);
  }
);

// Load backgroundTexture
loader.load(
  supportsWebP
    ? 'src/img/textures/background.webp'
    : 'src/img/textures/background.jpg',
  (backgroundTexture) => {
    scene.background = backgroundTexture;
  },
  undefined,
  (err) => {
    console.error('An error happened when loading backgroundTexture: ', err);
  }
);

Can you please verify if this issue is WebP related by always using JPG?

Could you write me please, what image format need I to use? PNG?

I have only the problem that some versions of Safari don’t work with texture or code.

Try it with JPG only. Maybe older Safari versions have issues processing WebP.

BTW: Does the following official example work on your problematic devices?

https://threejs.org/examples/webgl_geometry_cube

Your site doesn’t work on Safari less than 16 version

This code doesn’t work on some versions of Safari too:

// Set up the scene
const scene = new THREE.Scene();

const textureLoader = new THREE.TextureLoader();
const mapTexture = textureLoader.load('src/img/textures/map_lines_dots.jpg');

const backgroundTexture = textureLoader.load('src/img/textures/background.svg');
scene.background = backgroundTexture;

// Set up the camera
const camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 3;

// Set up the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true; // Enable shadow mapping
document.getElementById("scene-container").appendChild(renderer.domElement);

// Set the initial rotation angles of the camera
camera.rotation.z = Math.PI /-7;

// Create a sphere geometry
const geometry = new THREE.SphereGeometry(1, 50,50);
const material = new THREE.MeshStandardMaterial({
    map: mapTexture ,
    opacity: 0.8, // Set opacity (0 is fully transparent, 1 is fully opaque)
    transparent: true // Enable transparency
}); // Use MeshStandardMaterial for shadows
const sphere = new THREE.Mesh(geometry, material);

sphere.position.set(0, 0, 0);

// Enable shadow casting and receiving for the sphere
sphere.castShadow = true;
sphere.receiveShadow = true;

// Add the sphere to the scene
scene.add(sphere);

// Set up a directional light for shadows
const light = new THREE.DirectionalLight(0xffffff, 2);
light.position.set(3, 2, 5);
light.castShadow = true; // Enable shadow casting for the light
scene.add(light);

// // Set up a directional light for shadows
// const light2 = new THREE.DirectionalLight(0xffffff, 1);
// light2.position.set(-3, -4, -6);
// light2.castShadow = true; // Enable shadow casting for the light
// scene.add(light2);

// Set up the animation
const animate = function () {
    requestAnimationFrame(animate);

    // Rotate the sphere
    sphere.rotation.x = 0.3;
    sphere.rotation.y += 0.0025;

    // Render the scene with the camera
    renderer.render(scene, camera);
};

// Call the animate function
animate();

// Adjust camera aspect ratio and renderer size when the window is resized
window.addEventListener('resize', () => {
    const width = window.innerWidth;
    const height = window.innerHeight;

    renderer.setSize(width, height);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
});

Do you see any error logs or warning in the browser console?

I think you are running into this issue:

tl;dr: Older Safari version do not fully support import maps. You need at least Safari 16.4 or a polyfill.

1 Like

this one on my site

The problem is this code works on all versions of Safari except Safari 16.5 Ventura. Do you have any suggestions as to why this code doesn’t work on Safari Ventura?

// Set up the scene
const scene = new THREE.Scene();

const textureLoader = new THREE.TextureLoader();
const mapTexture = textureLoader.load('src/img/textures/map_lines_dots.jpg');

const backgroundTexture = textureLoader.load('src/img/textures/background.svg');
scene.background = backgroundTexture;

// Set up the camera
const camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 3;

// Set up the renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true; // Enable shadow mapping
document.getElementById("scene-container").appendChild(renderer.domElement);

// Set the initial rotation angles of the camera
camera.rotation.z = Math.PI /-7;

// Create a sphere geometry
const geometry = new THREE.SphereGeometry(1, 50,50);
const material = new THREE.MeshStandardMaterial({
    map: mapTexture ,
    opacity: 0.8, // Set opacity (0 is fully transparent, 1 is fully opaque)
    transparent: true // Enable transparency
}); // Use MeshStandardMaterial for shadows
const sphere = new THREE.Mesh(geometry, material);

sphere.position.set(0, 0, 0);

// Enable shadow casting and receiving for the sphere
sphere.castShadow = true;
sphere.receiveShadow = true;

// Add the sphere to the scene
scene.add(sphere);

// Set up a directional light for shadows
const light = new THREE.DirectionalLight(0xffffff, 2);
light.position.set(3, 2, 5);
light.castShadow = true; // Enable shadow casting for the light
scene.add(light);

// // Set up a directional light for shadows
// const light2 = new THREE.DirectionalLight(0xffffff, 1);
// light2.position.set(-3, -4, -6);
// light2.castShadow = true; // Enable shadow casting for the light
// scene.add(light2);

// Set up the animation
const animate = function () {
    requestAnimationFrame(animate);

    // Rotate the sphere
    sphere.rotation.x = 0.3;
    sphere.rotation.y += 0.0025;

    // Render the scene with the camera
    renderer.render(scene, camera);
};

// Call the animate function
animate();

// Adjust camera aspect ratio and renderer size when the window is resized
window.addEventListener('resize', () => {
    const width = window.innerWidth;
    const height = window.innerHeight;

    renderer.setSize(width, height);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
});

Hello, could you help me please with this problem?

I can only recommend you update iOS to a higher version.

1 Like