QT+OpenGL光照
QT+OpenGL光照
本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主
颜色
现实生活中看到的物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的颜色
太阳光能被看见的白光是多找演的的组合

颜色的数据化的由红色,绿色和蓝色三个分量组成,他们通常被缩写为RGB
例如:珊瑚红色
QVector3D color(1.0f, 0.5f, 0.31f);
上图颜色的代码展示
// 灯光颜色
QVector3D lightColor(1.0f, 1.0f, 1.0f);
// 珊瑚红色
QVector3D toyColor(1.0f, 0.5f, 0.31f);
QVector3D result = lightColor * toyColor; // 分量相乘,不是点乘也不是叉乘
代码展示:
light.frag
#version 330 core
out vec4 FragColor;
uniform vec3 lightColor;
void main()
{FragColor = vec4(lightColor, 1.0);
}
light.vert
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aTexCord;uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0);
}
void TurboOpenGLWidget::paintGL()
{QMatrix4x4 model;QMatrix4x4 view;float time = m_time.elapsed() / 50.0;model.rotate(time, 1.0f, 5.0f, 0.0f);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);shader_program_.bind();glBindVertexArray(VAO);QMatrix4x4 projection;projection.perspective(camera_.getZoom(), float(width() / height()), 0.1, 100);shader_program_.setUniformValue("projection", projection);view = camera_.getViewMatrix();switch(shape_){case Rect:shader_program_.setUniformValue("model", model);shader_program_.setUniformValue("view", view);for(const auto &item: cubePositions){model.setToIdentity();model.translate(item);model.rotate(time, 1.0, 5.0, 0.5);shader_program_.setUniformValue("model", model);glDrawArrays(GL_TRIANGLES,0,36);}break;}glBindVertexArray(0);glBindVertexArray(lightVAO);light_shader_program_.bind();light_shader_program_.setUniformValue("projection", projection);light_shader_program_.setUniformValue("model", model);light_shader_program_.setUniformValue("view", view);model.setToIdentity();model.translate(lightPos);model.rotate(1.0, 1.0, 5.0, 0.5);model.scale(0.2);light_shader_program_.setUniformValue("model", model);glDrawArrays(GL_TRIANGLES,0,36);update();
}
效果展示

冯氏光照模型
冯氏光照模型的主要结构有三个:
- 环境光(ambient)
- 即使在黑暗情况下,通常也仍然有一些光亮
- 漫反射(diffuse)
- 模拟光源对物体的方向性影响
- 镜面反射(specular)
- 模拟有光泽物体表面上出现的亮点
Iphong=ka⋅Iambient+∑i=1numLightsIi⋅(kd(L^i⋅N^)+ks⋅(R^i⋅V^)nshiny)I_{phong} = k_a\cdot I_{ambient} + \sum_{i = 1}^{numLights}I_i\cdot (k_d(\hat L_i\cdot \hat N) + k_s\cdot (\hat R_i \cdot \hat V)^{n^{shiny}}) Iphong=ka⋅Iambient+i=1∑numLightsIi⋅(kd(L^i⋅N^)+ks⋅(R^i⋅V^)nshiny)
其中kakdksk_a k_d k_skakdks是系数
环境光代码:
#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main()
{float ambientStrength = 0.2;vec3 ambient = ambientStrength * lightColor;vec3 result = ambient * objectColor;FragColor = vec4(result, 1.0);
}
向上面代码,如果我们只有环境光,会是如下效果,并不是完全黑的。

漫反射代码:
计算漫反射光照需要:
- 法向量:一个垂直于顶点表面的向量
- 定向的光线:作为光源的位置与片段的位置之间的向量差的方向向量;为了计算这个光线,我们需要光的位置向量和片段的位置向量
片段着色器:
#version 330 core
out vec4 FragColor;uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;in vec3 Normal;
in vec3 fragPos;void main()
{// ambientfloat ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;// diffusevec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - fragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff + lightColor;vec3 result = (ambient + diffuse) * objectColor;FragColor = vec4(result, 1.0);
}

镜面反射代码:
片段着色器:
#version 330 core
out vec4 FragColor;uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;in vec3 Normal;
in vec3 fragPos;void main()
{// ambientfloat ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;// diffusevec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - fragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;// specularfloat 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);
}

法向量
-
如果模型矩阵执行了不等比例的缩放,顶点的改变导致法向量不再垂直与表面。
-
修复这个行为的诀窍是使用一个为法向量专门定制的模型矩阵。这个矩阵称之为法线矩阵
Normal = mat3(transpose(inverse(model))) * aNormal;
相关文章:
QT+OpenGL光照
QTOpenGL光照 本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主 颜色 现实生活中看到的物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的颜色 太阳光能被看见的白光是多找演的的组合…...
OpenCV-PyQT项目实战(7)项目案例03:鼠标框选
欢迎关注『OpenCV-PyQT项目实战 Youcans』系列,持续更新中 OpenCV-PyQT项目实战(1)安装与环境配置 OpenCV-PyQT项目实战(2)QtDesigner 和 PyUIC 快速入门 OpenCV-PyQT项目实战(3)信号与槽机制 …...
vue2版本《后台管理模式》(上)
后台管理模式项目开发经验总结如下,希望对你们有些帮助: 文章目录一、app 出口位置二 、 index.js 路由配置三、package.json 文件四、 main.js 既然安装插件那就需要引入五、 跨域问题总结首先需要一个完整的v2版本的项目 vue2版本思路:首先…...
C++与C基础重叠部分
Cmake CPP程序开发过程 计算机硬件—>机器语言—>汇编—>cppcpp—>机器(gcc)Make(makefile)—>本地智能批处理翻译机制Cmake—>跨平台生成不同设备上的makefile进行执行 Cpp基础学习 基本知识 基本格式 #include<iostream> using namespace std;…...
神经网络基础部件-卷积层详解
前言 在全连接层构成的多层感知机网络中,我们要通过将图像数据展平成一维向量来送入模型,但这会忽略了每个图像的空间结构信息。理想的策略应该是要利用相近像素之间的相互关联性,将图像数据二维矩阵送给模型中学习。 卷积神经网络(convolu…...
【计算机网络】HTTPS协议原理
文章目录一、认识HTTPS协议二、为什么要发明HTTPS三、HTTP与HTTPS的区别四、常见的加密方式1. 对称加密2. 非对称加密3. 数据摘要4. 数字签名五、HTTPS的原理探究方案1:只使用对称加密方案2:只使用非对称加密方案3:双方都使用非对称加密方案4…...
21岁,华科博士在读,我的赛事Top经验
Datawhale干货 作者:vaew,华中科技大学,博士二年级在读简介笔者vaew,21岁,现为华中科技大学机械科学与工程学院陶波教授课题组博士二年级学生。主要研究方向是基于视触融合的机器人灵巧操作。学业之余的研究兴趣包括图…...
基于ThinkPHP6.0+Vue+uni-app的多商户商城系统好用吗?
likeshop多商户商城系统适用于B2B2C、多商户、商家入驻、平台商城场景。完美契合平台自营联营加盟等多种经营方式使用,系统拥有丰富的营销玩法,强大的分销能力,支持官方旗舰店,商家入驻,平台抽佣商家独立结算ÿ…...
Linux中断
文章目录 前言一、Linux 中断介绍二、中断上文和中断下文三、中断相关函数1 获取中断号相关函数2.申请中断3.释放中断4.中断处理函数四.中断下文之 tasklet1.概念2.Linux 内核中的 tasklet 结构体:3.使用步骤4.相关函数a.初始化 tasklet结构体b.调度 taskletc.杀死 tasklet总结…...
Excel+SQL实战项目 - 餐饮业日销售情况分析仪
目录1、要完成的任务2、认识数据3、SQL数据加工4、excel形成分析仪1、要完成的任务 目标:结合SQL和excel实现餐饮业日销售情况分析仪,如下表: 认识分析仪: 切片器:店面 分为四部分:KPI 、组合图、饼图、数…...
电商导购CPS,京东联盟如何跟单实现用户和订单绑定
前言 大家好,我是小悟 做过自媒体的小伙伴都知道,不管是发图文还是发短视频,直播也好,可以带货。在你的内容里面挂上商品,你自己都不需要囤货,如果用户通过这个商品下单成交了,自媒体平台就会…...
Redis学习【6】之BitMap、HyperLogLog、Geospatial操作命令 (1)
文章目录前言BitMap 操作命令1.1 BitMap 简介1.2 setbit1.3 getbit1.4 bitcount1.5 bitpos[pos:position]1.6 bitop1.7 应用场景二 HyperLogLog 操作命令2.1 HyperLogLog 简介2.2 pfadd2.3 pfcount2.4 pfmerge2.5 应用场景三 Geospatial【地理空间】操作命令3. 1 Geospatial 简…...
JAVA实现心跳检测【长连接】
文章目录1、心跳机制简介2、心跳机制实现方式3、客户端4 、服务端5、代码实现5.1 KeepAlive.java5.2 MyClient.java5.3 MyServer5.4 测试结果1、心跳机制简介 在分布式系统中,分布在不同主机上的节点需要检测其他节点的状态,如服务器节点需要检测从节点…...
python3.9安装和pandas安装踩坑处理
0、先决条件:系统内最好先安装有gcc、libffi-devel等 1、安装包下载 https://www.python.org/downloads/source/ 2、解压安装包并上传到/usr/local/python3.9 3、打开shell cd /usr/local/python3.9要先把python3.9的所有文件复制到/usr/local/python3.9才会成功…...
2023.2.15每日一题——867. 转置矩阵
每日一题题目描述解题核心解法一:二维表示 模拟解法二:一维表示 模拟题目描述 题目链接:867. 转置矩阵 给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。 矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵…...
【人脸识别】Partial-FC:让你在一台机器上训练1000万个id人脸数据集成为可能!
论文题目:”Killing Two Birds with One Stone: Efficient and Robust Training of Face Recognition CNNs by Partial FC“ -CVPR 2022 代码地址:https://arxiv.org/pdf/2203.15565.pdf 代码地址:https://github.com/deepinsight/insightfac…...
递归方法读取任意深度的 JSON 对象的键值
有以下json字符串 {"name":"John","age":30,"address":{"city":"New York","state":"NY","zip":"10001","coordinates":{"latitude":40.712776,&q…...
黑马redis学习记录:分布式锁
一、基本原理和实现方式对比 分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行…...
对React-Fiber的理解,它解决了什么问题?
对React-Fiber的理解,它解决了什么问题?Fiber用来解决什么问题?Fiber是什么?Fiber是如何解决问题的?Fiber用来解决什么问题? JavaScript引擎和页面渲染引擎两个线程是互斥的,当其中一个线程执行…...
【Linux】初学Linux你需要掌握这些基本指令(二)
目录 1.man指令 2.cp指令 3.mv指令 4.tree指令 5.echo指令 6.more指令 7.less指令(重要) 8.head与tail指令 9.date指令 显示时间常用参数: 设置时间常用参数: 10.cal指令 11.find & whereis & which指令 …...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...
C++ Saucer 编写Windows桌面应用
文章目录 一、背景二、Saucer 简介核心特性典型应用场景 三、生成自己的项目四、以Win32项目方式构建Win32项目禁用最大化按钮 五、总结 一、背景 使用Saucer框架,开发Windows桌面应用,把一个html页面作为GUI设计放到Saucer里,隐藏掉运行时弹…...
【AI News | 20250609】每日AI进展
AI Repos 1、OpenHands-Versa OpenHands-Versa 是一个通用型 AI 智能体,通过结合代码编辑与执行、网络搜索、多模态网络浏览和文件访问等通用工具,在软件工程、网络导航和工作流自动化等多个领域展现出卓越性能。它在 SWE-Bench Multimodal、GAIA 和 Th…...
