Qmatrix4x4 翻译不生效
Qmatrix4x4 translate does not take any effect
我在 opengl 方面没有太多经验,所以如果问题很愚蠢,请原谅。
我试图通过在 class glView 中转换 Qmatrix4x4 字段来使用 mouseMoveEvent 移动三角形。当我什么都没做(透视,用矩阵翻译)只是调用 m_program->setUniformValue(m_matrixUniform, m_matrix)
一切正常,但如果我只是做 this->m_matrix=matrix;
(其中矩阵只是 Qmatrix4x4 变量)然后 m_program->setUniformValue(m_matrixUniform, m_matrix)
方法无效。
在我看来,我在更新小部件(我只是调用 update())或所有着色器逻辑方面遇到了一些问题。谢谢!
//Here is glView.h
#ifndef GLVIEW_H
#define GLVIEW_H
#include <QtOpenGL>
#include <QGLWidget>
#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QMouseEvent>
//Class for drawing triangles
class glView : public QOpenGLWidget, public QOpenGLFunctions
{
public:
glView(float left, float right, float bot, float top, float minz, float maxz)
: QOpenGLWidget(), QOpenGLFunctions(), f_left(left), f_right(right), f_bot(bot), f_top(top), f_minz(minz), f_maxz(maxz)
{}
virtual~glView()
{}
void initializeGL() override;
void resizeGL(int w, int h)override;
void paintGL()override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent* pe) Q_DECL_OVERRIDE;
private:
struct CFace{
int v1,v2,v3;
};
GLuint m_posAttr;
GLuint m_colAttr;
GLuint m_matrixUniform;
QOpenGLShaderProgram *m_program;
int m_frame = 0;
QMatrix4x4 m_matrix;
QPoint mPrevMousePos;
};
#endif // GLVIEW_H
和 cpp
//Here is glView.cpp
#include <qopengl.h>
#include "glView.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QMatrix4x4>
#include <QtGui/QOpenGLShaderProgram>
#include <QMouseEvent>
static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute lowp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix*posAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
"void main() {\n"
" gl_FragColor = col;\n"
"}\n";
//------------------------------------------------------------------------------
void glView::initializeGL()
{
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
}
//------------------------------------------------------------------------------
void glView::paintGL()
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
const qreal retinaScale = devicePixelRatio();
f->glViewport(0, 0, width() * retinaScale, height() * retinaScale);
f->glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
//Here is the problem!
//matrix.perspective(0.0f, 4.0f/3.0f, 0.1f, 100.0f);
//matrix.translate(-5, -5, 0);
//???
this->m_matrix=matrix;
m_program->setUniformValue(m_matrixUniform, m_matrix);
GLfloat vertices[] = {
0.0f, 0.707f,
-0.5f, -0.5f,
0.5f, -0.5f
};
GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
f->glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
f->glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glDrawArrays(GL_TRIANGLES, 0, 3);
f->glDisableVertexAttribArray(1);
f->glDisableVertexAttribArray(0);
m_program->release();
++m_frame;
}
void glView::mousePressEvent(QMouseEvent *event)
{
mPrevMousePos = event->pos();
QOpenGLWidget::mousePressEvent(event);
}
void glView::mouseMoveEvent(QMouseEvent *event)
{
auto diff = event->pos() - mPrevMousePos;
//??
this->m_matrix.translate(diff.x()/(width()*0.5), -diff.y()/(height()*0.5));
mPrevMousePos = event->pos();
//?? m_program->setUniformValue(m_matrixUniform, m_matrix);
update();
QOpenGLWidget::mouseMoveEvent(event);
}
void glView::mouseReleaseEvent(QMouseEvent *event)
{
QOpenGLWidget::mouseReleaseEvent(event);
}
void glView::keyPressEvent(QKeyEvent *pe)
{
switch (pe->key())
{
case Qt::Key_Up:
this->m_matrix.scale(QVector3D(2.0f,2.0f,1.0f));
break;
case Qt::Key_Down:
this->m_matrix.translate(QVector3D(0,-1,0));
break;
}
update();
QOpenGLWidget::keyPressEvent(pe); // Передать событие дальше
}
QMatrix4x4::perspective
的第一个参数是以度为单位的垂直视场角。如果角度为0,视野无限小,是一个点。例如使用 90.0 度。
3D参数是到近平面的距离,第4个参数是到远平面的距离。近平面和远平面定义视锥体的界限。所有几何图形都必须位于该区域中。所以在你的情况下,近的是 0.1 而远的是 100.0.
由于 z 轴指向 viewspace 中的视口,您必须设置一个大于 -0.1 且小于 *-100.0.[=20= 的 z 平移]
由于透视投影的视图体积是一个平截头锥体(截头金字塔),在视口投影中的 x 和 y 平移量取决于深度(视图 space z 坐标)的几何形状和视野角度。无论如何 (-5, -5) 与此设置有很大关系,并且会将三角形移出视图。但是你可以使用 (-1, -1) 例如。
QMatrix4x4 matrix;
matrix.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(-1.0, -1.0, -2.0);
this->m_matrix=matrix;
m_program->setUniformValue(m_matrixUniform, m_matrix);
注意,通常使用视图矩阵来定义视角和场景的外观。
投影矩阵定义了 3 维场景在 2 维视口上的投影。在透视投影中,投影矩阵描述了从针孔相机看到的世界中的 3D 点到视口的 2D 点的映射。
视图矩阵定义了观察点和观察方向。
模型矩阵定义了对象在场景(世界)中的比例方向和位置。
模型视图投影矩阵是投影、视图和模型矩阵的串联,定义了顶点坐标从模型空间到裁剪的转换space:
mvp = projection * view * model
在您的情况下,这意味着:
QMatrix4x4 projection;
projection.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.translate(0, 0, -2.0);
QMatrix4x4 model = this->m_matrix;
QMatrix4x4 mvp = projection * view * model;
m_program->setUniformValue(m_matrixUniform, mvp);
但请注意,在透视投影中,位移量取决于在视口上拖动的对象的深度。
如果对象靠近眼睛位置,则视口上的平移会导致眼睛和目标位置发生小位移:
如果物体到眼睛的距离很远,那么视口上的平移会导致眼睛和目标位置发生较大的位移:
查看演示:
在这种情况下,数量将为 "equal",视野为 90 度,深度为 1:
QMatrix4x4 projection;
projection.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.translate(0, 0, -1.0);
我在 opengl 方面没有太多经验,所以如果问题很愚蠢,请原谅。
我试图通过在 class glView 中转换 Qmatrix4x4 字段来使用 mouseMoveEvent 移动三角形。当我什么都没做(透视,用矩阵翻译)只是调用 m_program->setUniformValue(m_matrixUniform, m_matrix)
一切正常,但如果我只是做 this->m_matrix=matrix;
(其中矩阵只是 Qmatrix4x4 变量)然后 m_program->setUniformValue(m_matrixUniform, m_matrix)
方法无效。
在我看来,我在更新小部件(我只是调用 update())或所有着色器逻辑方面遇到了一些问题。谢谢!
//Here is glView.h
#ifndef GLVIEW_H
#define GLVIEW_H
#include <QtOpenGL>
#include <QGLWidget>
#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QMouseEvent>
//Class for drawing triangles
class glView : public QOpenGLWidget, public QOpenGLFunctions
{
public:
glView(float left, float right, float bot, float top, float minz, float maxz)
: QOpenGLWidget(), QOpenGLFunctions(), f_left(left), f_right(right), f_bot(bot), f_top(top), f_minz(minz), f_maxz(maxz)
{}
virtual~glView()
{}
void initializeGL() override;
void resizeGL(int w, int h)override;
void paintGL()override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent* pe) Q_DECL_OVERRIDE;
private:
struct CFace{
int v1,v2,v3;
};
GLuint m_posAttr;
GLuint m_colAttr;
GLuint m_matrixUniform;
QOpenGLShaderProgram *m_program;
int m_frame = 0;
QMatrix4x4 m_matrix;
QPoint mPrevMousePos;
};
#endif // GLVIEW_H
和 cpp
//Here is glView.cpp
#include <qopengl.h>
#include "glView.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QMatrix4x4>
#include <QtGui/QOpenGLShaderProgram>
#include <QMouseEvent>
static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute lowp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix*posAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
"void main() {\n"
" gl_FragColor = col;\n"
"}\n";
//------------------------------------------------------------------------------
void glView::initializeGL()
{
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
}
//------------------------------------------------------------------------------
void glView::paintGL()
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
const qreal retinaScale = devicePixelRatio();
f->glViewport(0, 0, width() * retinaScale, height() * retinaScale);
f->glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
//Here is the problem!
//matrix.perspective(0.0f, 4.0f/3.0f, 0.1f, 100.0f);
//matrix.translate(-5, -5, 0);
//???
this->m_matrix=matrix;
m_program->setUniformValue(m_matrixUniform, m_matrix);
GLfloat vertices[] = {
0.0f, 0.707f,
-0.5f, -0.5f,
0.5f, -0.5f
};
GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
f->glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, 0, vertices);
f->glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glDrawArrays(GL_TRIANGLES, 0, 3);
f->glDisableVertexAttribArray(1);
f->glDisableVertexAttribArray(0);
m_program->release();
++m_frame;
}
void glView::mousePressEvent(QMouseEvent *event)
{
mPrevMousePos = event->pos();
QOpenGLWidget::mousePressEvent(event);
}
void glView::mouseMoveEvent(QMouseEvent *event)
{
auto diff = event->pos() - mPrevMousePos;
//??
this->m_matrix.translate(diff.x()/(width()*0.5), -diff.y()/(height()*0.5));
mPrevMousePos = event->pos();
//?? m_program->setUniformValue(m_matrixUniform, m_matrix);
update();
QOpenGLWidget::mouseMoveEvent(event);
}
void glView::mouseReleaseEvent(QMouseEvent *event)
{
QOpenGLWidget::mouseReleaseEvent(event);
}
void glView::keyPressEvent(QKeyEvent *pe)
{
switch (pe->key())
{
case Qt::Key_Up:
this->m_matrix.scale(QVector3D(2.0f,2.0f,1.0f));
break;
case Qt::Key_Down:
this->m_matrix.translate(QVector3D(0,-1,0));
break;
}
update();
QOpenGLWidget::keyPressEvent(pe); // Передать событие дальше
}
QMatrix4x4::perspective
的第一个参数是以度为单位的垂直视场角。如果角度为0,视野无限小,是一个点。例如使用 90.0 度。
3D参数是到近平面的距离,第4个参数是到远平面的距离。近平面和远平面定义视锥体的界限。所有几何图形都必须位于该区域中。所以在你的情况下,近的是 0.1 而远的是 100.0.
由于 z 轴指向 viewspace 中的视口,您必须设置一个大于 -0.1 且小于 *-100.0.[=20= 的 z 平移]
由于透视投影的视图体积是一个平截头锥体(截头金字塔),在视口投影中的 x 和 y 平移量取决于深度(视图 space z 坐标)的几何形状和视野角度。无论如何 (-5, -5) 与此设置有很大关系,并且会将三角形移出视图。但是你可以使用 (-1, -1) 例如。
QMatrix4x4 matrix;
matrix.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(-1.0, -1.0, -2.0);
this->m_matrix=matrix;
m_program->setUniformValue(m_matrixUniform, m_matrix);
注意,通常使用视图矩阵来定义视角和场景的外观。
投影矩阵定义了 3 维场景在 2 维视口上的投影。在透视投影中,投影矩阵描述了从针孔相机看到的世界中的 3D 点到视口的 2D 点的映射。
视图矩阵定义了观察点和观察方向。
模型矩阵定义了对象在场景(世界)中的比例方向和位置。
模型视图投影矩阵是投影、视图和模型矩阵的串联,定义了顶点坐标从模型空间到裁剪的转换space:
mvp = projection * view * model
在您的情况下,这意味着:
QMatrix4x4 projection;
projection.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.translate(0, 0, -2.0);
QMatrix4x4 model = this->m_matrix;
QMatrix4x4 mvp = projection * view * model;
m_program->setUniformValue(m_matrixUniform, mvp);
但请注意,在透视投影中,位移量取决于在视口上拖动的对象的深度。
如果对象靠近眼睛位置,则视口上的平移会导致眼睛和目标位置发生小位移:
如果物体到眼睛的距离很远,那么视口上的平移会导致眼睛和目标位置发生较大的位移:
查看演示:
在这种情况下,数量将为 "equal",视野为 90 度,深度为 1:
QMatrix4x4 projection;
projection.perspective(90.0f, 4.0f/3.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.translate(0, 0, -1.0);