Every color is mapped to exactly the same color. This is the LUT image that doesn't change any color. To get an understanding of how that is done, let's first look at the identity LUT image. Since the index is three-dimensional and the texture image only two-dimensional there needs to be a way to go from three dimensions to two. to get the integer representations using the float datatype. What the index really represents is a combination of three integer values but you store them as floats the entire time and use the built-in functions floor, clamp. The index is a vec3 where each of the components ranges between 0 and COLOR_NUM-1.0. This index is quite a special one: it is a three-dimensional index, with R, G and B making up a dimension each. It takes in an index and optionally an offset to be added to the index. Let's have a closer look at what happens behind the scenes to retrieve the corresponding color for a given input color! The LUT shader is an application of this general idea, though it is a bit more complex than the usual array lookup. new_color now holds the value of c_green / A lookup using structs - this one "rotates" the primary colors (R>G>B>R>G>B>.)Ĭolors = // The lookup "table" Suppose you'd want to code this in GML, then it would look something like this: The general idea behind a lookup table is that you use a value as an index into a table of values and then return the value that corresponds to that index. Lookup tables are used to do color grading, which is a way to adjust the colors of an image as a post-processing effect. YIQ.yz *= mat2(cos(ang), -sin(ang), sin(ang), cos(ang)) * sat Rotate I and Q chrominance values and scale for saturation The hue shift function first converts the input color in RGB to YIQ, then applies the rotation and scale and finally converts the result back to RGB (conversions between RGB/HSV are written as a matrix multiplication): So rotating the vector that represents the color in YIQ space corresponds to a hue shift, scaling it corresponds to a change in saturation.Ī visual representation of a hue shift and saturation scale in YIQ space (Y = 0.5) The Y component contains the black and white information, or the luma, and I and Q contain the color information, or the chrominance.Īn interesting thing about the phase and amplitude of the chrominance contained in the I and Q components is that they correspond approximately to the hue and saturation of a color. Hue shift and saturation in YIQ color spaceĪnother way to change the hue and saturation is by converting a color represented as RGB to YIQ and then applying a transform on that vector in YIQ space. Multiply by value and mix for saturation Finally that result is multiplied by the value. The RGB hue is calculated and then this value is mixed with white to apply the saturation. The code to convert from HSV to RGB is more straightforward. Find the difference between the highest and lowest RGB for saturation Sort red-green-blue channels (highest to lowest) Sort green-blue channels (highest to lowest) Near-zero epsilon (to avoid division by 0.0) The final code to convert from RGB to HSV is written quite compactly and looks like this: vec3 hsv(vec3 c) This is why the function sorts the RGB channels first. It can be shown that the hue of any color is equal to the maximum minus the minimum of the RGB channels. Starting at red and rotating clockwise you once again see the colors red, orange, yellow, green, blue, indigo, violet. The RGB cube seen from a different perspective As a result passing a value of 1 for brightness will give no change. (Notice that the vec3(0.5) means a color of 50% gray, in GameMaker this corresponds to the built-in c_gray color constant.)Ī value of 1 is subtracted from u_brightness. The color with the brightness value added to all the components is mixed with a grayscale value using the contrast which is finally multiplied by the vertex color. The main code to adjust brightness and contrast is fairly basic:Ĭolor.rgb = mix(vec3(0.5), color.rgb + u_brightness - 1.0, u_contrast) Contrast refers to the difference in brightness between the brightest and darkest elements. Brightness refers to the overall "lightness" of an image. You can also make some changes and play around a bit!īrightness and contrast are two basic properties of an image. If you are looking for an example project to follow along with this tutorial then feel free to use the GM Shaders Base project and have a look at the code. Today we'll go over brightness, contrast, hue shifting, converting between the RGB and HSV color spaces and LUT color grading.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |