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指令 …...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
