2021SC@SDUSC
分析概括
功能分析
模型通过面片粘合将二维平面合并在一起生成三维模型。modelmeshbinder类通过层层迭代的思路判断是否产生新网格。从最初的网格点开始判断,如果这些网格点间产生多个新的网格和法线,就删除初始的网格,留下新产生的网格继续迭代,直至形成可以确定出唯一几何体的网格模型,确定后在进行面片的粘合以及UV纹理的绑定。
库函数QOpengl学习
QOpengl是基于QT的Opengl功能集合,其中的QOpenGLTexture类封装了OpenGl纹理对象,可实现Opeb纹GL纹理及其提供的各种功能,其基本函数功能如下:
1、纹理创建
m_texture = new QOpenGLTexture(QImage(":/images/side6.png").mirrored());
2、纹理过滤
m_texture->setMinificationFilter(QOpenGLTexture::Nearest);
m_texture->setMagnificationFilter(QOpenGLTexture::Linear);
3、纹理环绕
m_texture->setWrapMode(QOpenGLTexture::Repeat);
关键代码分析
基于paint函数的纹理绑定
1、网格纹理绑定
if (m_mesh)
{//如果网格存在
m_hasTexture = nullptr != m_mesh->textureImage();//判断网格是否存在纹理
delete m_texture;
m_texture = nullptr;
if (m_hasTexture)
{//如果网格存在纹理,将此纹理赋予该网格形成平面
if (m_checkUvEnabled) {//查找UV图并进行纹理绑定
static QImage *s_checkUv = nullptr;
if (nullptr == s_checkUv)
s_checkUv = new QImage(":/resources/checkuv.png");
m_texture = new QOpenGLTexture(*s_checkUv);
} else {
m_texture = new QOpenGLTexture(*m_mesh->textureImage());
}
}
2、法线纹理(贴图/映射)绑定
m_hasNormalMap = nullptr != m_mesh->normalMapImage();//判断是否存在法线贴图
delete m_normalMap;//若存在,删除初始法线贴图
m_normalMap = nullptr;
if (m_hasNormalMap)//为新的法线贴图赋予纹理
m_normalMap = new QOpenGLTexture(*m_mesh->normalMapImage());
m_hasMetalnessMap = m_mesh->hasMetalnessInImage();
m_hasRoughnessMap = m_mesh->hasRoughnessInImage();
m_hasAmbientOcclusionMap = m_mesh->hasAmbientOcclusionInImage();
delete m_metalnessRoughnessAmbientOcclusionMap;
m_metalnessRoughnessAmbientOcclusionMap = nullptr;
if (nullptr != m_mesh->metalnessRoughnessAmbientOcclusionImage() &&(m_hasMetalnessMap || m_hasRoughnessMap || m_hasAmbientOcclusionMap))
m_metalnessRoughnessAmbientOcclusionMap = new QOpenGLTexture(*m_mesh->metalnessRoughnessAmbientOcclusionImage());
3、环境辐射纹理绑定
if (program->isCoreProfile() &&m_environmentLightEnabled) {//如果存在环境辐射纹理
if (nullptr == m_environmentIrradianceMap) {
DdsFileReader irradianceFile(":/resources/cedar_bridge_irradiance.dds");
m_environmentIrradianceMap = irradianceFile.createOpenGLTexture();
}
if (nullptr == m_environmentSpecularMap) {
DdsFileReader specularFile(":/resources/cedar_bridge_specular.dds");
m_environmentSpecularMap = specularFile.createOpenGLTexture();
}
}
基于paint函数的网格纹理映射应用
使用QOpenGLVertexArrayObject进行管线渲染时,通常使用VAO、VBO的方法进行点到点之间的映射,具体流程如下:
初始化 | 渲染 |
---|---|
绑定VAO | 绑定VAO |
为此可视对象设置顶点数据状态 | 调用glDraw*()函数 |
取消绑定 | 解除绑定 |
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTriangle);//为三角形绑定VAO
if (m_vboTriangle.isCreated())
m_vboTriangle.destroy();
m_vboTriangle.create();
m_vboTriangle.bind();
m_vboTriangle.allocate(m_mesh->triangleVertices(), m_mesh->triangleVertexCount() * sizeof(ShaderVertex));
m_renderTriangleVertexCount = m_mesh->triangleVertexCount();
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glEnableVertexAttribArray(0);//顶点属性数组
f->glEnableVertexAttribArray(1);
f->glEnableVertexAttribArray(2);
f->glEnableVertexAttribArray(3);
f->glEnableVertexAttribArray(4);
f->glEnableVertexAttribArray(5);
f->glEnableVertexAttribArray(6);
f->glEnableVertexAttribArray(7);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), 0);//顶点属性点
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(3 * sizeof(GLfloat)));
f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(6 * sizeof(GLfloat)));
f->glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(9 * sizeof(GLfloat)));
f->glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(11 * sizeof(GLfloat)));
f->glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(12 * sizeof(GLfloat)));
f->glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(13 * sizeof(GLfloat)));
f->glVertexAttribPointer(7, 1, GL_FLOAT, GL_FALSE, sizeof(ShaderVertex), reinterpret_cast<void *>(16 * sizeof(GLfloat)));
m_vboTriangle.release();