Skip to content

WebGPURenderer: Broken mesh rendering when using normalized, interleaved attributes. #29683

@Mugen87

Description

@Mugen87

Description

When working at WebGPURenderer support for GLTFExporter, it was noticed that a certain asset introduces rendering issues with the WebGPU backend (see #29509 (comment)). With WebGL, everything renders as expected. The problematic file is models/gltf/ShaderBall.glb which uses normalized (and interleaved) buffer attributes. For some reasons, the mesh itself or other meshes in the scene can end up distorted.

Reproduction steps

  1. Open one of the fiddles.
  2. The scene should render two meshes (ShaderBall.glb and a torus knot).
  3. Notice how the torus knot is distorted.

Code

import * as THREE from 'three';

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

let camera, scene, renderer;

init();

function init() {

	camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
	camera.position.set( 0, 1, 5 );

	scene = new THREE.Scene();

	//

	const ambientLight = new THREE.AmbientLight( 0xcccccc );
	scene.add( ambientLight );

	const dirLight = new THREE.DirectionalLight( 0xffffff, 3 );
	dirLight.target.position.set( 0, 0, - 1 );
	dirLight.add( dirLight.target );
	dirLight.lookAt( - 1, - 1, 0 );
	scene.add( dirLight );

	//

	const loader = new GLTFLoader();
	loader.load( 'models/gltf/ShaderBall.glb', function ( gltf ) {

		const model = gltf.scene;
		model.position.set( - 2, - 1, 0 );
		console.log( model );
		scene.add( model );

		const material = new THREE.MeshStandardMaterial( {
			color: 0xff0000,
			roughness: 1
		} );
		const object = new THREE.Mesh( new THREE.TorusKnotGeometry(), material );
		object.position.set( 2, 0, 0 );
		scene.add( object );

	} );

	//

	renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL: false } );
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize( window.innerWidth, window.innerHeight );
	renderer.setAnimationLoop( animate );
	renderer.toneMapping = THREE.ACESFilmicToneMapping;
	document.body.appendChild( renderer.domElement );

	const controls = new OrbitControls( camera, renderer.domElement );
	controls.minDistance = 2;
	controls.maxDistance = 10;

	window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();

	renderer.setSize( window.innerWidth, window.innerHeight );

}

//

function animate() {

	renderer.render( scene, camera );

}

Live example

Screenshots

image

Version

r169

Device

Desktop

Browser

Chrome

OS

MacOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions