Three.js: TextureNode colorspace/encoding issue

Created on 22 Jul 2019  路  6Comments  路  Source: mrdoob/three.js

Description of the problem

I have a discrepancy between MeshStandardMaterial and StandardNodeMaterial used with color textures. Unless I missed something, the texture generated by TextureNode seems to have an issue with color space or encoding.

Renderer:
renderer.gammaOutput = true;

Texture encoding:
texture.encoding = THREE.sRGBEncoding;

Node texture:
nodeTexture = new TextureNode(texture);

Example with three.js standard material system:
MeshStandardMaterial 1 (solid color):
mtl.color = new THREE.Color(_VALUE_).convertSRGBToLinear();

MeshStandardMaterial 2 (color texture):
mtl.map = texture;

MeshStandardMaterial

Example with three.js node system:
StandardNodeMaterial 1 (solid color):

mtl.color = new ColorNode(_VALUE_);
mtl.color.value.convertSRGBToLinear();

StandardNodeMaterial 2 (color texture):
mtl.color = nodeTexture;

StandardNodeMaterial

Both images shall be similar however we can notice that on the second one, the object with the texture is all washed out.

Three.js version
  • [x] Dev
Browser
  • [x] All of them
OS
  • [x] All of them
Bug

Most helpful comment

Thanks. I created a PR for this bug.

I did some pretty advanced stuff with your node system and I must say that I am really impressed. Except these few little things with the normals and color space, everything else is working perfectly so far.

All 6 comments

You might be using the wrong NodeMaterial. StandardNodeMaterial (as you write) is not the same as MeshStandardNodeMaterial unless that's a typo or I misunderstood 馃槃

No it is not a typo. I want to show that texture encoding is properly handled using the standard material system of Three.js (MeshStandardMaterial) but that when switching to the node system with a similar PBR workflow (e.g StandardNodeMaterial), using TextureNode the result is completely different when it shall be similar.

I added a jsfiddle to explain a bit better the issue.
Both parts shall look identical however the part using the texture with StandardNodeMaterial (object1) is not as expected.

@sunag I find a fix for this issue

In TextureNode.js, I replaced
this.colorSpace.fromEncoding( builder.getTextureEncodingFromMap( this.value ) );
by
this.colorSpace.fromDecoding( builder.getTextureEncodingFromMap( this.value ) );
on line 68

Tell me if I am wrong, but the result makes sense to me now:

Now when the encoding property of a texture is set to sRGBEncoding, TextureNode.generate triggers the function sRGBToLinear() instead of LinearTosRGB(). The result is that a sRGB PNG texture with a colour value X is displayed the exact same way as a solid color X converted using convertSRGBToLinear().

If the texture encoding value is left to default (LinearEncoding), the result is that a sRGB PNG texture with a colour value X is displayed the exact same way as a solid color X.

Yes! You are correct, it is a bug.
I still have to create examples to test all of these nodes properly...

Do you want to do a PR to fix this bug? or wait I fix this in a next revision?

NOTE: I just see your issue right now, for topics related to NodeMaterial you can ping my nick @sunag to that I can see faster.

Thanks!

Thanks. I created a PR for this bug.

I did some pretty advanced stuff with your node system and I must say that I am really impressed. Except these few little things with the normals and color space, everything else is working perfectly so far.

Was this page helpful?
0 / 5 - 0 ratings