为什么改变模型矩阵会改变 OpenGL 中错误对象的大小?
Why changing model matrix change size of wrong object in OpenGL?
缩放 model2 矩阵后。 model2 矩阵是网格矩阵
之前
我想增加网格而不是立方体的大小。为什么会这样?为什么缩放立方体的 y 为 0?错误在哪里?下面是我的所有代码。
查看draw_canvas.cpp paintGL 函数,有一个名为'model2' 的缩放矩阵。这一行 model2.scale(10.0f,0.0f,10.0f)。为什么这种缩放会改变我的立方体?
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
model2.scale(10.0f, 0.0f, 10.0f);
draw_canwas3D.h
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <list>
class Canvas3D : public QOpenGLWidget
{
public:
Canvas3D(QWidget *parent = nullptr) : QOpenGLWidget(parent) { };
~Canvas3D();
private:
QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vbo;
QOpenGLShaderProgram* m_program;
QOpenGLShaderProgram* gridShaderProgram;
QOpenGLShaderProgram* shLightprogram;
QVector3D cameraPos {0.0f, 0.0f, 3.0f};
QVector3D cameraFront{0.0f, 0.0f, -1.0f};
QVector3D cameraUp{0.0f, 1.0f, 0.0f};
float yaw = -90.0f;
float pitch = 0.0f;
float lastX = 400, lastY = 300;
float Zoom = 45.0;
unsigned int gridVAO;
unsigned int gridEBO;
GLuint lenght = 0;
//std::list<Object*>
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void keyPressEvent(QKeyEvent *ev) override;
bool eventFilter(QObject *obj, QEvent *event);
};
draw_canvas3D.cpp
#include "draw_canvas3D.h"
#include "src/common/geometry/shapes3D/cube.h"
#include <iostream>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions>
#include <QMatrix4x4>
#include <QVector3D>
#include <QtMath>
#include <QKeyEvent>
void Canvas3D::initializeGL()
{
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
auto functions = this->context()->functions();
functions->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
this->setGeometry(100, 100, 800, 600);
functions->glViewport(this->geometry().x(),
this->geometry().y(),
this->geometry().width(),
this->geometry().height());
m_program = new QOpenGLShaderProgram(this);
QOpenGLShader vxShader(QOpenGLShader::Vertex);
vxShader.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shader.vs");
QOpenGLShader frShader(QOpenGLShader::Fragment);
frShader.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shader.fs");
m_program->addShader(&vxShader);
m_program->addShader(&frShader);
m_program->link();
functions->glEnable(GL_DEPTH_TEST);
this->installEventFilter(this);
functions->glEnable(GL_POLYGON_SMOOTH);
functions->glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
functions->glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
/*GRID*/ //Create Class
auto additionalFunctions = this->context()->extraFunctions();
unsigned int gridVBO;
std::vector<QVector3D> vertices;
std::vector<unsigned int> indices;
int slices = 10;
for(int j=0; j<=slices; ++j) {
for(int i=0; i<=slices; ++i) {
float x = (float)i/(float)slices;
float y = 0;
float z = (float)j/(float)slices;
vertices.push_back(QVector3D(x, y, z));
}
}
for(int j=0; j<slices; ++j) {
for(int i=0; i<slices; ++i) {
int row1 = j * (slices+1);
int row2 = (j+1) * (slices+1);
indices.push_back(row1+i); indices.push_back(row1+i+1); indices.push_back(row1+i+1); indices.push_back(row2+i+1);
indices.push_back(row2+i+1); indices.push_back(row2+i); indices.push_back(row2+i); indices.push_back(row1+i);
}
}
lenght = (GLuint)indices.size()*4;
/*std::vector<QVector3D> vecLines;
std::vector<unsigned int> vecLinesIdx;*/
/*for(unsigned int nHorizontalLines = 0; nHorizontalLines < 10; ++nHorizontalLines)
{
vecLines.push_back(QVector3D(0.0f, 0.0, -(float)nHorizontalLines));
vecLines.push_back(QVector3D(9.0f, 0.0, -(float)nHorizontalLines));
}
for(unsigned int nVerticalLines = 0; nVerticalLines < 10; ++nVerticalLines)
{
vecLines.push_back(QVector3D((float)nVerticalLines, 0.0f, 0.0f));
vecLines.push_back(QVector3D((float)nVerticalLines, 0.0f, -9.0f));
}
for(unsigned int j = 0; j < 39; j+=2)
{
vecLinesIdx.push_back(j);
vecLinesIdx.push_back(j+1);
}*/
functions->glGenBuffers(1, &gridEBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridEBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
functions->glGenBuffers(1, &gridVBO);
additionalFunctions->glGenVertexArrays(1, &gridVAO);
additionalFunctions->glBindVertexArray(gridVAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, gridVBO);
functions->glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(QVector3D), vertices.data(), GL_STATIC_DRAW);
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), nullptr);
functions->glEnableVertexAttribArray(0);
gridShaderProgram = new QOpenGLShaderProgram(this);
QOpenGLShader vxShader2(QOpenGLShader::Vertex);
vxShader2.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shaderGrid.vs");
QOpenGLShader frShader2(QOpenGLShader::Fragment);
frShader2.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shaderGrid.fs");
gridShaderProgram->addShader(&vxShader2);
gridShaderProgram->addShader(&frShader2);
gridShaderProgram->link();
/*GRID END*/
}
void Canvas3D::resizeGL(int w, int h)
{
auto functions = this->context()->functions();
functions->glViewport(0,
0,
this->geometry().width(),
this->geometry().height());
}
void Canvas3D::paintGL()
{
auto functions = this->context()->functions();
//auto additionalFunctions = this->context()->extraFunctions();
functions->glClearColor(0.0f / 255.0f, 25.0f / 255.0f, 53.0f / 255.0f, 1.0f);
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 projection;
projection.perspective(Zoom, 800.0f / 600.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.lookAt(cameraPos,
cameraPos + cameraFront,
cameraUp);
unsigned int viewID = m_program->uniformLocation("view");
functions->glUniformMatrix4fv(viewID, 1, GL_FALSE, view.constData());
unsigned int projectionID = m_program->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID, 1, GL_FALSE, projection.constData());
QVector3D cubePositions[] = {
QVector3D(0.0f, 0.0, 0.0),
QVector3D( 0.5f, 0.0f, 0.5f),
QVector3D( 2.0f, 0.0f, 3.0f),
QVector3D(-1.5f, -2.2f, -2.5f),
QVector3D(-3.8f, -2.0f, -12.3f),
QVector3D( 2.4f, -0.4f, -3.5f),
QVector3D(-1.7f, 3.0f, -7.5f),
QVector3D( 1.3f, -2.0f, -2.5f),
QVector3D( 1.5f, 2.0f, -2.5f),
QVector3D( 1.5f, 0.2f, -1.5f),
QVector3D(-1.3f, 1.0f, -1.5f)
};
for(unsigned int i = 0; i < 2; i++)
{
QMatrix4x4 model(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID = m_program->uniformLocation("model");
model.translate(cubePositions[i]);
functions->glUniformMatrix4fv(modelID, 1, GL_FALSE, model.constData());
auto cube3d = new invar::geometry3D::Cube(cubePositions[i], 1*qSqrt(3), m_program);
cube3d->Draw();
}
auto additionalFunctions = this->context()->extraFunctions();
additionalFunctions->glBindVertexArray(0);
/*GRID*/
unsigned int viewID2 = gridShaderProgram->uniformLocation("view");
functions->glUniformMatrix4fv(viewID2, 1, GL_FALSE, view.constData());
unsigned int projectionID2 = gridShaderProgram->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID2, 1, GL_FALSE, projection.constData());
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
//model2.scale(10.0f, 0.0f, 10.0f); ------ THIS SCALING
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
functions->glUniformMatrix4fv(modelID2, 1, GL_FALSE, model2.constData());
gridShaderProgram->bind();
additionalFunctions->glBindVertexArray(gridVAO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridEBO);
functions->glDrawElements(GL_LINES, lenght, GL_UNSIGNED_INT, 0);
/*GRID END*/
}
void Canvas3D::keyPressEvent(QKeyEvent *ev)
{
const float cameraSpeed = 0.25f;
if(ev->key() == Qt::Key_W)
cameraPos += cameraSpeed * cameraFront;
else if(ev->key() == Qt::Key_S)
cameraPos -= cameraSpeed * cameraFront;
else if(ev->key() == Qt::Key_A)
cameraPos -= QVector3D(QVector3D::crossProduct(cameraFront, cameraUp)) * cameraSpeed;
else if(ev->key() == Qt::Key_D)
cameraPos += QVector3D(QVector3D::crossProduct(cameraFront, cameraUp)) * cameraSpeed;
else if(ev->key() == Qt::Key_Q)
{
/*Rotate camera*/
}
else if(ev->key() == Qt::Key_E)
{
/*Rotate camera*/
}
}
bool Canvas3D::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
lastX = mouseEvent->pos().x();
lastY = mouseEvent->pos().y();
}
if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
float xoffset = mouseEvent->pos().x() - lastX;
float yoffset = lastY - mouseEvent->pos().y();
lastX = mouseEvent->pos().x();
lastY = mouseEvent->pos().y();
float sensitivity = 0.1f;
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
QVector3D direction;
direction.setX(qCos(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
direction.setY(qSin(qDegreesToRadians(pitch)));
direction.setZ(qSin(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
cameraFront = direction.normalized();
}
else if (event->type() == QEvent::Wheel)
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
QPoint numDegrees = wheelEvent->angleDelta();
if (numDegrees.y() < 0 && Zoom < 45.0f)
Zoom += 1.0f;
if (numDegrees.y() > 0 && Zoom > 1.0f)
Zoom -= 1.0f;
}
return false;
}
Canvas3D::~Canvas3D()
{
//delete f;
}
cube.cpp
#include "src/common/geometry/shapes3D/cube.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QtMath>
#include <iostream>
namespace invar::geometry3D
{
void Cube::Draw()
{
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
m_program->bind();
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
int size;
functions->glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
functions->glDrawElements(GL_TRIANGLES, size/sizeof(float), GL_UNSIGNED_INT, 0);
}
void Cube::setupShape()
{
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
float vertices[] = {
-0.5f,0.5f,-0.5f, 0.0f, 0.0f, 0.0f,//Point A 0
-0.5f,0.5f,0.5f, 0.0f, 0.0f, 1.0f,//Point B 1
0.5f,0.5f,-0.5f, 0.0f, 1.0f, 0.0f,//Point C 2
0.5f,0.5f,0.5f, 0.0f, 1.0f, 1.0f,//Point D 3
-0.5f,-0.5f,-0.5f, 1.0f, 0.0f, 0.0f,//Point E 4
-0.5f,-0.5f,0.5f, 1.0f, 0.0f, 1.0f,//Point F 5
0.5f,-0.5f,-0.5f, 1.0f, 1.0f, 0.0f,//Point G 6
0.5f,-0.5f,0.5f, 1.0f, 1.0f, 1.0f//Point H 7
};
unsigned int indices[] = {
0,1,2,
1,2,3,
4,5,6,
5,6,7,
0,1,5,
0,4,5,
2,3,7,
2,6,7,
0,2,6,
0,4,6,
1,5,7,
1,3,7
};
functions->glGenBuffers(1, &EBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
unsigned int VBO;
functions->glGenBuffers(1, &VBO);
additionalFunctions->glGenVertexArrays(1, &VAO);
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, VBO);
functions->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
functions->glEnableVertexAttribArray(0);/*Check if need to normilize*/
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float),(void*)0);
functions->glEnableVertexAttribArray(1);
functions->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float),
(void*)(3*sizeof(float)));
additionalFunctions->glBindVertexArray(0);
}
Cube::Cube(QVector3D pos, float diagonal, QOpenGLShaderProgram* m_program):
pos(pos), diagonal(diagonal), m_program(m_program)
{
this->setupShape();
}
}
cube.h
#pragma once
#include "shape3D.h"
#include <QOpenGLContext>
#include <QVector3D>
#include <QOpenGLShaderProgram>
namespace invar::geometry3D
{
class Cube
{
public:
Cube(QVector3D pos, float diagonal, QOpenGLShaderProgram* program);
void Draw();
private:
unsigned int VAO;
unsigned int EBO;
QVector3D pos;
float diagonal;
QOpenGLShaderProgram* m_program;
void setupShape();
};
}
着色器很简单
shaderGrid.fs
#version 130
out vec4 FragColor;
void main()
{
FragColor = vec4(0, 1.0, 1.0, 1.0);
}
shaderGrid.vs
#version 130
in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
shader.fs //--- 立方体片段着色器
#version 130
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0);
}
shader.vs //--- 立方体顶点着色器
#version 130
in vec3 aPos;
in vec3 aColor;
out vec3 ourColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
ourColor = aColor;
}
glUniform*
更改当前安装的着色器程序的制服。因此,在设置制服之前必须安装(bind
)程序:
gridShaderProgram->bind(); // <--- INSERT
unsigned int viewID2 = gridShaderProgram->uniformLocation("view");
functions->glUniformMatrix4fv(viewID2, 1, GL_FALSE, view.constData());
unsigned int projectionID2 = gridShaderProgram->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID2, 1, GL_FALSE, projection.constData());
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
//model2.scale(10.0f, 0.0f, 10.0f); ------ THIS SCALING
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
functions->glUniformMatrix4fv(modelID2, 1, GL_FALSE, model2.constData());
// gridShaderProgram->bind(); <--- DELETE
缩放 model2 矩阵后。 model2 矩阵是网格矩阵
之前
我想增加网格而不是立方体的大小。为什么会这样?为什么缩放立方体的 y 为 0?错误在哪里?下面是我的所有代码。
查看draw_canvas.cpp paintGL 函数,有一个名为'model2' 的缩放矩阵。这一行 model2.scale(10.0f,0.0f,10.0f)。为什么这种缩放会改变我的立方体?
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
model2.scale(10.0f, 0.0f, 10.0f);
draw_canwas3D.h
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <list>
class Canvas3D : public QOpenGLWidget
{
public:
Canvas3D(QWidget *parent = nullptr) : QOpenGLWidget(parent) { };
~Canvas3D();
private:
QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vbo;
QOpenGLShaderProgram* m_program;
QOpenGLShaderProgram* gridShaderProgram;
QOpenGLShaderProgram* shLightprogram;
QVector3D cameraPos {0.0f, 0.0f, 3.0f};
QVector3D cameraFront{0.0f, 0.0f, -1.0f};
QVector3D cameraUp{0.0f, 1.0f, 0.0f};
float yaw = -90.0f;
float pitch = 0.0f;
float lastX = 400, lastY = 300;
float Zoom = 45.0;
unsigned int gridVAO;
unsigned int gridEBO;
GLuint lenght = 0;
//std::list<Object*>
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void keyPressEvent(QKeyEvent *ev) override;
bool eventFilter(QObject *obj, QEvent *event);
};
draw_canvas3D.cpp
#include "draw_canvas3D.h"
#include "src/common/geometry/shapes3D/cube.h"
#include <iostream>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLExtraFunctions>
#include <QMatrix4x4>
#include <QVector3D>
#include <QtMath>
#include <QKeyEvent>
void Canvas3D::initializeGL()
{
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
auto functions = this->context()->functions();
functions->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
this->setGeometry(100, 100, 800, 600);
functions->glViewport(this->geometry().x(),
this->geometry().y(),
this->geometry().width(),
this->geometry().height());
m_program = new QOpenGLShaderProgram(this);
QOpenGLShader vxShader(QOpenGLShader::Vertex);
vxShader.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shader.vs");
QOpenGLShader frShader(QOpenGLShader::Fragment);
frShader.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shader.fs");
m_program->addShader(&vxShader);
m_program->addShader(&frShader);
m_program->link();
functions->glEnable(GL_DEPTH_TEST);
this->installEventFilter(this);
functions->glEnable(GL_POLYGON_SMOOTH);
functions->glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
functions->glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
/*GRID*/ //Create Class
auto additionalFunctions = this->context()->extraFunctions();
unsigned int gridVBO;
std::vector<QVector3D> vertices;
std::vector<unsigned int> indices;
int slices = 10;
for(int j=0; j<=slices; ++j) {
for(int i=0; i<=slices; ++i) {
float x = (float)i/(float)slices;
float y = 0;
float z = (float)j/(float)slices;
vertices.push_back(QVector3D(x, y, z));
}
}
for(int j=0; j<slices; ++j) {
for(int i=0; i<slices; ++i) {
int row1 = j * (slices+1);
int row2 = (j+1) * (slices+1);
indices.push_back(row1+i); indices.push_back(row1+i+1); indices.push_back(row1+i+1); indices.push_back(row2+i+1);
indices.push_back(row2+i+1); indices.push_back(row2+i); indices.push_back(row2+i); indices.push_back(row1+i);
}
}
lenght = (GLuint)indices.size()*4;
/*std::vector<QVector3D> vecLines;
std::vector<unsigned int> vecLinesIdx;*/
/*for(unsigned int nHorizontalLines = 0; nHorizontalLines < 10; ++nHorizontalLines)
{
vecLines.push_back(QVector3D(0.0f, 0.0, -(float)nHorizontalLines));
vecLines.push_back(QVector3D(9.0f, 0.0, -(float)nHorizontalLines));
}
for(unsigned int nVerticalLines = 0; nVerticalLines < 10; ++nVerticalLines)
{
vecLines.push_back(QVector3D((float)nVerticalLines, 0.0f, 0.0f));
vecLines.push_back(QVector3D((float)nVerticalLines, 0.0f, -9.0f));
}
for(unsigned int j = 0; j < 39; j+=2)
{
vecLinesIdx.push_back(j);
vecLinesIdx.push_back(j+1);
}*/
functions->glGenBuffers(1, &gridEBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridEBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
functions->glGenBuffers(1, &gridVBO);
additionalFunctions->glGenVertexArrays(1, &gridVAO);
additionalFunctions->glBindVertexArray(gridVAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, gridVBO);
functions->glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(QVector3D), vertices.data(), GL_STATIC_DRAW);
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), nullptr);
functions->glEnableVertexAttribArray(0);
gridShaderProgram = new QOpenGLShaderProgram(this);
QOpenGLShader vxShader2(QOpenGLShader::Vertex);
vxShader2.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shaderGrid.vs");
QOpenGLShader frShader2(QOpenGLShader::Fragment);
frShader2.compileSourceFile("/main/stage/home/andreyp/fork_invar/invar/shaders/shaderGrid.fs");
gridShaderProgram->addShader(&vxShader2);
gridShaderProgram->addShader(&frShader2);
gridShaderProgram->link();
/*GRID END*/
}
void Canvas3D::resizeGL(int w, int h)
{
auto functions = this->context()->functions();
functions->glViewport(0,
0,
this->geometry().width(),
this->geometry().height());
}
void Canvas3D::paintGL()
{
auto functions = this->context()->functions();
//auto additionalFunctions = this->context()->extraFunctions();
functions->glClearColor(0.0f / 255.0f, 25.0f / 255.0f, 53.0f / 255.0f, 1.0f);
functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 projection;
projection.perspective(Zoom, 800.0f / 600.0f, 0.1f, 100.0f);
QMatrix4x4 view;
view.lookAt(cameraPos,
cameraPos + cameraFront,
cameraUp);
unsigned int viewID = m_program->uniformLocation("view");
functions->glUniformMatrix4fv(viewID, 1, GL_FALSE, view.constData());
unsigned int projectionID = m_program->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID, 1, GL_FALSE, projection.constData());
QVector3D cubePositions[] = {
QVector3D(0.0f, 0.0, 0.0),
QVector3D( 0.5f, 0.0f, 0.5f),
QVector3D( 2.0f, 0.0f, 3.0f),
QVector3D(-1.5f, -2.2f, -2.5f),
QVector3D(-3.8f, -2.0f, -12.3f),
QVector3D( 2.4f, -0.4f, -3.5f),
QVector3D(-1.7f, 3.0f, -7.5f),
QVector3D( 1.3f, -2.0f, -2.5f),
QVector3D( 1.5f, 2.0f, -2.5f),
QVector3D( 1.5f, 0.2f, -1.5f),
QVector3D(-1.3f, 1.0f, -1.5f)
};
for(unsigned int i = 0; i < 2; i++)
{
QMatrix4x4 model(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID = m_program->uniformLocation("model");
model.translate(cubePositions[i]);
functions->glUniformMatrix4fv(modelID, 1, GL_FALSE, model.constData());
auto cube3d = new invar::geometry3D::Cube(cubePositions[i], 1*qSqrt(3), m_program);
cube3d->Draw();
}
auto additionalFunctions = this->context()->extraFunctions();
additionalFunctions->glBindVertexArray(0);
/*GRID*/
unsigned int viewID2 = gridShaderProgram->uniformLocation("view");
functions->glUniformMatrix4fv(viewID2, 1, GL_FALSE, view.constData());
unsigned int projectionID2 = gridShaderProgram->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID2, 1, GL_FALSE, projection.constData());
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
//model2.scale(10.0f, 0.0f, 10.0f); ------ THIS SCALING
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
functions->glUniformMatrix4fv(modelID2, 1, GL_FALSE, model2.constData());
gridShaderProgram->bind();
additionalFunctions->glBindVertexArray(gridVAO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gridEBO);
functions->glDrawElements(GL_LINES, lenght, GL_UNSIGNED_INT, 0);
/*GRID END*/
}
void Canvas3D::keyPressEvent(QKeyEvent *ev)
{
const float cameraSpeed = 0.25f;
if(ev->key() == Qt::Key_W)
cameraPos += cameraSpeed * cameraFront;
else if(ev->key() == Qt::Key_S)
cameraPos -= cameraSpeed * cameraFront;
else if(ev->key() == Qt::Key_A)
cameraPos -= QVector3D(QVector3D::crossProduct(cameraFront, cameraUp)) * cameraSpeed;
else if(ev->key() == Qt::Key_D)
cameraPos += QVector3D(QVector3D::crossProduct(cameraFront, cameraUp)) * cameraSpeed;
else if(ev->key() == Qt::Key_Q)
{
/*Rotate camera*/
}
else if(ev->key() == Qt::Key_E)
{
/*Rotate camera*/
}
}
bool Canvas3D::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
lastX = mouseEvent->pos().x();
lastY = mouseEvent->pos().y();
}
if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
float xoffset = mouseEvent->pos().x() - lastX;
float yoffset = lastY - mouseEvent->pos().y();
lastX = mouseEvent->pos().x();
lastY = mouseEvent->pos().y();
float sensitivity = 0.1f;
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
QVector3D direction;
direction.setX(qCos(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
direction.setY(qSin(qDegreesToRadians(pitch)));
direction.setZ(qSin(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
cameraFront = direction.normalized();
}
else if (event->type() == QEvent::Wheel)
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
QPoint numDegrees = wheelEvent->angleDelta();
if (numDegrees.y() < 0 && Zoom < 45.0f)
Zoom += 1.0f;
if (numDegrees.y() > 0 && Zoom > 1.0f)
Zoom -= 1.0f;
}
return false;
}
Canvas3D::~Canvas3D()
{
//delete f;
}
cube.cpp
#include "src/common/geometry/shapes3D/cube.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QtMath>
#include <iostream>
namespace invar::geometry3D
{
void Cube::Draw()
{
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
m_program->bind();
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
int size;
functions->glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
functions->glDrawElements(GL_TRIANGLES, size/sizeof(float), GL_UNSIGNED_INT, 0);
}
void Cube::setupShape()
{
auto context = QOpenGLContext::currentContext();
auto functions = context->functions();
auto additionalFunctions = context->extraFunctions();
float vertices[] = {
-0.5f,0.5f,-0.5f, 0.0f, 0.0f, 0.0f,//Point A 0
-0.5f,0.5f,0.5f, 0.0f, 0.0f, 1.0f,//Point B 1
0.5f,0.5f,-0.5f, 0.0f, 1.0f, 0.0f,//Point C 2
0.5f,0.5f,0.5f, 0.0f, 1.0f, 1.0f,//Point D 3
-0.5f,-0.5f,-0.5f, 1.0f, 0.0f, 0.0f,//Point E 4
-0.5f,-0.5f,0.5f, 1.0f, 0.0f, 1.0f,//Point F 5
0.5f,-0.5f,-0.5f, 1.0f, 1.0f, 0.0f,//Point G 6
0.5f,-0.5f,0.5f, 1.0f, 1.0f, 1.0f//Point H 7
};
unsigned int indices[] = {
0,1,2,
1,2,3,
4,5,6,
5,6,7,
0,1,5,
0,4,5,
2,3,7,
2,6,7,
0,2,6,
0,4,6,
1,5,7,
1,3,7
};
functions->glGenBuffers(1, &EBO);
functions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
functions->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
unsigned int VBO;
functions->glGenBuffers(1, &VBO);
additionalFunctions->glGenVertexArrays(1, &VAO);
additionalFunctions->glBindVertexArray(VAO);
functions->glBindBuffer(GL_ARRAY_BUFFER, VBO);
functions->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
functions->glEnableVertexAttribArray(0);/*Check if need to normilize*/
functions->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float),(void*)0);
functions->glEnableVertexAttribArray(1);
functions->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float),
(void*)(3*sizeof(float)));
additionalFunctions->glBindVertexArray(0);
}
Cube::Cube(QVector3D pos, float diagonal, QOpenGLShaderProgram* m_program):
pos(pos), diagonal(diagonal), m_program(m_program)
{
this->setupShape();
}
}
cube.h
#pragma once
#include "shape3D.h"
#include <QOpenGLContext>
#include <QVector3D>
#include <QOpenGLShaderProgram>
namespace invar::geometry3D
{
class Cube
{
public:
Cube(QVector3D pos, float diagonal, QOpenGLShaderProgram* program);
void Draw();
private:
unsigned int VAO;
unsigned int EBO;
QVector3D pos;
float diagonal;
QOpenGLShaderProgram* m_program;
void setupShape();
};
}
着色器很简单
shaderGrid.fs
#version 130
out vec4 FragColor;
void main()
{
FragColor = vec4(0, 1.0, 1.0, 1.0);
}
shaderGrid.vs
#version 130
in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
shader.fs //--- 立方体片段着色器
#version 130
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0);
}
shader.vs //--- 立方体顶点着色器
#version 130
in vec3 aPos;
in vec3 aColor;
out vec3 ourColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
ourColor = aColor;
}
glUniform*
更改当前安装的着色器程序的制服。因此,在设置制服之前必须安装(bind
)程序:
gridShaderProgram->bind(); // <--- INSERT
unsigned int viewID2 = gridShaderProgram->uniformLocation("view");
functions->glUniformMatrix4fv(viewID2, 1, GL_FALSE, view.constData());
unsigned int projectionID2 = gridShaderProgram->uniformLocation("projection");
functions->glUniformMatrix4fv(projectionID2, 1, GL_FALSE, projection.constData());
QMatrix4x4 model2(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
unsigned int modelID2 = gridShaderProgram->uniformLocation("model");
//model2.scale(10.0f, 0.0f, 10.0f); ------ THIS SCALING
model2.translate(QVector3D(0.0f, 0.0f, 0.0f));
functions->glUniformMatrix4fv(modelID2, 1, GL_FALSE, model2.constData());
// gridShaderProgram->bind(); <--- DELETE