tag:blogger.com,1999:blog-5181746871086541575.post6739452554406947333..comments2024-03-22T09:36:46.384+00:00Comments on chilliant: RGB/HSV in HLSLIan Taylorhttp://www.blogger.com/profile/06869762490434824010noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-5181746871086541575.post-19127164126606007552014-04-23T09:20:12.549+00:002014-04-23T09:20:12.549+00:00Yes. That's a rather sweet optimization for RG...Yes. That's a rather sweet optimization for RGB-to-HSV. It doesn't seem to have an impact on modern scalar GPUs, but definitely faster for the SIMD generation. I'll write up an updated entry when I can. Sam's HSV-to-RGB is a little slower, so maybe we can trade ;-)Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-10020525069411711332014-04-09T08:06:04.744+00:002014-04-09T08:06:04.744+00:00Another fast (possibly faster - I have yet to benc...Another fast (possibly faster - I have yet to benchmark it) RGB to HSV algorithm is : http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glslCeeJay.dkhttps://www.blogger.com/profile/08747704052718341898noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-7727993332343424312012-07-25T10:37:09.272+00:002012-07-25T10:37:09.272+00:00P.S. I'm assuming you really want code for &qu...P.S. I'm assuming you really want code for "HCY"; "HSY" seems to be a bit of a Franken-colour space.Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-47771593711707061002012-07-25T10:13:25.921+00:002012-07-25T10:13:25.921+00:00HCY seems to be a rarely-used colour space, which ...HCY seems to be a rarely-used colour space, which gives me pause for thought. But I did find references to it in this Google Code project:<br /><br />https://code.google.com/p/colour-space-viewer/<br /><br />I'll try to unpick the code.Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-84225587162252099582012-07-16T08:46:23.701+00:002012-07-16T08:46:23.701+00:00Hi Hamster Beat, I've had a quick look at your...Hi Hamster Beat, I've had a quick look at your comments. As you say, I don't think it's a precision problem; most modern pipelines use floating point internals, so scaling uniformly by constants rarely affects precision.<br /><br />If, as you say (and Wikipedia suggests) the HSY model expects the Y component to be luma (weighted brightness according to some physical absorption model, e.g. the human eye) then RGB->HSY would simply require the R G and B multiplicative weights to be added to the formula. HSY->RGB should follow on from that, although you'd have to be sareful to make it reversible. I'll have a look at it during the week and see what I can come up with.Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-85223801549373286662012-07-11T23:04:38.916+00:002012-07-11T23:04:38.916+00:00Oh, i just got that my problem is not the precisio...Oh, i just got that my problem is not the precision i telling before. <br /><br />Color blend mode that i want to implement is similar to photoshop's color blend that is not HSL in terms of lighting. L stands for luma also known as Y and i need to convert RGB -> HSY and vise versa. <br /><br />But currently can't find fast alhorithm to do HSY -> RGB conversion.Hamster Beathttps://www.blogger.com/profile/12296377926089944741noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-66106697790829477202012-07-10T20:18:36.876+00:002012-07-10T20:18:36.876+00:00Hi, i've been looking for fast hsl/hsv/rgb tra...Hi, i've been looking for fast hsl/hsv/rgb transforms and found your blog, thanks for sharing. <br /><br />I am trying to implement photoshop color blending that replaces both hue and saturation of the image' pixel but preserves lightness. I am doing it under android os using gl es 2.0 and fragment shaders. <br /><br />I creates texture (render) buffer to store HSL data of the original texture. Then i passes it to pixel shader, applies hsl modifications and transforms back to rgb values. <br /><br />I am using your code to convert rgb->hsl and vise versa and it works perfect. Everything works correct but it seems like there is not enough presicion for lighting/saturation to store in regular unsigned byte rgba texture. <br /><br />In order to preserve precision i am using the following conversion: <br /><br />float hue = hsl.x * 1024.0;<br />float b1 = floor(hue / 32.0);<br />float b2 = hue - b1 * 32.0;<br /> <br />gl_FragColor = vec4(b1 / 32.0, b2 / 32.0, hsl.y, hsl.z);<br /><br />Is means R and G components are used to store hue value (0 to 360 that is greater than max value of 255 of unsigned byte) with 2^-10 precision (most likely supported precision on android devices). <br /><br />Than i unpacks it back in another fragment shader <br /><br />vec4 src = texture2D(texHSV, uv);<br />vec3 hsv = vec3((32.0 * src.r + src.g) / 32.0, src.b, src.a); <br /><br />When i used this packing/unpacking to store HSV values everything works correct. But when switching to HSL i got sharp differences on S and L near 1.0. <br /><br />May be you can give me some advice or something?) I wasted hours to get it worked, but currently have no mode ideas...Hamster Beathttps://www.blogger.com/profile/12296377926089944741noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-60557055470545728262011-01-31T10:44:15.796+00:002011-01-31T10:44:15.796+00:00BTW: Yes, CMPEQPS/CMPEQSS are candidatesBTW: Yes, CMPEQPS/CMPEQSS are candidatesPetr Kobalíčekhttps://www.blogger.com/profile/15634384573845850706noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-85267500005519894062011-01-31T10:42:33.387+00:002011-01-31T10:42:33.387+00:00Hi Ian,
sorry about the step(y, x), I missed the ...Hi Ian,<br /><br />sorry about the step(y, x), I missed the reversed order of arguments, I read x, y in MSDN :) I have no experience with shaders so these functions are new to me.<br /><br />In SSE it's possible to use lower-level tricks with masks, I will send you my version when ready.Petr Kobalíčekhttps://www.blogger.com/profile/15634384573845850706noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-28775824090717238712011-01-30T22:46:19.729+00:002011-01-30T22:46:19.729+00:00In HLSL, "step(y,x)" is equivalent to &q...In HLSL, "step(y,x)" is equivalent to "(x>=y)?1:0". As you correctly point out, C is between zero and one inclusive, so the substituted expression "(-C>=0)?1:0" is simply "(C==0)?1:0". A bit ugly, but does the job.<br /><br />In SSE land, could you use "CMPEQPS" or the like?Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-21989450121494140082011-01-30T19:28:50.953+00:002011-01-30T19:28:50.953+00:00Hi Ian,
it's betting better and better :) I h...Hi Ian,<br /><br />it's betting better and better :) I have also some inventions, but I don't understand the<br /><br />float D = step(0, -C);<br /><br />in your formula. Isn't the result always 1? (C is between 0 and 1 and -0 to -1 is always <= 0, true?)<br /><br />But I'm getting some ideas how to avoid efficiently division by zero. I need also to avoid frac().Petr Kobalíčekhttps://www.blogger.com/profile/15634384573845850706noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-11899621665962757022011-01-30T13:04:20.792+00:002011-01-30T13:04:20.792+00:00Petr,
Your comments on SSE nudged a corner of my ...Petr,<br /><br />Your comments on SSE nudged a corner of my brain. I've had a look at this over the last couple of days and think there might be some room for improvement, but it requires what SIMD geeks apparently call "horizontal minimum for packed floats" (see http://software.intel.com/en-us/forums/showthread.php?t=79647).<br /><br />The whole "if" statement in the "RGBtoHSV" code above can be replaced with the following:<br /><br /> float D = step(0, -C);<br /> HSV.y = C / (HSV.z + D);<br /> float3 Delta = (HSV.z - RGB) / (C + D);<br /> Delta -= Delta.brg;<br /> Delta += float3(2,4,6);<br /> Delta *= step(HSV.zzz, RGB.gbr);<br />#if NO_ASM<br /> HSV.x = max(Delta.r, max(Delta.g, Delta.b));<br />#else<br /> float4 Delta4 = Delta.rgbr;<br /> asm { max4 HSV.x, Delta4 };<br />#endif<br /> HSV.x = frac(HSV.x / 6);<br /><br />I'll check whether this improves typical pixel shader performance (I have doubts, because of the way predication works) but it might be an fruitful avenue to pursue in SSE land.Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-69502521449073524992011-01-28T14:58:36.700+00:002011-01-28T14:58:36.700+00:00Hi Ian,
Thank you very much for your code. I rewr...Hi Ian,<br /><br />Thank you very much for your code. I rewrote your formula using the SSE intrinsics and it works perfectly. It will be available in <a rel="nofollow">Fog</a>.<br /><br />Now I'd like to hear that the second formula can be also optimized using min/max/abs, but it's not trivial:)<br /><br />Thank youPetr Kobalíčekhttps://www.blogger.com/profile/15634384573845850706noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-80282435200503477032011-01-15T17:20:25.611+00:002011-01-15T17:20:25.611+00:00Hmmm, DDRKirby(ISQ), that's very strange. I...Hmmm, DDRKirby(ISQ), that's very strange. I've checked the HSV-to-RGB and RGB-to-HSV results against three other implementations without significant disagreements. I've also checked the round-trip results to make sure that HSV-to-RGB-to-HSV and RGB-to-HSV-to-RGB are sensible. I don't see any anomalies there, either. What GPU are you running on?<br /><br />[Sorry for the delay in getting back to you, but I've been testing this as extensively as I can in my spare time over the holidays]Ian Taylorhttps://www.blogger.com/profile/06869762490434824010noreply@blogger.comtag:blogger.com,1999:blog-5181746871086541575.post-64498961729816797092010-12-23T13:39:02.880+00:002010-12-23T13:39:02.880+00:00Not sure if it's specific to my setup, but I h...Not sure if it's specific to my setup, but I had to modify the RGBtoHSV function for my use as I found that the floating-point comparison tests were producing weird behavior for me. I think it has to do with edge cases where RGB.r or RGB.g is supposed to be equal to HSV.z. For example, I have a yellow RGB color that turns blue if I convert to HSV and then back to RGB, but if I use the following:<br /><br /> if (RGB.r+0.1 >= HSV.z)<br /> HSV.x = Delta.b;<br /> else if (RGB.g+0.1 >= HSV.z)<br /> HSV.x = Delta.r;<br /> else<br /> HSV.x = Delta.g;<br /><br />it remains yellow.<br /><br /><br /><br />here's "a version which works". Don't mind the braindead sloppiness; i'm just trying to illustrate the problem.<br /><br />float3 RGBtoHSV(in float3 RGB)<br />{<br /> int whichmax = 0;<br /> if (RGB.g > RGB.r)<br /> {<br /> if (RGB.b > RGB.g)<br /> whichmax = 2;<br /> else<br /> whichmax = 1;<br /> }<br /> else if (RGB.b > RGB.r)<br /> whichmax = 2;<br /><br /> float3 HSV = 0;<br /> HSV.z = max(RGB.r, max(RGB.g, RGB.b));<br /> float M = min(RGB.r, min(RGB.g, RGB.b));<br /> float C = HSV.z - M;<br /> if (C != 0)<br /> {<br /> HSV.y = C / HSV.z;<br /> float3 Delta = (HSV.z - RGB) / C;<br /> Delta.rgb -= Delta.brg;<br /> Delta.rg += float2(2,4);<br /> if (whichmax == 0)<br /> HSV.x = Delta.b;<br /> else if (whichmax == 1)<br /> HSV.x = Delta.r;<br /> else<br /> HSV.x = Delta.g;<br /> HSV.x = frac(HSV.x / 6);<br /> }<br /><br /> return HSV;<br />}DDRKirby(ISQ)https://www.blogger.com/profile/08625140929120610178noreply@blogger.com