Qt 顶点数组不适用于 QImage
首先,我对问题的长度表示歉意。我相信我犯了一些小而愚蠢的错误,但由于我完全找不到它,我决定发布所有相关代码以防万一。
我终于使用 QImage 进行纹理加载,并且能够以即时模式渲染纹理。 然而,顶点数组不起作用,我不知道为什么。 最明显的事情比如“你启用了顶点数组和纹理坐标数组吗?”可能不是答案。我将发布初始化代码。
这是初始化函数:
/* general OpenGL initialization function */
int initGL()
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0, 0, 0, 1); // Black Background
glEnable ( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glDisable(GL_DEPTH_TEST);
//ENABLED VERTEX ARRAYS AND TEXTURE COORDINATE ARRAYS
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
//ENABLED 2D TEXTURING
glEnable ( GL_TEXTURE_2D );
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//seed random
srand(time(NULL));
return( TRUE );
}
我有由 QGLWidget 调用的初始化、调整大小和绘制函数(它本身只是调用实际工作函数的骨架)
纹理加载函数:
GLuint LoadGLTextures( const char * name )
{
//unformatted QImage
QImage img;
//load the image from a .qrc resource
if(!img.load(":/star.bmp"))
{
qWarning("ERROR LOADING IMAGE");
}
//an OpenGL formatted QImage
QImage GL_formatted_image;
GL_formatted_image = QGLWidget::convertToGLFormat(img);
//error check
if(GL_formatted_image.isNull())
qWarning("IMAGE IS NULL");
else
qWarning("IMAGE NOT NULL");
//texture ID
GLuint _textures[1];
//enable texturing
glEnable(GL_TEXTURE_2D);
//generate textures
glGenTextures(1,&_textures[0]);
//bind the texture
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//generate texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_formatted_image.width(),
GL_formatted_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
GL_formatted_image.bits());
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//return the texture ID
return _textures[0];
}
这是绘制代码:
//this does draw
//get the texture ID
GLuint tex_id = LoadGLTextures(":/star.png");
glBindTexture(GL_TEXTURE_2D, tex_id); // Actually have an array of images
glColor3f(1.0f, 0.0f, 0.5f);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f);glVertex2f(1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);glVertex2f(0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);glVertex2f(0.0f, 0.0f);
glEnd();
//this does not draw
//translations code
glLoadIdentity();
glTranslatef(-1.0f, 0.0f, 0.0f);
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
//set color state
glColor4f(0.0f, 1.0f, 0.0f, 0.5);
//vertices to be rendered
static GLfloat vertices[] =
{
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
static GLshort coord_Data[] =
{
1, 0,
1, 1,
0, 1,
0, 0
};
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
//pointer to the vertex array
glVertexPointer(2, GL_FLOAT, 0, vertices);
//texture coordinate pointer
glTexCoordPointer(2, GL_SHORT, 0, coord_Data);
//draw the arrays
glDrawArrays(GL_QUADS, 0, 4);
感谢所有帮助, 龙鹪鹩
I'll begin by apologizing for the length of the question. I believe I've committed some small, dumb error, but since I'm entirely unable to find it, I decided to post all relevant code just in case.
I finally got texture loading working using QImage, and am able to render textures in immediate mode.
However, vertex arrays don't work, and I'm at a loss as to why.
The most obvious things like "Have you enabled vertex arrays and texture coordinate arrays?" are probably not the answer. I'll post the initialization code.
Here's the init function:
/* general OpenGL initialization function */
int initGL()
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0, 0, 0, 1); // Black Background
glEnable ( GL_COLOR_MATERIAL );
glColorMaterial ( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glDisable(GL_DEPTH_TEST);
//ENABLED VERTEX ARRAYS AND TEXTURE COORDINATE ARRAYS
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
//ENABLED 2D TEXTURING
glEnable ( GL_TEXTURE_2D );
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//seed random
srand(time(NULL));
return( TRUE );
}
I have initialization, resize and draw functions that are called by a QGLWidget (which is itself just a skeleton that calls the real work functions)
The texture loading function:
GLuint LoadGLTextures( const char * name )
{
//unformatted QImage
QImage img;
//load the image from a .qrc resource
if(!img.load(":/star.bmp"))
{
qWarning("ERROR LOADING IMAGE");
}
//an OpenGL formatted QImage
QImage GL_formatted_image;
GL_formatted_image = QGLWidget::convertToGLFormat(img);
//error check
if(GL_formatted_image.isNull())
qWarning("IMAGE IS NULL");
else
qWarning("IMAGE NOT NULL");
//texture ID
GLuint _textures[1];
//enable texturing
glEnable(GL_TEXTURE_2D);
//generate textures
glGenTextures(1,&_textures[0]);
//bind the texture
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//generate texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GL_formatted_image.width(),
GL_formatted_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
GL_formatted_image.bits());
glBindTexture(GL_TEXTURE_2D,_textures[0]);
//return the texture ID
return _textures[0];
}
Here's the draw code:
//this does draw
//get the texture ID
GLuint tex_id = LoadGLTextures(":/star.png");
glBindTexture(GL_TEXTURE_2D, tex_id); // Actually have an array of images
glColor3f(1.0f, 0.0f, 0.5f);
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f);glVertex2f(1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);glVertex2f(0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);glVertex2f(0.0f, 0.0f);
glEnd();
//this does not draw
//translations code
glLoadIdentity();
glTranslatef(-1.0f, 0.0f, 0.0f);
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
//set color state
glColor4f(0.0f, 1.0f, 0.0f, 0.5);
//vertices to be rendered
static GLfloat vertices[] =
{
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
static GLshort coord_Data[] =
{
1, 0,
1, 1,
0, 1,
0, 0
};
//bind the texture
glBindTexture(GL_TEXTURE_2D, tex_id);
//pointer to the vertex array
glVertexPointer(2, GL_FLOAT, 0, vertices);
//texture coordinate pointer
glTexCoordPointer(2, GL_SHORT, 0, coord_Data);
//draw the arrays
glDrawArrays(GL_QUADS, 0, 4);
Thanks for all help,
Dragonwrenn
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种可能性是问题源于在调用 glTexCoordPointer 之前调用 glVertexCoordPointer。当您在顶点坐标之后指定纹理坐标时,会发生奇怪的事情。我知道对于使用纹理坐标绘制单个顶点来说这是正确的。我不确定数组是否正确。
其他一些事情...
您尝试过使用 QPixMap 而不是 QImage 吗?我怀疑这就是您问题的答案,因为听起来纹理已正确应用于第一个四边形。
有两次对bindTexture 的调用。
您是否尝试过在代码的第二部分中仅绘制顶点(没有纹理)?
最后,您收到任何编译器警告吗?
One possibility is that the problem stems from calling glVertexCoordPointer before calling glTexCoordPointer. Weird things happen when you specify the texture coordinate after the vertex coordinate. I know this is true for drawing a single vertex with a texture coordinate. I'm not sure if it's true with arrays.
A few other things...
Have you tried using QPixMap instead of QImage? I doubt this is the answer to your problem since it sounds like the texture is applied to the first quad properly.
There are two calls to bindTexture.
Have you tried just drawing the vertices (without the texture) in the second part of the code?
Finally, do you get any compiler warnings?
您放置 OpenGL 状态操作的方式很难跟踪事物。按需设置 OpenGL 状态是个好主意。因此,
将其移到
前面
,您还应该从
initGL
中移动其他代码。属于纹理加载器,在向glTexImage提供数据之前:
属于绘图函数的开始:
按照方案,您应该在绘图函数中设置视口和投影矩阵, 也。我只是这么说,因为大多数教程的做法都不同,这会欺骗人们认为这是正确的方法。从技术上讲,投影和视口以及点播状态也是如此。
您不应该在每次绘制调用时重新加载纹理。请注意,通过绘图处理程序按需初始化纹理是一个好主意,您应该向纹理封装类添加一些标志,以告知引用的纹理是否已可用于 OpenGL。
仅出于调试目的,尝试将纹理坐标的类型更改为浮点数。
The way you place your OpenGL state manipulations, it is difficult to keep track of things. It's a good idea to set OpenGL state on demand. So
Move this
right before
also you should move the other code from
initGL
.Belonging into the texture loader, before supplying the data to glTexImage:
Belonging to the beginning of the drawing function:
Following the scheme you should set viewport and projection matrices in the drawing function, too. I'm just telling this, because most of the tutorials do it differently, which tricks people into thinking this was the right way. Technically projection and viewport and on-demand-states as well.
You should not re-load the texture with every draw call. Note that initializing the texture on demand through the drawing handler is a good idea, you should just add some flag to the texture encapsulating class telling, if the referenced texture is already available to OpenGL.
Just for debugging purposes try changing the type of the texture coordinates to floats.