本例依旧是改变3D视角。不同的是这个是视野位置不变而只改变观察方向。相当于一个人站在原地不动,旋转脑袋看周围的东西。测试的条件是VS2017和Qt5.9。主要的知识点就是欧拉角的计算。下面是效果图:
头文件:
class QOpenGLTexture; class QOpenGLBuffer; class MvOpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { Q_OBJECT private: struct VertexData { QVector3D pos; QVector3D normal; QVector3D color; }; public: MvOpenGLWidget(QWidget* parent = 0); private: void initializeGL() override; void paintGL() override; void resizeGL(int w, int h) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; QVector3D calcDirVec() const; private: QOpenGLShaderProgram* program; QOpenGLBuffer* vertexBuff; QOpenGLBuffer* indexBuff; /* 下面2个是相机方向,都为0时相机朝向X轴正方向 */ float yaw; /* 绕Y轴旋转 */ float pitch; /* 绕X轴旋转 */ /* 下面1个是鼠标上次点击的位置 */ QPoint lastPos; };
CPP文件:
MvOpenGLWidget::MvOpenGLWidget(QWidget* parent) : QOpenGLWidget(parent), lastPos(0xDEADBEEFi32, 0xDEADBEEFi32) { yaw = -90.0f; pitch = 0; QSurfaceFormat surface; surface.setSamples(4); setFormat(surface); } void MvOpenGLWidget::initializeGL() { initializeOpenGLFunctions(); glEnable(GL_DEPTH_TEST); program = new QOpenGLShaderProgram(this); const char* vsrc = u8R"( #version 330 core layout (location = 0) in vec3 aPos; // 空间坐标 layout (location = 1) in vec3 aNormal; // 法线向量 layout (location = 2) in vec3 aColor; // 顶点颜色 uniform mat4 modelMatrix; uniform mat4 mvpMatrix; out vec3 oNormal; out vec3 oFragPos; out vec3 oColor; void main() { oFragPos = vec3(modelMatrix * vec4(aPos, 1.0)); oNormal = mat3(transpose(inverse(modelMatrix))) * aNormal; oColor = aColor; gl_Position = mvpMatrix * vec4(aPos, 1.0); })"; program->addShaderFromSourceCode(QOpenGLShader::Vertex, vsrc); const char* fsrc = u8R"( #version 330 core uniform vec3 lightPos; uniform vec3 viewPos; uniform vec3 lightColor; in vec3 oNormal; in vec3 oFragPos; in vec3 oColor; void main() { // 环境光照 float ambientStrength = 0.4; vec3 ambient = ambientStrength * lightColor; // 漫反射光照 vec3 norm = normalize(oNormal); vec3 lightDir = normalize(lightPos - oFragPos); float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightColor; // 镜面光照 float specularStrength = 1.0; vec3 viewDir = normalize(viewPos - oFragPos); vec3 reflectDir = reflect(-lightDir, norm); float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0); vec3 specular = specularStrength * spec * lightColor; // 把纹理中的颜色和光照参数相乘 gl_FragColor = vec4((ambient + diffuse + specular) * oColor, 1.0); })"; program->addShaderFromSourceCode(QOpenGLShader::Fragment, fsrc); program->link(); program->bind(); VertexData vertices[] = { { QVector3D(-0.433f, 0, -0.25f), QVector3D(-0.816f, 0.333f, 0.471f), QVector3D(1.0f, 0, 0) }, { QVector3D(0, 0, 0.5f), QVector3D(-0.816f, 0.333f, 0.471f), QVector3D(0, 1.0f, 0) }, { QVector3D(0, 0.707f, 0), QVector3D(-0.816f, 0.333f, 0.471f), QVector3D(0, 0, 1.0f) }, { QVector3D(0, 0, 0.5f), QVector3D(0.816f, 0.333f, 0.471f), QVector3D(1.0f, 1.0f, 0) }, { QVector3D(0.433f, 0, -0.25f), QVector3D(0.816f, 0.333f, 0.471f), QVector3D(1.0f, 0, 1.0f) }, { QVector3D(0, 0.707f, 0), QVector3D(0.816f, 0.333f, 0.471f), QVector3D(0, 1.0f, 1.0f) }, { QVector3D(0.433f, 0, -0.25f), QVector3D(0, 0.333f, -0.943f), QVector3D(0, 0, 1.0f) }, { QVector3D(-0.433f, 0, -0.25f), QVector3D(0, 0.333f, -0.943f), QVector3D(0, 1.0f, 0) }, { QVector3D(0, 0.707f, 0), QVector3D(0, 0.333f, -0.943f), QVector3D(1.0f, 0, 0) }, { QVector3D(0, 0, 0.5f), QVector3D(0, -1.0f, 0), QVector3D(0, 1.0f, 1.0f) }, { QVector3D(-0.433f, 0, -0.25f), QVector3D(0, -1.0f, 0), QVector3D(1.0f, 1.0f, 0) }, { QVector3D(0.433f, 0, -0.25f), QVector3D(0, -1.0f, 0), QVector3D(1.0f, 0, 1.0f) }, /* 后面6个点绘制水平的地面 */ { QVector3D(-10.0f, -0.2f, -10.0f), QVector3D(0, 1.0f, 0), QVector3D(0, 1.0f, 1.0f) }, { QVector3D(-10.0f, -0.2f, 10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 1.0f, 0) }, { QVector3D(10.0f, -0.2f, -10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 0, 1.0f) }, { QVector3D(10.0f, -0.2f, -10.0f), QVector3D(0, 1.0f, 0), QVector3D(0, 1.0f, 1.0f) }, { QVector3D(-10.0f, -0.2f, 10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 1.0f, 0) }, { QVector3D(10.0f, -0.2f, 10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 0, 1.0f) }, }; GLushort indices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, }; vertexBuff = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); vertexBuff->create(); vertexBuff->bind(); vertexBuff->allocate(vertices, 18 * sizeof(VertexData)); indexBuff = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); indexBuff->create(); indexBuff->bind(); indexBuff->allocate(indices, 18 * sizeof(float)); int offset = 0; int vertexLocation = program->attributeLocation("aPos"); program->enableAttributeArray(vertexLocation); program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); offset += sizeof(QVector3D); int normalLocation = program->attributeLocation("aNormal"); program->enableAttributeArray(normalLocation); program->setAttributeBuffer(normalLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); offset += sizeof(QVector3D); int colorLocation = program->attributeLocation("aColor"); program->enableAttributeArray(colorLocation); program->setAttributeBuffer(colorLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); } #define LIGHT_COLOR QVector3D(0.9f, 1.0f, 2.0f) /* 这里的颜色值可以大于1不知道为什么 */ #define LIGHT_POS QVector3D(2.5f, 5.8f, 2.0f) #define VIEW_CENTER QVector3D(0.0f, 0.25f, 0.0f) void MvOpenGLWidget::paintGL() { QMatrix4x4 projection; projection.perspective(45.0f, 1, 0.1f, 100.0f); QMatrix4x4 viewMatrix; QVector3D eyeDir = calcDirVec(); QVector3D eyePos = VIEW_CENTER - 10 * eyeDir; viewMatrix.lookAt(eyePos, VIEW_CENTER, QVector3D(0, 1, 0)); QMatrix4x4 modelMatrix; modelMatrix.translate(0, -0.8, 0); // 平移 modelMatrix.rotate(0, 0, 1); // 旋转 modelMatrix.scale(4.0); // 缩放 QMatrix4x4 mvpMatrix = projection * viewMatrix * modelMatrix; program->setUniformValue("lightColor", LIGHT_COLOR); program->setUniformValue("lightPos", LIGHT_POS); program->setUniformValue("viewPos", eyePos); program->setUniformValue("mvpMatrix", mvpMatrix); program->setUniformValue("modelMatrix", modelMatrix); glDrawElements(GL_TRIANGLES, 18, GL_UNSIGNED_SHORT, 0); } #undef LIGHT_COLOR #undef LIGHT_POS #undef EYE_CENTER void MvOpenGLWidget::resizeGL(int w, int h) { } void MvOpenGLWidget::mousePressEvent(QMouseEvent *event) { lastPos = event->pos(); } void MvOpenGLWidget::mouseReleaseEvent(QMouseEvent *event) { lastPos = QPoint(0xDEADBEEFi32, 0xDEADBEEFi32); } void MvOpenGLWidget::mouseMoveEvent(QMouseEvent *event) { float xoffset = event->pos().x() - lastPos.x(); float yoffset = lastPos.y() - event->pos().y(); lastPos = event->pos(); float sensitivity = 0.25f; xoffset *= sensitivity; yoffset *= sensitivity; yaw += xoffset; pitch += yoffset; pitch = std::max(-89.0f, std::min(89.0f, pitch)); update(); } QVector3D MvOpenGLWidget::calcDirVec() const { QVector3D front; front.setX(cosf(qDegreesToRadians(yaw)) * cosf(qDegreesToRadians(pitch))); front.setY(sinf(qDegreesToRadians(pitch))); front.setZ(sinf(qDegreesToRadians(yaw)) * cosf(qDegreesToRadians(pitch))); return front.normalized(); }
标签:10.0,视角,1.0,例程,void,Qt3D,program,QVector3D,vec3 From: https://www.cnblogs.com/mengxiangdu/p/17798167.html