我正试图在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);
// 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
,yBottom
和yTop
是构成每个平方的顶点。
函数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
获得了该功能然而,当我画这个时,它看起来像这样:
我想要的是一系列红色,绿色,蓝色,靛蓝色,紫色(所以我想通过 Hue 线性迭代。但是,这似乎并不是真正发生的事情
我真的不明白pSetHSV()
中的RGB / HSV转换是如何工作的,所以我很难确定问题。
编辑:这是固定版本,受到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 :(得分:8)
我生成这样的光谱颜色:
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
波近似。你也可以从这里创建表并插入它或使用纹理...输出颜色是:
还有不同的方法,如:
线性颜色 - 复合渐变
人眼X,Y,Z
灵敏度曲线积分
你必须拥有非常精确的X,Y,Z
曲线,即使轻微偏差也会导致'不切实际'的颜色,如本例所示
为了使其更好,您必须标准化颜色并添加指数灵敏度校正。这些曲线也随着每一代而变化,并且在世界的不同地区有所不同。因此,除非你正在做一些特殊的医疗/物理软件,否则这样做并不是一个好主意。
| <- 380nm ----------------------------------------------------------------- 780nm -> |
[edit1] here 是我新的物理转换更准确
我强烈建议使用这种方法(以任何方式更准确,更好)
答案 1 :(得分:2)
嗯,不完全正确。在这里我做了一个javascript示例。 黄色钠(589nm)太橙色,Halpha红色(656nm)太棕色....
将此示例保存到HTML文件(需要jquery)并将其加载到浏览器中: page.html中ΔL= [纳米]
<!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>