Qt OPenGL 光的漫反射

16 篇文章 14 订阅
该代码示例展示了如何在OpenGL环境中实现基于Qt的3D场景,包括 DiffuseLightCamera 类用于处理摄像机的视角变化,以及 DiffuseLightWnd 类处理窗口渲染和用户输入交互。通过键盘和鼠标操作可以调整摄像机视角,滚轮改变缩放,同时展示了顶点着色器和片段着色器中漫射光照的计算过程。
摘要由CSDN通过智能技术生成

先看效果:
在这里插入图片描述
相机:

#pragma once
#include <QVector3D>
#include <QMatrix4x4>

class DiffuseLightCamera {
public:
	DiffuseLightCamera(QVector3D position, float pitch, float yaw, QVector3D wordUp);
	~DiffuseLightCamera();
	QMatrix4x4 getViewMatrix();

	void wheel(int detal);
	float&getZoom() {
		return _zoom;
	}

	void keyPress(int key);
	void mouseMove(float xoffset, float yoffset);
private:
	void updateCameraVector();
private:
	float _pitch = 0.0;
	float _yaw = 0.0;
	QVector3D _wordUp;
	QVector3D _right;

	QVector3D _position = QVector3D(0.0, 0.0, -3.0);
	QVector3D _up = QVector3D(0.0, 1.0, 0.0);
	QVector3D _front = QVector3D(0.0, 0.0, 0.0);


	float _zoom = 45.0;
	float _zoomStep = 2.0;

};


#include "DiffuseLightCamera.h"

DiffuseLightCamera::DiffuseLightCamera(QVector3D position, float pitch, float yaw, QVector3D wordUp) {
	_position = position;
	_pitch = pitch;
	_yaw = yaw;
	_wordUp = wordUp;

	updateCameraVector();
}


DiffuseLightCamera::~DiffuseLightCamera() {

}

QMatrix4x4 DiffuseLightCamera::getViewMatrix() {
	QMatrix4x4 viewMatrix;
	viewMatrix.lookAt(_position, _position + _front, _up);
	return viewMatrix;
}

void DiffuseLightCamera::wheel(int detal) {
	if (detal < 0) {
		_zoom += _zoomStep;
		if (_zoom >= 60.0) {
			_zoom = 60.0;
		}
	} else {
		_zoom -= _zoomStep;
		if (_zoom <= 1.0) {
			_zoom = 1.0;
		}
	}
}

void DiffuseLightCamera::keyPress(int key) {
	if (key == Qt::Key_A) {
		_position += _right * 0.1;
	} else if (key == Qt::Key_D) {
		_position -= _right * 0.1;
	} else if (key == Qt::Key_W) {
		_position -= _wordUp * 0.1;
	} else if (key == Qt::Key_S) {
		_position += _wordUp * 0.1;
	} else if (key == Qt::Key_E) {
		_position += _front *0.1;
	} else if (key == Qt::Key_Q) {
		_position -= _front *0.1;
	}
}

void DiffuseLightCamera::mouseMove(float xoffset, float yoffset) {
	xoffset *= 0.005;
	yoffset *= 0.005;

	_yaw -= xoffset;
	_pitch += yoffset;

	if (_pitch > 89.0f)
		_pitch = 89.0f;
	if (_pitch < -89.0f)
		_pitch = -89.0f;

	updateCameraVector();
}

void DiffuseLightCamera::updateCameraVector() {
	QVector3D front;
	front.setX(cos(_yaw) * cos(_pitch));
	front.setY(sin(_pitch));
	front.setZ(sin(_yaw) * cos(_pitch));
	_front = front.normalized();

	_right = QVector3D::crossProduct(_front, _wordUp).normalized();

	_up = QVector3D::crossProduct(_right, _front).normalized();
}

界面:

#pragma once

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

class DiffuseLightWnd : public QOpenGLWindow {
	Q_OBJECT

public:
	DiffuseLightWnd();
	~DiffuseLightWnd();

protected:
	void initializeGL()override;
	void paintGL()override;

	void keyPressEvent(QKeyEvent *event);
	void mouseMoveEvent(QMouseEvent *event);
	void wheelEvent(QWheelEvent *event);
	void mousePressEvent(QMouseEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);
	void resizeGL(int w, int h) Q_DECL_OVERRIDE;
private:
	void drawObj();

private:
	GLuint _VBO, _VAO;
	class QOpenGLFunctions_3_3_Core* _openGLCore;
	QOpenGLShaderProgram _shaderProgram;//着色器程序,所里系统所有的着色器

	QMatrix4x4 model, view, projection;

	class DiffuseLightCamera* _diffuseLightCamera = nullptr;

	bool _lBtnDown = false;
	QPoint _lBtnDownPos;
};

#include "DiffuseLightWnd.h"
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QTimer>
#include <QOpenGLFunctions_3_3_Core>
#include "DiffuseLightCamera.h"

DiffuseLightWnd::DiffuseLightWnd() {
	_diffuseLightCamera = new DiffuseLightCamera(QVector3D(0.0, 0.0, -4.0), 0.0, 90.0, QVector3D(0.0, 1.0, 0.0));
}

DiffuseLightWnd::~DiffuseLightWnd() {
}

void DiffuseLightWnd::initializeGL() {
	_openGLCore = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
	//开启深度测试
	_openGLCore->glEnable(GL_DEPTH_TEST);
	_openGLCore->glDepthFunc(GL_LESS);

	// 顶点数据(纹理坐标未使用)
	float vertices[] = {
		// positions          // normal vector     // texture  
		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
		 0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  0.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
		-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  1.0f,
		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
		// 2
		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
		 0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
		-0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  1.0f,
		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
		// 3
		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
		-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
		-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
		// 4
		 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
		 0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
		 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
		 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
		 0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
		 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
		// 5
		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
		 0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  1.0f,
		 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
		 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
		-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  0.0f,
		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
		// 6
		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
		-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f,
	};

	// 1.创建对象
	_openGLCore->glGenVertexArrays(1, &_VAO);
	_openGLCore->glGenBuffers(1, &_VBO);
	// 2.绑定对象
	_openGLCore->glBindVertexArray(_VAO);
	_openGLCore->glBindBuffer(GL_ARRAY_BUFFER, _VBO);
	// 3.数据存放
	_openGLCore->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// 4.解析数据
	_openGLCore->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	_openGLCore->glEnableVertexAttribArray(0);

	// 5.顶点法向量
	_openGLCore->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
	_openGLCore->glEnableVertexAttribArray(1);

	// 6.解绑
	_openGLCore->glBindBuffer(GL_ARRAY_BUFFER, 0);
	_openGLCore->glBindVertexArray(0);

	// 7.着色器程序
	_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "E:/Projects/QtGuiTest/OPenGLApp/DiffuseLight/DiffuseLight.vert");
	_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "E:/Projects/QtGuiTest/OPenGLApp/DiffuseLight/DiffuseLight.frag");
	_shaderProgram.link();
}

void DiffuseLightWnd::paintGL() {
	_openGLCore->glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
	_openGLCore->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	_openGLCore->glBindVertexArray(_VAO);

	drawObj();


	update();
}

void DiffuseLightWnd::keyPressEvent(QKeyEvent *event) {
	_diffuseLightCamera->keyPress(event->key());

}

void DiffuseLightWnd::mouseMoveEvent(QMouseEvent *event) {
	if (_lBtnDown) {
		float xpos = static_cast<float>(event->pos().x());
		float ypos = static_cast<float>(event->pos().y());

		float xoffset = _lBtnDownPos.x() - xpos;
		float yoffset = _lBtnDownPos.y() - ypos;

		_lBtnDownPos = event->pos();

		_diffuseLightCamera->mouseMove(xoffset, yoffset);
	}
}

void DiffuseLightWnd::wheelEvent(QWheelEvent *event) {
	_diffuseLightCamera->wheel(event->delta());
	update();
}

void DiffuseLightWnd::mousePressEvent(QMouseEvent *event) {
	if (event->button() == Qt::LeftButton) {
		_lBtnDown = true;
		_lBtnDownPos = event->pos();
	}
}

void DiffuseLightWnd::mouseReleaseEvent(QMouseEvent *event) {
	if (event->button() == Qt::LeftButton) {
		_lBtnDown = false;
	}
}

void DiffuseLightWnd::resizeGL(int w, int h) {
	glViewport(0, 0, w, h);

}

void DiffuseLightWnd::drawObj() {
	_shaderProgram.bind();

	QMatrix4x4 model;
	model.rotate(45.0, QVector3D(1.0, 1.0, 1.0));
	model.scale(0.5);
	QMatrix4x4 view = _diffuseLightCamera->getViewMatrix();
	QMatrix4x4 projection;
	projection.perspective(_diffuseLightCamera->getZoom(), width() / height(), 0.1, 100);

	_shaderProgram.setUniformValue("model", model);
	_shaderProgram.setUniformValue("view", view);
	_shaderProgram.setUniformValue("projection", projection);

	_shaderProgram.setUniformValue("objectColor", 1.0f, 0.5f, 0.31f);
	_shaderProgram.setUniformValue("lightColor", 1.0f, 1.0f, 1.0f);

	_shaderProgram.setUniformValue("lightPos", 0.0f, 0.0f, -4.0f);


	_openGLCore->glDrawArrays(GL_TRIANGLES, 0, 36);
}

顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out vec3 Normal;
out vec3 FragPos;
//矩阵必须初始化,初始化单位矩阵,否则GLSL语言中默认矩阵是0矩阵

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

void main(){
	gl_Position = projection * view * model * vec4(aPos, 1.0);
	FragPos = vec3(model * vec4(aPos, 1.0));   // 利用模型矩阵获取片元位置

	Normal = mat3(transpose(inverse(model))) * aNormal;
}

片段着色器:

#version 330 core
out vec4 fragColor;
in vec3 Normal;
in vec3 FragPos;

uniform vec3 lightPos; 
uniform vec3 lightColor;
uniform vec3 objectColor;

 uniform vec3 viewPos;//镜面反射使用  - 相机的位置
void main(){
	//环境光
	float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;

	//漫反射
    // 1.正则化片元位置矢量和光源方向矢量。
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);

    // 2.计算扩散光的对光源颜色的影响。
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    // 3.根据环境光和扩散光计算最终片元颜色。
    vec3 result = (ambient + diffuse) * objectColor;

   // 下面计算镜面光照
   /*
   ** float specularStrength = 0.5;
   ** vec3 viewDir = normalize(viewPos - FragPos);
   ** vec3 reflectDir = reflect(-lightDir, norm);
   ** float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
   ** vec3 specular = specularStrength * spec * lightColor;
   ** vec3 result = (ambient + diffuse + specular) * objectColor;
   */
   fragColor = vec4(result, 1.0);
}

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、付费专栏及课程。

余额充值