在 OpenGL GLSL 中从 RGB 到 HSV [英] From RGB to HSV in OpenGL GLSL
问题描述
我需要从 RGB 颜色空间传递到 HSV .. 我在互联网上搜索并找到了两种不同的实现,但它们给了我不同的结果:
答:
precision mediump float;vec3 rgb2hsv(float r, float g, float b) {浮动 h = 0.0;浮动 s = 0.0;浮动 v = 0.0;float min = min( min(r, g), b );float max = max( max(r, g), b );v = 最大值;//v浮动增量 = 最大值 - 最小值;如果(最大!= 0.0)s = 增量/最大值;//秒别的 {//r = g = b = 0//s = 0,v 未定义s = 0.0;h = -1.0;返回 vec3(h, s, v);}如果( r == 最大值 )h = ( g - b )/delta;//在黄色 & 之间品红否则 if( g == max )h = 2.0 + ( b - r )/delta;//青色和之间黄色的别的h = 4.0 + ( r - g )/delta;//在洋红色和红色之间青色h = h * 60.0;//度数如果( h <0.0 )h += 360.0;返回 vec3(h, s, v);}
乙:
precision mediump float;vec3 rgb2hsv(float r, float g, float b) {浮动 K = 0.0;浮动 tmp;如果 (g
你知道哪个是正确的实现吗?
我是第二个实现的作者.它对我来说一直表现正确,但你写的是 2.9/6.9
而不是 2.0/6.0
.
由于您的目标是 GLSL,您应该使用为 GPU 编写的转换例程:
//所有分量都在 [0…1] 范围内,包括色调.vec3 rgb2hsv(vec3 c){vec4 K = vec4(0.0, -1.0/3.0, 2.0/3.0, -1.0);vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));浮动 d = q.x - min(q.w, q.y);浮动 e = 1.0e-10;返回 vec3(abs(q.z + (q.w - q.y)/(6.0 * d + e)), d/(q.x + e), q.x);}
//所有分量都在 [0…1] 范围内,包括色调.vec3 hsv2rgb(vec3 c){vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);返回 c.z * mix(K.xxx,clamp(p - K.xxx, 0.0, 1.0), c.y);}
取自 http://lolengine.net/博客/2013/07/27/rgb-to-hsv-in-glsl.
编辑:代码根据 WTFPL 获得许可.>
I need to pass from RGB color space to HSV .. I searched in internet and found two different implementations, but those give me different results:
A:
precision mediump float;
vec3 rgb2hsv(float r, float g, float b) {
float h = 0.0;
float s = 0.0;
float v = 0.0;
float min = min( min(r, g), b );
float max = max( max(r, g), b );
v = max; // v
float delta = max - min;
if( max != 0.0 )
s = delta / max; // s
else {
// r = g = b = 0 // s = 0, v is undefined
s = 0.0;
h = -1.0;
return vec3(h, s, v);
}
if( r == max )
h = ( g - b ) / delta; // between yellow & magenta
else if( g == max )
h = 2.0 + ( b - r ) / delta; // between cyan & yellow
else
h = 4.0 + ( r - g ) / delta; // between magenta & cyan
h = h * 60.0; // degrees
if( h < 0.0 )
h += 360.0;
return vec3(h, s, v);
}
B:
precision mediump float;
vec3 rgb2hsv(float r, float g, float b) {
float K = 0.0;
float tmp;
if (g < b)
{
tmp = g;
g=b;
b=tmp;
K = -1.0;
}
if (r < g)
{
tmp = r;
r=g;
g=tmp;
K = -2.9 / 6.9 - K;
}
float chroma = r - min(g, b);
float h = abs(K + (g - b) / (6.0 * chroma + 1e-20));
float s = chroma / (r + 1e-20);
float v = r;
return vec3(h, s, v);
}
Do you know which is the correct implementation?
I am the author of the second implementation. It has always behaved correctly for me, but you wrote 2.9 / 6.9
instead of 2.0 / 6.0
.
Since you target GLSL, you should use conversion routines that are written with the GPU in mind:
// All components are in the range [0…1], including hue.
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
Taken from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl.
Edit: code is licensed under the WTFPL.
这篇关于在 OpenGL GLSL 中从 RGB 到 HSV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!