当前位置: 首页 > news >正文

UnityShader学习笔记——多种光源

——内容源自唐老狮的shader课程

目录

1.光源类型

2.判断光源类型

2.1.在哪判断

2.2.如何判断

3.光照衰减

3.1.基本概念

3.2.unity中的光照衰减

 3.3.光源空间变换矩阵

 4.点光源衰减计算

5.聚光灯衰减计算

5.1.聚光灯的cookie(灯光遮罩)

5.2.聚光灯衰减计算

6.应用

7.如有疏漏,还请指出


1.光源类型

        平行光:没有位置,没有衰减,只有方向,颜色,强度参与计算

        点光源:五个属性都需要考虑

        聚光灯:五个属性都需要考虑,并且因为他的范围(由Range和Spot Angle共同决定)特殊,所以需要进行更复杂的运算

        面光源:在烘培时使用


2.判断光源类型

2.1.在哪判断

        我们一般在Additional Pass中判断光源类型以分别处理各部分的逻辑,因为不同光源的处理不一样

2.2.如何判断

unity提供了三个宏:

  • _DIRECTIONAL_LIGHT(平行光)
  • _POINT_LIGHT(点光源)
  • _SPOT_LIGHT(聚光灯)
//在CG中使用条件语句来分别处理#if defined(_DIRECTIONAL_LIGHT)
平行光逻辑
#elif defined(_POINT_LIGHT)
点光源逻辑
#elif defined(_SPOT_LIGHT)
聚光灯逻辑
#else
其他逻辑
#endif

        unity底层会根据该条件编译指令,生成多个 Shader Variants(着色器变体),这些变体共享相同的核心代码,但会根据条件选择执行不同的代码块。

        Shader Variants是在编写Shader时根据不同的配置(如条件编译指令下不同的条件)生成的多个版本的Shader


3.光照衰减

3.1.基本概念

        通常是指渲染过程中考虑光线在传播过程中的减弱效应。

        一般常见的光照衰减计算方式有:线性衰减和平方衰减,后者更符合现实

3.2.unity中的光照衰减

        为了提高性能,我们一般不会直接通过数学公式计算衰减,而是使用一张纹理作为查找表,在片元着色器中计算逐像素光照的衰减。

        为此,unity准备了一个内置的纹理类型的变量 _LightTexture0,unity会在内部计算好相关数据并存储到这个变量中。其上的纹理颜色值,表明了光源空间中不同位置的点对应的衰减值。

        起点(0,0)位置,表明和光源重合的点的衰减值

        终点(1,1)位置,表明光源空间中离光源最远的点的衰减值

        

        一般我们会直接从_LightTexture0纹理中进行纹理采样,利用其中的UNITY_ATTEN_CHANNE宏来获得衰减值所在的分量,即:

tex2D(_LightTexture0,,对应纹理坐标).UNITY_ATTEN_CHANNEL

         要注意的是:如果光源存在cookie(灯光遮罩),那么衰减查找纹理就变成_LightTextureB0

 3.3.光源空间变换矩阵

        由于我们要从光照纹理中取得对应的衰减数据,因此我们需要将顶点坐标从世界空间变换到光源空间,然后再去获取衰减数据,使用如下公式即可:

mul(unity_WorldToLight,世界空间下顶点坐标)


 4.点光源衰减计算

        1.将顶点从世界空间下转换到光源空间,并且只取xyz分量,也就是说lightCoord是一个float3的变量。需要了解的是,unity_WorldToLight计算所得的是一个规范在0~1之间的值,这个值可视为与光源的距离

        2.利用该光源空间的坐标来计算离光源的距离,并利用距离参数,从衰减纹理中采样

fixed atten = tex2D(_LightTexture0,dot(lightCoord,lightCoord).xx).UNITY_ATTEN_CHANNEL

            纹理坐标使用distance ^ 2是为了符合现实。ligthCoord是光源空间下顶点位置


5.聚光灯衰减计算

5.1.聚光灯的cookie(灯光遮罩)

        unity会默认为聚光灯弄个cookie,这玩意主要是用来模拟聚光灯的区域性,就像打手电一样

        此时,_LightTexture0 存储的变为cookie纹理信息,_LightTextureB0 存储的才是光照纹理信息,也就是说衰减值要从这里面取

5.2.聚光灯衰减计算

        1.将顶点从世界空间转换到光源空间,并且这里的lightCoord是一个float4变量,也就是取了w

        2.利用光源空间下的坐标信息与一些数据获取聚光灯的衰减信息,公式为(好长):

fixed atten = (lightCoord.z > 0) *

tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w *

tex2D(_LightTextureB0, dot(lightCoord, lightCoord).xx).UNITY_ATTEN_CHANNEL

        第一行:判断物体是不是在聚光灯的背面,如果在背面返回值是0,即不受聚光灯影响

        第二行:后半部分就是把xy变到01区间内,xy/w能变到-0.5~0.5之间,加个0.5就正好,然后对遮罩纹理采样获取遮罩衰减值(就是那个w)。为什么要这么变换可以画个图根据相似三角形推导一下

        第三行:正常取出基于距离的光照衰减值,需要了解的是,dot不会计算w


6.应用

        1.为BasePass添加编译指令 #pragma multi_compile_fwdbase

           为AdditionalPass添加编译指令 #pragma multi_compile_fwdadd

           这些编译指令会帮我们编译对应Pass中所有变体,并且附加通道的编译指令还可以确保在附加渲染通道中能访问到正确的光照变量

        2.在附加通道中加入混合命令 Blend One One,即线性简单效果

        3.根据条件判断语句,基于不同的光照类型计算光的方向和衰减值。方向是因为点光源和聚光灯需要用光源位置减去顶点位置,平行光不用

        4.计算最终颜色,附加通道中的最后颜色不需要再加环境光,只需要将满反射颜色和高光反射颜色相加然后乘以衰减值即可

 //这是附加通道Pass{Tags { "LightMode" = "ForwardAdd" }Blend One OneCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdadd#include "Lighting.cginc"#include "UnityCG.cginc"#include "AutoLight.cginc"fixed4 _DiffuseColor;fixed4 _SpecularColor;float _Gloss;struct v2f{float4 pos : SV_POSITION;float3 wNormal : NORMAL;float3 wPos : TEXCOORD0;};v2f vert(appdata_full v){v2f data;data.pos = UnityObjectToClipPos(v.vertex);data.wNormal = UnityObjectToWorldNormal(v.normal);float3 wPos = mul(unity_ObjectToWorld, v.vertex).xyz;data.wPos = wPos;return data;}fixed4 frag(v2f f) : SV_TARGET{float3 wNormal = normalize(f.wNormal);float3 wLightDir = float3(0, 0, 0);#if defined(_DIRECTIONAL_LIGHT)wLightDir = normalize(_WorldSpaceLightPos0);#else// 点光源和聚光灯的灯光方向需要用 位置 减去 顶点位置wLightDir = normalize(_WorldSpaceLightPos0.xyz - f.wPos);#endiffloat3 wViewDir = normalize(_WorldSpaceCameraPos - f.wPos).xyz;float3 halfAngle = normalize(wLightDir + wViewDir);fixed3 lambertColor = _LightColor0.rgb * _DiffuseColor.rgb * max(0, dot(wNormal, wLightDir));fixed3 blinn_PhongColor = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(wNormal, halfAngle)), _Gloss);//这个条件判断不止一种写法,还有别的写法#if defined(_DIRECTIONAL_LIGHT)float atten = 1;#else#if defined(_POINT_LIGHT)//注意由世界坐标向空间左边转换时,将wPos作为四维向量转换并只取xyz(因为w没用)float3 lightCoord = mul(unity_WorldToLight, float4(f.wPos, 1)).xyz;float atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).xx).UNITY_ATTEN_CHANNEL;#elif defined(_SPOT_LIGHT)//这里w就有用了float4 lightCoord = mul(unity_WorldToLight, float4(f.wPos, 1));//1.判断能否照到;  2.映射到最大平面;  3.距离的平方采样;  float atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;#elsefloat atten = 1;#endif#endif//附加渲染通道中不需要加 环境光颜色,原因是再基础通道中就已经计算了//衰减值 乘以 兰伯特光照和布林芳高光的颜色之和fixed3 finalColor = (lambertColor + blinn_PhongColor) * atten;return fixed4(finalColor, 1);}ENDCG}
多种光源

7.如有疏漏,还请指出

相关文章:

UnityShader学习笔记——多种光源

——内容源自唐老狮的shader课程 目录 1.光源类型 2.判断光源类型 2.1.在哪判断 2.2.如何判断 3.光照衰减 3.1.基本概念 3.2.unity中的光照衰减 3.3.光源空间变换矩阵 4.点光源衰减计算 5.聚光灯衰减计算 5.1.聚光灯的cookie(灯光遮罩) 5.2.聚…...

深入浅出谈VR(虚拟现实、VR镜头)

1、VR是什么鬼? 近两年VR这次词火遍网上网下,到底什么是VR?VR是“Virtual Reality”,中文名字是虚拟现实,是指采用计算机技术为核心的现代高科技手段生成一种虚拟环境,用户借助特殊的输入/输出设备&#x…...

项目2 车牌检测

检测车牌 1. 基本思想2. 基础知识2.1 YOLOV5(参考鱼苗检测)2.1.1 模型 省略2.1.2 输入输出 省略2.1.3 损失函数 省略2.2 LPRNet2.2.1 模型2.2.2 输入输出2.2.3 损失函数3. 流程3.1 数据处理3.1.1 YOLOV5数据处理3.2.2 LPRNet数据处理3.2 训练3.2.1 YOLOV5训练 省略3.2.2 LPRN…...

Linux: 网络基础

1.协议 为什么要有协议:减少通信成本。所有的网络问题,本质是传输距离变长了。 什么是协议:用计算机语言表达的约定。 2.分层 软件设计方面的优势—低耦合。 一般我们的分层依据:功能比较集中,耦合度比较高的模块层…...

【实战篇】巧用 DeepSeek,让 Excel 数据处理更高效

一、为何选择用 DeepSeek 处理 Excel 在日常工作与生活里,Excel 是我们频繁使用的工具。不管是统计公司销售数据、分析学生成绩,还是梳理个人财务状况,Excel 凭借其强大的功能,如数据排序、筛选和简单公式计算,为我们提供了诸多便利。但当面对复杂的数据处理任务,比如从…...

Flink CDC YAML:面向数据集成的 API 设计

摘要:本文整理自阿里云智能集团 、Flink PMC Member & Committer 徐榜江(雪尽)老师在 Flink Forward Asia 2024 数据集成(一)专场中的分享。主要分为以下四个方面: Flink CDC YAML API Transform A…...

RabbitMQ技术深度解析:打造高效消息传递系统

引言 在当前的分布式系统架构中,消息队列作为一种高效的消息传递机制,扮演着越来越重要的角色。RabbitMQ,作为广泛使用的开源消息代理,以其高可用性、扩展性和灵活性赢得了众多开发者的青睐。本文将深入探讨RabbitMQ的核心概念、…...

DeepSeek与人工智能的结合:探索搜索技术的未来

云边有个稻草人-CSDN博客 目录 引言 一、DeepSeek的技术背景 1.1 传统搜索引擎的局限性 1.2 深度学习在搜索中的优势 二、DeepSeek与人工智能的结合 2.1 自然语言处理(NLP) 示例代码:基于BERT的语义搜索 2.2 多模态搜索 示例代码&…...

TAPEX:通过神经SQL执行器学习的表格预训练

摘要 近年来,语言模型预训练的进展通过利用大规模非结构化文本数据取得了巨大成功。然而,由于缺乏大规模高质量的表格数据,在结构化表格数据上应用预训练仍然是一个挑战。本文提出了TAPEX,通过在一个合成语料库上学习神经SQL执行…...

Qt:Qt基础介绍

目录 Qt背景介绍 什么是Qt Qt的发展史 Qt支持的平台 Qt版本 Qt的优点 Qt的应用场景 Qt的成功案例 Qt的发展前景及就业分析 Qt背景介绍 什么是Qt Qt是⼀个跨平台的C图形用户界面应用程序框架。它为应用程序开发者提供了建立艺术级图形界面所需的所有功能。它是完全面向…...

加速度计信号处理

【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)_加速度计滤波器-CSDN博客 https://wenku.baidu.com/view/622d38b90f22590102020740be1e650e52eacff9.html?_wkts_1738906719916&bdQ…...

基于SpringBoot养老院平台系统功能实现六

一、前言介绍: 1.1 项目摘要 随着全球人口老龄化的不断加剧,养老服务需求日益增长。特别是在中国,随着经济的快速发展和人民生活水平的提高,老年人口数量不断增加,对养老服务的质量和效率提出了更高的要求。传统的养…...

Conmi的正确答案——Rider中添加icon作为exe的图标

C#版本&#xff1a;.net 8.0 Rider版本&#xff1a;#RD-243.22562.250&#xff08;非商业使用版&#xff09; 1、添加图标到解决方案下&#xff1a; 2、打开“App.xaml”配置文件&#xff0c;添加配置&#xff1a; <Applicationx:Class"ComTransmit.App"xmlns&q…...

机试题——DNS本地缓存

题目描述 正在开发一个DNS本地缓存系统。在互联网中&#xff0c;DNS&#xff08;Domain Name System&#xff09;用于将域名&#xff08;例如www.example.com&#xff09;解析为IP地址&#xff0c;以便将请求发送到正确的服务器上。通常情况下&#xff0c;DNS请求会发送到互联…...

Day38【AI思考】-彻底打通线性数据结构间的血脉联系

文章目录 **彻底打通线性数据结构间的血脉联系****数据结构家族谱系图****一、线性表&#xff08;老祖宗的规矩&#xff09;****核心特征** **二、嫡系血脉解析**1. **数组&#xff08;规矩森严的长子&#xff09;**2. **链表&#xff08;灵活变通的次子&#xff09;** **三、庶…...

【LeetCode】152、乘积最大子数组

【LeetCode】152、乘积最大子数组 文章目录 一、dp1.1 dp1.2 简化代码 二、多语言解法 一、dp 1.1 dp 从前向后遍历, 当遍历到 nums[i] 时, 有如下三种情况 能得到最大值: 只使用 nums[i], 例如 [0.1, 0.3, 0.2, 100] 则 [100] 是最大值使用 max(nums[0…i-1]) * nums[i], 例…...

[MRCTF2020]Ez_bypass1(md5绕过)

[MRCTF2020]Ez_bypass1(md5绕过) ​​ 这道题就是要绕过md5强类型比较&#xff0c;但是本身又不相等&#xff1a; md5无法处理数组&#xff0c;如果传入的是数组进行md5加密&#xff0c;会直接放回NULL&#xff0c;两个NuLL相比较会等于true&#xff1b; 所以?id[]1&gg…...

MySQL 缓存机制与架构解析

目录 一、MySQL缓存机制概述 二、MySQL整体架构 三、SQL查询执行全流程 四、MySQL 8.0为何移除查询缓存&#xff1f; 五、MySQL 8.0前的查询缓存配置 六、替代方案&#xff1a;应用层缓存与优化建议 总结 一、MySQL缓存机制概述 MySQL的缓存机制旨在提升数据访问效率&am…...

LabVIEW自定义测量参数怎么设置?

以下通过一个温度采集案例&#xff0c;说明在 LabVIEW 中设置自定义测量参数的具体方法&#xff1a; 案例背景 ​ 假设使用 NI USB-6009 数据采集卡 和 热电偶传感器 监测温度&#xff0c;需自定义以下参数&#xff1a; 采样率&#xff1a;1 kHz 输入量程&#xff1a;0~10 V&a…...

海思的一站式集成环境Hispark Studio更新了

HiSpark Studio是海思提供的面向智能设备开发者提供一站式集成开发环境&#xff0c;支持代码编辑、编译、烧录和调试等功能。我以前在评测星闪芯片的时候用过&#xff0c;当时写了篇博客&#xff1a;【星闪开发连载】WS63E开发板Windows环境的构建_hispark studio-CSDN博客。那…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...