【从UnityURP开始探索游戏渲染】专栏-直达

法线贴图呈现蓝紫色调(尤其以蓝色为主)是由其‌存储原理、切线空间坐标系设计及颜色编码规则共同决定的‌。

核心原因:法线向量的存储规则‌

‌法线向量的物理范围‌

法线是单位向量,每个分量(X, Y, Z)的取值范围为 ‌[-1, 1],分别代表切线空间中的方向:

  • ‌X(红色通道):左右偏移(左为负,右为正)
  • ‌Y(绿色通道):上下偏移(下为负,上为正)
  • ‌Z(蓝色通道):垂直表面的方向(指向外部为正)‌。

‌颜色空间的映射限制‌

图像颜色值范围是 ‌[0, 1](对应0~255),因此需要进行转换:

RGB=(Normalxyz+1)/2

  • 默认法线方向‌:当表面完全垂直(无倾斜)时,法线向量为 ‌(0, 0, 1)。
  • 转换结果‌:
    • R=20+1=0.5 (128)
    • G=20+1=0.5 (128)
    • B=21+1=1 (255)
    • 最终颜色为 ‌(128, 128, 255),即 ‌蓝紫色‌(蓝色占主导)‌。

‌现实模型的主导方向

  • 大多数模型表面(如墙面、地面)以‌垂直方向为主‌(Z≈1),因此蓝色通道值接近255,而XY通道接近128(中性灰),整体呈现蓝色基调‌。

‌颜色变化的场景解释‌

颜色表现对应的法线方向表面形态
‌深蓝色 (0,0,1)完全垂直向外平坦表面(如地板)
‌蓝紫色 (0.5,0.5,1)轻微倾斜缓坡、弧形表面
‌青色/绿色 (低R,高G,中B)明显上/下倾斜(Y≠0)边缘、陡坡
‌红色/粉色 (高R,中G,中B)‌明显左/右倾斜(X≠0)侧壁、凹凸边缘

💎 ‌示例‌:墙面法线贴图中,砖缝凹陷处因法线指向侧方(X/Y增大),可能呈现红绿色调,但整体仍以蓝紫色为基底‌。


️ ‌技术实现验证‌

‌生成与解码逻辑‌

  • 生成法线贴图‌:通过公式 color = (normal + 1) / 2 将高模法线烘焙为贴图‌。

  • Shader解码‌:在着色器中逆向计算还原法线向量:此步骤是光照计算的基础‌。

    glsl
    vec3 normal = texture(normalMap, uv).rgb * 2.0 - 1.0; // [0,1] → [-1,1]
    

‌切线空间的意义‌

法线贴图通常在‌ 切线空间(Tangent Space)中定义:

  • 以顶点法线为Z轴,切线为X轴,副切线为Y轴构建坐标系。
  • 优势‌:无论模型如何旋转,法线方向始终相对于表面本地坐标,确保凹凸效果稳定‌。

常见误区澄清‌

  • 误区1‌:蓝色是人为设定的美术风格。‌真相‌:蓝色是数学映射的必然结果,由垂直方向(0,0,1)的编码规则决定‌。
  • 误区2‌:法线贴图的颜色代表凹凸高度。‌真相‌:它存储的是‌方向‌而非高度,凹凸感通过光照模拟实现‌。

实际应用案例‌

  • Unity 工作流‌:将法线贴图拖入材质球的 ‌Normal Map‌ 插槽,通过 UnpackNormal() 函数解码(内置管线见 UnityCG.cginc,URP管线UnpackNormalScale()见Packing.hlsl)‌。
  • 效果增强‌:调整 ‌Normal Scale‌ 参数控制凹凸强度(值>1增强凸起,<1弱化)‌。

‌URP中的法线贴图

法线贴图设置流程

  • 导入法线贴图
    • 纹理类型设为"Default/Normal map"
    • 压缩格式推荐BC5(DXT5nm)或BC7
    • 勾选"sRGB"选项确保正确色彩空间转换
  • 创建URP材质
    • 使用Shader路径:Universal Render Pipeline/Lit
    • 将法线贴图拖拽到Normal Map插槽
    • 调整Normal Scale参数(建议0.5-1.5)

完整Shader代码实现

  • NormalMapURP.shader

    Shader "Custom/URPNormalMap"
    {Properties{_BaseMap("Albedo", 2D) = "white" {}_BaseColor("Color", Color) = (1,1,1,1)_NormalMap("Normal Map", 2D) = "bump" {}_NormalScale("Normal Scale", Range(0,2)) = 1_Metallic("Metallic", Range(0,1)) = 0_Smoothness("Smoothness", Range(0,1)) = 0.5}SubShader{Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline"}HLSLINCLUDE#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"TEXTURE2D(_BaseMap);SAMPLER(sampler_BaseMap);TEXTURE2D(_NormalMap);SAMPLER(sampler_NormalMap);CBUFFER_START(UnityPerMaterial)float4 _BaseMap_ST;half4 _BaseColor;half _Metallic;half _Smoothness;half _NormalScale;CBUFFER_ENDstruct Attributes{float4 positionOS : POSITION;float3 normalOS : NORMAL;float4 tangentOS : TANGENT;float2 uv : TEXCOORD0;};struct Varyings{float4 positionCS : SV_POSITION;float2 uv : TEXCOORD0;float3 normalWS : TEXCOORD1;float4 tangentWS : TEXCOORD2;float3 positionWS : TEXCOORD3;};ENDHLSLPass{Name "ForwardLit"Tags { "LightMode"="UniversalForward" }HLSLPROGRAM#pragma vertex vert#pragma fragment fragVaryings vert(Attributes input){Varyings output;VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);output.positionCS = vertexInput.positionCS;output.positionWS = vertexInput.positionWS;output.uv = TRANSFORM_TEX(input.uv, _BaseMap);output.normalWS = normalInput.normalWS;output.tangentWS = float4(normalInput.tangentWS, input.tangentOS.w);return output;}half4 frag(Varyings input) : SV_Target{// 采样基础贴图half4 baseColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv) * _BaseColor;// 采样和解压法线贴图half4 normalSample = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.uv);half3 normalTS = UnpackNormalScale(normalSample, _NormalScale);// 构建TBN矩阵half3 bitangentWS = cross(input.normalWS, input.tangentWS.xyz) * input.tangentWS.w;half3x3 TBN = half3x3(input.tangentWS.xyz, bitangentWS, input.normalWS);half3 normalWS = TransformTangentToWorld(normalTS, TBN);// 光照计算Light mainLight = GetMainLight();half3 lightDir = normalize(mainLight.direction);half NdotL = saturate(dot(normalWS, lightDir));half3 diffuse = baseColor.rgb * NdotL * mainLight.color;// 高光计算half3 viewDir = normalize(_WorldSpaceCameraPos - input.positionWS);half3 halfVec = normalize(lightDir + viewDir);half NdotH = saturate(dot(normalWS, halfVec));half specular = pow(NdotH, _Smoothness * 256) * _Metallic;half3 finalColor = diffuse + specular * mainLight.color;return half4(finalColor, baseColor.a);}ENDHLSL}}
    }
    

关键实现说明

  • 法线解压‌:使用UnpackNormalScale函数处理法线贴图数据,支持强度调节
  • TBN矩阵‌:通过切线、副切线和法线构建转换矩阵,将切线空间法线转到世界空间
  • 光照模型‌:采用Blinn-Phong模型计算漫反射和高光
  • URP适配‌:使用URP特有的GetVertexPositionInputs等函数替代传统Shader写法

常见问题解决方案

  • 法线效果异常‌:检查切线空间计算是否正确,确保模型导入时勾选"Calculate Tangents"
  • 性能优化‌:移动端可考虑在切线空间计算光照减少矩阵运算
  • 多光源支持‌:需添加AdditionalLights Pass处理额外光源

总结

法线贴图的蓝色基调本质是‌垂直方向向量(0,0,1)经归一化映射后的颜色表达‌,这种方法平衡了存储效率与光照计算需求,是3D渲染中模拟表面细节的核心技术‌,直观的颜色样式只是数据可视化的一种直观显示。


【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,🙏)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93924.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93924.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/93924.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

驱动开发系列63 - NVIDIA 开源GPU驱动open-gpu-kernel-modules编译调试

目录 一:通过apt方式安装nvidia 驱动 二:通过 .run 方式安装nvidia驱动 三:编译安装nvidia开源内核驱动 四:验证和调试 五:卸载驱动 1. 以apt方式安装nvidia 驱动的卸载方法 2. 以.run方式安装nvidia驱动的卸载方法 六:安装CUDA环境 一:通过apt方式安装nvidia 驱动…

对KingbaseES架构的解析:从读写分离到异地灾备的技术实现与保障机制

声明&#xff1a;文章为本人真实测评博客&#xff0c;非广告&#xff0c;并没有推广该平台 &#xff0c;为用户体验文章 本人旨在分享最真实的用户体验&#xff0c;为关注此类产品的朋友们提供一个客观的参考。 文章目录一、架构全景&#xff1a;四级高可用构建数字基础1.1 物…

Visual Studio中的常用调试功能(上)

1、利用断点进行调试添加断点的方式有以下几种1.键盘快捷键F92.通过菜单【Debug&#xff08;调试&#xff09;】-》【Toggle BreakPoint&#xff08;切换断点&#xff09;】3.点击代码行左边的空白处&#xff08;推荐&#xff09;设置断点后&#xff0c;按F5运行程序&#xff0…

Linux -- 线程同步

1.1条件变量 (1)当⼀个线程互斥地访问某个变量时&#xff0c;它可能发现在其它线程改变状态之前&#xff0c;它什么也做不了。 (2)例如⼀个线程访问队列时&#xff0c;发现队列为空&#xff0c;它只能等待&#xff0c;只到其它线程将⼀个节点添加到队列 中。这种情况就需要⽤到…

前端进阶指南:JavaScript性能优化实战全解析

深入剖析 JavaScript 性能瓶颈&#xff0c;分享优化技巧与最佳实践&#xff0c;让你的前端应用更快、更稳、更流畅。 &#x1f4d1; 目录 一、前言 二、性能瓶颈的常见来源 三、JavaScript代码优化技巧 1. 避免重复计算 2. 合理使用防抖与节流 3. 使用事件委托 四、渲染…

RabbitMQ:SpringAMQP Direct Exchange(直连型交换机)

目录一、案例需求二、基础配置三、代码实现直连型交换机也叫做定向交换机&#xff0c;通过RoutingKey绑定交换机与队列直接的关系。 生产者源码 消费者源码 一、案例需求 在RabbitMQ控制台中&#xff0c;声明队列direct.queue1和direct.queue2。在RabbitMQ控制台中&#xff…

implement libtime on Windows

因为Windows的time命令和Linux的time命令不一样&#xff0c;尝试实现libtime libtime.h /** libtime.h - 跨平台时间测量库* 功能&#xff1a;执行外部命令并测量其运行时间和资源使用*/#ifndef LIBTIME_H #define LIBTIME_H#include <stdio.h> #include <stdlib.h>…

Unity进阶--C#补充知识点--【C#各版本的新功能新语法】C#1~4与C#5

来源于唐老狮的视频教学&#xff0c;仅作记录和感悟记录&#xff0c;方便日后复习或者查找 一.C#版本与Unity的关系 1.各Unity版本支持的C#版本 更多信息可以在Untiy官网说明查看 https://docs.unity3d.com/2020.3/Documentation/Manual/CSharpCompiler.html&#xff08;这个好…

水闸安全综合监测系统解决方案

一、方案概述 水闸作为重要的水利工程设施&#xff0c;承担着防洪、排涝、供水和灌溉等关键功能。其安全性直接关系到下游人民群众的生命财产安全以及区域经济的稳定发展。近年来&#xff0c;随着极端天气频发和工程老化问题日益突出&#xff0c;水闸安全监测工作显得尤为重要。…

基于单片机智能点滴输液系统

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 该系统基于单片机控制技术&#xff0c;结合传感器和无线通信模块&#xff0c;实现对输液过程的实…

AI数据仓库管理提升效率

内容概要在数字化转型浪潮中&#xff0c;AI数据仓库管理正重塑企业数据处理格局。本部分简要介绍其核心机制&#xff0c;即通过智能API接入外部数据源实现多平台数据无缝整合&#xff0c;随后应用数据清洗技术去除冗余信息&#xff0c;确保数据质量。同时&#xff0c;加密存储机…

使用 Docker 安装长安链管理平台 + 部署区块链与示例合约

文章目录简介登录官网GithubPodman 配置&#xff08;Docker 配置 registry 地址&#xff09;安装长安链管理平台下载源码docker-compose.yml登录管理平台部署区块链Dockerfile构建镜像部署长安链订阅区块链部署合约下载示例合约部署示例合约投票管理文件哈希存证查找存证信息区…

Python训练营打卡 DAY 41 简单CNN

知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 → Batch归一化层…

云端赋能,智慧运维:分布式光伏电站一体化监控平台研究

摘要 本文针对分布式光伏电站存在的监管困难、火灾隐患、系统繁杂及运维不规范等行业痛点&#xff0c;提出AcrelCloud-1200光伏运维云平台解决方案。平台通过ANet-1E2S-4G网关集成多品牌逆变器数据&#xff0c;结合视频监控与气象站&#xff0c;实现电站全域监测&#xff1b;开…

CVPR 2025 | 具身智能 | HOLODECK:一句话召唤3D世界,智能体的“元宇宙练功房”来了

关注gongzhonghao【CVPR顶会精选】1.导读1.1 论文基本信息论文标题&#xff1a;《HOLODECK: Language Guided Generation of 3D Embodied AI Environments》作者&#xff1a;Yue Yang*1, Fan-Yun Sun*2, Luca Weihs*4, Eli Vanderbilt4, Alvaro Herrasti4,Winson Han4, Jiajun …

迅为RK3568开发板搭建Ubuntu环境

本小节介绍开发所需 Ubuntu 环境的搭建方法。系统要求:Ubuntu 系统要求&#xff1a;Ubuntu18.04~21.10 版本。推荐使用 20.04 版本&#xff0c;内存 16GB 及以上&#xff0c;硬盘 100GB 及以上。Ubuntu 系统的用户名不能包含中文字符。建议 Ubuntu 和 Windows 系统上安装的 Dev…

【数据结构】用堆解决TOPK问题

设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。示例&#xff1a;输入&#xff1a; arr [1,3,5,7,2,4,6,8], k 4 输出&#xff1a; [1,2,3,4]比较替换堆顶的数时&#xff0c;不需要让堆顶与数组的每一个数再进行比较&#xff0c;比较数组减去k个…

【深度长文】Anthropic发布Prompt Engineering全新指南

目录 1.什么时候适合用提示工程? 2.如何进行提示工程 2.1 使用提示模板 2.1.1 使用提示模板和变量 2.1.2 何时使用提示模板和变量 2.1.3 提示模板示例 2.2 保持清晰和直接 2.2.1 如何保持清晰、具有上下文和具体 2.2.2 示例 ​2.3 使用示例&#xff08;多示例提示…

【基础-判断】HarmonyOS提供了基础的应用加固安全能力,包括混淆、加密和代码签名能力

正确 解释如下: 应用加固: 这是指对应用程序进行保护,使其更难被逆向工程、篡改或盗版。HarmonyOS 作为现代操作系统,确实提供了这样的基础安全能力。 混淆: HarmonyOS 的 SDK 提供了代码混淆工具(通常基于 ProGuard 或类似技术)。开发者在构建应用时启用混淆,可以将类…

HTML 框架:构建网页布局的基石

HTML 框架&#xff1a;构建网页布局的基石 引言 HTML 框架是网页设计中不可或缺的一部分&#xff0c;它为网页内容的布局提供了强大的支持。本文将深入探讨 HTML 框架的概念、种类、应用以及如何有效地使用它们来构建网页布局。 什么是 HTML 框架&#xff1f; HTML 框架是一种网…