计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 10.增强表面细节(二)法线贴图
1. 法线贴图(Normal Mapping)
法线贴图是一种在3D图形渲染中广泛使用的表面细节增强技术。它通过存储每个像素的法线信息来模拟表面的细微凹凸细节,而无需增加实际的几何复杂度。
1.1. 工作原理
-
纹理存储
- 使用RGB通道存储法线向量的XYZ分量
- 通常呈现出偏蓝色的外观(因为默认法线指向Z轴)
- 每个像素都包含表面法线方向信息
-
切线空间
- 法线贴图通常在切线空间(TBN空间)中定义
- 包含切线(Tangent)、副切线(Bitangent)和法线(Normal)
- 便于将法线信息应用到任意曲面
1.2. 优势
-
高效率
- 不增加模型的多边形数量
- 能够呈现出丰富的表面细节
- 性能开销相对较小
-
灵活性
- 可以与其他贴图技术结合使用
- 适用于静态和动态物体
- 便于美术人员制作和修改
1.3. 应用场景
- 游戏角色的皮肤细节
- 建筑物表面的砖块纹理
- 布料的褶皱效果
- 地形的细节增强
1.4. TBN空间
TBN空间(Tangent Space)是法线贴图中的一个关键概念,它由三个相互垂直的向量构成:切线(Tangent)、副切线(Bitangent)和法线(Normal)。
-
T - 切线(Tangent)
- 沿着纹理坐标U方向的向量
- 通常与物体表面相切
- 在顶点着色器中计算
-
B - 副切线(Bitangent)
- 沿着纹理坐标V方向的向量
- 与切线和法线都垂直
- 可以通过叉积计算:B = N × T
-
N - 法线(Normal)
- 垂直于物体表面的向量
- 决定了表面的朝向
- 由模型数据提供
1.5. TBN矩阵的作用
// TBN矩阵的构建
mat3 TBN = mat3(T, B, N);
主要用途:
- 将法线贴图中的法线向量从切线空间转换到世界空间
- 保证法线方向在任意曲面上都正确
- 使法线贴图可以在不同的表面上重复使用
1.6. 优势
- 空间一致性:保证法线方向在任何表面都能正确表现
- 可重用性:同一个法线贴图可以应用到不同的模型上
- 精确性:提供了准确的法线方向计算
1.7. 实现流程
可以在顶点着色器中计算TBN矩阵,并在片段着色器中应用它,也可以在片段着色器中计算TBN矩阵。
以下代码展示了如何在片段着色器中计算TBN矩阵:
layout (binding =0) uniform sampler2D normalMap; // 法线贴图
//uniform sampler2D heightMap; // 高度贴图// 计算法线的函数
// normal: 顶点的法线向量
// tangent: 顶点的切线向量
// texCoord: 纹理坐标
vec3 calcNormal(vec3 normal, vec3 tangent, vec2 texCoord)
{// 使用Gram-Schmidt正交化计算切线T// 确保切线与法线垂直vec3 T = normalize(tangent - dot(tangent, normal) * normal);// 通过叉积计算副切线B// T和N叉积得到B,确保三个向量相互垂直vec3 B = normalize(cross(T, normal));// 从法线贴图中获取法线数据并转换到[-1,1]范围vec3 N = normalize(texture(normalMap, texCoord).xyz * 2.0 - 1.0);// 构建TBN矩阵// 用于将切线空间的法线转换到世界空间mat3 TBN = mat3(T, B, N);// 从法线贴图中获取法线数据vec3 retrivedNormal = texture(normalMap, texCoord).xyz;// 将法线从[0,1]范围转换到[-1,1]范围retrivedNormal = normalize(retrivedNormal * 2.0 - 1.0);// 使用TBN矩阵将法线从切线空间转换到世界空间vec3 newNormal = normalize(TBN * retrivedNormal);return newNormal;
}
1.8. 进一步说明切线向量
实际中,切线向量通常由模型数据提供,例如顶点法线、顶点切线等。这些数据通常存储在模型文件中,例如OBJ文件。
如果模型中没有提供切线向量,就需要通过计算得到。对于表面可导的曲面,可以通过计算得到切线向量。而如果 曲面不可导,就需要使用其他方法来计算切线向量。一种折中的方式是将每个顶点指向下一个顶点的向量作为切线向量。但这样会造成顶点法线与切线向量不垂直,从而影响法线贴图的效果。因此,在着色器中计算切线向量时,需要使用一些技巧来保证切线向量与顶点法线垂直。
// 确保切线与法线垂直vec3 T = normalize(tangent - dot(tangent, normal) * normal);
1.9. 法线贴图内容说明
法线贴图通常由RGB三个通道组成,分别表示法线向量的X、Y、Z分量。每个分量取值范围为[-1,1],但实际文件存贮为[0,1],所以需要经过转换。
// 法线贴图中的法线向量从[0,1]范围转换到[-1,1]范围retrivedNormal = normalize(retrivedNormal * 2.0 - 1.0);
下图为法线贴图
法线贴图呈现蓝色的原因
- 法线向量的存储方式
- RGB通道分别对应XYZ轴向
- 值范围从[-1,1]映射到[0,1]存储
- 转换公式:color = normal * 0.5 + 0.5
- 默认法线方向
- 在切线空间中,默认法线指向Z轴正方向(0,0,1)
- 转换到[0,1]范围后变为(0.5,0.5,1.0)
- 这导致蓝色通道(Z轴)的值最大
- 颜色表现
- R通道(X)≈0.5:中等红色
- G通道(Y)≈0.5:中等绿色
- B通道(Z)≈1.0:最大蓝色
- 三个通道叠加后呈现出偏蓝色的外观
2. 高度贴图(Height Mapping)
高度贴图是一种使用灰度图来存储表面高度信息的技术,用于在渲染时动态改变表面几何形状。
2.1. 工作原理
-
纹理存储
- 使用单通道灰度图存储高度信息
- 黑色(0.0)表示最低点
- 白色(1.0)表示最高点
- 灰度值表示中间高度
-
置换映射
- 根据高度值沿法线方向移动顶点
- 可以实际改变几何形状
- 需要较高的网格分辨率
-
视差映射
- 不改变实际几何形状
- 通过调整纹理坐标创造深度错觉
- 性能消耗较小
2.2. 优势
-
真实的凹凸效果
- 可以产生实际的几何变化
- 在边缘处有正确的轮廓
- 可以产生自遮挡效果
-
易于制作和编辑
- 使用常规图像编辑工具即可创建
- 直观的黑白高度表示
- 便于美术人员使用
2.3. 应用示例
// 顶点着色器 中得到的原始顶点位置为vertPos,经过处理后的顶点位置为pvec3 p=vertPos+ vertNormal*texture(heightMap,vertTexCoord).r*0.2;
2.4. 与法线贴图的区别
-
几何影响
- 高度贴图可以实际改变几何形状
- 法线贴图只改变光照计算
-
资源消耗
- 高度贴图需要更多的顶点数据
- 法线贴图主要影响像素着色
-
效果表现
- 高度贴图可以产生真实的凹凸轮廓
- 法线贴图在边缘处效果有限
以下是高度图 (灰度图)
以下是示例中采用的纹理图,为简便起见,只是将高度图加了绿色
3. 参考
- 学习笔记完整代码下载
- OpenGL shader开发实战学习笔记:第十章 法线贴图_法线贴图是什么意思-CSDN博客
相关文章:
计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 10.增强表面细节(二)法线贴图
1. 法线贴图(Normal Mapping) 法线贴图是一种在3D图形渲染中广泛使用的表面细节增强技术。它通过存储每个像素的法线信息来模拟表面的细微凹凸细节,而无需增加实际的几何复杂度。 1.1. 工作原理 纹理存储 使用RGB通道存储法线向量的XYZ分量…...
使用 OpenCV 将图像中标记特定颜色区域
在计算机视觉任务中,颜色替换是一种常见的图像处理操作,广泛用于视觉增强、目标高亮、伪彩色渲染等场景。本文介绍一种简单而高效的方式,基于 OpenCV 检测图像中接近某种颜色的区域,并将其替换为反色(对比色࿰…...
Service Mesh
目录 一、Service Mesh 的核心特点 二、Service Mesh 的典型架构 1. Sidecar 模式 2. 控制平面与数据平面分离 三、Service Mesh 解决的核心问题 四、典型应用场景 五、主流 Service Mesh 框架对比 六、挑战与局限性 七、未来趋势 总结 Istio 一、Istio 核心组件与…...
反射机制详细说明
反射机制详细说明 1. 反射的基本概念 反射(Reflection)是Java提供的一种在运行时(Runtime)动态获取类信息并操作类属性、方法和构造器的机制。通过反射,程序可以在运行时检查类、接口、字段和方法,并且可以实例化对象、调用方法、访问或修改字段值,甚至操作私有成员,…...
基于Mongodb的分布式文件存储实现
分布式文件存储的方案有很多,今天分享一个基于mongodb数据库来实现文件的存储,mongodb支持分布式部署,以此来实现文件的分布式存储。 基于 MongoDB GridFS 的分布式文件存储实现:从原理到实战 一、引言 当系统存在大量的图片、…...
相机Camera日志分析之九:高通相机Camx 基于预览1帧的ConfigureStreams二级日志分析详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:高通相机Camx 日志分析之三:camx hal预览1帧logcat日志opencamera详解 相机Camera日志分析之三:不想输出每秒30帧巨量日志,如何只输出1帧日志作为学习使用? 这一篇我们开始讲: 高通相机Camx 日志…...
neo4j框架:ubuntu系统中neo4j安装与使用教程
在使用图数据库的时候,经常需要用到neo4j这一图数据库处理框架。本文详细介绍了neo4j安装使用过程中的问题与解决方法。 一、安装neo4j 在安装好了ubuntu系统、docker仓库和java的前提下 在ubuntu系统命令行依次输入如下命令: # 安装依赖库 sudo apt-…...
k8s灰度发布
基于 Traefik 的加权灰度发布-腾讯云开发者社区-腾讯云 Traefik | Traefik | v1.7 Releases traefik/traefik GitHub 从上面连接下载后上传到harbor虚拟机 vagrant upload /C/Users/HP280/Downloads/traefik 下载配置文件 wget -c http://raw.githubusercontent.com/conta…...
K8S从Harbor拉取镜像
参考 配置cri-docker使kubernetes1.24以docker作为运行时_启动cirdocker_跳跃音符#3712的博客-CSDN博客 部署Harbor私有容器镜像仓库并配置Kubernetes从Harbor拉取镜像的方法_运维个西瓜的博客-CSDN博客 K8S连接Harbor私有仓库_k8s harbor 登录-CSDN博客 K8S集群配置使用私…...
【Spring Boot后端组件】mybatis-plus使用
文章目录 mybatis-plus使用一、依赖引入二、添加相关配置项三、功能详解1.自增主键2.逻辑删除3.操作时间自动填充4.其他字段自动填充5.分页查询6.自定义动态查询7.代码生成器8.代码生成器(自定义模板) mybatis-plus使用 一、依赖引入 pom.xml文件 <?xml version"1.…...
Oc语言学习 —— 重点内容总结与拓展(下)
类别(分类)和拓展 分类: 专门用来给类添加新方法 不能给类添加成员属性,添加成员属性也无法取到 注意:其实可与通过runtime 给分类添加属性,即属性关联,重写setter,getter方法 分类…...
智脑进化:神经网络如何从单层感知机迈向深度学习新纪元
第一章:神经元的启示——从生物大脑到人工神经元 1.1 生物神经元的智慧:860亿神经元的协同网络 人类大脑的860亿神经元通过突触形成动态网络,每个神经元通过树突接收信号,在胞体整合后经轴突传递输出。这种“接收-处理-输出”的…...
雷云4 鼠标滚轮单击失灵解决办法
问题现象:打开雷云4 ,滚轮单击才有反应,退出雷云4,滚轮单击没反应。 解决方案: 打开雷云4, 选中鼠标中键,选择鼠标功能,选择滚轮单击,保存 然后退出后, …...
Spring Cloud动态配置刷新:@RefreshScope与@Component的协同机制解析
在微服务架构中,动态配置管理是实现服务灵活部署、快速响应业务变化的关键能力之一。Spring Cloud 提供了基于 RefreshScope 和 Component 的动态配置刷新机制,使得开发者可以在不重启服务的情况下更新配置。 本文将深入解析 RefreshScope 与 Component…...
vue2集成可在线编辑的思维导图(simple-mind-map)
最近要求做一个可在线编辑的思维导图,经过层层调研和实测,最简单的思维导图导图实现还得是simple-mind-map组件 simple-mind-map中文文档 当前我使用的是vue2项目,目前没试过是否支持vue3,但是看官网描述他们也给了有vue3的demo项…...
【开源Agent框架】CAMEL:角色扮演+任务分解
一、项目概览:重新定义智能体协作范式 CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)是由camel-ai社区开发的开源多智能体框架,致力于探索智能体的规模法则(Scaling Laws)。该项目通过构建包含百万级智能体的复杂社会系统,研…...
Elasticsearch-kibana索引操作
1索引模版 添加索引 PUT /_index_template/account_transaction {"priority": 0,"index_patterns": ["account_transaction*"],"template": {"settings": {"index": {"number_of_shards": "50&q…...
【python编程从入门到到实践】第十章 文件和异常
一、读取文件 pi_digits.txt3.1415926535897932384626433832791.读取文件的全部内容 # file_reader.pyfrom pathlib import Pathpath Path("pi_digits.txt") contents path.read_text() print(contents)2.相对文件路径和绝对文件路径 当相对路径行不通时&#x…...
Reactive与Ref的故事
Vue 3的两位"响应式英雄":Reactive与Ref的故事 基本介绍:响应式的两种武器 Vue 3提供了两种创建响应式数据的主要API:reactive()和ref()。它们像两种不同的魔法工具,各有所长,共同构建Vue的响应式王国。 ┌────────────────────────…...
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
1. 引言 在旅游行业和城市规划中,热门景点的数据分析具有重要意义。通过爬取景点数据并生成热力图,可以直观展示游客分布、热门区域及人流趋势,为商业决策、景区管理及智慧城市建设提供数据支持。 然而,单机爬虫在面对大规模数据…...
MySQL数据库——支持远程IP访问的设置方法总结
【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实…...
现在环保方面有什么新的技术动态
环保领域的技术发展迅速,尤其在“双碳”目标、数字化转型和可持续发展背景下,涌现出许多创新技术和应用。以下是当前环保领域的新技术动态(截至2024年): 一、碳中和与碳减排技术 CCUS(碳捕集、利用与封存&a…...
[模型部署] 1. 模型导出
👋 你好!这里有实用干货与深度分享✨✨ 若有帮助,欢迎: 👍 点赞 | ⭐ 收藏 | 💬 评论 | ➕ 关注 ,解锁更多精彩! 📁 收藏专栏即可第一时间获取最新推送🔔…...
Neo4j 图书馆借阅系统知识图谱设计
一、数据模型设计 节点类型 读者(Reader) 属性: reader_id, name, age, gender, phone, email, register_date 图书(Book) 属性: book_id, title, author, publisher, publish_date, isbn, price, category 图书副本(BookCopy) 属性: copy_id, status (在馆/借出/维修), loca…...
android 安装openwrt 安正步骤
安装 QEMU 模拟器 bash 复制 编辑 pkg install wget pkg install qemu-utils pkg install qemu-system-aarch64-headless 可选 x86 模拟支持: bash 复制 编辑 pkg install qemu-system-x86-64-headless ✅ 下载 OpenWRT 镜像(armvirt 64) bash 复制 编辑 mkdir -p ~/openwr…...
大规模CFD仿真计算中,SIMPLE或者PISO算法中加速压力场方程迭代求解
文章目录 在SIMSOL或PISO算法中加速压力场方程的迭代求解是提高CFD计算效率的关键。以下从算法优化、数值技巧和并行计算等方面总结加速策略:**1. 压力方程求解器的选择与优化****2. 算法层面的加速****3. 离散格式与网格优化****4. 并行计算与硬件加速****5. 代码级…...
【C#】 lock 关键字
在 C# 里,lock 关键字就是对 Monitor.Enter/Exit 的简写。它的作用是保证“同一时刻只有一个线程能进入被保护的代码块”,从而避免多个线程同时修改同一个共享状态导致竞态条件(race condition)。 一、结合Jog 的例子讲解 // Mot…...
前端脚手架开发指南:提高开发效率的核心操作
前端脚手架通过自动化的方式可以提高开发效率并减少重复工作,而最强大的脚手架并不是现成的那些工具而是属于你自己团队量身定制的脚手架!本篇文章将带你了解脚手架开发的基本技巧,帮助你掌握如何构建适合自己需求的工具,并带着你…...
职坐标AIoT技能培训课程实战解析
职坐标AIoT技能培训课程以人工智能与物联网技术深度融合为核心,构建了“理论实战行业应用”三位一体的教学体系。课程体系覆盖Python编程基础、传感器数据采集、边缘计算开发、云端服务部署及智能硬件开发全链路,通过分层递进的知识模块帮助学员建立系统…...
Yocto Project 快速构建
此文为机器辅助翻译,仅供个人学习使用,如有翻译不当之处欢迎指正 1 Yocto 项目快速构建 1.1 欢迎! 本简短文档将引导您完成使用 Yocto Project 进行典型镜像构建的流程,并介绍如何为特定硬件配置构建环境。您将使用 Yocto Proj…...
git相关配置
git相关配置 欢迎使用Markdown编辑器修改Git默认编辑器为vimgit配置默认用户名和密码: 欢迎使用Markdown编辑器 修改Git默认编辑器为vim #方法1:直接执行 git config --global core.editor vim#方法2:修改git的配置文件.git/config文件&am…...
ci/cd全流程实操
本次采用架构,gitlab + jenkins + 镜像仓库+ k8s 准备工作 一、gitlab部署 拉取镜像 部署环境: macbook m2中docker部署gitlab (m2平台架构问题,这里只能用yrzr/gitlab-ce-arm64v8 这个容器镜像) docker pull yrzr/gitlab-ce-arm64v8 在 Docker 里,–privileged=tr…...
Python中in和is关键字详解和使用
在 Python 中,in 和 is 是两个常用但含义不同的关键字,初学者很容易混淆它们的用法。下面是关于它们的详细解释、注意事项及常见示例。 一、关键字 in:成员运算符 1. 功能 用于判断某个元素是否存在于序列(如列表、元组、字符串…...
ACM模式用Scanner和System.out超时的解决方案和原理
Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:笔试强训 📚本系列文章为个人学…...
微服务中服务降级和异常的区别
在Java中,服务降级和异常处理是两个相关但不同的概念。它们的主要区别如下: 1. 服务降级(Service Degradation): 定义:服务降级是指在系统中某个服务或功能出现问题时,通过采取某些策略来降低服务的质量或…...
MYSQL创建索引的原则
创建索引的原则包括: 表中的数据量超过10万以上时考虑创建索引。 选择查询频繁的字段作为索引,如查询条件、排序字段或分组字段。 尽量使用复合索引,覆盖SQL的返回值。 如果字段区分度不高,可以将其放在组合索引的后面。 对于…...
29、魔法微前端——React 19 模块化架构
一、时空结界分割术(模块化架构设计) 1. 次元切割协议 // 主应用入口const HogwartsMain () > {const [subApps] useState({potion: React.lazy(() > import(./PotionShop)),library: React.lazy(() > import(./LibraryApp)),quidditch: R…...
【PmHub后端篇】PmHub 中缓存与数据库一致性的实现方案及分析
在软件开发项目中,缓存的使用十分普遍。缓存作为一种存储机制,能够暂时保存数据,从而加速数据的读取和访问。然而,当数据同时存在于缓存和数据库中时,如何保证两者的数据一致性成为了一个关键问题。在 PmHub 项目中&am…...
Verilog HDL 语言整理
Verilog HDL 语言 Verilog HDL 简介 硬件描述语言Hardware Description Language是一种用形式化方法即文本形式 来描述和设计数字电路和数字系统的高级模块化语言 Verilog HDL(Hardware Description Language)是一种硬件描述语言,用于建模…...
[250516] OpenAI 升级 ChatGPT:GPT-4.1 及 Mini 版上线!
目录 ChatGPT 迎来重要更新:GPT-4.1 和 GPT-4.1 mini 正式上线用户如何访问新模型?技术亮点与用户体验优化 ChatGPT 迎来重要更新:GPT-4.1 和 GPT-4.1 mini 正式上线 OpenAI 宣布在 ChatGPT 平台正式推出其最新的 AI 模型 GPT-4.1 和 GPT-4.…...
R语言学习--Day03--数据清洗技巧
在一般情况下,我们都是在数据分析的需求前提下去选择使用R语言。而实际上,数据分析里,百分之八十的工作,都是在数据清洗。并不只是我们平时会提到的异常值处理或者是整合格式,更多会涉及到将各种各样的数据整合&#x…...
文件系统交互实现
关于之前的搭建看QT控件文件系统的实现-CSDN博客,接下来是对本程序的功能完善,我想着是这样设计的,打开一个目录以后,鼠标选中一个项可以是目录,也可以是文件,右键可以出现一个菜单选择操作,比如…...
SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。
/// <summary> /// SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。 /// </summary> public class SqlHelper : IDbHelper {private readonly IDbConnectionFactory _connectionFactory;private…...
DevExpressWinForms-RichEditControl-基础应用
RichEditControl-基础应用 在企业级WinForms应用开发中,富文本编辑与文档处理是常见需求。DevExpress WinForms的RichEditControl作为一款功能强大的富文本编辑控件,提供了媲美Microsoft Word的文档处理能力,支持复杂格式编辑、打印导出、界…...
Elasticsearch 索引副本数
作者:来自 Elastic Kofi Bartlett 解释如何配置 number_of_replicas、它的影响以及最佳实践。 更多阅读:Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica 想获得 Elastic 认证?查看下一期 Elasticsearc…...
RabbitMQ 扇形交换器工作原理详解
目录 一、扇形交换器简介二、扇形交换器工作原理2.1 消息广播机制2.2 路由键的忽略三、代码示例3.1 生产者代码3.2 消费者代码四、实际应用场景4.1 日志收集系统4.2 实时通知系统4.3 事件驱动架构五、总结在 RabbitMQ 的众多交换器类型中,扇形交换器(Fanout Exchange)是一种…...
IDEA中springboot项目中连接docker
具体内容如下: 1、在Linux中安装docker 使用安装命令: apt-get install docker.io 还有一个是更新软件并安装docker: sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io 运行docker systemctl start …...
arxiv等开源外文书数据的获取方式
一、一些基本说明 开放API接口文档:https://info.arxiv.org/help/api/user-manual.html#2-api-quickstart研究领域分类说明文档:https://arxiv.org/category_taxonomy 二、基于url接口方式检索并获取数据 本质是get方式,在url中传检索参数…...
ChatGPT再升级!
近日,OpenAI 正式发布 GPT-4.1 和轻量级版本 GPT-4.1mini,并已全面上线 ChatGPT 平台,迅速引发全球 AI 圈热议,标志着 ChatGPT 在智能化和效率上再登新高峰。 GPT-4.1 是为编程与任务处理优化的高性能模型。相较前作 GPT-4o&#…...
23、电网数据管理与智能分析 - 负载预测模拟 - /能源管理组件/grid-data-smart-analysis
76个工业组件库示例汇总 电网数据管理与智能分析组件 1. 组件概述 本组件旨在模拟一个城市配电网的运行状态,重点关注数据管理、可视化以及基于模拟数据的智能分析,特别是负载预测功能。用户可以通过界面交互式地探索电网拓扑、查看节点状态、控制时间…...