MeshBasicMaterial: wrong color rendered

Hi, I’m trying to compose the most simple example for MeshBasicMaterial, but it fails to accurately render a color passed to the material constructor. The code looks like this:

<html>
	<head><script src="three158.js"></script></head>
	<body>
		<canvas id="main" style="color: transparent; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;"></canvas>
	</body>
	<script>
		window.onload = function() {
			THREE.ColorManagement.enabled = false;
			var cnv = document.getElementById('main'),
			renderer = new THREE.WebGLRenderer({ canvas: cnv });
			renderer.setClearColor(0x000000, 1);
			//renderer.outputColorSpace = THREE.NoColorSpace;
			renderer.render(new THREE.Mesh(new THREE.CircleGeometry(1, 4), new THREE.MeshBasicMaterial({ color: 0x0000c0 })), new THREE.OrthographicCamera(-1, 1, 1, -1, -1, 1));
		};
	</script>
</html>

I was expecting that this default setup would product a rhombus the color of which is exactly 0x0000c0, but in practice it is 0x0014e1 with ColorManagement.enabled = false, and 0x0010c0 otherwise.

Can somebody suggest how to get that damn color rendered correctly?

As a side note, setting renderer.outputColorSpace = THREE.NoColorSpace; before the rendering call it produced the following error since COLOR_SPACES doesn’t have a key for the NoColorSpace

Uncaught TypeError: Cannot read properties of undefined (reading ‘primaries’)
at Object.getPrimaries (three158.js:1699:38)
at getEncodingComponents (three158.js:19163:45)
at getTexelEncodingFunction (three158.js:19225:22)
at new WebGLProgram (three158.js:19946:5)
at Object.acquireProgram (three158.js:20903:15)
at getProgram (three158.js:29806:29)
at setProgram (three158.js:30042:16)
at WebGLRenderer.renderBufferDirect (three158.js:28949:21)
at renderObject (three158.js:29743:12)
at renderObjects (three158.js:29712:7)

The renderer cannot output without a color space. renderer.outputColorSpace=LinearSRGBColorspace is allowed, and is sometimes paired with ColorManagement.enabled = false.

But you shouldn’t need any of these settings. The defaults should work correctly. In your example you don’t use tone mapping, but if you were be sure to use material.toneMapped = false here.

How are you measuring the output color of the canvas? If you are using something like macOS “Digital Color Meter”, be sure to select “Display in sRGB”. And, what browser are you testing in?

1 Like

Example:

Screenshot 2024-02-16 at 11.53.32 AM

For color picking I use the standard built-in Chrome Dev Tool picker. But there’s no need in it actually, if I set the clearColor to the same 0x0000c0 — I can see that the rhombus is lighter. When I set renderer.outputColorSpace=LinearSRGBColorspace it still ends up failing to lookup the empty string in the COLOR_SPACES

Thanks! That fiddle works properly on my side. Will try to inspect what could lead to such a difference.

@donmccurdy It appears that not only setting ColorManagement.enabled to false was responsible for the color mismatch, but also the Display Profile of my display. Without changing it I was getting 0x0010c0 instead of 0x0000c0 with the color meter, as I wrote earlier. But after setting the profile to sRGB IEC61966-2.1 it produced the expected value. Thanks for your help!

3 Likes