代码如下:
void OpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
f = QOpenGLContext::currentContext()->functions();
f->glEnable(GL_DEPTH_TEST);
this->initializeShaders();
}
void OpenGLWidget::initializeShaders()
{
this->m_ModelShader = new QOpenGLShaderProgram(this);
// 加载着色器程序
/*--------m_ModelShader------------*/
if (!m_ModelShader->addShaderFromSourceFile(QOpenGLShader::Vertex, \
ModelvertexShaderPath))
qDebug() << "Failed to load Vert shader:" << m_ModelShader->log();
if (!m_ModelShader->addShaderFromSourceFile(QOpenGLShader::Fragment, \
ModelfragmentShaderPath))
qDebug() << "Failed to load fragment shader:" << m_ModelShader->log();
if (!m_ModelShader->link())
std::cout << "ERROR: failed to link: " << m_ModelShader->log().toStdString();
}
void OpenGLWidget::resizeGL(int w, int h)
{
this->SCR_WIDTH = w;
this->SCR_HEIGHT = h;
this->SelectProjection(this->operatePro);
}
void OpenGLWidget::paintGL()
{
f = QOpenGLContext::currentContext()->functions();
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
f->glClearColor(0.0f, 0.5f, 0.7f, 1.0f);
if (isValid())
switch (RenderModel)
{
case Model://平滑渲染
{
makeCurrent();
m_VAO = new QOpenGLVertexArrayObject(this);
m_VBO = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_EBO = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
this->DrawModelData();
m_ModelShader->bind();
{
m_VAO->bind();
m_EBO->bind();
this->setModelShaderMatrix();
// 绘制
f->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
}
m_ModelShader->release();
break;
}
case Line://平滑渲染加渲染模型线框
{
break;
}
case Points://渲染模型线框
{
break;
}
}
}
void OpenGLWidget::DrawModelData()
{
this->m_ModelShader->bind();
/*--------------------------初始化------------------*/
if (!m_VAO->create())
std::cerr << "ERROR: faild to create vertex array object" << std::endl;
if (!m_VBO->create())
std::cerr << "ERROR: failed to create vertex buffer object" << std::endl;
if (!m_EBO->create())
std::cerr << "ERROR: failed to create index buffer object" << std::endl;
/*-------------------顶点数组绑定------------------*/
m_VAO->bind();
if (!m_VBO->bind())
{
std::cerr << "ERROR: failed to bind vertex buffer object" << std::endl;
}//将与该对象相关联的缓存绑定到当前OpenGL环境
m_VBO->allocate(&meshes[0], meshes.size() * sizeof(Vertex));
if (!m_EBO->bind())
{
std::cerr << "ERROR: failed to bind index buffer object" << std::endl;
}
m_EBO->allocate(&indices[0], sizeof(unsigned int) * indices.size());
int vertexLocation = m_ModelShader->attributeLocation("aPos"); // 位置属性的位置为 0
int normalLocation = m_ModelShader->attributeLocation("aNormal"); // 法线属性的位置为 1
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Position));
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
glEnableVertexAttribArray(normalLocation);
//this->m_ModelShader->enableAttributeArray(vertexLocation);
//this->m_ModelShader->setAttributeBuffer(vertexLocation, GL_FLOAT, offsetof(Vertex, Position), 3, sizeof(Vertex));
//this->m_ModelShader->enableAttributeArray(normalLocation);
//this->m_ModelShader->setAttributeBuffer(normalLocation, GL_FLOAT, offsetof(Vertex, Normal), 3, sizeof(Vertex));
m_VBO->release();
m_EBO->release();
m_VAO->release();
m_ModelShader->release();
}
void OpenGLWidget::setModelShaderMatrix()
{
// DirLight变量
GLint ViewPos = glGetUniformLocation(m_ModelShader->programId(), "viewPos");
GLint lightDir = glGetUniformLocation(m_ModelShader->programId(), "dirLight.direction");
GLint lightAmb = glGetUniformLocation(m_ModelShader->programId(), "dirLight.ambient");
GLint lightDif = glGetUniformLocation(m_ModelShader->programId(), "dirLight.diffuse");
GLint lightSpe = glGetUniformLocation(m_ModelShader->programId(), "dirLight.specular");
// Material变量
GLint materAmb = glGetUniformLocation(m_ModelShader->programId(), "material.ambient");
GLint materDif = glGetUniformLocation(m_ModelShader->programId(), "material.diffuse");
GLint materSpe = glGetUniformLocation(m_ModelShader->programId(), "material.specular");
GLint materShi = glGetUniformLocation(m_ModelShader->programId(), "material.shininess");
GLint alpha = glGetUniformLocation(m_ModelShader->programId(), "alpha");
GLint Model_model = glGetUniformLocation(m_ModelShader->programId(), "model");
GLint Model_view = glGetUniformLocation(m_ModelShader->programId(), "view");
GLint Model_proj = glGetUniformLocation(m_ModelShader->programId(), "projection");
m_ModelShader->setUniformValue(ViewPos, m_Camera->getPosition());
m_ModelShader->setUniformValue(lightAmb, Light_ambient);
m_ModelShader->setUniformValue(lightDir, Light_direction);
m_ModelShader->setUniformValue(lightDif, Light_diffuse);
m_ModelShader->setUniformValue(lightSpe, Light_specular);
m_ModelShader->setUniformValue(materAmb, Model_ambient);
m_ModelShader->setUniformValue(materDif, Model_diffuse);
m_ModelShader->setUniformValue(materSpe, Model_specular);
m_ModelShader->setUniformValue(materShi, Model_shininess);
m_ModelShader->setUniformValue(alpha, 1.0f);
//视图、投影、模型矩阵
this->m_view = m_Camera->GetViewMatrix();
// 将QMatrix4x4转换为float数组
m_ModelShader->setUniformValue(Model_view, m_view);
m_ModelShader->setUniformValue(Model_proj, m_projection);
// 设置模型矩阵
m_scale_rate = max(0.75f / max_len, m_scale_rate);//以导入的最小模型为标准
this->m_model.scale(m_scale_rate);
this->m_model = m_scale * m_model;
this->m_middle = QVector3D(this->bbox.centerPoint.x, this->bbox.centerPoint.y, this->bbox.centerPoint.z);
this->m_model.translate(-m_middle);
this->m_model = m_move * m_rotate * m_model;
m_ModelShader->setUniformValue(Model_model, m_model);
}
【以下回答由 GPT 生成】
该问题可能是由于在改变窗口尺寸或点击屏幕外部时,OpenGL上下文被重建导致的。为了解决这个问题,你可以尝试在重新调整窗口尺寸或点击屏幕外部时重新初始化OpenGL的相关资源。
一个可能的解决方案如下:
void OpenGLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
f = QOpenGLContext::currentContext()->functions();
f->glEnable(GL_DEPTH_TEST);
// 在这里添加一个标志,用于检查是否需要重新初始化OpenGL资源
this->isOpenGLInitialized = false;
// 将下面的代码移到resizeGL函数中
// this->initializeShaders();
}
void OpenGLWidget::resizeGL(int w, int h)
{
this->SCR_WIDTH = w;
this->SCR_HEIGHT = h;
// 在这里添加一个条件,仅当OpenGL未初始化时才进行初始化
if (!this->isOpenGLInitialized)
{
this->initializeShaders();
this->isOpenGLInitialized = true;
}
this->SelectProjection(this->operatePro);
}
// ...
通过添加一个isOpenGLInitialized
标志来跟踪OpenGL是否已经初始化,当需要重新初始化时(例如改变窗口尺寸)才会执行初始化代码。这可以确保在重新调整窗口尺寸或点击屏幕外部时,模型不会消失。
【相关推荐】