2013-02-26 11 views
19

ho bisogno di passare da spazio colore RGB per HSV .. ho cercato in internet e ho trovato due implementazioni diverse, ma quelli che mi danno risultati diversi:da RGB a HSV in 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); 
} 

sai che è la corretta attuazione?

risposta

65

Sono l'autore della seconda implementazione. Si è sempre comportato correttamente per me, ma hai scritto 2.9/6.9 invece di 2.0/6.0.

Dal momento che il target GLSL, si consiglia di utilizzare routine di conversione che sono scritte con la GPU in mente:

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

Tratto da http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl.

+0

ho provato questo sul sito web shadertoy e ha detto che nessuna funzione di sovraccarico corrispondente trovata, non può convertire da mediump a Vector3 –

+0

Bello! Ti capita di avere già lo stesso tipo di funzioni per lo spazio colore HSL? – wil

+1

[Ho appena implementato 'hsv2rgb()' con l'hardware blending] (http://stackoverflow.com/a/28897272/1888983). Completamente stupido ma sono ancora leggermente orgoglioso di me stesso. – jozxyqk

2

Non ho un ambiente di sviluppo da controllare, ma è possibile utilizzare wolframAlpha per creare alcuni asserzioni.

For Instance: rgb (1,0,0) (rosso puro) a hsv è 0, 100%, 100% in hsv.