QOpenGLWidget纹理映射导致黑屏

Posted

技术标签:

【中文标题】QOpenGLWidget纹理映射导致黑屏【英文标题】:QOpenGLWidget Texture Mapping results in Black screen 【发布时间】:2016-04-14 15:48:32 【问题描述】:

我正在尝试使用 QOpenGLWidget 使用四边形作为纹理来渲染简单的 2d 图像。但无论我尝试什么,我总是得到一个黑匣子。

我已经阅读了很多教程,我有一个像这样的简单像素缓冲区

uchar* m_pData;

存储我的 RGB 值。这是有效的,因为我已经用glDrawPixles() 对其进行了测试。我将发布考虑到 OpenGLWidget 的三个最重要的功能。

首先初始化GL():

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!");



然后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();

    


最后但同样重要的是 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);


我正在使用 Qt5.6 和 Microsoft Visual Studio 2015 编译器。

【问题讨论】:

【参考方案1】:

该死,问题出在

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

我的成员变量m_orgiWm_orgiH 被初始化为0。我的代码不起作用,这并不奇怪。

作为记录,我将发布我的运行代码,QOpenGLWidget 的三个最重要的功能,希望它对遇到同样问题的人有用。

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

现在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();



还有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);


【讨论】:

以上是关于QOpenGLWidget纹理映射导致黑屏的主要内容,如果未能解决你的问题,请参考以下文章

我的渲染技术进阶之旅解决显示3D模型时因为使用stb_image库或者opencv库加载纹理时未翻转y轴导致模型纹理映射出错的问题

opengl 把纹理映射到立方体的六个面。

OpenGL纹理映射总结

FBO:渲染到纹理,绘制渲染纹理时纹理映射错误

OpenGL_Qt学习笔记之_05(纹理映射)(转)

计算机图形学-纹理映射计算重心坐标UV插值双线性插值MipMap