使用glVertex2i()绘制图形时,使用glScaled()缩放时会显示伪影

时间:2019-05-14 20:27:08

标签: c++ opengl opengl-compat

我正在使用OpenGL绘制RGB图像直方图。由于这是一个8位图像直方图,因此我的数据集包含从零到255的数据点。

如果我在不使用glScaled()的情况下绘制直方图,则该图将按预期进行绘制,但是当然不会填充分配的区域(其宽度是可变的,高度常数是恒定的)。但是,当我使用glScaled()时,该图显示出奇怪的伪像。

请查看以下图片以查看问题的示例:

Histogram without glScale

上图显示的直方图是用256个数据点绘制的,而没有使用glScaled()进行缩放。

Histogram plot with glScale

Same as above but with a larger scale

上面的两幅图像显示了使用256个数据点绘制的直方图,并使用glScaled()对其进行了缩放。奇怪的伪像很明显(缺少数据?)。请注意,由于光线水平的变化,第三个直方图的形状略有不同。

这是我的OpenGL初始化代码的相关部分:

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// If this line is removed then the graph plots correctly
// m_scale_factor = width / 256
glScaled(m_scale_factor, 1.0, 1.0);

glClear(GL_COLOR_BUFFER_BIT);

这是我的情节代码的相关部分:

glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);

glBegin(GL_LINE_STRIP);
for (int n = 0; n < m_histogram_X; n++)
{
    glColor4ub(255, 0, 0, 255);
    glVertex2i(n, m_Hist_Channel_R[n]);
    glVertex2i(n, GRAPH_HEIGHT);

    glColor4ub(0, 255, 0, 255);
    glVertex2i(n, m_Hist_Channel_G[n]);
    glVertex2i(n, GRAPH_HEIGHT);

    glColor4ub(0, 0, 255, 255);
    glVertex2i(n, m_Hist_Channel_B[n]);
    glVertex2i(n, GRAPH_HEIGHT);
}
glEnd()

...

在这个阶段,我觉得我必须声明自己是OpenGL的新手,所以可能我误解了许多OpenGL的东西...

我的问题是:是否可以在OpenGL中解决此问题,还是我必须通过某种插值来增加数据点的数量,然后在不缩放的情况下进行绘制?

感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:2)

没有数据丢失。只是,您使用的绘图图元不适合数据。 GL_LINE_STRIP绘制一条连续的长线,将点通过时连接起来,并在设置的颜色之间进行插值。

基本上,您要做的是,从最后一个蓝色垃圾箱到下一个红色垃圾箱高度,然后从红色垃圾箱到绿色垃圾箱,再从那里到蓝色垃圾箱,绘制一条蓝红色的线。然后,您跳到下一个红色垃圾箱,依此类推。因此,从本质上讲,您正在绘制带有红色和蓝色之间连接线的小“尖峰”。当然,如果宽度上要填充的像素多于容器,则将存在间隙。

我建议您拿一张(绘图)纸,亲自进行绘制步骤,以了解结果如何发生。

要告诉的真相:无论如何,这不是绘制直方图的最有效方法。一种更好的方法是将直方图数据加载到一维纹理中,绘制一个大的四边形(或者更好的是将视口填充为三角形,使用剪刀测试将视口切成矩形),然后为每个片段(大约是一个像素) fragment shader 中的一些额外内容)使用X坐标从纹理中查找bin,然后从纹理中减去Y坐标并将结果传递到step或{{1 }} GLSL函数可确定像素的颜色。奇怪的是,对于新手来说,这听起来似乎很奇怪,但是绘制单个三角形并在片段着色器 中进行其余操作效率更高,即提交大量多边形。它还提供了更好的质量!

更新-着色器示例

一个实际的应用程序可以使用这样的着色器(Shadertoy语义)来实现:

smoothstep

然后结果看起来像这样

Shader based histogram

答案 1 :(得分:2)

如果将渲染分为3个遍,则应该能够使用三角形条代替线条(应填充间隙)。

glBegin(GL_TRIANGLE_STRIP);
glColor4ub(255, 0, 0, 255);
for (int n = 0; n < m_histogram_X; n++)
{
    glVertex2i(n, m_Hist_Channel_R[n]);
    glVertex2i(n, GRAPH_HEIGHT);
}
glEnd()

glBegin(GL_TRIANGLE_STRIP);
glColor4ub(0, 255, 0, 255);
for (int n = 0; n < m_histogram_X; n++)
{
    glVertex2i(n, m_Hist_Channel_G[n]);
    glVertex2i(n, GRAPH_HEIGHT);
}
glEnd()

glBegin(GL_TRIANGLE_STRIP);
glColor4ub(0, 0, 255, 255);
for (int n = 0; n < m_histogram_X; n++)
{
    glVertex2i(n, m_Hist_Channel_B[n]);
    glVertex2i(n, GRAPH_HEIGHT);
}
glEnd()