Blending mode works different for iOS?

Hi everyone, I’m making a project that has 2 layers. One for blending, the other for a solid piece. The thing is, the CustomBlending I’m implementing works great in Android and PC, but for iOS somehow it’s kind of poor. Someone know how to solve this issue? Or is it something of three.js or iOS?

Android:

iOS:

PC:

Thanks in advance

What’s the custom blending you’re implementing? Can’t help you debug without the code that could be causing the problem.

Also, check out this example with the 3 different devices to see if it’s happening there too. It’s got a lot of options on the left panel: foreground, background, equation, and premultiply alpha.

Hey, thanks for answering. Going deeper on my code, it seems to be something about rendering order. But seems weird to me that it doesn’t work with iOS.

This is the code as it is right now:

import * as THREE from './three/build/three.module.js';
import { OrbitControls } from './three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from './three/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from './three/examples/jsm/loaders/RGBELoader.js';

var container, controls;
var camera, scene, renderer, boxMesh;

init();
animate();

function init() {
    container = document.createElement('div');
    document.body.appendChild(container);
    camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.25, 20);
    camera.position.set(1, 1, 1);
    scene = new THREE.Scene();
    var ambient = new THREE.AmbientLight(0x777777);
    scene.add(ambient);
    new RGBELoader()
        .setDataType(THREE.UnsignedByteType)
        .setPath('assets/')
        .load('studio3.hdr', function (texture) {
            var envMap = pmremGenerator.fromEquirectangular(texture).texture;
            scene.background = new THREE.Color(0xffffff);
            scene.environment = envMap;
            texture.dispose();
            pmremGenerator.dispose();
            let i = 0;
            var loader = new GLTFLoader().setPath('assets/');
            loader.load('MetalObjects.glb', function (gltf) {
                var model = gltf.scene;
                model.children.forEach(function (element) {
                    element.renderOrder = i;
                    i += 1;
                    element.material.color = new THREE.Color(0xffffff);
                    element.material.side = THREE.FrontSide;
                    element.material.blending = THREE.NoBlending;
                    //element.material.depthTest = false;
                    element.material.DepthWrite = false;
                });
                scene.add(model);
                //render();
            });
            loader.load('BlendingObjects.glb', function (gltf) {
                var model = gltf.scene
                model.children.forEach(function (element) {
                    element.renderOrder = i;
                    i += 1;
                    element.material.side = THREE.FrontSide;
                    element.material.depthTest = false;
                    element.material.DepthWrite = false;
                    element.material.blending = THREE.CustomBlending;
                    element.material.blendEquation = THREE.ReverseSubtractEquation;
                    element.material.blendSrc = THREE.DstAlphaFactor;
                    element.material.blendDst = THREE.OneMinusSrcColorFactor;
                });
                model.onBeforeRender = function( renderer ) { renderer.clearDepth(); };
                scene.add(model);
                render();
            });
        });
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 0.8;
    renderer.outputEncoding = THREE.sRGBEncoding;
    container.appendChild(renderer.domElement);
    var pmremGenerator = new THREE.PMREMGenerator(renderer);
    pmremGenerator.compileEquirectangularShader();
    controls = new OrbitControls(camera, renderer.domElement);
    controls.addEventListener('onclick', render); // use if there is no animation loop
    controls.minDistance = 1.5;
    controls.maxDistance = 2;
    controls.enableDamping = true;
    controls.target.set(0, 0, 0);
    controls.update();
    window.addEventListener('resize', onWindowResize, false);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    render();
}

function animate() {
    requestAnimationFrame(animate);
    render();
}
function render() {
    //deviceCon.update();
    controls.update();
    renderer.render(scene, camera);
}