three.js: Texture bug on r137

Describe the bug

DDS and PNG textures lose all color, I don’t know how to really explain, I attached screenshots bellow. Since I only use these 2 types of textures, I can’t test other types.

If the browser has DDS support, it will be used, otherwise fallback to PNG. This happens on all browsers and devices I tested.

To Reproduce

Steps to reproduce the behavior: Go to either of the live examples below and press on a weapon or amor icon, the differences will be visible.

Code

A code snippet of how I’m using it.

		const manager = new THREE.LoadingManager(() => {
			const loadingScreen = document.getElementById('loading-screen')
			if (loadingScreen) {
				loadingScreen.classList.add('fade-out')

				loadingScreen!.addEventListener('transitionend', onTransitionEnd)
			}
		})
		manager.addHandler(/\.dds$/i, new DDSLoader())

		const mtlLoader = new MTLLoader(manager)
		mtlLoader.setPath(url!)
		mtlLoader.load(`${model}.mtl`, (materials) => {
			materials.preload()

			const objLoader = new OBJLoader(manager)
			objLoader.setMaterials(materials)
			objLoader.setPath(url!)
			objLoader.load(`${model}.obj`, (object) => {
				object.scale.setScalar(1 / 200)

				object.traverse((child) => {
					child.frustumCulled = false
					if ((child as any).material instanceof THREE.MeshPhongMaterial) {
						(child as any).material.side = THREE.DoubleSide
					}
				})
				scene.add(object)
			}, undefined, (error) => console.error(error))
		})

Live example

Screenshots

Public version with r136: Public version with r136

Dev version with r137 Dev version with r137

Platform:

  • Device: Desktop, Mobile
  • OS: Windows, Android
  • Browser: Tested on Vivaldi (both Desktop and Android), Chrome, Firefox and Edge
  • Three.js version: r137

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 16 (8 by maintainers)

Most upvoted comments

@Karbust If you update to 0.137.4 you shoudn’t need the alphaWrite code anymore.

Correct, it’s working without alphaWrite. Thank you

As far as I can see the only issue of #18631 is that it broke this use case:

Confirmed. This breaks AdditiveBlending when texture.a < 1 and material.transparent is false.

In this new world of alpha: true, I think I’m totally okay with breaking that use case.

And then we’ll be able to get rid of material.alphaWrite.

So if transparent === false we have to add gl_FragColor.a = 1.0 chunk at the end then.

I was reading the migration guide but I wasn’t able to pinpoint where the problem was coming from.

I’ve added a note that OBJ/MTLLoader now requires a sRGB workflow and also the alphaWrite solution.

But I fear many user will not understand that 3D objects are potentially blended with the HTML background and thus don’t understand the note in the migration guide. It seems these cases will require some support.

Makes me wonder if this line:

https://github.com/mrdoob/three.js/blob/63650755e03cfe983a42bca3a489f71930fff3b7/src/renderers/webgl/WebGLPrograms.js#L181

Should be this instead:

alphaWrite: material.alphaWrite && material.transparent,

This stuff hurts my brain a bit.

/cc @donmccurdy

Perfect, it worked.

I was reading the migration guide but I wasn’t able to pinpoint where the problem was coming from.

Thank you.

This issue is related to the latest alpha change, see #23230.

The problem is that your asset is blended with the HTML background since for some reasons the DDS texture holds alpha values < 1.

One workaround to solve the issue is to add this block to your onLoad() callback:

object.traverse( function ( child ) {

     if ( child.material ) child.material.alphaWrite = false;

} );

This will define the material as opaque by setting a 1 alpha value to all fragments.