2014-03-03 71 views
7

我想在openGL中繪製彩虹色的圖例。以下是我到目前爲止有:如何在Freeglut中繪製彩虹?

glBegin(GL_QUADS); 
for (int i = 0; i != legendElements; ++i) 
{ 
    GLfloat const cellColorIntensity = (GLfloat) i/(GLfloat) legendElements; 
    OpenGL::pSetHSV(cellColorIntensity*360.0f, 1.0f, 1.0f); 

    // draw the ith legend element 
    GLdouble const xLeft = xBeginRight - legendWidth; 
    GLdouble const xRight = xBeginRight; 
    GLdouble const yBottom = (GLdouble)i * legendHeight/
    (GLdouble)legendElements + legendHeight; 
    GLdouble const yTop = yBottom + legendHeight; 

    glVertex2d(xLeft, yTop); // top-left 
    glVertex2d(xRight, yTop); // top-right 
    glVertex2d(xRight, yBottom); // bottom-right 
    glVertex2d(xLeft, yBottom); // bottom-left 
} 

glEnd(); 

legendElements是離散的方格組成的「彩虹」的數量。 xLeft,xRight,yBottomyTop是組成每個平方的頂點。

在功能OpenGL::pSetHSV看起來是這樣的:

void pSetHSV(float h, float s, float v) 
{ 
    // H [0, 360] S and V [0.0, 1.0]. 
    int i = (int)floor(h/60.0f) % 6; 
    float f = h/60.0f - floor(h/60.0f); 
    float p = v * (float)(1 - s); 
    float q = v * (float)(1 - s * f); 
    float t = v * (float)(1 - (1 - f) * s); 
    switch (i) 
    { 
     case 0: glColor3f(v, t, p); 
      break; 
     case 1: glColor3f(q, v, p); 
      break; 
     case 2: glColor3f(p, v, t); 
      break; 
     case 3: glColor3f(p, q, v); 
      break; 
     case 4: glColor3f(t, p, v); 
      break; 
     case 5: glColor3f(v, p, q); 
    } 
} 

我從http://forum.openframeworks.cc/t/hsv-color-setting/770

但是,該功能時,我得出這樣它看起來像這樣:

enter image description here

什麼我想要的是紅色,綠色,藍色,靛藍,紫羅蘭色譜(所以我想直線迭代thr儘管色相。然而,這似乎並不是真正發生的事情。

我真的不明白是怎麼RGB/HSV轉換在pSetHSV()作品所以這是我很難找出問題..

編輯:這是固定的版本,由Jongware作爲靈感(矩形正在不正確地繪製)

// draw legend elements 
glBegin(GL_QUADS); 
for (int i = 0; i != legendElements; ++i) 
{ 
    GLfloat const cellColorIntensity = (GLfloat) i/(GLfloat) legendElements; 
    OpenGL::pSetHSV(cellColorIntensity * 360.0f, 1.0f, 1.0f); 

    // draw the ith legend element 
    GLdouble const xLeft = xBeginRight - legendWidth; 
    GLdouble const xRight = xBeginRight; 
    GLdouble const yBottom = (GLdouble)i * legendHeight/
    (GLdouble)legendElements + legendHeight + yBeginBottom; 
    GLdouble const yTop = yBottom + legendHeight/legendElements; 

    glVertex2d(xLeft, yTop); // top-left 
    glVertex2d(xRight, yTop); // top-right 
    glVertex2d(xRight, yBottom); // bottom-right 
    glVertex2d(xLeft, yBottom); // bottom-left 
} 

glEnd(); 
+0

什麼''legendElements''用於圖片?並在一個隨機的旁註:'GLdouble const yBottom =(1.0f + cellColorIntensity)* legendHeight;'' – cfrick

+0

@cfrick'legendElements'是組成「彩虹」的離散正方形的數量。 'xLeft','xRight','yBottom'和'yTop'是組成每個平方的頂點。 (將此添加到OP中)。 – arman

+1

你可以嘗試每個x座標偏移一點嗎?你的顏色計算看起來很好,所以我想知道你的矩形可能是錯誤的尺寸,最後一個是頂部的巨大紅色。 – usr2564301

回答

7

我生成光譜顏色這樣的:

void spectral_color(double &r,double &g,double &b,double l) // RGB <- lambda l = < 380,780 > [nm] 
    { 
     if (l<380.0) r=  0.00; 
    else if (l<400.0) r=0.05-0.05*sin(M_PI*(l-366.0)/ 33.0); 
    else if (l<435.0) r=  0.31*sin(M_PI*(l-395.0)/ 81.0); 
    else if (l<460.0) r=  0.31*sin(M_PI*(l-412.0)/ 48.0); 
    else if (l<540.0) r=  0.00; 
    else if (l<590.0) r=  0.99*sin(M_PI*(l-540.0)/104.0); 
    else if (l<670.0) r=  1.00*sin(M_PI*(l-507.0)/182.0); 
    else if (l<730.0) r=0.32-0.32*sin(M_PI*(l-670.0)/128.0); 
    else    r=  0.00; 
     if (l<454.0) g=  0.00; 
    else if (l<617.0) g=  0.78*sin(M_PI*(l-454.0)/163.0); 
    else    g=  0.00; 
     if (l<380.0) b=  0.00; 
    else if (l<400.0) b=0.14-0.14*sin(M_PI*(l-364.0)/ 35.0); 
    else if (l<445.0) b=  0.96*sin(M_PI*(l-395.0)/104.0); 
    else if (l<510.0) b=  0.96*sin(M_PI*(l-377.0)/133.0); 
    else    b=  0.00; 
    } 
  • l是輸入波長[nm] < 380,780 >
  • r,g,b被輸出的RGB顏色< 0,1 >

這是簡單的實際光譜顏色數據的粗略sin波近似。您也可以從中創建表並插入它或使用紋理...輸出顏色如下:

spectral_colors

也有類似的不同方法:

  1. 線性顏色 - 複合梯度

  2. 人眼X,Y,Z靈敏度曲線積分

    你必須有真正精確X,Y,Z曲線,即使是輕微的偏差導致「不現實」的顏色一樣,在這個例子中

    human eye XYZ sensitivity

要使最好你必須對顏色進行歸一化處理,並添加指數靈敏度修正。而且這些曲線隨着每一代都在變化,並且在世界的不同地區有所不同。所以除非你正在做一些特殊的醫療/物理軟件,否則這不是一個好主意。

spectral colors comparison

| <- 380nm ----------------------------------------------------------------- 780nm -> |

[EDIT1]here是我的新的物理更精確的轉換

我強烈建議,而不是用這種辦法(更準確,更好方式)

+0

酷,我我現在在路上,但當我回家時我會檢查一下。你已經把「彩虹」的概念比我的字面上的更多一點了(我真的只是想通過「色調」值進行迭代,但這很棒)。 – arman

+0

我自己發現了問題並更新了帖子。儘管如此,這仍然是一個非常好的答案,所以我會將其標記爲答案。謝謝! – arman

2

那麼,不完全正確。在這裏我做了一個JavaScript的例子。 鈉黃色(589nm下)太橙色和紅色Halpha(656nm)是太黃....

保存本例中爲一個HTML文件(jQuery的需要),並將其加載到瀏覽器: page.html中升= [納米]

<!DOCTYPE html> 
<html><head> 
<script src='jquery.js'></script> 
<script> 


/* 
* Return parameter value of name (case sensitive !) 
*/ 
function get_value(parametername) 
{ 
    readvalue=(location.search ? location.search.substring(1) : false); 

    if (readvalue) 
    { 
     parameter=readvalue.split('&'); 
     for (i=0; i<parameter.length; i++) 
     { 
      if (parameter[i].split('=')[0] == parametername) 
      return parameter[i].split('=')[1]; 
     } 
    } 
    return false; 
} 

function spectral_color(l) // RGB <- lambda l = < 380,780 > [nm] 
{ 
    var M_PI=Math.PI; 
    var r=0,g,b; 
    if (l<380.0) r=  0.00; 
    else if (l<400.0) r=0.05-0.05*Math.sin(M_PI*(l-366.0)/ 33.0); 
    else if (l<435.0) r=  0.31*Math.sin(M_PI*(l-395.0)/ 81.0); 
    else if (l<460.0) r=  0.31*Math.sin(M_PI*(l-412.0)/ 48.0); 
    else if (l<540.0) r=  0.00; 
    else if (l<590.0) r=  0.99*Math.sin(M_PI*(l-540.0)/104.0); 
    else if (l<670.0) r=  1.00*Math.sin(M_PI*(l-507.0)/182.0); 
    else if (l<730.0) r=0.32-0.32*Math.sin(M_PI*(l-670.0)/128.0); 
    else    r=  0.00; 
     if (l<454.0) g=  0.00; 
    else if (l<617.0) g=  0.78*Math.sin(M_PI*(l-454.0)/163.0); 
    else    g=  0.00; 
     if (l<380.0) b=  0.00; 
    else if (l<400.0) b=0.14-0.14*Math.sin(M_PI*(l-364.0)/ 35.0); 
    else if (l<445.0) b=  0.96*Math.sin(M_PI*(l-395.0)/104.0); 
    else if (l<510.0) b=  0.96*Math.sin(M_PI*(l-377.0)/133.0); 
    else    b=  0.00; 
    var rgb = Math.floor(r*256)*65536+Math.floor(g*256)*256 + Math.floor(b*256); 
    rgb = '000000' + rgb.toString(16); 
    rgb = '#' + rgb.substr(-6).toUpperCase(); 

    $('#color').html([r,g,b,rgb,l]); 
    $('body').css('background-color', rgb); 
} 

</script> 
</head><body> 
<div id='color'></div> 
<script> 
spectral_color(get_value('l')); 
</script> 
</body> 
</html>