Changing Hue or Saturation not working in a SpriteMaterial using setHSL

Not sure if is possible to change the saturation or the hue to a SpriteMaterial. But using setHSL does nothing. The only parameter that seems affect the sprite is the Lightness.

Is this the right way to use it?

const material = new THREE.SpriteMaterial({map: texture})
material.color.setHSL(0.5, 0.5, 1)

Here an example:
https://jsfiddle.net/0kLw18y9/1/

Hi!
When you’ve got a blue texture, what result do you expect to get, if the result color comes from channel-wise multiplication?
For example, if you have color from the texture [0, 0, 1] (pure blue), then, when you try to set .color of material, say [1, 1, 0.5], then the resulting color will be
[0, 0, 1] * [1, 1, 0.5] => [0 * 1, 0 * 1, 1 * 0.5] => [0, 0, 0.5]
So, in any case you’ll get blue of different shades.
An option is to use black and white texture (or grayscale, if you want).

Fiddle works fine for me. I think the confusion is over how the HSL values interact with the texture. Basically they’re converted to RGB then the R, G, and B values are multiplied by the R, G, B of the texture pixels.

So consider a full red of setHSL(0, 1, 0.5). That’s the same as setRGB(1, 0, 0) – filter out everything but red. With your cyan texture, you’ll see that leaves a very dim red color. If you do setHSL(1/3, 1, 0.5) that’s like setRGB(0, 1, 0) and keeps just the green — much brighter result when multiplied by your texture.

Possibly the problem is that HSL, while very useful, isn’t as intuitive to use as HSV. I like checking with http://hslpicker.com

Just in case, how .setHSL() works under the hood: https://github.com/mrdoob/three.js/blob/7c1424c5819ab622a346dd630ee4e6431388021e/src/math/Color.js#L129L153 . The result is RGB.
And then what happens in material: https://github.com/mrdoob/three.js/blob/7c1424c5819ab622a346dd630ee4e6431388021e/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js

I just want to convert that sprite in a grayscale. Is that possible using just setHSL?

Is it an option to make it grayscale before you loading it?

Not sure what you mean. Loading two sprites?

Just convert it to grayscale, then load it.

Can you refer an example to do that task? I mean, I’d like to apply that filter on run time. Because I need the blue version and the grayscale version. And I don’t want to load the same image twice.

  • You can load that image, make a copy of it, turn the copy into grayscale on js side.
  • You can modify material’s shader to show that texture in grayscale.
    Creativity is up to you :slight_smile:

Do you know any site that have a bunch of examples using shaders like we have with three.js (https://threejs.org/examples/)?

Could you also provide more context on how to achieve this? “make a copy of it, turn the copy into grayscale on js side.”

I know one site with a bunch of shaders: https://www.shadertoy.com/results?query=grayscale

Type in “js image grayscale” in google and the first link will be: https://stackoverflow.com/q/37174616/4045502

1 Like