Skip to content

WebGPUBackend: Textures are not always filtered correctly. #31631

@Mugen87

Description

@Mugen87

Description

While working at blurred mipmaps for SSRNode, I've realized WebGPURenderer has no support for manual defined mipmaps for regular (not compressed) textures so far. Meaning mipmaps defined in Texture.mipmaps are currently ignored by the renderer which explains why webgl_materials_texture_manualmipmap fails when switching to WebGPURenderer.

On my dev branch I have already implemented basic support for image and data textures but now encountered a strange issue that only happens with the WebGPU backend.

If two meshes share the same material but use different filtered textures, the filtering is not always correctly applied to both meshes. It depends on the render order which highly suggest some sort of resource sharing bug.

Reproduction steps

  1. Open https://jsfiddle.net/m4gzanwt/
  2. Observe how both planes have a nearest filtered texture although the right one actually uses linear filtering with mipmapping.
  3. Comment out the line with renderOrder to fix the rendering.
  4. Switching to the WebGL backend also fixed the issue. Probably because texture filtering is handled differently in WebGL compared to WebGPU.

Code

import * as THREE from "three";

let renderer, scene, camera;

init();

async function init() {
  camera = new THREE.PerspectiveCamera(
    70,
    window.innerWidth / window.innerHeight,
    0.1,
    100,
  );
  camera.position.z = 1;

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x000000);

  const texture1 = await new THREE.TextureLoader().loadAsync(
    "https://threejs.org/examples/textures/crate.gif",
  );
  texture1.colorSpace = THREE.SRGBColorSpace;

  const texture2 = texture1.clone();
  texture2.minFilter = texture2.magFilter = THREE.NearestFilter;

  const geometry = new THREE.PlaneGeometry( 2, 2 );
  const material1 = new THREE.MeshBasicMaterial({ map: texture1 });
  const material2 = new THREE.MeshBasicMaterial({ map: texture2 });

  const mesh1 = new THREE.Mesh(geometry, material1);
  mesh1.position.x = 1;
  scene.add(mesh1);

  const mesh2 = new THREE.Mesh(geometry, material2);
  mesh2.renderOrder = - Infinity; // comment out to fix filtering in right texture
  mesh2.position.x = -1;
  scene.add(mesh2);

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

function animate() {
  renderer.render(scene, camera);
}

Live example

https://jsfiddle.net/m4gzanwt/

Screenshots

No response

Version

r179

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