Qt OpenGL相机的使用

先看效果:
在这里插入图片描述
顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTextureCoord;
out vec3 outColor;
out vec2 textureCoord;

//矩阵必须初始化,初始化单位矩阵,否则GLSL语言中默认矩阵是0矩阵
uniform mat4 trans = mat4(1.0);

uniform mat4 model = mat4(1.0);
uniform mat4 view = mat4(1.0);
uniform mat4 projection = mat4(1.0);

void main(){
	//gl_Position = trans * vec4(aPos.x, aPos.y, aPos.z, 1.0);//在矩阵乘法中是右乘左,与显实的乘法不同
	gl_Position = projection * view * model * vec4(aPos, 1.0);
	textureCoord = aTextureCoord;
}

片段着色器:

#version 330 core
out vec4 fragColor;
in vec3 outColor;//从顶点着色器中传过来的颜色
in vec2 textureCoord;
uniform sampler2D textureImg;
uniform sampler2D textureCpp;
void main(){
	//fragColor = texture(textureImg, textureCoord);
	 fragColor = mix(texture(textureImg,textureCoord), texture(textureCpp,textureCoord), 0.5);
}

相机类:

#pragma once

#include <QVector3D>
#include <qmatrix4x4.h>

// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
enum Camera_Movement {
	FORWARD,
	BACKWARD,
	LEFT,
	RIGHT,
	UP,
	DOWN
};

// Default camera values
const float YAW = -90.0f;
const float PITCH = 0.0f;
const float SPEED = 2.5f;
const float SENSITIVITY = 0.005f;
const float ZOOM = 45.0f;


class Camera {
public:
	// camera Attributes
	QVector3D Position;
	QVector3D Front;
	QVector3D Up;
	QVector3D Right;
	QVector3D WorldUp;
	// euler Angles
	float Yaw;
	float Pitch;
	// camera options
	float MovementSpeed;
	float MouseSensitivity;
	float Zoom;

	// constructor with vectors
	Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM) {
		Position = position;
		WorldUp = up;
		Yaw = yaw;
		Pitch = pitch;
		updateCameraVectors();
	}
	// constructor with scalar values
	Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM) {
		Position = QVector3D(posX, posY, posZ);
		WorldUp = QVector3D(upX, upY, upZ);
		Yaw = yaw;
		Pitch = pitch;
		updateCameraVectors();
	}
	~Camera();

	// returns the view matrix calculated using Euler Angles and the LookAt Matrix
	QMatrix4x4 GetViewMatrix() {
		QMatrix4x4 view;
		view.lookAt(Position, Position + Front, Up);
		return view;
	}

	// processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
	void ProcessKeyboard(Camera_Movement direction, float deltaTime) {
		float velocity = MovementSpeed * deltaTime;
		if (direction == FORWARD)
			Position += Front * velocity;
		if (direction == BACKWARD)
			Position -= Front * velocity;
		if (direction == LEFT)
			Position -= Right * velocity;
		if (direction == RIGHT)
			Position += Right * velocity;
		if (direction == UP)
			Position += WorldUp * velocity;
		if (direction == DOWN)
			Position -= WorldUp * velocity;
		//updateCameraVectors();
	}

	// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
	void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true) {
		xoffset *= MouseSensitivity;
		yoffset *= MouseSensitivity;

		Yaw += xoffset;
		Pitch += yoffset;

		// make sure that when pitch is out of bounds, screen doesn't get flipped
		if (constrainPitch) {
			if (Pitch > 89.0f)
				Pitch = 89.0f;
			if (Pitch < -89.0f)
				Pitch = -89.0f;
		}

		// update Front, Right and Up Vectors using the updated Euler angles
		updateCameraVectors();
	}

	// processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
	void ProcessMouseScroll(float yoffset) {
		Zoom -= (float)yoffset;
		if (Zoom < 1.0f)
			Zoom = 1.0f;
		if (Zoom > 45.0f)
			Zoom = 45.0f;
	}

private:
	// calculates the front vector from the Camera's (updated) Euler Angles
	void updateCameraVectors() {
		// calculate the new Front vector
		QVector3D front;
		front.setX(cos(Yaw) * cos(Pitch));
		front.setY(sin(Pitch));
		front.setZ(sin(Yaw) * cos(Pitch));
		Front = front.normalized();
		// also re-calculate the Right and Up vector
		Right = QVector3D::crossProduct(Front, WorldUp).normalized();
		Up = QVector3D::crossProduct(Right, Front).normalized();
	}
};


界面类:

#pragma once

#include <QOpenGLWindow>

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QDebug>
#include <QOpenGLTexture>
#include <QElapsedTimer>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>

#include "camera.h"
class CameraWnd : public QOpenGLWindow {
	Q_OBJECT

public:
	CameraWnd();
	~CameraWnd();

protected:
	virtual void initializeGL();
	virtual void resizeGL(int w, int h);
	virtual void paintGL();

	void keyPressEvent(QKeyEvent *event);
	void mouseMoveEvent(QMouseEvent *event);
	void wheelEvent(QWheelEvent *event);
	void mousePressEvent(QMouseEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);
private:
	class QOpenGLTexture *_texture1;
	class QOpenGLTexture *_texture2;
	QElapsedTimer m_time;

	Camera m_camera;
	float m_lastX;
	float m_lastY;
	float m_deltaTime = 0.0f;
	float m_lastFrame = 0.0f;
	bool m_firstMouse = true;
	bool m_isMousePress = false;
	class QOpenGLFunctions_3_3_Core* _openGLCore;
	QOpenGLShaderProgram _shaderProgram;//着色器程序,所里系统所有的着色器
};

#include "CameraWnd.h"
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QOpenGLFunctions_3_3_Core>

static GLuint VBO, VAO = 0;
// world space positions of our cubes
static QVector3D cubePositions[] = {
	QVector3D(0.0f,  0.0f,  0.0f),
	QVector3D(2.0f,  5.0f, -15.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)
};

CameraWnd::CameraWnd() {
	m_camera.Position = QVector3D(0.0f, 0.0f, 3.0f);
	m_lastX = width() / 2;
	m_lastY = height() / 2;
}

CameraWnd::~CameraWnd() {
}

void CameraWnd::initializeGL() {
	_openGLCore = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();

	_openGLCore->glEnable(GL_DEPTH_TEST);

	float vertices[] = {
		-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
		0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
		0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
		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,  0.0f, 0.0f,
		0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
		0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
		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,
		-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, 1.0f,
		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
		-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

		0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
		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, 1.0f,
		0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
		0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
		0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
		0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
		0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
		-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
		-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

		-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
		0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
		0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
		0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
		-0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
		-0.5f,  0.5f, -0.5f,  0.0f, 1.0f
	};
	_openGLCore->glGenVertexArrays(1, &VAO);
	_openGLCore->glGenBuffers(1, &VBO);

	_openGLCore->glBindVertexArray(VAO);

	_openGLCore->glBindBuffer(GL_ARRAY_BUFFER, VBO);
	_openGLCore->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// position attribute
	_openGLCore->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
	_openGLCore->glEnableVertexAttribArray(0);
	// texture coord attribute
	_openGLCore->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
	_openGLCore->glEnableVertexAttribArray(1);

	//垂直镜像mirrored
	_texture1 = new QOpenGLTexture(QImage("E:/Projects/QtGuiTest/OPenGLApp/shader/1.jpg").mirrored());
	if (!_texture1->isCreated()) {
		qDebug() << "Failed to load texture";
	}
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	_texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	_texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	_texture1->setMinificationFilter(QOpenGLTexture::Linear);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	_texture1->setMagnificationFilter(QOpenGLTexture::Linear);
	_texture2 = new QOpenGLTexture(QImage("E:/Projects/QtGuiTest/OPenGLApp/shader/2.png").mirrored());
	if (!_texture2->isCreated()) {
		qDebug() << "Failed to load texture";
	}
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	_texture2->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	_texture2->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	_texture2->setMinificationFilter(QOpenGLTexture::Linear);
	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	_texture2->setMagnificationFilter(QOpenGLTexture::Linear);

	//设置纹理单元编号
	_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "E:/Projects/QtGuiTest/OPenGLApp/shader/Camera.vert");
	_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "E:/Projects/QtGuiTest/OPenGLApp/shader/Camera.frag");

	_shaderProgram.link();


	//如果是一张图片就不用绑定,默认绑定。如果是多于1张就需要主动绑定,
	_shaderProgram.bind();
	/*
	** textureImg:对应的片元着色器的 uniform sampler2D textureImg;
	** textureCpp:对应的片元着色器的 uniform sampler2D textureCpp;
	*/
	_shaderProgram.setUniformValue("textureImg", 0);
	_shaderProgram.setUniformValue("textureCpp", 1);

	m_time.start();
}

void CameraWnd::resizeGL(int w, int h) {
	_openGLCore->glViewport(0, 0, w, h);
}

void CameraWnd::paintGL() {
	_openGLCore->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	_openGLCore->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	float currentFrame = (float)m_time.elapsed() / 100;
	m_deltaTime = currentFrame - m_lastFrame;
	m_lastFrame = currentFrame;

	//激活纹理单元0
	_openGLCore->glActiveTexture(GL_TEXTURE0);
	_texture1->bind();
	_openGLCore->glActiveTexture(GL_TEXTURE1);
	_texture2->bind();

	// render container
	_shaderProgram.bind();
	QMatrix4x4 view = m_camera.GetViewMatrix();
	QMatrix4x4 projection;

	view.translate(QVector3D(0.0f, 0.0f, -3.0f));
	projection.perspective(m_camera.Zoom, (float)width() / (float)height(), 0.1f, 100.0f);

	for (unsigned int i = 0; i < 10; i++) {
		QMatrix4x4 model;
		model.translate(cubePositions[i]);
		float angle;
		if (i % 3 == 0) {
			angle = (float)m_time.elapsed() / 10;
		} else {
			angle = i * 20.0f;
		}
		model.rotate(angle, QVector3D(1.0f, 0.3f, 0.5f));
		_shaderProgram.setUniformValue("model", model);
		_shaderProgram.setUniformValue("view", view);
		_shaderProgram.setUniformValue("projection", projection);
		_openGLCore->glDrawArrays(GL_TRIANGLES, 0, 36);
	}
	update();
}

void CameraWnd::keyPressEvent(QKeyEvent *event) {
	if (event->key() == Qt::Key_A) {
		m_camera.ProcessKeyboard(Camera_Movement::LEFT, m_deltaTime);
	} else if (event->key() == Qt::Key_D) {
		m_camera.ProcessKeyboard(Camera_Movement::RIGHT, m_deltaTime);
	} else if (event->key() == Qt::Key_W) {
		m_camera.ProcessKeyboard(Camera_Movement::FORWARD, m_deltaTime);
	} else if (event->key() == Qt::Key_S) {
		m_camera.ProcessKeyboard(Camera_Movement::BACKWARD, m_deltaTime);
	} else if (event->key() == Qt::Key_E) {
		m_camera.ProcessKeyboard(Camera_Movement::UP, m_deltaTime);
	} else if (event->key() == Qt::Key_Q) {
		m_camera.ProcessKeyboard(Camera_Movement::DOWN, m_deltaTime);
	}
}

void CameraWnd::mouseMoveEvent(QMouseEvent *event) {
	float xpos = static_cast<float>(event->pos().x());
	float ypos = static_cast<float>(event->pos().y());
	if (!m_isMousePress)
		return;

	if (m_firstMouse) {
		m_lastX = xpos;
		m_lastY = ypos;
		m_firstMouse = false;
	}

	float xoffset = xpos - m_lastX;
	float yoffset = m_lastY - ypos; // reversed since y-coordinates go from bottom to top

	m_lastX = xpos;
	m_lastY = ypos;

	m_camera.ProcessMouseMovement(xoffset, yoffset);
}

void CameraWnd::wheelEvent(QWheelEvent *event) {
	m_camera.ProcessMouseScroll((float)event->angleDelta().y() / 60.0f);
}

void CameraWnd::mousePressEvent(QMouseEvent *event) {
	if (event->button() == Qt::LeftButton)
		m_isMousePress = true;
}

void CameraWnd::mouseReleaseEvent(QMouseEvent *event) {
	if (event->button() == Qt::LeftButton) {
		m_isMousePress = false;
		m_firstMouse = true;
	}
}

aaa

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值