Qt Opengl VBO数据损坏

时间:2015-12-03 17:49:50

标签: c++ qt opengl vbo

到目前为止,我已经尝试了将近两周的时间让VBO在Qt环境中工作,但到目前为止还没有任何效果。我的目标是创建一个三角形网格,用作某些地形的基础,就像在Lighthouse3D教程中一样。我的计划的相关部分如下:

GameWindow.h

@implementation ReservasViewController
{
NSMutableArray *arrayPartidos;
MBProgressHUD *HUD;
NSInteger idPartidoEstado;
}

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[self navigationController] setNavigationBarHidden:NO animated:NO];
self.navigationController.navigationBarHidden = NO;
self.navigationController.navigationBar.hidden = NO;

[self obtenerPartidosJugador];
}

-(void)obtenerPartidosJugador
{
HUD = [[MBProgressHUD alloc] init];
HUD.delegate = self;
HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
HUD.labelText = @"Cargando partidos...";

//----------------------
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];

NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%s%s", root_server, obtener_reservas]];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:@"POST"];

NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *dataRaw, NSURLResponse *header, NSError *error) {

    NSDictionary *respServidor = [NSJSONSerialization JSONObjectWithData:dataRaw options:0 error:&error];
    NSLog(@"respServidor %@", respServidor);

    if(!error){

        if([[respServidor valueForKey:@"status"]  isEqual: @"true"]){

            arrayPartidos = [[NSMutableArray alloc] init];
            arrayPartidos = [[respServidor objectForKey:@"partidos"] mutableCopy];

            [self.tableView reloadData];

        }else{
            arrayPartidos = nil;
        }

    } else {
        NSLog(@"error --> %@", error);
    }

    [HUD hide:YES];
    [HUD show:NO];

}];

[dataTask resume];
}

//this function is called by a IBAction
-(void)cambiarEstadoPartido:(NSInteger)estado idPartido:(NSInteger)idpartido
{
HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];
HUD.labelText = @"Actualizando...";

NSString *noteDataString = [NSString stringWithFormat:@"estado=%ld&idpartido=%ld", estado, idpartido];
//----------------------
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];

NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%s%s", root_server, cambiar_estado_partido]];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:@"POST"];
[urlRequest setHTTPBody:[noteDataString dataUsingEncoding:NSUTF8StringEncoding]];

NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *dataRaw, NSURLResponse *header, NSError *error) {

    NSDictionary *respServ = [NSJSONSerialization JSONObjectWithData:dataRaw options:0 error:&error];
    NSLog(@"respServidor %@", respServ);

    if(!error){

        if([[respServ valueForKey:@"status"]  isEqual: @"true"]){

            [HUD hide:YES];
            [HUD show:NO];

            [self obtenerPartidosJugador];

        }else{

            [HUD hide:YES];
            [HUD show:NO];

            UIAlertView *alertConfirm = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Ocurrio un error, vuelve a intentarlo" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
            alertConfirm.tag = 0;
            [alertConfirm show];

        }

    } else {

        [HUD hide:YES];
        [HUD show:NO];

        NSLog(@"error --> %@", error);
        UIAlertView *alertConfirm = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Ocurrio un error, vuelve a intentarlo" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        alertConfirm.tag = 0;
        [alertConfirm show];

    }

}];

[dataTask resume];
}

GameWindow.cpp

class GameWindow : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    GameWindow(QWidget *parent = 0);
    ~GameWindow();

protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int width, int height) override;
    virtual void paintGL() override;

    QGLShaderProgram *shaderProgram;

private:
    int frame;

    std::vector<GLfloat> grid;

    QOpenGLBuffer vbo;
    GLuint vboId;

    QVector3D position;
};

着色

GameWindow::GameWindow(QWidget *parent) :
    QOpenGLWidget(parent),
    position(QVector3D(0, 5, -5)),
    vbo(QOpenGLBuffer(QOpenGLBuffer::VertexBuffer))
{}

GameWindow::~GameWindow()
{}

void GameWindow::initializeGL()
{
    QOpenGLWidget::initializeGL();
    initializeOpenGLFunctions();

    shaderProgram = new QGLShaderProgram(QGLContext::currentContext());

    QGLShader vertex(QGLShader::Vertex);
    vertex.compileSourceFile(QDir(":/shaders").absoluteFilePath("basic.vert"));
    shaderProgram->addShader(&vertex);

    QGLShader fragment(QGLShader::Fragment);
    fragment.compileSourceFile(QDir(":/shaders").absoluteFilePath("basic.frag"));
    shaderProgram->addShader(&fragment);

    shaderProgram->link();

    QImage image;
    image.load("C:\\test.png");

    int width = image.width(); //=10
    int height = image.height(); //=10

    for (int i = 0; i < height-1; i++) {
        for (int j = 0; j < width-1; j++) {
            grid.push_back(GLfloat(j));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i));

            grid.push_back(GLfloat(j));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i+1));

            grid.push_back(GLfloat(j+1));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i+1));


            grid.push_back(GLfloat(j+1));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i+1));

            grid.push_back(GLfloat(j+1));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i));

            grid.push_back(GLfloat(j));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i));
        }
    }

    vbo.create();
    vbo.bind();
    vbo.allocate(grid.size()*sizeof(GLfloat));

    vbo.write(0, grid.data(), grid.size()*sizeof(GLfloat));
    vbo.release();

    /*
    glGenBuffers(1, &vboId);

    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, grid.size() * sizeof(GLfloat), grid.data(), GL_STATIC_DRAW);
    //*/

    std::cout << std::boolalpha << (glGetError() == GL_NO_ERROR) << std::endl;
}

void GameWindow::resizeGL(int width, int height)
{
    QOpenGLWidget::resizeGL(width, height);
}

void GameWindow::paintGL()
{
    shaderProgram->bind();

    QMatrix4x4 projection;
    projection.perspective(45, qreal(width())/qreal(height() > 0 ? height() : 1), 0.1f, 100.0f);

    QMatrix4x4 view;
    view.lookAt(position, QVector3D(0, 0, 0), QVector3D(0, 1, 0));

    QMatrix4x4 model;
    model.translate(-0.5f, 0, 0);

    QMatrix4x4 mvp;
    mvp = projection * view * model;

    shaderProgram->setUniformValue("matrix", mvp);

    glClear(GL_COLOR_BUFFER_BIT);

    vbo.bind();

    shaderProgram->enableAttributeArray("vertex");
    shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
    glDrawArrays(GL_TRIANGLES, 0, vbo.size());

    shaderProgram->disableAttributeArray("vertex");

    /*
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, 0);

    glDrawArrays(GL_TRIANGLES, 0, grid.size());

    glDisableVertexAttribArray(0);
    */

    shaderProgram->release();

    update();
}

最后我像这样打开窗户:

//Vertex Shader
attribute vec3 vertex;
uniform mat4 matrix;

varying vec3 pos;

void main(void)
{
    gl_Position = matrix * vec4(vertex, 1);

    pos = vertex;
}

//Fragment Shader
void main(void)
{
    gl_FragColor.rgb = pos;
}

运行此程序后,我得到类似的东西,虽然它经常变化: Weird Result

从代码中可以看出,我尝试使用QSurfaceFormat format; format.setVersion(3, 3); format.setProfile(QSurfaceFormat::CoreProfile); format.setSamples(4); QSurfaceFormat::setDefaultFormat(format); GameWindow *w = new GameWindow(); w->show(); 和raw QOpenGLBuffer命令创建并绘制我的VBO,结果相似。谷歌没有任何帮助,所以现在我求助于你。我的VBO有什么问题,为什么数据损坏了?

注意:

当我跑步时,我在stdout中收到此错误:

gl*

但我不知道这与它有什么关系。

注2:

尝试使用[opengl\qopenglframebufferobject.cpp line 565] OpenGL Error: 1286 QOpenGLFramebufferObject: Unsupported framebuffer format. QOpenGLFramebufferObject: Unsupported framebuffer format. [opengl\qopenglframebufferobject.cpp line 720] OpenGL Error: 1280 会导致程序崩溃。

2 个答案:

答案 0 :(得分:3)

发出此命令时:

shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);

你确实说过,每3个浮点数就被解释为1个属性。所以,要画画,你需要打电话:

glDrawArrays(GL_TRIANGLES, 0, grid.size()/3);

请注意。在我看来,vbo.size()为你提供了vbo对象的字节数,而不是缓冲区中元素的数量

答案 1 :(得分:0)

在Qt中,OpenGL操作仅在放置在makeCurrent ... doneCurrent块内或…GL方法内时才有效。由于没有满足前提条件,因此VBO无法创建OpenGL。

解决方案:将OpenGL初始化代码从构造函数移动到initializeGL