小弟在做一个项目过程中需要完成这样的一个功能在运行过程中需要动态修改EBO和VBO以达到画面动态显示的目的,大致就是在mainwindow下选择需要载入的文件,然后程序读取文件,根据文件的内容改变原有的EBO和VBO于是有如下程序
首先是初始化
void SandTable::initializeGL()
{
initializeOpenGLFunctions();
// vertex shader
QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
vshader->compileSourceFile("://shader/vert_green.vert");
// fragment shader
QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
fshader->compileSourceFile("://shader/frag_green.frag");
program = new QOpenGLShaderProgram;
program->addShader(vshader);
program->addShader(fshader);
program->link();
program->bind();
read_csv();//读取点和引索
QVector<float> pointindex;
{
QFile file("../DEM/demo.txt"); //DEM路径这里读取引索
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
qDebug()<<"文件不存在";
return;
}
QTextStream in(&file);
QString line=in.readLine();
while(!line.isNull())
{
pointindex.append(line.toFloat());
line=in.readLine();
}
}
{ //重点关注这里面的代码
GLfloat tempData[5*csv_height.size()];
GLint tempIndex[pointindex.size()];
for(int i=0;i<csv_height.size();i++)
{
tempData[5*i] = (csv_x[i]-40000000)/10000;
tempData[5*i+2] = csv_y[i]/10000;
tempData[5*i+1] = csv_height[i]/1000;
tempData[5*i+3] = csv_x_texture[i];
tempData[5*i+4] = csv_y_texture[i];
}
for(int i = 0;i < pointindex.size();i++)
{
tempIndex[i]=pointindex[i];
}
dem_size = pointindex.size();
cameraPos = QVector3D(tempData[0],tempData[1],tempData[2]);
glEnable(GL_DEPTH_TEST);//设置Z缓冲
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);//绑定VAO
glBindBuffer(GL_ARRAY_BUFFER, VBO);//声名VBO的属性
glBufferData(GL_ARRAY_BUFFER, sizeof(tempData), tempData, GL_STATIC_DRAW);//给VBO赋值
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//声名EBO的属性
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(tempIndex), tempIndex, GL_STATIC_DRAW);//给EBO赋值
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//告诉GPU编译该如何读取数据 0代表vert中的地址
glEnableVertexAttribArray(0);//启用设置
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3*sizeof(float)));//告诉GPU编译该如何读取数据 0代表vert中的地址
glEnableVertexAttribArray(1);//启用设置
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
}
void SandTable::paintGL()
{
//绘制模式
if(demType == "tin")
{
glBindVertexArray(VAO);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //线框模式
glDrawElements(GL_TRIANGLES,dem_size, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
if(demType == "grid")
{
glBindVertexArray(VAO);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //线框模式
glDrawElements(GL_TRIANGLES,grid_size, GL_UNSIGNED_INT, 0);
glDrawArrays(GL_POINTS, 0, grid_size);
glBindVertexArray(0);
}
}
MainWindow下有一个按钮控制LoadModel()函数改函数用于读取和加载选择文件从而改变VBO和EBO
void SandTable::LoadModel()
{
this->makeCurrent();
//选择加载数据库
QString fileName = QFileDialog::getOpenFileName(this, "选择数据库文件","/",tr("Files (*.db)"));
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(fileName);
if(!db.open())
{
QMessageBox::warning(this,"error",db.lastError().text());
}
else
{
//获取dem的长度和宽度
QSqlQuery query;
query.exec("SELECT * FROM attribute");
while(query.next())
{
// qDebug()<<query.value("dem_index").toInt()
// <<query.value("dem_colum").toInt()
// <<query.value("downleft_lon").toFloat()
// <<query.value("downleft_lat").toFloat()
// <<query.value("downright_lon").toFloat();
dem_width = query.value("dem_colum").toInt();
dem_height = query.value("dem_index").toInt();
}
//获取dem的高程信息
query.exec("SELECT * FROM dem");
while(query.next())
{
DEM_X.append(query.value("X").toFloat());
DEM_Y.append(query.value("Y").toFloat());
DEM_Z.append(query.value("Z").toFloat());
DEM_TEX_X.append(query.value("TEX_X").toFloat());
DEM_TEX_Y.append(query.value("TEX_Y").toFloat());
}
GLfloat DemdData[5*DEM_X.size()];
GLint DemIndex[(dem_width-1)*(dem_height-1)*6];
for(int i=0;i<DEM_X.size();i++)
{
DemdData[5*i] = (DEM_X[i]-34000000)/10000;
DemdData[5*i+2] = DEM_Y[i]/10000;
// DemdData[5*i+1] = DEM_Z[i]/1000;
DemdData[5*i+1] = 0;
DemdData[5*i+3] = DEM_TEX_X[i];
DemdData[5*i+4] = DEM_TEX_Y[i];
}
int k = 0;
for(int i = 0;i < dem_height-1;i++)
{
for(int j = 0;j <dem_width-1;j++)
{
DemIndex[k++] = i*dem_width+j;
DemIndex[k++] = i*dem_width+j+1;
DemIndex[k++] = (i+1)*dem_width+j;
DemIndex[k++] = (i+1)*dem_width+j;
DemIndex[k++] = i*dem_width+j+1;
DemIndex[k++] = (i+1)*dem_width+j+1;
}
}
qDebug()<<"height"<<dem_height<<"width"<<dem_width;
cameraPos = QVector3D(DemdData[0],DemdData[1],DemdData[2]);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(DemdData), DemdData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//声名EBO的属性
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (dem_width - 1)*(dem_height - 1) * 6*sizeof(GLint), DemIndex, GL_STATIC_DRAW);//给EBO赋值
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);//告诉GPU编译该如何读取数据 0代表vert中的地址
glEnableVertexAttribArray(0);//启用设置
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3*sizeof(GLfloat)));//告诉GPU编译该如何读取数据 0代表vert中的地址
glEnableVertexAttribArray(1);//启用设置
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
this->doneCurrent();
this->update();
}
程序运行完后有一个奇怪的现象就是在LoadModel()实现了VBO的修改,但是EBO没有任何变化,他们的修改函数都在同一个函数中,按道理来讲VBO修改了,EBO也会跟着修改,但事实却是只修改了VBO!然后考虑到如果写入的EBO数据过多的原因,我特地的减小了EBO写入数据的大小,结果还是没有变化,求懂行的大神给予答复,解决后私我发红包!!
注:更新一下,试了下直接把更改EBO的代码放在resizeGL()中能够实现修改,后来又去查阅了资料发现在main函数中设置QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);也无效,知道了思路一定是在opengl上下文上出问题,但是在这个loadmodel函数里始终无法更改EBO不知道为什么,我也在loadmodel函数中调用了make、done这两个函数了呀
修改VBO和EBO之前绑定了VAO。
glBindVertexArray(VAO);
加一下错误检查: