2011-03-17 72 views
9

我最近選擇了Qt,並將其與OpenGL一起使用 但是,將我的SDL代碼移動到Qt並更改紋理代碼以使用QImage時,它停止工作。在OpenGL中使用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; 
} 
+2

請問您是否可以詳細說明「停止」工作的含義?紋理不再顯示?你是否改變了'glTexImage2D'的任何參數,除了明顯的'GL_formatted_image.xxx'?您的圖像是否提供alpha通道,即RGBA? – Thomas 2011-03-17 07:43:46

+0

將GL_RGBA更改爲GL_RGB給出了相同的結果 通過停止工作,我的意思是紋理不顯示 – Prime 2011-03-17 18:55:10

+0

是您發佈的代碼的第一部分的代碼?你的繪製循環如何看起來像? 也請檢查fa的帖子,看看你是否以類似的方式進行了初始化。 – Thomas 2011-03-17 22:45:33

回答

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); 
} 

而且在構造函數的幾個性能比較調整

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);   
} 
+0

你在繪畫功能中做得太多。沒有必要設置投影/視圖矩陣。它只能在調整大小功能中完成。還有,每次重繪都會向GPU發送數據。 – 2014-04-14 09:21:40

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; 
} 
+0

你在幾個地方缺少'glEnable(GL_TEXTURE_2D);'和'glDisable(GL_TEXTURE_2D);',但這個建議比其他答案更優越。 – 2014-04-14 09:37:17

+0

另外,小心圖像,誰的尺寸是非2的力量 – 2014-04-14 11:08:38

6

這是我從Qt來轉換解決方案GL 這也可以以相反的方式工作,只需很少的改變; 歡呼聲 - Daimon

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++; 
    } 
} 
+3

或者使用'QImage :: rgbSwapped()'? – Dreiven 2013-12-11 16:51:14

+0

@Diveiven:不,rgbSwapped()將ARGB轉換爲ABGR。 – RyanCu 2016-02-04 08:53:59