2013-02-26 49 views
19

tôi cần phải vượt qua từ không gian màu RGB để HSV .. Tôi đã tìm kiếm trên internet và tìm thấy hai hiện thực khác nhau, nhưng những người cho tôi kết quả khác nhau:Từ RGB để HSV trong OpenGL GLSL

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); 
} 

Bạn có biết triển khai chính xác không?

Trả lời

65

Tôi là tác giả của triển khai thứ hai. Nó luôn luôn cư xử đúng cho tôi, nhưng bạn đã viết 2.9/6.9 thay vì 2.0/6.0.

Kể từ khi bạn nhắm mục tiêu GLSL, bạn nên sử dụng chuyển đổi thói quen đó được viết với GPU trong tâm trí:

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); 
} 

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 từ http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl.

+0

tôi đã thử điều này trên trang web shadertoy và nó cho biết không tìm thấy chức năng quá tải phù hợp, không thể chuyển đổi từ mediump sang Vector3 –

+0

Nice! Bạn có đã có cùng một loại chức năng cho không gian màu HSL? – wil

+1

[Tôi vừa triển khai 'hsv2rgb()' với phần cứng trộn] (http://stackoverflow.com/a/28897272/1888983). Hoàn toàn ngu ngốc nhưng tôi vẫn tự hào về bản thân mình. – jozxyqk

2

Tôi không có môi trường phát triển để kiểm tra, nhưng bạn có thể sử dụng wolframAlpha để xây dựng một số xác nhận.

For Instance: rgb (1,0,0) (màu đỏ tinh khiết) để hsv là 0, 100%, 100% trong hsv.

Các vấn đề liên quan