Search code examples
c++qtopengltexture-mapping

QOpenGLWidget Texture Mapping results in Black screen


I am trying to render a simple 2d Image with the QOpenGLWidget using a quad as a texture. But no matter what I am trying, I always get a black box.

I have read many tutorials, I have a simple pixelbuffer like this

uchar* m_pData;

which stores my RGB values. This is valid, since I have it tested with glDrawPixles(). I will post the three most important functions considering the OpenGLWidget.

initializeGL() first:

void QGLImageviewer::initializeGL()
{
initializeOpenGLFunctions();

// Clear the color
float r = ((float)m_backColor.darker().red())/255.0f;
float g = ((float)m_backColor.darker().green())/255.0f;
float b = ((float)m_backColor.darker().blue())/255.0f;
glClearColor(r,g,b,1.0f);

// Set shading model.
glShadeModel(GL_SMOOTH);

// Set the viewport
glViewport(0.f, 0.f, m_origW, m_origH);

// Init. Projection Matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, m_origW, m_origH,0.0,1.0,-1.0);

// Init Modelview Matrix
glClearColor(0.f, 0.f, 0.f, 1.f);

// Enable texturing
glEnable(GL_TEXTURE_2D);


// Generate texture ID
glGenTextures(1, &m_textureID);

// Bind texture ID
glBindTexture(GL_TEXTURE_2D, m_textureID);

// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

// Generate Texture, and assign pixles to our texture ID 
if (m_pData != nullptr)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_origW, m_origH, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)m_pData);
}
else
{
    qCritical("Buffer is empty!!");
}

// Unbind texture
glBindTexture(GL_TEXTURE_2D, NULL);

// Check for Error
GLenum error_ = glGetError();
if (error_ != GL_NO_ERROR)
{
    qCritical("Error Loading Texture!");
}

}

Then paintGL():

void QGLImageviewer::paintGL()
{
makeCurrent();

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// Clear Screen And Depth Buffer
glClear(GL_COLOR_BUFFER_BIT);

if (!(m_renderQtImg->isNull()))
{
    //QImage image;

    int imWidth = m_renderQtImg->width();
    int imHeight = m_renderQtImg->height();

    // The image has to be resized to fit the widget
    if (imWidth != this->size().width() &&
        imHeight != this->size().height())
    {

        imWidth = this->size().width();
        imHeight = this->size().height();
    }
    else
    {
        //image = *m_renderQtImg;

        imWidth = m_origW;
        imHeight = m_origH;
    }

    if (m_textureID != 0)
    {
        glMatrixMode(GL_MODELVIEW);
        // Remove any previous transformations
        glLoadIdentity();

        glPushMatrix();

        // Move to rendering point
        glTranslatef(0.f, 0.f, 0.f);
        glColor3f(0.0f, 0.0f, 0.5f);

        // Set texture ID
        glBindTexture(GL_TEXTURE_2D, m_textureID);

        glBegin(GL_QUADS);
        glTexCoord2f(0.f, 0.f); glVertex2f(0.f, 0.f);
        glTexCoord2f(1.f, 0.f); glVertex2f(imWidth, 0.f);
        glTexCoord2f(1.f, 1.f); glVertex2f(imWidth, imHeight);
        glTexCoord2f(0.f, 1.f); glVertex2f(0.f, imHeight);
        glEnd();

        //glDisable(GL_TEXTURE_2D);
        glPopMatrix();
        glFlush();

    }
}
}

And last but not least resizeGL():

void QGLImageviewer::resizeGL(int width, int height)
{
makeCurrent();
glViewport(0,0,(GLint)width,(GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluOrtho2D(0.0, width, 0.0, height);
glOrtho(0.0, width, 0.0, height, 0.0, 1.0);

}

I am using Qt5.6 and the Microsoft Visual Studio 2015 compiler.


Solution

  • Damn, the problem was on

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_origW  , m_origH, 0, GL_RGB, GL_UNSIGNED_BYTE, (float*)m_pData);
    

    My member variables m_orgiW and m_orgiH were initialized to 0. So quite unsurprising that my code did not work.

    For the record I will post my running code, the three most important functions of the QOpenGLWidget, hope that it will be useful to somebody with the same issue.

    void QGLImageviewer::initializeGL()
    {
    initializeOpenGLFunctions();
    
    float r = ((float)m_backColor.darker().red())/255.0f;
    float g = ((float)m_backColor.darker().green())/255.0f;
    float b = ((float)m_backColor.darker().blue())/255.0f;
    glClearColor(r,g,b,1.0f);
    
    // Generate texture ID
    glGenTextures(1, &m_textureID);
    
    // Bind texture ID
    glBindTexture(GL_TEXTURE_2D, m_textureID);
    
    if (m_pData != nullptr)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_origW  , m_origH, 0, GL_RGB, GL_UNSIGNED_BYTE, (float*)m_pData);
    }
    else
    {
        qCritical("Buffer is empty!!");
    }
    
    // Set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //IMPORTANT FOR NON POWER OF 2 TEXTURES
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    // Enable texturing Mapping
    glEnable(GL_TEXTURE_2D);
    
    // Enable Smooth Shading
    glShadeModel(GL_SMOOTH);
    
    // Black Background
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    
    // Depth Buffer Setup
    glClearDepth(1.0f);
    
    // Enables Depth Testing
    glEnable(GL_DEPTH_TEST);
    
    // Type of depth testing to do
    glDepthFunc(GL_LEQUAL);
    
    // Really Nice Perspective Calculations
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    
    // Unbind Texture
    glBindTexture(GL_TEXTURE_2D, NULL);
    }
    

    Now paintGL()

    void QGLImageviewer::paintGL()
    {
    makeCurrent();
    
    // Clear Screen And Depth Buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, m_textureID);
    
    glBegin(GL_QUADS);
    // Drawing the quad with the texture mapped on it
    //
    // OpenGL 2D Coordinates 
    // Sticking with the Coordinate Convention mentioned here
    glTexCoord2f(1.0f, 0.0f); glVertex2f(m_width, 0.0f); // vertex 1
    glTexCoord2f(1.0f, 1.0f); glVertex2f(m_width, m_height); // vertex 2
    glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, m_height); // vertex 3
    glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // vertex 4
    
    glEnd();
    
    
    }
    

    And resizeGL()

    void QGLImageviewer::resizeGL(int width, int height)
    {
    makeCurrent();
    
    m_width = width;
    m_height = height;
    
    // Compute aspect ratio of the new window
    if (height == 0) height = 1;                // To prevent divide by 0
    GLfloat aspect = (GLfloat)width / (GLfloat)height;
    
    // Set the viewport to cover the new window
    glViewport(0, 0, width, height);
    
    // Set the aspect ratio of the clipping area to match the viewport
    glMatrixMode(GL_PROJECTION);  // To operate on the Projection matrix
    glLoadIdentity();             // Reset the projection matrix
    
    glOrtho(0, m_width/ m_zoomFactor, m_height/ m_zoomFactor,0, -1, 1);
    
    }