Saturday, April 9, 2016

Hashtag Chromancy

Okay, yes, I hear what you're saying: "That's not a real word, Justin. You can't just make up words and put them in hashtags like that." Don't worry, I hear you; but have you perhaps considered the possibility that "shut up"? Dr. Seuss made up words all the time, and he was a totally-certified actual doctor. No one ever gave him any flak for making things up.

"What is that word even supposed to mean, though?" some of you continue to say. Well, I'll tell you! The prefix "chrom-" denotes that the word has something to do with color, and the suffix "-mancy" implies the seeking of knowledge by means of the accompanying prefix (usually with some sort of mystical connotation). As such, "chromancy" is how I refer to my recent studies of color theory and various different mathematical formulae relating to color.

"Doesn't that word imply that you're magical, though? You're not magical," you chastise. I mean, no, not in the strictest definition; but technology is basically indistinguishable from magic, so, in a way, all computer scientists are basically wizards.

Just... just let me have this one.

Anyway, enough with the nomenclature discussion--let's talk colors. I've learned a lot about color over the past semester or so, and there's a lot more to it than you'd expect. For one thing, there are a variety ways to define a given color--of which, I've focused on three in particular:

RGB (Red-Green-Blue): This is the way computers actually display color (as a composite of red, green, and blue light). You've probably heard of this one, even if you aren't incredibly tech-savvy. All colors need to be converted to RGB in order to be used by a computer; but it isn't always the best format to work with from an artistic standpoint, because transitioning from one color to another behaves differently from what we expect (computers are just weird like that).

HSV (Hue-Saturation-Value): If you've ever worked with any sort of computer art program, you've probably seen an HSV color picker--it's the one that has the rainbow slider (for selecting a hue), next to which is a box of every tint and shade of the hue that's currently selected. Sometimes the rainbow slider is actually a circle around the box instead, because hue is measured in degrees from 0 to 360. HSV is much better than RGB for interpolating between colors, because it behaves in a way that's more like what we expect. For example: if we wanted to slowly change an object's color from red to green, we'd expect it to pass through orange and yellow on the way, not through brown (the latter of which is what RGB does and it looks gross).

Luma-Chroma (or Luminance and Chrominance): This is one that I hadn't learned about until recently, and is apparently the way that television displays used to be encoded (and perhaps still are? I don't know). It basically separates the color of the image (chroma) from the lightness of the image (luma). If you tried to visualize just the luma component by itself, you'd have a grayscale representation of the image in question. In this scenario, the chroma component would basically be like a colorful, translucent overlay that you can put over the top of the grayscale image to get the image you started with.

CMYK is also a thing, but I'm ignoring it because it's generally only used for things that you plan to print (and it's a pain in the ass to reliably convert to from any of the other formats).

Most of what I've been doing with color lately has involved switching between these three different formats and then doing fancy math stuff to get the result I want. Generally, I tend to start and end with RGB, because that's what the computer recognizes as a color, and I almost always calculate the hue from the RGB color--as HSV and Luma-Chroma both use it (chroma is actually just hue and saturation combined).

Here are some examples of what I've done with color (with a brief explanation of how I did each):

Single-Hue Shader:

This one is actually super easy to implement. I have a box for inputting the desired hue (in this case, a kind of greenish cyan) which the shader takes in as a value between 0 and 360. All the shader does afterwards is calculate the saturation and value from each color in the image, and then use those values in conjunction with the hue from the input field to convert back to RGB. This shader also has scan lines and makes the image flicker a bit, which I added to make it look like a hologram projector.





CRT Shader:

Oh look, the scan lines again! I actually made this shader after I made the first one, so I used the same formula for adding scan lines. This time, however, I didn't use HSV. Instead, I only used the red, green, or blue value of each pixel depending on where it was located in the image. In this way, I attempted to emulate what a CRT screen would look like--because each cell in a CRT screen only emits either red, green, or blue light. I was actually kind of shocked that the colors were still recognizable. Our eyes sure are weird.




Pixelation Shader:

Of all the shaders I've made so far, this is the one I'm the proudest of. I was inspired by Lazerhorse's style after watching a certain music video, and I felt compelled to make a pixel-art shader. There's still a long way to go with this before I can get it to the level I want it to be at, but I think it's a good start.

The two biggest pieces of this shader are the "hue-clamping" and "checkerboarding" functions. Currently, the shader converts all of the colors to HSV, and then rounds the hues to the nearest multiple of 30 (which means there are only 12 possible hues in the final image). After the hue has been clamped, the saturation and value are each clamped to the closest multiple of 0.5, with a slight bias based on the position of each pixel--this is what makes the "checkerboarding" effect happen (which is the thing from the music video I most wanted to emulate). The result is an image that contains a maximum of 51 colors--4 for each hue and 3 grayscale (white, black, and 50% grey)--though it would probably end up being less in practice, depending on the colors present in the original image. World of Plankton (the research project I've been working on for almost a year here at RPI) has primarily greens with a few yellows, so the picture below is highly monochromatic.


Disclaimer: World of Plankton will not actually be using this shader in the final version, I just wanted to see what it would do with a more complex image than the three primitive shapes I have above.

Anyway, I think I'll probably start to wrap this post up. I'll definitely do another post about color in the near future, because there's a lot I still want to touch on, and I'll hopefully be working more on this shader as part of a final project (I need an academic excuse to do it or I won't be able to justify setting aside the time), so I should have updates at some point. I also want to expand upon the color palette tool I made for Unity3D and make it more flexible, because I think it could be really useful if it had a bit more functionality--and perhaps I'll even make it interface with a future version of the pixelation shader so we can do some really  A E S T H E T I C  stuff. We'll see what happens, I suppose.

That's it for now, guys; thanks again for reading, and I'll have another post up soon!
--JBird

No comments:

Post a Comment

Want to tell me something? I would say I'm all ears, but that'd be a gross exaggeration of my physical appearance.