Objects render multiple times

I’m working on an interactive map: https://test.xtrahost.nl/

It al seems to be working fine, but if I visit it on a mobile device (an iPhone 12 in this example), the models seem to load multiple times, yet only the ‘main’ model is interactive.

Is there anything known to cause this?

Can you post your code where models are loaded?

Thanks for your response. Yes I can, the regions are al loaded as separate objects because they are going to be interactive, this is one of them, the others are all similar to this:

var alkmaar;
new GLTFLoader().load('assets/regios_textures/Alkmaar.gltf', function ( object ) {
    alkmaar = object.scene; // THREE.Group
    alkmaar.scale.set(10, 10, 10 );
    alkmaar.position.y = 0;
    alkmaar.traverse(function(child) { if (child instanceof THREE.Mesh) {
            child.castShadow = true;
            child.receiveShadow = true;
            child.callback = clickalkmaar;
            child.material.metalness = 0;
    scene.add( alkmaar );
    }, function ( xhr ) {
        console.log( 'Alkmaar ' + ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
    }, function ( error ) {
        console.log( 'An error happened' );

I can confirm I see this bug on an iPhone 13 , running iOS 15.4.1, too. Both in Safari and Firefox, btw.
The problem does not occur in macOS 10.15.7. Neither in Safari, Firefox, Chrome nor Opera.

It looks to me like you have two (2!) cameras, and only one of them is OrbitControlled, while the other one seems to remain at a fixed position and orientation.

When you move the cursor up or down, once you move the cursor from a flat-on view further up, the lower half of the island comes forward (being clipped at the far end btw.),

and if you move the cursor from a flat-on view further down, the upper half of the island comes forward (being clipped at the far end also.)

On a completely unrelated note:

if you want to unleash the full 60 fps on your iPhone, all you have to do is turn off the Settings/Battery/Powersavings mode:

Thanks for taking your time to respond!

Yes, it seems to be happening only on iPhones and on every browser on them. I even checked it on an iPad and it didn’t seem to happen there strangely enough.

I checked my code for errors in my renderer of camera, but there didn’t seem to be any error that could make this happen.

Thank you for the note about the powersavings mode by the way.

I looked a little more into this. It appears that ALL browsers on iOS must use WebKit as their base, as per the Apple App Store rules. See section 2.5.6 on this:

Or, as some other user paraphrased this:

On iOS there are no web browsers other than Safari, per the app store rules. “Chrome” / “Firefox” / etc on iOS are just basically skins on top of Webkit.

This is why you don’t get any of the features / extensions / etc of Chrome or Firefox on iOS.

So your problem seems to be boiling down to being a Webkit bug.

1 Like

I’ve seen this before as well on other WebGL demos. Like this one: Cosmic Platform

It feels like the first frame of the depth&color buffer gets stored, and then the subsequent renders are fighting with that first one. Definitely a WebKit bug because it started happening on my iPhone 11 since I upgraded to iOS 15. Anything in front of the depth of the first frame renders, but anything further behind it doesn’t:

However, opening a new tab, or rotating the phone, then returning to the original view fixes it:

Are you using any RenderTargets or post-processing passes, by any chance? I’m asking because it seems to happen also on the official Unreal bloom pass example


@marquizzo experiencing this too, is there a fix for this?

That’s an interesting workaround. :+1:

Putting it all together, it looks like a double-buffering initialisation bug. Which then, through your workaround, is forced into a proper re-initialization.

Maybe @vincentbosch7 could experiment with getting (forcing) a different rendering context through variations of the renderer options. The .autoClear option should be a good starting point.

1 Like

I haven’t found a way to fix it. I need to find out when exactly it’s happening in the first place. My suspicion is to resize the culprit rendertarget by 1px, but I cannot confirm that would work.

OK yes a resize down then back up by one pixel sounds feasible, if not what’s your opinion on something like “if ios” completely drop and reassigning render target?

Try it out and, see if it works, then let us know!

1 Like

Thank you all for taking your time to reply!

This sadly didn’t do anything for me.

This seems to work, I execute the following function on orientationchange and resize:

function screenchange() {
    var width = $('.tourwrap').width(); //declare width
    var height = $('.tourwrap').height(); //declare height

    camera.aspect = width / height;
    raycaster.setFromCamera( mouse, camera );
    renderer.setSize( width, height );

However if I just execute this function after everything is completely loaded, it doesn’t fix it.

So I tried to combine it with this:

Now after every 3D model is loaded, I resize the canvas to 100% - 1px and after that I execute that same function I mentioned before. This seems to fix it! It’s not the most beautiful way but it seems to do the job. Thank you all for your help.

1 Like

Sad that such an inelegant solution was needed, but I’m glad that something worked!

What was your setup? Are you using a post-processing effect, or using your own Rendertarget setup? Could you share more info here? I’m trying to figure out when exactly it happens to hopefully file a bug report with the WebKit team.

To be honest I wouldn’t know. I’ve tested a lot to find out if I could get rid of this bug, but nothing seemed to fix it (except for this inelegant solution). I’ve done many similar projects to these, and this is the first time this happened. The only big difference between those projects and this one, is the fact that I tried working with importmaps and a polyfill

<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.5.5/dist/es-module-shims.js"></script>

<script type="importmap">
        "imports": {
            "three": "./three/build/three.module.js"

I saw that the Unreal bloom pass example also uses this, but I could be completely wrong about the fact that this even matters for the current bug.

If you find anything related I would be very interested to know!