关于C#:如何在Freeglut中画彩虹?

How do I draw a rainbow in Freeglut?

我正在尝试在openGL中绘制彩虹色的情节图例。这是到目前为止我得到的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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是组成"彩虹"的离散正方形的数量。 xLeftxRightyBottomyTop是组成每个平方的顶点。

函数OpenGL::pSetHSV如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

我不太了解pSetHSV()中RGB / HSV转换的工作原理,因此很难识别问题。.

编辑:这是固定的版本,受到Jongware的启发(矩形的绘制不正确):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 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();


我生成如下光谱颜色:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

也有不同的方法,例如:

  • 线性颜色-复合渐变

    • 像这样:http://www.physics.sfasu.edu/astro/color/spectra.html
    • 但是输出对我来说不够好
  • 人眼X,Y,Z灵敏度曲线积分

    您必须具有非常精确的X,Y,Z曲线,即使轻微的偏差也会导致"不真实"的颜色,如本例中所示

    human

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

    [edit1]这是我的新的物理上更准确的转换

    我强烈建议您改用这种方法(以任何方式更准确,更好)


    嗯,不是完全正确。在这里,我做了一个JavaScript示例。
    钠黄色(589nm)太橙色,而Halpha红色(656nm)太棕色....

    将此示例保存到HTML文件(需要jquery)并将其加载到浏览器中:
    page.html?l = [纳米]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    <!DOCTYPE html>
    <html><head>
    <script src='jquery.js'>



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


    </head><body>


    spectral_color(get_value('l'));

    </body>
    </html>