What I would like to do is to keep the saturation-values as they are, modify the brightness-values, and shift all hue-values to one color (or maybe if it's possible even several?).
I have a Vampire-character ( no, not a sparkling one :p ) and he should be able to see in the dark, get blinded by bright lights and see only in shades of gray and red.
If I wanted only red (without true gray and white) it would be easy.
(Grayscale obviously allows for no other color.
So is it possible to access the HSB-Colorspace or do some work-around?
(I'd like to avoid just doing this with textures as I also have another character that should be able to see all colors except for red, thus I would need to exchange all my textures in the whole scene each time one switches between them...)
Thanks a lot & Greetz, Ky.
asked Jan 21 '10 at 08:29 PM
Not sure if this question is still active, but running through the unanswered questions, it seemed fairly simple.
The title of the question doesn't match the first line of the description:
How is that "Color-correct my scene to have Grayscale + one Color? Access HSB-Colorspace?"
If you want to keep the saturation values as they are, then you don't really have grayscale + one color as you don't have grayscale at all.
Shifting hues is fairly easy - see below about HSV conversion and then you just clamp/scale the values to a certain range and convert back or in the better solution, you would simply do a texture look-up and the texture would have the shifted colours/brightness at the coordinates for the input luminance or value, and hue. For several, you would set different ranges for the clamp/scaling or more simply just change them in the texture of the look-up texture method.
If you want to make only certain things blinding, I'd recommend a script that checks against the shader in use and applies this change. If you mean to make lights and lit areas very bright to indicate that they'll burn you to dust or some such, I'd recommend using a glow effect or simply applying a ramp to the brightness as described below. For blinding by bright lights, you could just do it with a script controlled glow effect. This should really be a separate question though.
Depending on your use case, the script linked by Jaap is relevant, but if you're looking for something like a screen space script akin to the GrayscaleEffect, why not just take that and change it?
The brute force HSV approach
Note that all code here is untested.
In the GrayscaleEffect shader, adding what you want, the fragment shader would then look something like:
To convert from RGB to HSV, NVidia even has a CGshader which does this in its colorspace include, but the conversion is well documented regardless, so you should have no trouble writing one if you ever need.
With some playing with the math, we can get the code NVidia used. I'm not sure where it ends up being fewer instructions along the mathematical conversions, so play with it a bit if you like.
A more elegant approach
OK. Above we calculated redness, but that's not very scalable to the general case. If we simply calculate Hue and luminance with a different ramp texture, we can do this much more simply like so:
What's different between this and the grayscale? First, we still are calculating hue but that is shorter than
Secondly, the texture mapping coordinate was changed to use hue as a y coordinate. This means that with a ramp texture that has colors mapped with hues at y coordinates, it will simply lookup the color. A 256 x 240 texture as you'd see in a color picker, only on its side, should give you the original image and if you simply desaturated or replaced the colors that you want grayscale, you could achieve your effect for red in this case, but for other colors if you so desired. This can be easily achieved in Photoshop or Gimp or what have you with some clever effect layer masking.
This should show all reds as they are and everything else as true grayscale, with a transitional zone around the extent of the red hues if you do that. Is this what you really want?
From a gameplay/conceptual perspective, I can see why a vampire would see only reds for like blood and for stuff that you want to emphasize (Like The Sixth Sense or like Sin City). With this broad-stroke method of highlighting though, in order to be well-designed, would need you to be very selective about what you make red because everything in red will stand out a lot, even some red in an awning or a painting or on someone's shoes.
From a design standpoint, you'd be better off setting up either a mechanism of swapping in grayscale textures or changing the shaders for given objects to switch to grayscale or adding some scripting to the grayscale script in stead of its shader to check the shader in use on the object and then only grayscale stuff that isn't using given shader(s).
Take a look at this Unite Presentation where they talk about their transition from "bleak and gray" to "colorful" and their selective glow effect that was only applied to the character. Something like this should apply to selectively making stuff red in a grayscale environment or for making some stuff selectively stand out.
Unless you're switching between views of the world on the fly (like a werewolf (which you could fake) or some kind of hyper mode or different kinds of special goggles), texture/shader changes aren't too costly. If you are doing something like that, I can see why you'd want a camera effect and if you must go this route for whatever reason, I'd strongly recommend a script that checks for certain shaders or the like rather than simply making all reds stand out regardless of what they are.
Although it doesn't do exactly what you want it looks like it could be a good starting point for a shader.
answered Jan 21 '10 at 10:45 PM
Not sure if that's what you want, but you could convert your rgb-pixels to grayscale by calculating the luminance and then setting r, g and b to that value. (r = g = b = gray ;))
To get some red in your scene you could increase the r value after you converted to gray.
If you want to do it in HSB-Colorspace you could just convert rgb to hsb, apply your transformation and convert it back to rgb. If you need help with that let me know.
answered Jan 22 '10 at 10:29 AM