如何在Freeglut中绘制彩虹? [英] How do I draw a rainbow in Freeglut?

查看:232
本文介绍了如何在Freeglut中绘制彩虹?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在openGL中绘制彩虹色的图例。这是我到目前为止:

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

//绘制第i个legend元素
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 yBottom yTop 是构成每个平方的顶点。



其中函数 OpenGL :: pSetHSV 看起来像这样:

  void pSetHSV(float h,float s,float v)
{
// H [0,360] S和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);
}
}

我从

  • 但输出对我来说不够好
  • ,Z 敏感性曲线集成



    您必须有非常精确的 X,Y,Z




    为了更好地进行颜色标准化和指数灵敏度修正。此外,这些曲线随着每一代而变化,并且在世界的不同区域中是不同的。因此,除非你正在做一些特殊的医疗/物理软件,这不是一个好主意。





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



    [edit1] 这里 是我的新身体更准确的转换



    我强烈建议改用这种方法并以任何方式更好)


    I'm trying to draw a rainbow-coloured plot legend in openGL. Here is what I've got so far:

    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 is the number of discrete squares that make up the "rainbow". xLeft,xRight,yBottom and yTop are the vertices that make up each of the squared.

    where the function OpenGL::pSetHSV looks like this:

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

    I got that function from http://forum.openframeworks.cc/t/hsv-color-setting/770

    However, when I draw this it looks like this:

    What I would like is a spectrum of Red,Green,Blue,Indigo,Violet (so I want to iterate linearly through the Hue. However, this doesn't really seem to be what's happening.

    I don't really understand how the RGB/HSV conversion in pSetHSV() works so it's hard for me to identify the problem..

    EDIT: Here is the fixed version, as inspired by Jongware (the rectangles were being drawn incorrectly):

    // 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();
    

    解决方案

    I generate spectral colors like this:

    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 is input wavelength [nm] < 380,780 >
    • r,g,b is output RGB color < 0,1 >

    This is simple rough sin wave approximation of real spectral color data. You can also create table from this and interpolate it or use texture ... output colors are:

    there are also different approaches like:

    1. linear color - composite gradients

    2. human eye X,Y,Z sensitivity curves integration

      you have to have really precise X,Y,Z curves, even slight deviation causes 'unrealistic' colors like in this example

    To make it better you have to normalize colors and add exponential sensitivity corrections. Also these curves are changing with every generation and are different in different regions of world. So unless you are doing some special medical/physics softs it is not a good idea to go this way.

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

    [edit1] here is mine new physically more accurate conversion

    I strongly recommend to use this approach instead (it is more accurate and better in any way)

    这篇关于如何在Freeglut中绘制彩虹?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆