Material Color vs Map

Hello,
I want to use material color instead of texture, but I’m getting diffrent results even if texture has same color as I set on material.

Is there proper way to set material color so the results is the same as if I used texture with that color?

Material with texture (and white default color)
image

Material with color only (same color as texture)
image

Look at the color picker - matches texture, but dont match if u use color only.
if (matConfig.useMap) {
material.map = textures[matConfig.texture];
material.color = null;
} else {
material.map = null;
material.color = new THREE.Color(matConfig.color);
}

The base color (.color), base color texture (.map), and vertex colors are all multiplied against one another for the final output. This has its uses — you can get different variations of colors on plants by multiplying different colors against the same texture, for example, to improve performance. However, it also means that setting the same color to both .color and .map will not give you that color back. You need to make one of the two white, or remove the base color map.

I am actually using JUST color or JUST map, not both at the same time.
If you look at images, top has just map and bottom has just color. In reality, these two options have same color, but they are rendered diffrentely.

I just want to understand why if I put that color #311b0f as .color, it looks brighter on render. But when i make texture of that color, its ok.

I managed to bypass this by generating 1x1 canvas of specific color and passing it as texture. But it is two hacky and I am propably doings something wrong. It just looks that .map and .color arent simply multiplied.

Oops I see, sorry I misunderstood what you were doing.

Here are some settings you should know about, to get color matching right in three.js and across modeling+texturing programs:

  1. renderer.gammaOutput = true; renderer.gammaFactor = 2.2; This ensures the renderer is gamma-correcting its output.
  2. texture.encoding = THREE.sRGBEncoding. If you create a base color texture in a program like photoshop, it’s probably in sRGB color space. Unless you are sure you’ve chosen linear color space instead, mark the texture as sRGB this way. If you do this after the texture has been rendered, also set texture.needsUpdate = true; and/or material.needsUpdate = true;.
  3. color.convertGammaToLinear( 2.2 ) When you create a new color in three.js with a hex value of 0x311b0f, three.js will assume it is linear. If it’s the same color you used to create an sRGB texture, it’s probably not. So, use this line to convert it to linear.

There are two ways you can use all of those settings to get your texture and your color to match. Skip (1), skip (2), and just do (3). Or, do (1), (2), and (3). Either choice will get your colors to match, but doing all of the above should give you better workflows from modeling tools, and correct lighting if you eventually start doing PBR rendering.

7 Likes

Thank you for very descriptive answer. I played with those params a little bit, it definitely helped. I understand that using renderer.gammaInput and .gammaOutput is must have for PBR.
What i dont understand is why gamma factor 2.2 and also in your color conversion.

Anyway, I could not mach both colors perfectly.
My map is saved with Photoshop as sRGB. Only way so far i found is that canvas 1px method matches sRGB image loaded WITHOUTtexture.encoding = THREE.sRGBEncoding;

In all other cases, using .color sems just slightly brighter/lighter (almost not visible)

If you specify nothing, the default is 2.0, for legacy reasons. But a gamma factor of 2.2 is (most often) what you want for sRGB transfer functions. See sRGB - Wikipedia.

How close are you able to get the colors, with chose changes? There is some approximation involved, I think, but unfortunately I don’t know of any other settings to suggest sorry.

For your dynamic texture created with <canvas/>, I’m not sure whether you want to change encoding or not… do whatever looks right I guess, heh.

Thank you, I think its ok enough :slight_smile: