直接给出一个例子供参考。此例子参考了以下博文中公开的代码并做了整理:
这里把立方体换成了四面体,贴图也换成了顶点的颜色。并对代码结构做了简化,以使读者更容易看懂。有兴趣的读者可以调节软件中相机位置、EYE位置和视角方向(即调整lookAt(...)函数的参数)等观察这些参数对渲染结果的影响。本文开发环境是VS2017和Qt5.9。软件效果如下图:
头文件如下:
class QOpenGLTexture; class QOpenGLBuffer; class MwOpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { Q_OBJECT private: struct VertexData { QVector3D pos; QVector3D normal; QVector3D color; }; public: MwOpenGLWidget(QWidget* parent = 0); private: void initializeGL() override; void paintGL() override; void resizeGL(int w, int h) override; private: QOpenGLShaderProgram* program; QOpenGLBuffer* vertexBuff; QOpenGLBuffer* indexBuff; int iter; };
CPP文件:
MwOpenGLWidget::MwOpenGLWidget(QWidget* parent) : QOpenGLWidget(parent), iter(0) { QSurfaceFormat surface; surface.setSamples(4); setFormat(surface); QTimer* timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&MyOpenGLWidget::update)); timer->setInterval(100); timer->start(); } void MwOpenGLWidget::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.1; 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) }, }; GLushort indices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, }; vertexBuff = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); vertexBuff->create(); vertexBuff->bind(); vertexBuff->allocate(vertices, 12 * sizeof(VertexData)); indexBuff = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); indexBuff->create(); indexBuff->bind(); indexBuff->allocate(indices, 12 * 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, 2.8f, 2.0f) #define EYE_CENTER QVector3D(0.0, -1.4, 8.0) void MwOpenGLWidget::paintGL() { QMatrix4x4 projection; projection.perspective(45.0f, 1, 0.1f, 100.0f); QMatrix4x4 viewMatrix; viewMatrix.lookAt(EYE_CENTER, QVector3D(0, 2, -5), QVector3D(0, 1, 0)); QMatrix4x4 modelMatrix; modelMatrix.translate(0, -0.8, 0); // 平移 modelMatrix.rotate(iter, 0, 1); // 旋转 modelMatrix.scale(4.0); // 缩放 QMatrix4x4 mvpMatrix = projection * viewMatrix * modelMatrix; program->setUniformValue("lightColor", LIGHT_COLOR); program->setUniformValue("lightPos", LIGHT_POS); program->setUniformValue("viewPos", EYE_CENTER); program->setUniformValue("mvpMatrix", mvpMatrix); program->setUniformValue("modelMatrix", modelMatrix); glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, 0); iter++; } #undef LIGHT_COLOR #undef LIGHT_POS #undef EYE_CENTER void MwOpenGLWidget::resizeGL(int w, int h) { }
标签:1.0,modelMatrix,0.333,Qt3D,program,QVector3D,vec3,绘制,光照 From: https://www.cnblogs.com/mengxiangdu/p/17721798.html