【问题标题】:Create contour plot in opengl using grid data and a 1D texture map使用网格数据和一维纹理图在 opengl 中创建等高线图
【发布时间】:2012-01-11 18:50:09
【问题描述】:

我在规则间隔的网格上有一组 X、Y、Z 值,我需要使用 C++ 创建一个填充颜色的等高线图。我已经在谷歌上搜索了好几天,共识似乎是使用openGL中的一维纹理贴图可以实现这一点。但是,我还没有找到一个如何实际执行此操作的示例,而且仅阅读 openGL 文档就没有任何进展。我的困惑归结为一个核心问题:

我的数据不包含每个像素的 X、Y 值 - 它是一个规则间隔的网格,在 X 和 Y 轴上每 4 个单位包含一个数据,具有一个正整数 Z 值。

例如:(0, 0, 1), (4, 0, 1), (8, 0, 2), (0, 4, 2), (0, 8, 4), (4, 4 , 3) 等。

由于轮廓将基于 Z 值并且数据点之间存在间隙,因此应用 1D 纹理如何实现此数据的轮廓(即应用 1D 纹理如何在网格点之间进行插值?)强>

我找到的最接近的例子是在茶壶示例中的红皮书 (http://fly.cc.fer.hr/~unreal/theredbook/chapter09.html) 的在线版本中,但是我假设茶壶模型的每个像素都有数据,因此不需要在数据点之间进行插值。

如果有人能阐明我的问题,或者更好地指出一个以这种方式使用 1D 纹理贴图的具体示例,我将永远感激不尽,因为我在这个项目上花了 2 天时间,几乎没有什么可展示的它。

编辑:

以下代码是我正在使用的代码,虽然它确实在正确的位置显示了点,但没有发生插值或轮廓 - 这些点只是显示为点。

//Create a 1D image - for this example it's just a red line
int stripeImageWidth = 32;
GLubyte   stripeImage[3*stripeImageWidth];
for (int j = 0; j < stripeImageWidth; j++) {
    stripeImage[3*j] = j < 2 ? 0 : 255;
    stripeImage[3*j+1] = 255;
    stripeImage[3*j+2] = 255;
}
glDisable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage1D(GL_TEXTURE_1D, 0, 3, stripeImageWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, stripeImage);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
float s[4] = { 0,1,0,0 };
glTexGenfv( GL_S, GL_OBJECT_PLANE, s );
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_1D );
glBegin(GL_POINTS);

//_coords contains X,Y,Z data - Z is the value that I'm trying to contour
for (int x = 0; x < _coords.size(); ++x)
{
    glTexCoord1f(static_cast<ValueCoord*>(_coords[x])->GetValue());
    glVertex3f(_coords[x]->GetX(), _coords[x]->GetY(), zIndex);
}
glEnd();

【问题讨论】:

    标签: c++ opengl texture-mapping


    【解决方案1】:

    这个想法是使用 Z 坐标作为 S 坐标进入纹理。纹理坐标上的线性插值然后创建轮廓。请注意,通过使用着色器,您可以将 XY->Z 数据放入 2D 纹理中,并使用着色器在 1D 纹理的色带中对 2D 采样器的值进行间接处理。

    更新:代码示例

    首先我们需要稍微改变一下使用纹理的方式。

    为此准备纹理:

    //Create a 1D image - for this example it's just a red line
    int stripeImageWidth = 32;
    GLubyte   stripeImage[3*stripeImageWidth];
    for (int j = 0; j < stripeImageWidth; j++) {
        stripeImage[3*j] = j*255/32; // use a gradient instead of a line
        stripeImage[3*j+1] = 255;
        stripeImage[3*j+2] = 255;
    }
    
    GLuint texID;
    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_1D, texID);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage1D(GL_TEXTURE_1D, 0, 3, stripeImageWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, stripeImage);
    
    // We want the texture to wrap, so that values outside the range [0, 1] 
    // are mapped into a gradient sawtooth
    glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    

    还有 this 绑定它以供使用。

    // The texture coordinate comes from the data, it it not
    // generated from the vertex position!!!
    glDisable( GL_TEXTURE_GEN_S ); 
    glDisable(GL_TEXTURE_2D);
    glEnable( GL_TEXTURE_1D );
    glBindTexture(GL_TEXTURE_1D, texID);
    

    现在你的概念问题:你不能直接从 XYZ 数据制作等高线图。 XYZ 只是稀疏的采样点。您需要填补空白,例如首先将其放入 2D 直方图中。为此创建一个网格,每个方向都有一定数量的 bin,初始化为所有 NaN(伪代码)

    float hist2D[bins_x][bins_y] = {NaN, NaN, ...}
    

    然后对于每个 XYZ,如果不是 NaN,则将 Z 值添加到网格的 bin 中,否则将 NaN 替换为 Z 值。然后在直方图上使用拉普拉斯滤波器来平滑仍然包含 NaN 的 bin。最后,您可以使用

    将网格渲染为等高线图
    glBegin(GL_QUADS);
    for(int y=0; y<grid_height; y+=2) for(int x=0; x<grid_width; x+=2) {
        glTexCoord1f(hist2D[x  ][y  ]]); glVertex2i(x  ,y);
        glTexCoord1f(hist2D[x+1][y  ]]); glVertex2i(x+1,y);
        glTexCoord1f(hist2D[x+1][y+1]]); glVertex2i(x+1,y+1);
        glTexCoord1f(hist2D[x  ][y+1]]); glVertex2i(x  ,y+1);
    }
    glEnd();
    

    或者您可以将网格上传为 2D 纹理并使用片段着色器间接进入色带。

    另一种填补稀疏 XYZ 数据空白的方法是找到 XY 集的 2D Voronoi 图并使用它来创建采样几何。顶点的 Z 值将是导致 Voronoi 单元相交的 XYZ 的距离加权平均值。

    【讨论】:

    • 精彩的详细答案!谢谢
    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2017-07-16
    • 2021-04-03
    • 1970-01-01
    相关资源
    最近更新 更多