opengl 3 qt渲染空白屏幕

Posted

技术标签:

【中文标题】opengl 3 qt渲染空白屏幕【英文标题】:opengl 3 qt rendering blank screen 【发布时间】:2016-06-14 08:19:56 【问题描述】:

我是 OpenGL 新手。我正在使用 OpenGL 3 和 QT5 来最终渲染类似地形的我的世界。到目前为止,我只尝试渲染一个立方体,但我一直得到一个空白屏幕。我正在关注本教程系列:https://www.youtube.com/playlist?list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY,这是代码:

glwindow.h:

#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_3_Core>


class glWiwndow : public QOpenGLWidget,
                  protected QOpenGLFunctions_4_3_Core

protected:
    void sendDataToOpenGL();
    void installShaders();
    QString readShaderCode(const QString fileName);
    void initializeGL();
    void paintGL();
    void teardownGL();
public:

;

顶点.h:

#pragma once
#include <glm\glm.hpp>

struct Vertex

    glm::vec3 position;
    glm::vec3 color;
    glm::vec3 normal;
;

shapedata.h:

#pragma once
#include <QOpenGLShaderProgram>
#include"vertex.h"

struct shapeData

    shapeData() :
        vertices(0), numVertices(0),
        indices(0), numIndices(0) 
    Vertex* vertices;
    GLuint numVertices;
    GLushort* indices;
    GLuint numIndices;
    GLsizeiptr vertexBufferSize() const
    
        return numVertices * sizeof(Vertex);
    
    GLsizeiptr indexBufferSize() const
    
        return numIndices * sizeof(GLushort);
    
    void cleanup()
    
        delete [] vertices;
        delete [] indices;
        numVertices = numIndices = 0;
    
;

shapegenerator.h:

#include"shapedata.h"
class ShapeGenerator

public:
    ShapeGenerator();
    static shapeData makeTriangle();
    static shapeData makeCube();
;

glwindow.cpp:

#include "glwindow.h"
#include"shapegenerator.h"
#include<iostream>
#include <QDebug>
#include <QString>
#include <QOpenGLShaderProgram>
#include<QMessageBox>
#include<QStringList>
#include <QMatrix4x4>
#include<QFile>
#include "glm\gtc\matrix_transform.hpp"
#include "glm\gtx\transform.hpp"
using glm::mat4;
using glm::vec3;


GLint  programID;
GLuint numIndices;

QString  glWiwndow::readShaderCode(const QString  fileName)

    QFile file(fileName);
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) 
        return NULL;
     

     QByteArray total;
     QByteArray line;
     while (!file.atEnd()) 
        line = file.read(1024);
        total.append(line);
     

     return QString(total);




void glWiwndow::installShaders()

    GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    const GLchar * adapter[1];
    QString temp = readShaderCode(":/vertexshader.vert");
    adapter[0] = temp.toStdString().c_str();
    glShaderSource(vertexShaderID,1,adapter,0);
    temp = readShaderCode(":/fragmentshader.frag");
    adapter[0] = temp.toStdString().c_str();
    glShaderSource(fragmentShaderID,1,adapter,0);
    //cout<<"here";
    glCompileShader(vertexShaderID);
    //cout<<"yoo";
    glCompileShader(fragmentShaderID);


    GLuint programID = glCreateProgram();
    glAttachShader(programID,vertexShaderID);
    glAttachShader(programID,fragmentShaderID);

    glLinkProgram(programID);

    glUseProgram(programID);



void glWiwndow :: initializeGL()
    // Initialize OpenGL Backend
    initializeOpenGLFunctions();
    connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(teardownGL()), Qt::DirectConnection);
    glEnable(GL_DEPTH_TEST);

    shapeData cube = ShapeGenerator::makeCube();


    GLuint myBufferID;
    glGenBuffers(1,&myBufferID);
    glBindBuffer(GL_ARRAY_BUFFER,myBufferID);
    glBufferData(GL_ARRAY_BUFFER,cube.vertexBufferSize(),cube.vertices,GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(float)*6,0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(float)*6,(char*)(sizeof(float)*3));

    GLuint indexArrayBufferID;
    glGenBuffers(1,&indexArrayBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indexArrayBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,cube.indexBufferSize(),cube.indices,GL_STATIC_DRAW);
    numIndices = cube.numIndices;

    installShaders();




void glWiwndow :: paintGL()

    glClearColor(0.0f,0.0f,0.0f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glViewport(0,0,width(),height());


    mat4 modelTransformMatrix = glm::translate(mat4(),vec3(0.0f,0.0f,-3.0f));
    mat4 projectionMatrix = glm::perspective(60.0f, ((float)width()) / height(), 0.1f, 20.0f);

    GLint modelTransformMatrixUniformLocation = glGetUniformLocation(programID,"modelTransformMatrix");

    GLint projectionMatrixUniformLocation = glGetUniformLocation(programID,"projectionMatrix");

    glUniformMatrix4fv(modelTransformMatrixUniformLocation,1,GL_FALSE,&modelTransformMatrix[0][0]);

    glUniformMatrix4fv(projectionMatrixUniformLocation,1,GL_FALSE,&projectionMatrix[0][0]);


    glDrawElements(GL_TRIANGLES,numIndices,GL_UNSIGNED_SHORT,0);



void glWiwndow::teardownGL()



shapegenerator.cpp:

#include "ShapeGenerator.h"
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <vertex.h>
using glm::vec3;
using glm::mat4;
using glm::mat3;
#define NUM_ARRAY_ELEMENTS(a) sizeof(a) / sizeof(*a)

glm::vec3 randomColor()

    glm::vec3 ret;
    ret.x = rand() / (float)RAND_MAX;
    ret.y = rand() / (float)RAND_MAX;
    ret.z = rand() / (float)RAND_MAX;
    return ret;


shapeData ShapeGenerator::makeTriangle()

    shapeData ret;

    Vertex verts[] =
    
        glm::vec3(+0.0f, +1.0f, +0.0f),
        glm::vec3(+0.0f, +1.0f, +0.0f),


        glm::vec3(-1.0f, -1.0f, +0.0f),
        glm::vec3(+0.0f, +1.0f, +0.0f),


        glm::vec3(+1.0f, -1.0f, +0.0f),
        glm::vec3(+0.0f, +0.0f, +1.0f),

    ;
    ret.numVertices = NUM_ARRAY_ELEMENTS(verts);
    ret.vertices = new Vertex[ret.numVertices];
    memcpy(ret.vertices, verts, sizeof(verts));

    GLushort indices[] =  0, 1, 2 ;
    ret.numIndices = NUM_ARRAY_ELEMENTS(indices);
    ret.indices = new GLushort[ret.numIndices];
    memcpy(ret.indices, indices, sizeof(indices));

    return ret;


shapeData ShapeGenerator::makeCube() 
    shapeData ret;
    Vertex stackVerts[] =
    
        vec3(-1.0f, +1.0f, +1.0f),  // 0
        vec3(+1.0f, +0.0f, +0.0f),  // Color

        vec3(+1.0f, +1.0f, +1.0f),  // 1
        vec3(+0.0f, +1.0f, +0.0f),  // Color

        vec3(+1.0f, +1.0f, -1.0f),  // 2
        vec3(+0.0f, +0.0f, +1.0f),  // Color

        vec3(-1.0f, +1.0f, -1.0f),  // 3
        vec3(+1.0f, +1.0f, +1.0f),  // Color


        vec3(-1.0f, +1.0f, -1.0f),  // 4
        vec3(+1.0f, +0.0f, +1.0f),  // Color

        vec3(+1.0f, +1.0f, -1.0f),  // 5
        vec3(+0.0f, +0.5f, +0.2f),  // Color

        vec3(+1.0f, -1.0f, -1.0f),  // 6
        vec3(+0.8f, +0.6f, +0.4f),  // Color

        vec3(-1.0f, -1.0f, -1.0f),  // 7
        vec3(+0.3f, +1.0f, +0.5f),  // Color


        vec3(+1.0f, +1.0f, -1.0f),  // 8
        vec3(+0.2f, +0.5f, +0.2f),  // Color

        vec3(+1.0f, +1.0f, +1.0f),  // 9
        vec3(+0.9f, +0.3f, +0.7f),  // Color

        vec3(+1.0f, -1.0f, +1.0f),  // 10
        vec3(+0.3f, +0.7f, +0.5f),  // Color

        vec3(+1.0f, -1.0f, -1.0f),  // 11
        vec3(+0.5f, +0.7f, +0.5f),  // Color


        vec3(-1.0f, +1.0f, +1.0f),  // 12
        vec3(+0.7f, +0.8f, +0.2f),  // Color

        vec3(-1.0f, +1.0f, -1.0f),  // 13
        vec3(+0.5f, +0.7f, +0.3f),  // Color

        vec3(-1.0f, -1.0f, -1.0f),  // 14
        vec3(+0.4f, +0.7f, +0.7f),  // Color

        vec3(-1.0f, -1.0f, +1.0f),  // 15
        vec3(+0.2f, +0.5f, +1.0f),  // Color


        vec3(+1.0f, +1.0f, +1.0f),  // 16
        vec3(+0.6f, +1.0f, +0.7f),  // Color

        vec3(-1.0f, +1.0f, +1.0f),  // 17
        vec3(+0.6f, +0.4f, +0.8f),  // Color

        vec3(-1.0f, -1.0f, +1.0f),  // 18
        vec3(+0.2f, +0.8f, +0.7f),  // Color

        vec3(+1.0f, -1.0f, +1.0f),  // 19
        vec3(+0.2f, +0.7f, +1.0f),  // Color


        vec3(+1.0f, -1.0f, -1.0f),  // 20
        vec3(+0.8f, +0.3f, +0.7f),  // Color

        vec3(-1.0f, -1.0f, -1.0f),  // 21
        vec3(+0.8f, +0.9f, +0.5f),  // Color

        vec3(-1.0f, -1.0f, +1.0f),  // 22
        vec3(+0.5f, +0.8f, +0.5f),  // Color

        vec3(+1.0f, -1.0f, +1.0f),  // 23
        vec3(+0.9f, +1.0f, +0.2f),  // Color

    ;

    ret.numVertices = NUM_ARRAY_ELEMENTS(stackVerts);
    ret.vertices = new Vertex[ret.numVertices];
    memcpy(ret.vertices, stackVerts, sizeof(stackVerts));

    unsigned short stackIndices[] = 
        0,   1,  2,  0,  2,  3, // Top
        4,   5,  6,  4,  6,  7, // Front
        8,   9, 10,  8, 10, 11, // Right
        12, 13, 14, 12, 14, 15, // Left
        16, 17, 18, 16, 18, 19, // Back
        20, 22, 21, 20, 23, 22, // Bottom
    ;
    ret.numIndices = NUM_ARRAY_ELEMENTS(stackIndices);
    ret.indices = new GLushort[ret.numIndices];
    memcpy(ret.indices, stackIndices, sizeof(stackIndices));

    return ret;

main.cpp:

#include "glwindow.h"
#include <QApplication>

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    glWiwndow w;
    w.show();

    return a.exec();

顶点着色器代码:(vertexshader.vert)

#version 430
layout(location = 0) in vec3 position;
layout(location=1) in vec3 vertexColor;
uniform mat4 modelTransformMatrix;
uniform mat4 projectionMatrix;
out vec3 theColor;
void main()

  vec4 v = vec4(position,1.0);
  vec4 newPosition = modelTransformMatrix * v;
  vec4 projectedPosition = projectionMatrix * newPosition;
  gl_Position = projectedPosition;
  theColor = vertexColor;

片段着色器代码:(fragmentshader.frag)

#version 430
out highp vec4 fColor;
in vec3 theColor; 
void main()

   fColor =vec4(theColor,1.0);

【问题讨论】:

至少glVertexAttribPointer的步幅是错误的。您的顶点结构有 9 个浮点数,而不是 6 个。您是否检查过着色器编译和链接是否成功? 您好,谢谢您的回复,是的,着色器编译和链接已经成功。我的顶点结构确实有 9 个浮点数,但到目前为止我只使用了 6 个浮点数,我没有使用法线还没有。 您在 makeTriangle 和 makeCube 中初始化顶点数组的方式可能与您期望的不太一样。即,我认为 makeTriangle 将返回一个 shapeData 结构,其中 numVertices 设置为 2。 我尝试手动设置 NumVertices(在 makeCube 中设置为 144)但没有任何变化,我仍然得到一个空白屏幕。 您目前仅使用 6 个浮点数,但您仍然为每个顶点上传其中的 9 个到缓冲区。步幅告诉 OpenGL 连续顶点的起点彼此相距多少字节。因此,如果您为每个顶点上传 9 个浮点数,则 vertex[i+1] 将在 vertex[i] 之后开始 9 个浮点数。 【参考方案1】:

问题在于programID,但不是因为我在评论中概述的原因。目前你有一个全球可验证...

GLint  programID;

但是在glWiwndow::installShaders 你有...

GLuint programID = glCreateProgram();

因此,您的代码使用本地范围的programID 调用glUseProgram,但随后在glWiwndow::paintGL 中,您将未初始化的全局programID 传递给glGetUniformLocation,它返回-1 表示失败。您确实需要在 GL 中检查这些类型的错误。

【讨论】:

以上是关于opengl 3 qt渲染空白屏幕的主要内容,如果未能解决你的问题,请参考以下文章

具有独特着色器的 OpenGL 多次绘制调用会产生空白屏幕

用 D 语言用 OpenGL 3 渲染一个简单的矩形

Qt OpenGL 渲染文本问题 QGLWidget

Qt 5.1.1 和 OpenGL - 渲染速度

OpenGL 显示空白屏幕

Opengl:2d HUD 超过 3D