我最近选择了Qt并在OpenGL中使用它 但事情是,当我将SDL代码移动到Qt并更改纹理代码以使用QImage时,它会停止工作。
图像确实正确加载,如错误检查代码所示。
谢谢!
P.S:请不要建议我使用glDrawPixels,我需要解决手头的问题。其中一些原因是1.慢2.安卓(这个代码可能最终运行)是OpenGL ES并且不支持glDrawPixels
以下是代码:
//original image
QImage img;
if(!img.load(":/star.png"))
{
//loads correctly
qWarning("ERROR LOADING IMAGE");
}
//array for holding texture ID
GLuint texture[1];
//get the OpenGL-friendly image
QImage GL_formatted_image;
GL_formatted_image = QGLWidget::convertToGLFormat(img);
//make sure its not null
if(GL_formatted_image.isNull())
qWarning("IMAGE IS NULL");
else
qWarning("IMAGE NOT NULL");
//generate the texture name
glGenTextures(1, texture);
//bind the texture ID
glBindTexture(GL_TEXTURE_2D, texture[0]);
//generate the 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() );
//texture parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//draw the texture
glPushMatrix();
glTranslatef(-2.0f, 0.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLES);
glVertex2f(1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(0.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glEnd();
glPopMatrix();
这是SDL的原始纹理加载函数:
GLuint loadTexturewithSDL(const char* FILE, GLenum texture_format)
{
GLuint texture; // This is a handle to our texture object
SDL_Surface *surface; // This surface will tell us the details of the image
GLint nOfColors;
if ( (surface = SDL_LoadBMP(FILE)) ) {
// Check that the image's width is a power of 2
if ( (surface->w & (surface->w - 1)) != 0 ) {
printf("warning: image's width is not a power of 2\n");
}
// Also check if the height is a power of 2
if ( (surface->h & (surface->h - 1)) != 0 ) {
printf("warning: image's height is not a power of 2\n");
}
// get the number of channels in the SDL surface
nOfColors = surface->format->BytesPerPixel;
if (nOfColors == 4) // contains an alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
} else if (nOfColors == 3) // no alpha channel
{
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
} else {
printf("warning: the image is not truecolor.. this will probably break\n");
// this error should not go unhandled
}
// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &texture );
// Bind the texture object
glBindTexture( GL_TEXTURE_2D, texture );
// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels );
}
else {
printf("SDL could not load image %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
// Free the SDL_Surface only if it was successfully created
if ( surface ) {
SDL_FreeSurface( surface );
}
return texture;
}
答案 0 :(得分:6)
我有类似的代码,但使用 glTexSubImage2D :
void Widget::paintGL()
{
glClear (GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,win.width(),0,win.height());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0 , image.width(), image.height(), glFormat, glType, image.bits() );
glBegin(GL_QUADS); // in theory triangles are better
glTexCoord2i(0,0); glVertex2i(0,win.height());
glTexCoord2i(0,1); glVertex2i(0,0);
glTexCoord2i(1,1); glVertex2i(win.width(),0);
glTexCoord2i(1,0); glVertex2i(win.width(),win.height());
glEnd();
glFlush();
}
void Widget::initializeGL()
{
glClearColor (0.0,0.0,0.0,1.0);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,win.width(),0,win.height());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glGenTextures(3,&texture);
glBindTexture(GL_TEXTURE_2D,texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, image.width(), image.height(), 0, glFormat, glType, NULL );
glDisable(GL_TEXTURE_2D);
}
在ctor中进行了一些性能调整
void Widget::setDisplayOptions()
{
glFormat = GL_RGB; // QImage RGBA is BGRA
glType = GL_UNSIGNED_BYTE;
QGL::setPreferredPaintEngine(QPaintEngine::OpenGL2);
QGLFormat glFmt;
glFmt.setSwapInterval(1); // 1= vsync on
glFmt.setAlpha(GL_RGBA==glFormat);
glFmt.setRgba(GL_RGBA==glFormat);
glFmt.setDoubleBuffer(true); // default
glFmt.setOverlay(false);
glFmt.setSampleBuffers(false);
QGLFormat::setDefaultFormat(glFmt);
setAttribute(Qt::WA_OpaquePaintEvent,true);
setAttribute(Qt::WA_PaintOnScreen,true);
}
答案 1 :(得分:6)
这是我从Qt转换为GL的解决方案 这也可以反过来,几乎没有变化; 干杯 - 大门
void Image::Convert32bitARGBtoRGBA()
{
if(!isQtImage()) return;
QImage& q = *(m_data->image);
U32 count=0, max=(U32)(q.height()*q.width());
U32* p = (U32*)(q.bits());
U32 n;
while( count<max )
{
n = p[count]; //n = ARGB
p[count] = 0x00000000 |
((n<<8) & 0x0000ff00) |
((n<<8) & 0x00ff0000) |
((n<<8) & 0xff000000) |
((n>>24) & 0x000000ff);
// p[count] = RGBA
count++;
}
}
void Image::Convert32bitRGBAtoARGB()
{
if(!isQtImage()) return;
QImage& q = *(m_data->image);
U32 count=0, max=(U32)(q.height()*q.width());
U32* p = (U32*)(q.bits());
U32 n;
while( count<max )
{
n = p[count]; //n = RGBA
p[count] = 0x00000000 |
((n>>8) & 0x000000ff) |
((n>>8) & 0x0000ff00) |
((n>>8) & 0x00ff0000) |
((n<<24) & 0xff000000);
// p[count] = ARGB
count++;
}
}
答案 2 :(得分:4)
看起来您的问题不在这里,因为我对以下代码没有任何问题。 您应该检查GL初始化和显示设置。
你在某处有一个glEnable(GL_TEXTURE_2D)吗?
另请注意,glTexCoord2f必须在glVertex2f之前。
#include <GL/glut.h>
#include <QtOpenGL/qgl.h>
#include <iostream>
GLuint texture[1] ;
void LoadGLTextures( const char * name )
{
QImage img;
if( ! img.load( name ) )
{
std::cerr << "error loading " << name << std::endl ;
exit( 1 );
}
QImage GL_formatted_image;
GL_formatted_image = QGLWidget::convertToGLFormat(img);
if( GL_formatted_image.isNull() )
{
std::cerr << "error GL_formatted_image" << std::endl ;
exit( 1 );
}
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
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() );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
void resize(int Width, int Height)
{
glViewport( 0 , 0 , Width , Height );
}
void draw()
{
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f);
glClear( GL_COLOR_BUFFER_BIT );
gluOrtho2D( -1 , 1 , -1 , 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glShadeModel( GL_FLAT );
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_TRIANGLES);
glTexCoord2f( 1.0f, 0.0f);
glVertex2f( 1.0f, 0.0f);
glTexCoord2f( 0.0f, 1.0f);
glVertex2f( 0.0f, 1.0f);
glTexCoord2f( 0.0f, 0.0f);
glVertex2f( 0.0f, 0.0f);
glEnd();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA );
glutInitWindowSize(640, 480);
glutCreateWindow("Texture");
LoadGLTextures( "star.png" );
glutDisplayFunc( & draw );
glutReshapeFunc( & resize );
glutMainLoop();
return 1;
}