制作人在那个网站能看,简单的网页开发,wordpress收录优化,产品推广的重要性1 在前几期的文章中#xff0c;我们已经实现了三维正方体的显示了#xff0c;那我们来实现让物体的由远及近#xff0c;和由近及远。这里我们需要了解一个概念摄像机。
1.1 摄像机定义#xff1a;在世界空间中位置、观察方向、指向右侧向量、指向上方的向量。如下图所示: …1 在前几期的文章中我们已经实现了三维正方体的显示了那我们来实现让物体的由远及近和由近及远。这里我们需要了解一个概念摄像机。
1.1 摄像机定义在世界空间中位置、观察方向、指向右侧向量、指向上方的向量。如下图所示: 1.2 实现一个摄像机
首先定义一个摄像机位置,然后获取一个摄影机指向原点的向量,并且获取指向摄像机的单位向量(只关心摄像机的方向,不关心其长度).代码如下所示: QVector3D cameraPos(0, 0, 3) QVector3D cameraTarget(0, 0, 0); QVector3D cameraDirection( (cameraTarget- cameraPos).normalized() )
1.3 摄像机位置
摄像机位置是在世界空间中一个指向摄像机位置的向量。右手坐标系大拇指指向正x轴方向食指指向正y轴方向中指指向正z轴方向z正轴从屏幕指向自己。 通过改变摄像机的位置就可以实现物体的远近效果。
在qt opengl 函数里面我们有函数实现了
void QMatrix4x4::lookAt(const QVector3D eye, const QVector3D center, const QVector3D up)
//获取lookAt矩阵.
//eye: 设置摄像机(眼睛)位置比如QVector3D(0,0,3)
//center:表示摄像机(眼睛)正在看的视图的中心,比如原点QVector3D(0,0,0)
//up:眼睛的上向量,一般为QVector3D(0,1,0),通过该向量就能获取到眼睛的右轴和上轴 这里我们只需要设置相应的参数就可以了
eye 就是我们眼睛的位置这里我们设置Z轴正方向 QVector3D(0, 0, 3);
center : 就是我们以什么地方为中心点观察物体如QVector3D(0, 0, 0);原点。
up:眼睛的上向量,一般为QVector3D(0,1,0),通过该向量就能获取到眼睛的右轴和上轴 好了那么我们现在来修改glsl语句和代码实现。
#include glwidget.h
#include QOpenGLShaderProgram
#include QOpenGLTexture
#include QMouseEvent
#include QDateTime
#include QtMathstatic const char *vertexShaderSource #version 330\nlayout (location 0) in vec4 vertex;\nlayout (location 1) in vec4 texCoord;\nout vec4 texc;\nuniform mat4 matrix;\nuniform mat4 model;\nuniform mat4 view;\nuniform mat4 projection;\nvoid main(void)\n{\n gl_Position projection*view* matrix * vertex;\n texc texCoord;\n}\n;static const char *fragmentShaderSource #version 330\nuniform sampler2D texture;\nin vec4 texc;\nvoid main(void)\n{\n gl_FragColor texture2D(texture, texc.st);\n}\n;GLWidget::GLWidget():QOpenGLWidget(),m_xRos(0),m_yRos(0)
{cam QVector3D(m_xRos, m_yRos, m_zRos);cameraPos QVector3D(0, 0, 3); 近---远// cameraPos QVector3D(0, 0, 30);远---近timer new QTimer;timer-setInterval(20);connect(timer,QTimer::timeout,this,[]{qDebug()timeoutnCountm_xRos;rotateBy(2 * 16, 2 * 16, -1 * 16);});}
GLWidget::~GLWidget()
{makeCurrent();vbo.destroy();for (int i 0; i 6; i)delete textures[i];delete program;doneCurrent();
}QSize GLWidget::minimumSizeHint() const
{return QSize(400, 400);
}QSize GLWidget::sizeHint() const
{return QSize(400, 400);
}void GLWidget::rotateBy(int xAngle, int yAngle, int zAngle)
{float cameraSpeed 0.2;cameraPos cameraSpeed * QVector3D(0, 0, 1);//由远到近//cameraPos - cameraSpeed * QVector3D(0, 0, 1);//由近到远xRot xAngle;yRot yAngle;zRot zAngle;update();
}void GLWidget::setClearColor(const QColor color)
{clearColor color;update();
}void GLWidget::initializeGL()
{vertices {// ---- 位置---- - 纹理坐标 - ---- 颜色 ----0.5f, -0.5f, -0.5f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f,//10.5f, 0.5f, -0.5f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,//20.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,//3-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 0.0f,//40.5f, -0.5f, 0.5f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f,//5-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,};initializeOpenGLFunctions();// makeObject();glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);//#define PROGRAM_VERTEX_ATTRIBUTE 0
//#define PROGRAM_TEXCOORD_ATTRIBUTE 1program new QOpenGLShaderProgram;program-addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);program-addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);program-link();program-bind();//激活Program对象vbo.create();vbo.bind(); //绑定到当前的OpenGL上下文,vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));//初始化VAO,设置顶点数据状态(顶点法线纹理坐标等)vao.create();vao.bind();for (int j 0; j 6; j){textures[j] new QOpenGLTexture(QImage(QString(:/cube%1.png).arg(j 1)).mirrored());textures[j]-setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);textures[j]-setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);textures[j]-setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);}program-setAttributeBuffer(0, GL_FLOAT, 0, 3, 5 * sizeof(float)); //设置aPos顶点属性program-setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 2, 5 * sizeof(float)); //设置aColor顶点颜色program-enableAttributeArray(0); //使能aPos顶点属性program-enableAttributeArray(1); //使能aColor顶点颜色program-setUniformValue(texture, 0);QMatrix4x4 projection;projection.perspective(60,(float)width()/height(),0.1,100);//构建透视矩阵,这个可以是固定写法program-setUniformValue(projection, projection);// vao.release();
// vbo.release();
}void GLWidget::paintGL()
{//glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());glEnable(GL_DEPTH_TEST);glClearColor(0.1f,0.5f,0.7f,1.0f); //设置清屏颜色glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);QMatrix4x4 m;//m.ortho(-0.5f, 0.5f, 0.5f, -0.5f, 4.0f, 15.0f);m.translate(0.0f, 0.0f, 0.0f);m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);m.scale(0.5);program-setUniformValue(matrix, m);// QMatrix4x4 view;
// view.translate(0.0f,0.0f,-3.0f);
// program-setUniformValue(view, view);QMatrix4x4 view;view.lookAt(cameraPos, QVector3D(0, 0, 0), QVector3D(0, 1, 0));//view.lookAt(cameraPos, cameraPosQVector3D(0,0,-1), QVector3D(0,1,0));program-setUniformValue(view, view);for (int i 0; i 6; i) {textures[i]-bind();glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);}
}
void GLWidget::resizeGL(int width, int height)
{this-glViewport(0,0,width,height); //定义视口区域
}void GLWidget::mousePressEvent(QMouseEvent *event)
{lastPos event-pos();timer-start();
}void GLWidget::mouseMoveEvent(QMouseEvent *event)
{int dx event-x() - lastPos.x();int dy event-y() - lastPos.y();if (event-buttons() Qt::LeftButton) {rotateBy(8 * dy, 8 * dx, 0);} else if (event-buttons() Qt::RightButton) {rotateBy(8 * dy, 0, 8 * dx);}lastPos event-pos();
}void GLWidget::mouseReleaseEvent(QMouseEvent * /* event */)
{emit clicked();
}
#ifndef GLWIDGET_H
#define GLWIDGET_H#include QOpenGLWidget
#include QOpenGLFunctions
#include QOpenGLBuffer
#include QOpenGLVertexArrayObject
#include QTimer
#include QOpenGLTexture
#include QOpenGLShaderProgramQT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram);
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{Q_OBJECTpublic://using QOpenGLWidget::QOpenGLWidget;GLWidget();~GLWidget();QSize minimumSizeHint() const override;QSize sizeHint() const override;void rotateBy(int xAngle, int yAngle, int zAngle);void setClearColor(const QColor color);signals:void clicked();protected:void initializeGL() override;void paintGL() override;void resizeGL(int width, int height) override;void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private:QColor clearColor Qt::black;QPoint lastPos;int xRot 0;int yRot 0;int zRot 0;QOpenGLTexture *textures[6] {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};QOpenGLShaderProgram *program nullptr;QOpenGLBuffer vbo;QVectorfloat vertices;QOpenGLVertexArrayObject vao;QTimer* timer;float m_xRos 0.0f;float m_yRos 0.0f;float m_zRos 3.0f;QVector3D cam;int nCount0;QVector3D cameraPos;QVector3D cameraTarget;QVector3D cameraDirection;
};#endif运行下代码是不是就是可以由远到近和由近到远了呢.
我们初始化
cameraPos QVector3D(0, 0, 3);
cameraPos cameraSpeed * QVector3D(0, 0, 1);//由近到远
这样写就是近--远了呢
cameraPos QVector3D(0, 0, 30);
cameraPos - cameraSpeed * QVector3D(0, 0, 1);//由远到近了呢我们这样写是固定了摄像机观察的点是QVector3D(0, 0, 0),可是有个问题是不是当我们设置eye为
cameraPos QVector3D(0, 0, 30);的时候运行出来显示出来的效果是由远到近然后又近到远了呢为什么因为
cameraPos - cameraSpeed * QVector3D(0, 0, 1);这个值减少到负方向了?
所以我们修改下程序修改center摄像机观察的点让观察点随着摄像机变化是不是就没有由远到近 然后又由近到远呢上代码 #include glwidget.h
#include QOpenGLShaderProgram
#include QOpenGLTexture
#include QMouseEvent
#include QDateTime
#include QtMathstatic const char *vertexShaderSource #version 330\nlayout (location 0) in vec4 vertex;\nlayout (location 1) in vec4 texCoord;\nout vec4 texc;\nuniform mat4 matrix;\nuniform mat4 model;\nuniform mat4 view;\nuniform mat4 projection;\nvoid main(void)\n{\n gl_Position projection*view* matrix * vertex;\n texc texCoord;\n}\n;static const char *fragmentShaderSource #version 330\nuniform sampler2D texture;\nin vec4 texc;\nvoid main(void)\n{\n gl_FragColor texture2D(texture, texc.st);\n}\n;GLWidget::GLWidget():QOpenGLWidget(),m_xRos(0),m_yRos(0)
{cam QVector3D(m_xRos, m_yRos, m_zRos);cameraPos QVector3D(0, 0, 3);timer new QTimer;timer-setInterval(20);connect(timer,QTimer::timeout,this,[]{qDebug()timeoutnCountm_xRos;rotateBy(2 * 16, 2 * 16, -1 * 16);});}
GLWidget::~GLWidget()
{makeCurrent();vbo.destroy();for (int i 0; i 6; i)delete textures[i];delete program;doneCurrent();
}QSize GLWidget::minimumSizeHint() const
{return QSize(400, 400);
}QSize GLWidget::sizeHint() const
{return QSize(400, 400);
}void GLWidget::rotateBy(int xAngle, int yAngle, int zAngle)
{float cameraSpeed 0.2;cameraPos - cameraSpeed * QVector3D(0, 0, -1);//由远到近//cameraPos cameraSpeed * QVector3D(0, 0, -1);//由近到远xRot xAngle;yRot yAngle;zRot zAngle;update();
}void GLWidget::setClearColor(const QColor color)
{clearColor color;update();
}void GLWidget::initializeGL()
{vertices {// ---- 位置---- - 纹理坐标 - ---- 颜色 ----0.5f, -0.5f, -0.5f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f,//10.5f, 0.5f, -0.5f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,//20.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,//3-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 0.0f,//40.5f, -0.5f, 0.5f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f,//5-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,};initializeOpenGLFunctions();// makeObject();glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);//#define PROGRAM_VERTEX_ATTRIBUTE 0
//#define PROGRAM_TEXCOORD_ATTRIBUTE 1program new QOpenGLShaderProgram;program-addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);program-addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);program-link();program-bind();//激活Program对象vbo.create();vbo.bind(); //绑定到当前的OpenGL上下文,vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));//初始化VAO,设置顶点数据状态(顶点法线纹理坐标等)vao.create();vao.bind();for (int j 0; j 6; j){textures[j] new QOpenGLTexture(QImage(QString(:/cube%1.png).arg(j 1)).mirrored());textures[j]-setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);textures[j]-setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);textures[j]-setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);}program-setAttributeBuffer(0, GL_FLOAT, 0, 3, 5 * sizeof(float)); //设置aPos顶点属性program-setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 2, 5 * sizeof(float)); //设置aColor顶点颜色program-enableAttributeArray(0); //使能aPos顶点属性program-enableAttributeArray(1); //使能aColor顶点颜色program-setUniformValue(texture, 0);QMatrix4x4 projection;projection.perspective(60,(float)width()/height(),0.1,100);//构建透视矩阵,这个可以是固定写法program-setUniformValue(projection, projection);// vao.release();
// vbo.release();
}void GLWidget::paintGL()
{//glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());glEnable(GL_DEPTH_TEST);glClearColor(0.1f,0.5f,0.7f,1.0f); //设置清屏颜色glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);QMatrix4x4 m;//m.ortho(-0.5f, 0.5f, 0.5f, -0.5f, 4.0f, 15.0f);m.translate(0.0f, 0.0f, 0.0f);m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);m.scale(0.5);program-setUniformValue(matrix, m);// QMatrix4x4 view;
// view.translate(0.0f,0.0f,-3.0f);
// program-setUniformValue(view, view);QMatrix4x4 view;view.lookAt(cameraPos, cameraPosQVector3D(0,0,-1), QVector3D(0,1,0));program-setUniformValue(view, view);for (int i 0; i 6; i) {textures[i]-bind();glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);}
}
void GLWidget::resizeGL(int width, int height)
{this-glViewport(0,0,width,height); //定义视口区域
}void GLWidget::mousePressEvent(QMouseEvent *event)
{lastPos event-pos();timer-start();
}void GLWidget::mouseMoveEvent(QMouseEvent *event)
{int dx event-x() - lastPos.x();int dy event-y() - lastPos.y();if (event-buttons() Qt::LeftButton) {rotateBy(8 * dy, 8 * dx, 0);} else if (event-buttons() Qt::RightButton) {rotateBy(8 * dy, 0, 8 * dx);}lastPos event-pos();
}void GLWidget::mouseReleaseEvent(QMouseEvent * /* event */)
{emit clicked();
}
我们运行程序最后点击下屏幕是不是实现了呢