The*_*eOx 3 c++ opengl texture-mapping
我在一个规则间隔的网格上有一组X,Y,Z值,我需要使用C++创建一个颜色填充的等高线图.我已经在谷歌上搜索了好几天,而且似乎是在openGL中使用1D纹理贴图可以实现这一点.但是我还没有找到一个如何实际执行此操作的示例,并且我没有在任何地方阅读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值并且数据点之间存在间隙,因此应用一维纹理如何实现轮廓此数据(即如何在网格点之间应用一维纹理内插?)
我最接近找到这个例子的是红茶书的在线版本(http://fly.cc.fer.hr/~unreal/theredbook/chapter09.html),但是我是茶壶假设茶壶模型具有每个像素的数据,因此不需要数据点之间的插值.
如果有人能够阐明我的问题或更好地指出以这种方式使用一维纹理贴图的具体例子,我会永远感激,因为我已经在这个项目上烧了两天而没什么可展示的.
编辑:
下面的代码是我正在使用的,虽然它确实显示了正确位置的点,但没有插值或轮廓发生 - 这些点只显示为点.
//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();
Run Code Online (Sandbox Code Playgroud)
这个想法是将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);
Run Code Online (Sandbox Code Playgroud)
并将其绑定以供使用.
// 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);
Run Code Online (Sandbox Code Playgroud)
现在来看你的概念问题:你不能直接用XYZ数据绘制等高线图.XYZ只是稀疏的采样点.您需要填补空白,例如首先将其放入2D直方图中.为此创建一个网格,每个方向都有一定数量的bin,初始化为所有NaN(伪代码)
float hist2D[bins_x][bins_y] = {NaN, NaN, ...}
Run Code Online (Sandbox Code Playgroud)
然后对于每个XYZ,如果不是NaN,则将Z值添加到网格的bin中,否则将NaN替换为Z值.然后在直方图上使用拉普拉斯滤波器来平滑仍然包含NaN的箱.最后,您可以使用将网格渲染为等高线图
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();
Run Code Online (Sandbox Code Playgroud)
或者您可以将网格作为2D纹理上传,并使用片段着色器间接进入颜色渐变.
填充稀疏XYZ数据中的间隙的另一种方法是找到XY集的2D Voronoi图并使用它来创建采样几何.顶点的Z值将是有助于Voronoi单元相交的XYZ的距离加权平均值.
| 归档时间: |
|
| 查看次数: |
4914 次 |
| 最近记录: |