在Qt中使用OpenGL(七)

QT中OpenGL开发起步 OpenGL中环境搭建 近期由于需要做一个GUI展示的OpenGL程序,因此想到用QT来做界面,需要在QT中写OpenGL,配完环境后,在这里总计一下。 QT基础 总体看来,QT的版本较为混乱,有时候傻傻弄不清楚,QT dialog/widget/mainwindow。又需要有界面,又要有pro文件,一圈下来,加上网上教程版本混乱,已经凌乱了。后来在同学帮助下,看了一些博客教程,综合... 阅读详情

前言

在Qt中使用OpenGL(一)
在Qt中使用OpenGL(二)
在Qt中使用OpenGL(三)
在Qt中使用OpenGL(四)
在Qt中使用OpenGL(五)
在Qt中使用OpenGL(六)
在前面的文章中,我们实现了对模型的封装。目前我们对于简单的3D世界的构建已经快要接近完成了。
接下来,我们需要的实现的,就是3D世界中很重要的一个元素:光照。

现实中的光照

很显然,在OpenGL的3D世界中,你看到的绝大部分看似符合现实世界中的样子,都是通过数学手段模拟出来的。
光照当然也不例外。
让我们思考一个问题,在阴天你根本看不到太阳的时候,事实上你依旧可以看清楚周围的事物,无论你从任何角度观察一个物体,大概率你看到的这个物体的亮度在各个方向上看起来都是一样。
可是当晚上你在屋里开了灯,你应该能够注意到一个物体的各个表面的亮度并不是一致的——面向灯的那一面比较亮,背向灯的那一面比较暗。而且面向灯的那一面,你还能看到一些闪亮亮的高光的部分。
我们接下来要做的事情,就是将你在现实中看到的情况给模拟出来。

环境光,漫反射与镜面反射

首先,在阴天,虽然没有太阳的直射,你也可以清晰的看到周围的事物,是因为环境光的缘故。
也就是你所处的位置,周围的环境的亮度。
它的成因在于绝大部分的物体都可以反射与透射太阳光,于是虽然没有太阳光的直射,在各种各样的物体上来回反射的太阳光造就了你的周围环境的亮度。
对比一下,哪怕在屋子里你拉上了窗帘,实际上你依旧可以看到屋子里的物品,只不过变暗了而已。这就是光无孔不入的反射造成的。
为了模拟这个现象,我们需要有一个叫做环境光的概念,它实际上就表示了在没有光线直射时,物体受到的光照。
那么我们很容易的就可以推测出来,接下来我们就需要一个在有光线直射时,物体受到的光照的概念了吧。对,它叫做漫反射。
你看到的物体的颜色,绝大部分都是因为它可以反射一部分的光造成的。
例如,光线照射到了物体上,但是物体只会反射绿色,那么你看到的物体就是绿色的。
没错,你周围的所有绿色植物,是因为它们不喜欢绿色的光,将绿色反射回去了,你看到的绿色植物才是绿色的。
什么是镜面反射?顾名思义,将所有的光给反射回去的,就是镜面反射。有时,你会在物体上看到亮闪闪的部分,那就是镜面。比如光滑的地面,虽然不是镜子,但是有时是可以看到反射过来的光源的。这一部分的反射,就被称为镜面反射
有了这三个概念,我们就可以将这三个概念赋予给模型了。
没错,我们依旧需要使用模型中的逻辑来处理光照,虽然光照是一个全局性的概念,但是我们只能逐个模型的进行处理。
一般的,我们将这三个概念,统称材质

法线 与 材质

再继续之前,我们还需要了解另一个概念,它和漫反射还有镜面反射息息相关。
让我们思考一个简单的问题,我们怎么知道,物体的一个面,是朝向光源的?
现实中我们可以很容的通过物体和光源的位置来观察得到,但是具体到了OpenGL的3D世界中,我们怎么就能说一个面就是朝向光源而不是背向光源的呢?
索性我们不需要进行过多的思考,因为在3D世界中,已经存在着这么一个概念了,那就是法线。
什么是法线?数学概念中,垂直于一个平面的向量就被称为这个平面的法线。有了法线,我们就可以计算这个面到底是朝向光源还是背向光源了。
简单来讲,就是计算一下法线向量和从平面上一个点到光源方向向量的点乘,也就是cos值即可。‘
众所周知,cos值在角度[-90°, +90°]范围内的时候是正值,并且越接近±90°值越接近0。让我们想象一下,一个平面的法线,就是你站在这个平面上向上方看,平面上到光源的向量,就是你站在这个平面上向光源看。如果你需要低下头才能看到光源,就证明这个光源和你的头顶的夹角大于90°了,同时这个光源已经在这个平面的下方了,对吧。
于是,只要cos值大于0,就证明这个面被光照到了。

有了以上的知识,我们就可以开始改造之前的模型类了。
首先,我们需要在顶点信息中增加法线的概念,以便可以用来计算光是否照到了这个顶点所在的平面。
其次,我们需要材质这个概念,来模拟环境光,漫反射与镜面反射。
所以,我们就可以这么定义顶点与材质:

struct Vertex
{
   
   
	QVector3D pos;
	QVector2D texture;
	QVector3D normal;
};

struct Material
{
   
   
	float ambient = 1;
	float diffuse = 0;
	float specular = 0;
	float shininess = 16;
};

normal就是法线。
ambient 指的是环境光,范围[0,1]。事实上,之前我们的所有模型就是按照100%的环境光来渲染的。也就是哪怕没有任何直射的光线,你也可以以100%亮度看到这个物体。如果你完全不关心光照,那么就可以将这个值设置为1即可(但你依旧会受到光源颜色的影响)。
diffuse是指漫反射,范围[0,1]。一般情况下,环境光和漫反射加起来要达到1,但是达不到也不要紧。
因为,环境光和漫反射共同决定了你看到的物体的颜色是什么(对应到3D中,实际上就指是你能以多高的亮度看到物体的贴图),如果最终的值不到1,那么只不过是一个看起来比较暗的物体罢了,可以用来模拟晚上或者昏暗的地下室+昏暗的灯光。
specular是指镜面反射,范围[0,1]。值越大,越闪亮。
shininess是指最终计算出来的镜面反射的效果。值越大,光斑越明显。

然后,我们仿照纹理,也增加添加材质的接口(因为一个模型既然可以有多个纹理,那有多个材质也无可厚非):

public:
	void setMaterial(const Material &material, int index  = -1);
private:
	QMap<int, Material> m_materials;
void Model::setTexture(QOpenGLTexture *texture, int index)
{
   
   
	if (index == -1)
	{
   
   
		if (m_textures.isEmpty())
		{
   
   
			index = 0;
		}
		else
		{
   
   
			index = m_textures.keys().last() + 1;
		}
	}
	m_textures.insert(index, texture);
}

设置法线和材质

我们依旧使用之前的色子模型来举例,由于我们修改了基类,于是最新的包含了法线初始化顶点数据的代码如下:

setVertices({
   
   
	//   顶点           纹理	          法线
	// 1
		{
   
   {
   
   -1,  1,  1,}, {
   
   0.50, 0.25}, {
   
   0, 0, 1}},	// 左上
		{
   
   {
   
   -1, -1,  1,}, {
   
   0.50, 0.50}, {
   
   0, 0, 1}},	// 左下
		{
   
   {
   
    1, -1,  1,}, {
   
   0.75, 0.50}, {
   
   0, 0, 1}},	// 右下
		{
   
   {
   
    1,  1,  1,}, {
   
   0.75, 0.25}, {
   
   0, 0, 1}},	// 右上
	// 6							
		{
   
   {
   
    1,  1, -1,}, {
   
   0.00, 0.25}, {
   
   0, 0, -1}},	// 左上
		{
   
   {
   
    1, -1, -1,}, {
   
   0.00, 0.50}, {
   
   0, 0, -1}},	// 左下
		{
   
   {
   
   -1, -1, -1,}, {
   
   0.25, 0.50}, {
   
   
从零开始:在Qt中使用OpenGL绘制指南 本文详解如何通过Qt的QOpenGLWidget和QOpenGLFunctions实现跨平台GPU渲染,以绘制三角形为例。从OpenGL函数跨平台加载原理切入,解析Qt对底层API的封装价值,逐步讲解顶点缓冲、着色器编译及渲染流程,提供完整代码和常见问题解决思路,助力开发者高效降低CPU负载,掌握Qt与OpenGL整合的核心实践。 阅读详情

相关推荐

Qt+OpenGL基础教程

基于Qt与OpenGL的UR3机械臂仿真与控制程序的先行文,介绍了如何画出一个可以变换视角的坐标系。

mai0026的博客 1万+

用于OpenGl的Camera类(QT实现的3D摄像机类)

最近在搞QT上的OPENGL,有好多库都要自己写啊 哐哧哐哧写了一大顿,已经写好了,回过头来记录一下 这篇讲的时关于opengl自由摄像机的问题 写摄像机的思路是,写一个万能的摄像机基类,可以支持各种基本操作(没有添加左右晃镜头的功能) 然后如果你需要用到什么样的摄像机,继承基类,然后重写他的移动函数和改变镜头方向函数(这两个函数为虚函数) 这样的话,你不用考虑是什么类型的摄像机,把摄像...

Miao的博客 3331

Qt中使用GLEW进行OpenGL开发

Qt中使用GLEW进行OpenGL开发(Windows平台)为什么要使用GLEW使用VS创建Qt项目设置Widget重新实现paintEngine添加GLEW库到工程设置OpenGL上下文设置GL像素格式检测支持OpenGL的力度创建GLRC把当前窗口设置为OpenGL上下文绘制背景颜色更新视口绘制添加QtEvent调用绘制Post绘制事件绘制测试源码下载开启新征程 为什么要使用GLEW 因为工作需求绘制视频,原本使用的Qt(我使用的是5.9.8的版本)自带的QOpenGL进行视频绘制,但是在稳定行测试中经

sttplay666 4096

Qt中的OpenGL

也叫可编程管线,提供了更多的灵活性,更高的效率,更重要的是可以更深入的理解图形编程。其中,顶点着色器和片段着色器需要自己去编写,几何着色器可选择性编写,有这三个可以编辑的部分,即为可编程管线(管线可以理解为一个处理流程)。Ps:状态机是一种理论模型,用于描述一个系统在不同时间点的行为和状态转移规律。OpenGL自身是一个巨大的状态机上下文(Context)通常把OpenGL上下文比作一个大的结构体,包含很多子集:当前状态只有一份。

MasterPJ的博客 5202

关于QT5.10+opengl的使用

本人最近在用qt5.10和opengl结合,看了一些博主写的文章,但是在编写程序时还是遇到了各种各样的问题,想来总结下。现在QT5之后有两种方式来结合opengl,最新的可以看看qt官方的opengl window的例子,本人暂时没有用到,还是用旧的方式。现在开始介绍吧!~~~问题总结:1.出现undefined reference to 。。。。的问题2.运行后界面全黑,不显示你所画的内容3.想...

黑手 1万+

Qt中的OpenGL函数使用

注意,在使用QOpenGLFunctions类时,需要先在对应的函数中调用initializeOpenGLFunctions()函数来初始化OpenGL的函数。并且,在使用OpenGL的函数时,需要保证当前的OpenGL上下文是活跃的,通常在paintGL()函数中当前的OpenGL上下文是活跃的。这个类是一个抽象基类,定义了OpenGL ES 2.0、OpenGL 3.0和OpenGL 4.3的函数,我们可以通过继承这个类或者创建它的派生类来使用OpenGL的函数。Qt中的OpenGL函数使用。

ByteProwl的博客 1125

200SMART PLC时间不准?手把手教你用MCGS触摸屏实现自动校时(附完整代码)

本文针对西门子200SMART PLC时钟不准的常见问题,提供了一套基于MCGS触摸屏的自动校时解决方案。文章详细阐述了时钟偏差的根源、时间同步方案的技术选型,并手把手指导如何配置MCGS与PLC的通信,以及编写完整的PLC时间读取、转换与设置代码,最终实现稳定可靠的自动时间同步功能。

jupyter5notebook的博客 457

记录一下本地部署Dify的坑

1. 截止2025-3-4为止,请注意,不要直接拉Dify的1.0.0版本。请先试用0.15.3版本。1.0.0有一个bug需要解决。3. 请使用docker-ce 新版本,docker-engine等老版本可能会有部分容器启动脚本执行莫名报错。2. 注意,请使用docker-compose V2版本,或者V1较高版本,否则会导致解析官方yml模板错误。

哈利路亚的收藏夹 5346

CLIP-Count代码配置以及踩坑记录

CLIP-Count代码配置以及踩坑记录

学术菜鸡 1011

保姆级教程:用rosbag录制和回放你的第一个ROS机器人数据(附C++/Python代码)

本文提供了一份详细的ROS机器人数据录制与回放教程,涵盖从命令行操作到C++/Python编程实现的全流程。通过rosbag工具,开发者可以高效记录和回放机器人运行时的传感器数据和控制指令,适用于故障复现、算法调试等多种场景。教程还包含高级技巧如时间同步和大文件处理,帮助用户快速掌握ROS数据管理核心技能。

weixin_29313239的博客 285

Python实战:3步搞定DICOM转JPG/PNG(附批量处理脚本)

本文详细介绍了如何使用Python在3步内将DICOM医学影像转换为JPG/PNG格式,并提供了批量处理脚本。通过Pydicom、Pillow和NumPy库的组合,解决了像素值处理、批量转换效率和医学图像特性保留等关键问题,适合医疗AI开发者和放射科医生快速集成到工作流中。

numpy6sculptor的博客 592

Sigrity Power SI Model Extraction模式如何提取电源网络的S参数和阻抗操作指导(一)

34. 默认格式是BNP format格式,会被Sigrity识别的S参数文件,在仿真完成后,默认会在文件夹中生成bnp和ckt(MCP)文件,无需这步操作。由于port设置的ref Z是50ohm,实际上电源网络的阻抗是没有这么高的,所以S参数回损曲线是基本上全反射的一个状态。Sigrity PowerSI是频域电磁场仿真工具,以下图为例介绍如果用它观测电源的网络的S参数以及阻抗的频域曲线.42. Spice格式的加载进来图标是橙色的,BNP格式的图标是灰色的。

weixin_54787054的博客 1280

27、自闭症儿童治疗与玩具设计研究

本研究探讨了自闭症儿童的治疗方法与玩具设计之间的关联,分析了游戏疗法、音乐疗法和职业疗法等在治疗中的应用,并介绍了多种针对自闭症儿童的治疗玩具案例。通过用户研究和多学科合作,提出了以Pro-Ability为核心的设计理念,开发了结合音乐疗法和精细运动训练的智能玩具套件。研究总结了当前成果与局限性,并展望了未来发展方向,旨在为自闭症儿童提供更有效的康复支持。

keras9composer的博客 211

C#上位机+YOLO工业视觉全实战:从ONNX部署到产线缺陷检测落地(2026年工业级实战指南)

在2026年,工业视觉落地的核心挑战不是“能不能做”,而是“能不能在产线实时跑起来C#为何成为最优解?

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 733

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: 在Qt中使用OpenGL(六)
下一篇: 在Qt中使用OpenGL(八)
Ninsun Closear
博客等级 码龄12年 321粉丝 22原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值