到目前为止,我已经尝试了将近两周的时间让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;
}
从代码中可以看出,我尝试使用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*
但我不知道这与它有什么关系。
尝试使用[opengl\qopenglframebufferobject.cpp line 565] OpenGL Error: 1286
QOpenGLFramebufferObject: Unsupported framebuffer format.
QOpenGLFramebufferObject: Unsupported framebuffer format.
[opengl\qopenglframebufferobject.cpp line 720] OpenGL Error: 1280
会导致程序崩溃。
答案 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
。