如何在 3d 图形 OpenGL 中使用纹理
How to use texture in 3d graphic OpenGL
正如汤米所说,我做了一些改变:
So, I'd say steps would be:
- make sure all of your arrays have at least 11 elements in them;
- enable texturing.
为什么这段代码不会显示草纹理?
首先加载纹理图片:
QImage img;
if(!img.load("../g.jpg")){
qDebug("Texture not found!");
}
else {
t = QGLWidget::convertToGLFormat(img);
qDebug("Textture Converted to GLFormat.");
}
然后调用 draw 方法用顶点数组绘制一个不平坦的地面:
GLfloat vertices2[] = {
2,2,0 , 2,-2,0 , -2,-2,0 , -2,2,0,
0.7,0.6,0.6 , 0.4,0.9,0.1 , 0.1,0.2,0.3 , 0.8,0.3,0.8 ,
0.5,-0.5,0.12 , 0,-0.9,0.4 , -0.8,-0.2,0.6
};
GLfloat colors[] = {35 , 73 , 12 , 10 , 6 , 41 , 32 , 10 , 13 , 35 , 42 , 86 , 12 , 2 , 6 ,9};
GLfloat TexCoords[] = {
0.449,0.911,0.056,
0.911,0.056,0.17,
0.056,0.17,0.902,
0.17,0.902,0.873,
0.902,0.873,0.061,
0.873,0.061,0.557,
0.061,0.557,0.517,
0.557,0.517,0.131,
0.517,0.131,0.855,
0.131,0.855,0.533,
0.855,0.533,0.896,
0.533,0.896,0.178,
0.896,0.178,0.303,
0.178,0.303,0.358,
0.303,0.358,0.064,
0.358,0.064,0.156,
0.064,0.156,0.199,
0.156,0.199,0.32,
0.199,0.32,0.636,
0.32,0.636,0.306,
0.636,0.306,0.445,
0.306,0.445,0.166,
0.445,0.166,0.572,
0.166,0.572,0.249,
0.572,0.249,0.29,
0.249,0.29,0.389,
0.29,0.389,0.79,
0.389,0.79,0.567,
0.79,0.567,0.692,
0.567,0.692,0.202,
0.692,0.202,0.913,
0.202,0.913,0.498
};
GLfloat NormalP[] = { 0.383,0.29,0.746,
0.29,0.746,0.301,
0.746,0.301,0.675,
0.301,0.675,0.541,
0.675,0.541,0.677,
0.541,0.677,0.896,
0.677,0.896,0.915,
0.896,0.915,0.295,
0.915,0.295,0.423,
0.295,0.423,0.76,
0.423,0.76,0.89,
};
GLubyte indices[] = {
1,2,9 , 9,8,1 , 1,8,7 , 7,1,0 ,
0,7,4 , 0,4,5 , 0,5,3 , 3,5,6 ,
3,6,10 , 3,10,2 , 2,10,9 , 9,6,10 ,
6,5,4 , 6,4,7 , 6,7,8 , 6,8,9
};
GLuint mHandle;
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_2D, mHandle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,t.width(),t.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,t.bits());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glColorPointer(3,GL_FLOAT,0,colors);
glVertexPointer(3, GL_FLOAT, 0, vertices2);
glTexCoordPointer(3,GL_FLOAT,0,TexCoords);
glNormalPointer(GL_FLOAT,0,NormalP);
glDrawElements(GL_TRIANGLES,54, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
在固定管线中,纹理仅在启用时应用。您没有显示对 glEnable(GL_TEXTURE_2D)
.
的调用
话虽这么说,但看起来您的数组大小可能不正确。
glTexCoordPointer(3,GL_FLOAT,0,TexCoords); ... glDrawElements(GL_TRIANGLES,54, GL_UNSIGNED_BYTE, indices);
的最终效果是从TexCoords
中读取11组纹理坐标,因为indices
中的最大索引是10
。但是,假设您在 3d 中指定它们,您的纹理坐标数组中只有两个纹理坐标。
所以,我认为步骤是:
- 确保所有数组中至少有 11 个元素;
- 启用纹理。
如果您只使用 2d 纹理并且没有对纹理矩阵堆栈做任何巧妙的处理,您可能还想切换到在 2d 中提供纹理坐标。
根据 j-p,公然抄袭这就是为什么现在将其标记为社区 wiki:您在创建新纹理 ID 后也未能绑定它。 OpenGL 有点奇怪,因为在显示列表被证明不具有最初希望的属性之后,纹理 ID 是一个螺栓,所以你可以在没有生成纹理的情况下做所有事情,前提是你也永远不会绑定一个,假设你只有一个纹理.但是,如果您要对此保持明智并生成它们,那么请确保绑定它们。生成不隐式绑定。
另一个问题是您启用 mipmapping 作为采样参数的一部分:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
但纹理没有 mipmap。要生成 mipmap,请在 glTexImage2D()
之后添加以下调用:
glGenerateMipmap(GL_TEXTURE_2D);
正如汤米所说,我做了一些改变:
So, I'd say steps would be:
- make sure all of your arrays have at least 11 elements in them;
- enable texturing.
为什么这段代码不会显示草纹理?
首先加载纹理图片:
QImage img;
if(!img.load("../g.jpg")){
qDebug("Texture not found!");
}
else {
t = QGLWidget::convertToGLFormat(img);
qDebug("Textture Converted to GLFormat.");
}
然后调用 draw 方法用顶点数组绘制一个不平坦的地面:
GLfloat vertices2[] = {
2,2,0 , 2,-2,0 , -2,-2,0 , -2,2,0,
0.7,0.6,0.6 , 0.4,0.9,0.1 , 0.1,0.2,0.3 , 0.8,0.3,0.8 ,
0.5,-0.5,0.12 , 0,-0.9,0.4 , -0.8,-0.2,0.6
};
GLfloat colors[] = {35 , 73 , 12 , 10 , 6 , 41 , 32 , 10 , 13 , 35 , 42 , 86 , 12 , 2 , 6 ,9};
GLfloat TexCoords[] = {
0.449,0.911,0.056,
0.911,0.056,0.17,
0.056,0.17,0.902,
0.17,0.902,0.873,
0.902,0.873,0.061,
0.873,0.061,0.557,
0.061,0.557,0.517,
0.557,0.517,0.131,
0.517,0.131,0.855,
0.131,0.855,0.533,
0.855,0.533,0.896,
0.533,0.896,0.178,
0.896,0.178,0.303,
0.178,0.303,0.358,
0.303,0.358,0.064,
0.358,0.064,0.156,
0.064,0.156,0.199,
0.156,0.199,0.32,
0.199,0.32,0.636,
0.32,0.636,0.306,
0.636,0.306,0.445,
0.306,0.445,0.166,
0.445,0.166,0.572,
0.166,0.572,0.249,
0.572,0.249,0.29,
0.249,0.29,0.389,
0.29,0.389,0.79,
0.389,0.79,0.567,
0.79,0.567,0.692,
0.567,0.692,0.202,
0.692,0.202,0.913,
0.202,0.913,0.498
};
GLfloat NormalP[] = { 0.383,0.29,0.746,
0.29,0.746,0.301,
0.746,0.301,0.675,
0.301,0.675,0.541,
0.675,0.541,0.677,
0.541,0.677,0.896,
0.677,0.896,0.915,
0.896,0.915,0.295,
0.915,0.295,0.423,
0.295,0.423,0.76,
0.423,0.76,0.89,
};
GLubyte indices[] = {
1,2,9 , 9,8,1 , 1,8,7 , 7,1,0 ,
0,7,4 , 0,4,5 , 0,5,3 , 3,5,6 ,
3,6,10 , 3,10,2 , 2,10,9 , 9,6,10 ,
6,5,4 , 6,4,7 , 6,7,8 , 6,8,9
};
GLuint mHandle;
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_2D, mHandle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,t.width(),t.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,t.bits());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glColorPointer(3,GL_FLOAT,0,colors);
glVertexPointer(3, GL_FLOAT, 0, vertices2);
glTexCoordPointer(3,GL_FLOAT,0,TexCoords);
glNormalPointer(GL_FLOAT,0,NormalP);
glDrawElements(GL_TRIANGLES,54, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
在固定管线中,纹理仅在启用时应用。您没有显示对 glEnable(GL_TEXTURE_2D)
.
话虽这么说,但看起来您的数组大小可能不正确。
glTexCoordPointer(3,GL_FLOAT,0,TexCoords); ... glDrawElements(GL_TRIANGLES,54, GL_UNSIGNED_BYTE, indices);
的最终效果是从TexCoords
中读取11组纹理坐标,因为indices
中的最大索引是10
。但是,假设您在 3d 中指定它们,您的纹理坐标数组中只有两个纹理坐标。
所以,我认为步骤是:
- 确保所有数组中至少有 11 个元素;
- 启用纹理。
如果您只使用 2d 纹理并且没有对纹理矩阵堆栈做任何巧妙的处理,您可能还想切换到在 2d 中提供纹理坐标。
根据 j-p,公然抄袭这就是为什么现在将其标记为社区 wiki:您在创建新纹理 ID 后也未能绑定它。 OpenGL 有点奇怪,因为在显示列表被证明不具有最初希望的属性之后,纹理 ID 是一个螺栓,所以你可以在没有生成纹理的情况下做所有事情,前提是你也永远不会绑定一个,假设你只有一个纹理.但是,如果您要对此保持明智并生成它们,那么请确保绑定它们。生成不隐式绑定。
另一个问题是您启用 mipmapping 作为采样参数的一部分:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
但纹理没有 mipmap。要生成 mipmap,请在 glTexImage2D()
之后添加以下调用:
glGenerateMipmap(GL_TEXTURE_2D);