QT OpenGL,glDrawElements和glDrawArray只显示空白屏幕

时间:2016-08-23 06:06:20

标签: c++ qt opengl

我正在使用Qt(5.6.0)与Qt中的界面和OpenGL中的游戏场景(3D地图,角色,怪物......)制作一个地下城爬虫/流氓。视图是一个提升的QWidget,我可以使用旧的glBegin / glEnd方法进行绘制,但每当我尝试使用glDrawArrays或glDrawElements时,我都会得到一个空白屏幕。

清晰的颜色正在工作,并且设置为比黑色略亮,因此应显示黑色形状。我使用glBegin / glEnd方法测试相同的顶点,它确实渲染它应该。我已经尝试了一种或多或少直接的OpenGL方法,如Jamie King所示,通过几个示例和教程,最后以this example结束,以便使用QOpenGLShaderProgram和QOpenGLVertexArrayObject对象以及QOpenGLShaderProgram Qt doc中的示例。目前,initializeGL函数中的着色器代码阻止了绘制glBegin / glEnd三角形。

当前代码:

oglwidget.cpp:

#include "GL/glew.h"
#include "GL/glext.h"
#include "oglwidget.h"
#include "general.h"

#define BUFFER_OFFSET(bytes) ((GLubyte*) NULL + (bytes))

extern const char * vertexShader;
extern const char * fragmentShader;

OGLWidget::OGLWidget(QWidget *parent): QOpenGLWidget(parent){

}

OGLWidget::~OGLWidget(){

}

void OGLWidget::initializeGL(){
    QOpenGLFunctions gl;
    gl.initializeOpenGLFunctions();
    cout<<"Init"<<endl;
    //-----Create Shader
    shader2.create();
    shader2.addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShader);
    shader2.addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShader);
    shader2.link();
    shader2.bind();
    int vertexLocation = shader2.attributeLocation("vertex");
    int matrixLocation = shader2.uniformLocation("matrix");
    int colorLocation = shader2.uniformLocation("color");
    QMatrix4x4 pmvMatrix;
    pmvMatrix.ortho(rect());
    QColor color(0, 255, 0, 255);

    shader2.enableAttributeArray(vertexLocation);
    shader2.setAttributeArray(vertexLocation, verts, 3);
    shader2.setUniformValue(matrixLocation, pmvMatrix);
    shader2.setUniformValue(colorLocation, color);

    //-----Create VAO2
    VAO2=new QOpenGLVertexArrayObject(this);
    VAO2->create();
    VAO2->bind();
    //-----Create VBO2
    VBO2.create();
    VBO2.setUsagePattern(QOpenGLBuffer::StaticDraw);
    VBO2.bind();
    VBO2.allocate(verts,sizeof(verts));
}

void OGLWidget::paintGL(){
    cout<<"Painting"<<endl;
    QOpenGLFunctions gl;
    gl.initializeOpenGLFunctions();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.05,0.05,0.05,1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0f,0.0f,-2.0f);

    //draw();
    shader2.bind();
    VAO2->bind();
    glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_INT,inds);
    VAO2->release();
}


void OGLWidget::resizeGL(int w, int h){
    cout<<"Resizing"<<endl;
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //glFrustum (-1.0, 1.0, -1.0, 1.0, 1, 1000.0); //-----Assuming this is right?
    glOrtho(-5,5,-5,5,-5,5);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
int OGLWidget::loadModel(string path){
    //-----loads the model path if not already loaded, returns the index of the model
    //---check if already loaded
    for(int p=0;p<loadedPaths.size();p++){
        if(!loadedPaths[p].compare(path)){
            return p;
        }
    }
    loadedPaths.push_back(path);
    //-----continue with path loading
    Model m;
    m.loadModel(path);
    return loadedPaths.size()-1;
}

void OGLWidget::draw(){
    cout<<"drawing..."<<endl;
    glBegin(GL_TRIANGLES);
    for(int i=0;i<sizeof(verts)/sizeof(GLfloat);i+=3){
        //cout<<i<<endl;
        glVertex3f(verts[i],verts[i+1],verts[i+2]);
    }
    glEnd();
}

oglwidget.h:

#ifndef OGLWIDGET_H
#define OGLWIDGET_H

#include <QWidget>
#include <QOpenGLWidget>
#include <glm/glm.hpp>
#include <QOpenGLFunctions>
#include <vector>
#include "entity.h"
#include "general.h"
#include <qopenglfunctions_3_3_core.h>
//#include <GL/glu.h>
//#include <GL/gl.h>

#define VERTEXATTR 0
#define INDEXATTR 1
#define POSITIONATTR 2
#define ROTATIONATTR 3

using namespace std;


class OGLWidget : public QOpenGLWidget
{
    //QOpenGLFunctions gl;
    //QOpenGLFunctions_3_3_Core core;
    QOpenGLVertexArrayObject *VAO2;
    QOpenGLBuffer VBO2;
    QOpenGLShaderProgram shader2;
    QOpenGLContext *m_context;
    vector<GLuint>statics;  //-----buffer number for static models
    vector<GLuint>dynamics; //-----buffer number of dynamic models

    vector<GLfloat[1]>staticVerts;   //-----vertex data for static models
    vector<GLfloat[1]>dynamicVerts;  //-----vertex data for dynamic models

    vector<vector<GLfloat>*>staticPos;   //-----position data for static models
    vector<vector<GLfloat>*>dynamicPos;  //-----position data for dynamic models

    vector<GLfloat>staticRot;   //-----rotation data for static models
    vector<GLfloat>dynamicRot;  //-----rotation data for dynamic models

    vector<string>loadedPaths;  //-----name in folder of matching VBO
    GLuint VBO;
    GLuint IND;
    GLuint FragID;
    GLuint VertID;
    GLuint shader;

    //-----Testing
    GLfloat verts[9]={-1.0f, 0.0f, 0.0f,
                      0.0f, 1.0f, 0.0f,
                      1.0f, 0.0f, 0.0f};
    GLuint inds[3]={0,1,2};

public:
    OGLWidget(QWidget *parent = 0);
    ~OGLWidget();
    int loadModel(string path);
private:
    void draw();
    QGLShaderProgram m_shader;
    QGLBuffer m_vertexBuffer;

protected:
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();
};

#endif // OGLWIDGET_H

shader.cpp:

const char * vertexShader=
        "attribute highp vec4 vertex;\n"
        "uniform highp mat4 matrix;\n"
        "void main(void)\n"
        "{\n"
        "   gl_Position = matrix * vertex;\n"
        "}";
const char * fragmentShader=
        "uniform mediump vec4 color;\n"
        "void main(void)\n"
        "{\n"
        "   gl_FragColor = color;\n"
        "}";

从我读过的内容(如果我错了,请纠正我)使用VAO将顶点,颜色,纹理和其他数据加载到GPU内存,在绘图前重新绑定VAO,使用glDrawArrays进行绘制或glDrawElements并发布VAO。使用该函数的索引版本将允许更改位置,比例和旋转,这意味着更快的渲染更大量的相同对象(即游戏磁贴)和GL_STATIC_DRAW应该用于不经常更新的对象,使用GL_DYNAMIC_DRAW其他一切。

我想知道我错过了什么,或者做错了什么应该是一个简单的练习。我已经重做了至少5次,完全失去了。

  • 操作系统:Debian测试
  • GPU:GeForce 610m
  • OpenGL Core:3.3
  • Qt:5.6
  • 软件:Qt Creator

1 个答案:

答案 0 :(得分:0)

感谢评论中的@PeterT:将着色器enableAttributeArray和setAttributeBuffer(从setAttributeArray更改)移动到VBO分配之后,将顶点坐标和ortho修改为“更大”。

void OGLWidget::initializeGL()
{
    QOpenGLFunctions gl;
    gl.initializeOpenGLFunctions();
    glDisable(GL_CULL_FACE);
    cout<<"Init"<<endl;
    shader2.create();
    shader2.addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShader);
    shader2.addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShader);
    shader2.link();
    shader2.bind();
    int vertexLocation = shader2.attributeLocation("vertex");
    int matrixLocation = shader2.uniformLocation("matrix");
    int colorLocation = shader2.uniformLocation("color");
    QMatrix4x4 pmvMatrix;
    //pmvMatrix.ortho(rect());
    pmvMatrix.ortho(-100,100,-100,100,-1000,1000);
    QColor color(0, 255, 0, 255);

    shader2.enableAttributeArray(vertexLocation);
    shader2.setUniformValue(matrixLocation, pmvMatrix);
    shader2.setUniformValue(colorLocation, color);

    //-----Create VAO2
    VAO2=new QOpenGLVertexArrayObject(this);
    VAO2->create();
    VAO2->bind();

    VBO2.create();
    VBO2.setUsagePattern(QOpenGLBuffer::StaticDraw);
    VBO2.bind();
    VBO2.allocate(verts,sizeof(verts));

    shader2.enableAttributeArray("vertex");
    shader2.setAttributeBuffer("vertex",GL_FLOAT,0,3,0);
}

*

GLfloat verts[9]={-100.0f, 0.0f, 30.0f,
                      0.0f, 100.0f, 50.0f,
                      100.0f, 0.0f, 30.0f};