使用 glTexGen 在 OpenGL 中对球体进行纹理化
Texturing a sphere in OpenGL with glTexGen
我想在球体上获得地球纹理。我的球体是一个由许多三角形 (100+) 构建的圆角球体,我发现为整个球体设置 UV 坐标会让人感到困惑。我尝试使用 glTexGen,效果非常接近,但我的纹理重复了 8 次(见图)。我找不到一种方法让它只包装整个对象一次。这是我创建球体和纹理的代码。
glEnable(GL_TEXTURE_2D);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glBegin(GL_TRIANGLES);
for (int i = 0; i < new_sphere->NumOfTrians; i++)
{
Triangle *draw_Trian = new_sphere->Trians+i;
glVertex3f(draw_Trian->pnts[0].coords[0], draw_Trian->pnts[0].coords[1], draw_Trian->pnts[0].coords[2]);
glVertex3f(draw_Trian->pnts[1].coords[0], draw_Trian->pnts[1].coords[1], draw_Trian->pnts[1].coords[2]);
glVertex3f(draw_Trian->pnts[2].coords[0], draw_Trian->pnts[2].coords[1], draw_Trian->pnts[2].coords[2]);
}
glDisable(GL_TEXTURE_2D);
free(new_sphere->Trians);
free(new_sphere);
glEnd();
您需要定义纹理应该如何映射到三角形。这取决于您使用的纹理。有多种方法可以用纹理映射球体的表面(因为没有一种映射是没有奇点的)。看起来你那里有一个圆柱形投影纹理。所以我们将发射圆柱形 UV 坐标。
我试图在这里给你一些代码,但它假设
- 您的网格是一个单位球体(即以 0 为中心,半径为 1)
pnts.coords
是一个浮点数组
- 您想使用第二个坐标 (
coord[1]
) 作为 'up' 方向(或圆柱映射中的 height
)
您的代码看起来像这样。我定义了一个发射圆柱形 UV 的新函数,所以你可以把它放在任何你喜欢的地方。
/* Map [(-1, -1, -1), (1, 1, 1)] into [(0, 0), (1, 1)] cylindrically */
inline void uvCylinder(float* coord) {
float angle = 0.5f * atan2(coord[2], coord[0]) / 3.14159f + 0.5f;
float height = 0.5f * coord[1] + 0.5f;
glTexCoord2f(angle, height);
}
glEnable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLES);
for (int i = 0; i < new_sphere->NumOfTrians; i++) {
Triangle *t = new_sphere->Trians+i;
uvCylinder(t->pnts[0].coords);
glVertex3f(t->pnts[0].coords[0], t->pnts[0].coords[1], t->pnts[0].coords[2]);
uvCylinder(t->pnts[1].coords);
glVertex3f(t->pnts[1].coords[0], t->pnts[1].coords[1], t->pnts[1].coords[2]);
uvCylinder(t->pnts[2].coords);
glVertex3f(t->pnts[2].coords[0], t->pnts[2].coords[1], t->pnts[2].coords[2]);
}
glEnd();
glDisable(GL_TEXTURE_2D);
free(new_sphere->Trians);
free(new_sphere);
投影注意事项
为整个球体构建 UV 坐标令人困惑的原因是没有一种 'correct' 方法可以做到这一点。从数学上讲,没有完美的球体二维映射这样的东西;这就是为什么我们有这么多不同类型的 projections。当您的 2D 图像是球形对象的纹理时,您需要知道该图像是为哪种类型的投影构建的,以便您可以为该纹理发出正确的 UV 坐标。
我想在球体上获得地球纹理。我的球体是一个由许多三角形 (100+) 构建的圆角球体,我发现为整个球体设置 UV 坐标会让人感到困惑。我尝试使用 glTexGen,效果非常接近,但我的纹理重复了 8 次(见图)。我找不到一种方法让它只包装整个对象一次。这是我创建球体和纹理的代码。
glEnable(GL_TEXTURE_2D);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glBegin(GL_TRIANGLES);
for (int i = 0; i < new_sphere->NumOfTrians; i++)
{
Triangle *draw_Trian = new_sphere->Trians+i;
glVertex3f(draw_Trian->pnts[0].coords[0], draw_Trian->pnts[0].coords[1], draw_Trian->pnts[0].coords[2]);
glVertex3f(draw_Trian->pnts[1].coords[0], draw_Trian->pnts[1].coords[1], draw_Trian->pnts[1].coords[2]);
glVertex3f(draw_Trian->pnts[2].coords[0], draw_Trian->pnts[2].coords[1], draw_Trian->pnts[2].coords[2]);
}
glDisable(GL_TEXTURE_2D);
free(new_sphere->Trians);
free(new_sphere);
glEnd();
您需要定义纹理应该如何映射到三角形。这取决于您使用的纹理。有多种方法可以用纹理映射球体的表面(因为没有一种映射是没有奇点的)。看起来你那里有一个圆柱形投影纹理。所以我们将发射圆柱形 UV 坐标。
我试图在这里给你一些代码,但它假设
- 您的网格是一个单位球体(即以 0 为中心,半径为 1)
pnts.coords
是一个浮点数组- 您想使用第二个坐标 (
coord[1]
) 作为 'up' 方向(或圆柱映射中的height
)
您的代码看起来像这样。我定义了一个发射圆柱形 UV 的新函数,所以你可以把它放在任何你喜欢的地方。
/* Map [(-1, -1, -1), (1, 1, 1)] into [(0, 0), (1, 1)] cylindrically */
inline void uvCylinder(float* coord) {
float angle = 0.5f * atan2(coord[2], coord[0]) / 3.14159f + 0.5f;
float height = 0.5f * coord[1] + 0.5f;
glTexCoord2f(angle, height);
}
glEnable(GL_TEXTURE_2D);
glBegin(GL_TRIANGLES);
for (int i = 0; i < new_sphere->NumOfTrians; i++) {
Triangle *t = new_sphere->Trians+i;
uvCylinder(t->pnts[0].coords);
glVertex3f(t->pnts[0].coords[0], t->pnts[0].coords[1], t->pnts[0].coords[2]);
uvCylinder(t->pnts[1].coords);
glVertex3f(t->pnts[1].coords[0], t->pnts[1].coords[1], t->pnts[1].coords[2]);
uvCylinder(t->pnts[2].coords);
glVertex3f(t->pnts[2].coords[0], t->pnts[2].coords[1], t->pnts[2].coords[2]);
}
glEnd();
glDisable(GL_TEXTURE_2D);
free(new_sphere->Trians);
free(new_sphere);
投影注意事项
为整个球体构建 UV 坐标令人困惑的原因是没有一种 'correct' 方法可以做到这一点。从数学上讲,没有完美的球体二维映射这样的东西;这就是为什么我们有这么多不同类型的 projections。当您的 2D 图像是球形对象的纹理时,您需要知道该图像是为哪种类型的投影构建的,以便您可以为该纹理发出正确的 UV 坐标。