Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Hue Shift

Name: Anonymous 2019-07-19 9:30

Ok. The HSV formula for transferring RGB triplet into the HSV form is widely published. But I've failed to find any hints to how one arrives at it, so I could try to optimize it for my game's blitter routine. Therefore I tried to infer h,s,v formula myself, using basic vector math.

v = (r+g+b)/3 //value
hs = v-r,v-g,v-b //hue*saturation vector
s = hs.length //saturation
h = angle(hs/s) //hue is the angle of the vector


Guess when one needs to just change the saturation, there is no reason compute the angle or even vector length in full, but the common requirement to change the hue requires nasty computation. Can anyone hint at any efficient way of shifting hue?

Name: Anonymous 2019-08-03 8:26

>>80

r/2 + g/4 + b/2 is not a proper luma function. Proper luma is 0.299*r + 0.587*g + 0.114*b.

You can't even do a proper sprite recolor inside YCoCg. I.e. if you have a colorable font and make to draw it as blue, then in YCoCg your blue would be too dark and unreadable.

Name: Anonymous 2019-08-03 15:38

>>72
Not fully consistent however. Every single AES implementation that uses sboxes that I know of has been broken. Would you like some cia nigger to be able to see what is on your screen based on a timing attack?

Name: Anonymous 2019-08-04 0:15

>>82
*Using sbox values specially chosen by the people trying to break in

Name: Anonymous 2019-08-05 15:35

>>82
Not with real-time kernel patches, with fine grained multithreading its impossible once you run background task.

Name: Anonymous 2019-08-05 22:44

Instead of introducing the previously devised custom color space, I want to see how fast I can do hue-saturation change in plain RGB. It seems not exactly fast. But would it be fast enough for my game? Here is the saturation multiplier function.
void saturate(int *sr, int *sg, int *sb, int f) {
int r, g, b, l;
r = *sr;
g = *sg;
b = *sb;
r = r*r; g = g*g; b = b*b;
l = LUMA8(r,g,b);
l = l*(256-f);
r = (r*f + l)>>8;
g = (g*f + l)>>8;
b = (b*f + l)>>8;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
r = isqrt16(r); g = isqrt16(g); b = isqrt16(b);
*sr = clamp_byte255(r);
*sg = clamp_byte255(g);
*sb = clamp_byte255(b);
}



Yes. You see it right. A mere saturation boost/reduce requires 3 square roots and a lot of other operations. That is for each pixel. Ideally gamma function should be 2.2, but that would be even more expensive, square roots map better to a lookup table and there is that old Quake hack you can use to computer them lightning fast. In addition, gamma=2.2 would require doing r=pow22lut[r], instead of less expensive r*r, but 256 byes LUT isn't that expensive. Disabling gamma correction leads to heavy artifacts, like de-saturated sprite being too dark.

Still in my format changing saturation would be as simple as moving the U,V coords towards the whitepoint:
NV = (V-WV)*Saturation + WV
NU = (U-WU)*Saturation + WU

I.e. far more simpler code. So if one does full scene saturation change, then RGB is not an option. Hue shifting can be solved in part by recoloring, but even recoloring is expensive in general case, because of requiring to compute 256 byte LUT for every shade of recolored color.

Generally one reduces saturation to make special effects more eye popping. I.e. if on a bomb explosion you reduce surroundings saturation, that explosion would look more heavy.

TLDR: gamedev isn't easy.

Name: Anonymous 2019-08-06 3:26

>>85
Use the sqrt lookup tables instead of Isqrt
if (r < 0) r = 0; replaced by r*=(r>0) or something similar; which doesn't require a branch.
*sr = clamp_byte255(r); use ternary *sr= (r>255?255:r)

Name: Anonymous 2019-08-06 7:22

>>86
cmov is faster than imul. Although I should probably use uint32_t instead of int. then just one r>255 check would suffice.

Name: Anonymous 2019-08-06 8:28

also, 32-bit ints are not enough for gamma unpacked r,g,b, so one has to use floats or 64-bit ints.

Name: Anonymous 2019-08-06 9:39

Ok. For now I will use the following code:
static INLINE void saturate(int *sr, int *sg, int *sb, int f) {
int r = unglut[*sr];
int g = unglut[*sg];
int b = unglut[*sb];
int l = LUMA8(r,g,b)*(256-f);
*sr = glut[clamp(0,MAX_GAMMA,(r*f + l)>>8)];
*sg = glut[clamp(0,MAX_GAMMA,(g*f + l)>>8)];
*sb = glut[clamp(0,MAX_GAMMA,(b*f + l)>>8)];
}


Before transitioning to proper color space.

The problem is that I still have to support RGB color space for stuff like sprite sheet packing, because such transition from RGB to another color space is not one-to-one, and therefore lossy.

Name: Anonymous 2019-08-06 12:29

https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/

Nice article about gamma. Unfortunately I've stumbled upon it only after learning the lesson that sRGB is non-linear in the hard way. Still that guy explains a few quirks, like notice incorrect render and why font rasterizers use unusual 1.42 gamma.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List