UnityShader(十)实现标准光照模型中的漫反射光照

基本光照模型中漫反射计算公式:

c_{diffuse}=(c_{light}\cdot m_{diffuse})max(0,\widehat{n}\cdot \widehat{I})

从公式可以看出,要计算漫反射需要知道四个参数:入射光线的颜色和强度clight,材质的漫反射系数mdiffuse,表面的法线n和光源方向I

为了防止点积的结果为负数,需要使用max操作,Cg提供了这样的函数,使用另一个函数也可以达到同样的目的,即saturate函数。

函数:saturate(x)

参数:x为用于操作的标量或者矢量,可以是floatfloat2float3等类型。

描述:x截取在[0,1]范围内,如果x是一个矢量,那么会对它的每一个分量进行这样的操作。

逐顶点光照

新建材质和Shader,并且重命名

打开Shader进行编辑

//为Shader命名
Shader "MyShader/DiffuseVertex"
{Properties{//定义一个Color属性,用于控制材质的漫反射颜色_Diffuse ("Diffuse",Color)=(1,1,1,1)}SubShader  {//定义Pass语义块,顶点/片元着色器的代码需要写在Pass语义块中Pass{/*LightMode标签是Pass标签中的一种,用于定义该Pass在Unity的光照流水线中的角色只有正确定义了LightMode,我们才能得到一些Unity的内置光照模型*/Tags{"LightMode"="ForwardBase"}CGPROGRAM//使用#pragma指令告诉Unity我们定义的顶点着色器和片元着色器叫什么名字#pragma vertex vert#pragma fragment frag//为了使用Unity内置的一些变量,还需要包含进Unity的内置文件Lighting.cginc#include "Lighting.cginc"//为了在Shader中使用Properties语义块中声明的属性,需要定义一个和该属性类型相匹配的变量fixed4 _Diffuse;/*定义顶点着色器的输入和输出结构体(输出结构体同时也是片元着色器的输入结构体)为了访问顶点的法线,需要在av2中定义一个normal变量,并通过使用NORMAL语义告诉Unity要把模型顶点的法线信息存储到normal变量中为了把在顶点着色器中计算得到的光照颜色传递给片元着色器,需要在v2f中定义一个color变量,并且不是必须使用COLOR语义,一些资料中会使用TEXCOORD0语义。*/struct a2v{float4 vertex: POSITION;float3 normal:NORMAL;};struct v2f{float4 pos:SV_POSITION;fixed3 color:COLOR;};/*在顶点着色器中进行逐顶点的漫反射光照在第一行定义了返回值o,顶点着色器最近本的任务是把顶点位置从模型空间转换到裁剪空间中因此需要使用Unity内置的模型*世界*投影矩阵UNITY_MATRIX_MVP完成这样的坐标转换,高版本写法为UnityObjectToClipPos(*)然后通过Unity内置的UNITY_LIGHTMODEL_AMBIENT得到环境光部分*/v2f vert(a2v v){v2f o;o.pos=UnityObjectToClipPos(v.vertex);fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;/*我们已经知道啦材质的漫反射颜色_Diffuse以及顶点法线v,normal我们还需要知道光源的颜色和强度信息以及光源的方向Unity提供内置变量_LightColor0来访问该Pass处理的光源的颜色和强度信息(注意:想要得到正确的值需要定义合适的LightMode标签)光源方向可以由_WorldSpaceLightPos0来得到(需要注意的是,这里对光源方向的计算不具有通用性,这里我们假设场景中只有一个光源且该光源的类型是平行光。但如果场景中有多个光源并且类型可能是点光源等其它类型,直接使用_WorldSpaceLightPos0就不能得到正确的结果)在计算法线和光源方向之间的点积时,我们需要选择它们所在的坐标系,只有两者处于同坐标空间下它们的点积才有意义,在这里我们选择了世界坐标空间。由于av2得到的顶点法线位于模型空间中,我们需要把法线转换到世界空间中。我们知道可以使用顶点变换矩阵的逆转置矩阵对法线进行相同的变换,因此我们首先得到模型空间到世界空间的变换矩阵的逆矩阵unity_WorldToObject,然后通过调换它在mul函数中的位置,得到和转置矩阵相同的矩阵乘法。由于法线是一个三维矢量,因此只需要截取unity_WorldToObject的前三行前三列即可。在得到世界空间中的法线和光源方向后需要进行归一化操作,在得到点积结果后需要防止结构为负数。因此使用了saturate函数。saturate函数是Cg提供的一种函数,作用是把参数截取到[0,1]范围内。最后在与光源的颜色和强度以及材质的漫反射颜色相乘即可得到最终的漫反射部分。*/fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject));fixed3 worldDir=normalize(_WorldSpaceLightPos0.xyz);fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldDir));//对环境光和漫反射光部分相加,得到最终的光照部分。o.color=ambient+diffuse;return o;}//所有的计算都在顶点着色器中,因此片元着色器只需要直接把顶点颜色输出即可fixed4 frag(v2f i):SV_TARGET{return fixed4(i.color,1.0);}ENDCG}}FallBack "Diffuse"}

效果:

 

逐像素光照

只需要对Shader进行一些更改就可以实现逐像素的漫反射效果。

 

Shader "MyShader/DiffusePiexl"
{Properties{_Diffuse ("Diffuse",Color)=(1,1,1,1)}SubShader  {Pass{Tags{"LightMode"="ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"fixed4 _Diffuse;struct a2v{float4 vertex: POSITION;float3 normal:NORMAL;};//修改顶点着色器的输出结构struct v2f{float4 pos:SV_POSITION;fixed3 worldNormal:TEXCOORD0;};//顶点着色器不需要计算光照模型,只需要把世界空间下的法线传递给片元着色器v2f vert(a2v v){v2f o;o.pos=UnityObjectToClipPos(v.vertex);o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);return o;}//片元着色器需要计算漫反射光照,与逐顶点光照过程完全相同fixed4 frag(v2f i):SV_TARGET{fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;fixed3 worldNormal=normalize(i.worldNormal);fixed3 worldDir=normalize(_WorldSpaceLightPos0.xyz);fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldDir));fixed3 color=ambient+diffuse;return fixed4(color,1.0);}ENDCG}}FallBack "Diffuse"}

效果:

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

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

相关文章

速卖通半托管优缺点是什么?速卖通半托管和全托管的区别是什么?速卖通半托管怎么发货?

1月5日,阿里速卖通AliExpress正式向全体卖家推出半托管模式,并且官方连续发放多重补贴,重金加码半托管模式,推广力度非常大。 关于速卖通半托管服务春节补贴政策 图源:阿里巴巴全球速卖通官方 由此可见,半…

一种手机短信验证码登录平台的解决方案

前提 爬取数据时,请求需要带上Cookie,这是很常见的一种防爬手段。更新Cookie,常用的方法就是Selenium模拟输入用户名和密码;偶尔会遇到图片验证码,现在打码平台很多且技术也很成熟,这个已经不成问题。所谓…

使用Postman做API自动化测试

Postman最基本的功能用来重放请求,并且配合良好的response格式化工具。 高级点的用法可以使用Postman生成各个语言的脚本,还可以抓包,认证,传输文件。 仅仅做到这些还不能够满足一个系统的开发,或者说过于琐碎&#…

java代码中调用自定义函数

定义函数 CREATE DEFINERrootlocalhost FUNCTION test_fun1(num1 FLOAT,num2 FLOAT) RETURNS float BEGINDECLARE SUM FLOAT DEFAULT 0;SET SUMnum1num2;RETURN SUM; END <select id"cunchu" resultType"java.util.Map">SELECT test_fun1(1,2) as r…

海外短剧系统国际短剧源码h5多语言版app挂载tiktok油管ins

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目 前言 一、海外短剧系统是什么&#xff1f; 二、海外短剧系统功能与运营方式介绍 1.系统功能 2.短剧APP运营方式 总结 前言 本文简单介绍海外短剧系统的功能&#xff…

Java项目:基于SSM框架实现的家纺用品销售管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm814基于SSM框架实现的家纺用品销售管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试…

langchain+xray:prompt控制漏洞扫描

写在前面 xray是长亭推出的一款漏洞扫描工具。 langchain是调用LLM大模型完成自动化任务的框架。 本篇文章是对langchain自定义工具的探索&#xff0c;通过编写一个xray调用的工具&#xff0c;联合ChatGPT对xray进行调用&#xff0c;实现对目标的漏洞扫描。 xray功能分析 …

3 款最好的电脑硬盘数据迁移软件

您将从本页了解 3 款最好的 SSD硬盘数据迁移软件&#xff0c;磁盘供应商提供的软件和可靠的第三方软件。仔细阅读本文并做出您的选择。 什么是数据迁移&#xff1f; 数据迁移是将数据移动到其他计算机或存储设备的过程。在日常工作活动中&#xff0c;常见的数据迁移有三种&…

应用宝 <危害支付安全>

游戏未收到任何通知被应用宝下架&#xff0c;问了客服 客服&#xff1a;应用危害支付安全&#xff0c; 我&#xff1a;什么是危害支付安全&#xff0c; 客服&#xff1a;存在非腾讯的支付方式 我&#xff1a;应用没有非腾讯的支付方式&#xff0c;都是用的米大师支付 过去很久。…

KAFKA节点故障的容错方案

KAFKA节点故障的容错方案 1. broker启动加载逻辑1.1 日志组成和分析1.2 snapshot文件1.3 broker启动流程1.4 LogManager的初始化和启动过程 2. controller高可用1.1 选主逻辑1.2 HA切换1.3 controller的职责 3. partition高可用3.1 ISR列表3.1 选举Leader 4. 疑问和思考4.1 如果…

安卓开发转鸿蒙开发到底有多简单?

前言 相信各位搞安卓的同学多多少少都了解过鸿蒙了&#xff0c;有些一知半解而有些已经开始学习起来。那这个鸿蒙到底好不好搞&#xff1f;要不要搞&#xff1f; 安卓反正目前工作感觉不好找&#xff0c;即便是上海这样的大城市也难搞&#xff0c;人员挺饱和的。最近临近年关…

发布技术路线图!美国量子计算公司QuEra公开三年OKR

​编辑丨慕一 编译/排版丨琳梦 卉可 深度好文&#xff1a;1100字丨8分钟阅读 近期&#xff0c;美国量子计算公司QuEra Computing宣布了一系列关于容错量子计算机的战略路线图&#xff0c;该路线图从2024年开始&#xff0c;最终目标是打造具有100纠错逻辑量子比特的系统。 在…

银行数据仓库体系实践(10)--汇总指标层和集市模型设计

建立多层次的数据访问服务体系&#xff0c;有力提升数据仓库的价值。基于指标汇总层、集市层、可以提供面向业务人员的即席数据查询、以及面向应用开发者的数据接口、应用访问接口&#xff0c;满足不同类型应用的需要。 1、汇总指标层模型设计原则及步骤 1.1建设目标&#xff…

Blender教程(基础)-面的细分与删除、挤出选区-07

一、Blender之面的细分 新建一个立方体&#xff0c;在编辑模式下、选中一个面。 在选中的面上单击右键弹出细分选项&#xff0c;选择细分。 在选中细分后、会默认细分1次。修改细分次数在左下角 二、Blender之面的删除 选择中需要操作的面&#xff0c;在英文状态下按X键弹…

Flutter开发2:安装Flutter

在本篇博客中&#xff0c;我们将详细介绍如何安装Flutter开发环境。安装Flutter是开始使用Flutter进行跨平台移动应用开发的第一步。让我们开始吧&#xff01; 官方安装文档 步骤1&#xff1a;下载Flutter SDK 打开浏览器&#xff0c;访问Flutter官方网站&#xff1a;https://…

SSRF靶场实践(作业)

Pikachu靶场 进入ssrf的页面&#xff0c;点击连接&#xff0c;发现url中记载了另一个url的内容 通过加载百度的网址发现可以返回内容 利用伪协议进行读取本地文件powershell.exe&#xff1b;不能执行&#xff0c;只能读取 查看源码&#xff0c;发现是通过curl_exec()读取网页/…

如何在Excel中清除单元格的格式?这里有详细步骤

Microsoft Excel提供了大量样式选项来自定义电子表格的外观。但是&#xff0c;如果你需要删除格式&#xff0c;则可以很容易地删除选定单元格和整个工作表的格式。我们将向你展示如何操作。 ​注意&#xff1a;清除格式只会删除文本的样式&#xff1b;将保留你的实际文本。 如…

java.util.LinkedHashSet cannot be cast to java.util.List 的解决方案

出现 “java.util.LinkedHashSet cannot be cast to java.util.List” 的错误&#xff0c;通常是因为你试图将一个 LinkedHashSet 对象直接强制转换为 List 类型。在 Java 中&#xff0c;LinkedHashSet 和 List 是两种不同的集合类型&#xff0c;不能直接进行转换。LinkedHashS…

USB清理软件USBclean轻松清理.DS_Store,Thumbs.db,.Spotlight文件

USBclean for Mac是一款Mac上的USB清理工具&#xff0c;USBclean mac版能够帮助我们快捷方便地为你清理外部磁盘垃圾文件&#xff0c;它支持将.DS_Store, Thumbs.db, .Spotlight 以及回收站中的垃圾文件进行清理。操作也十分简单&#xff0c;只需要将要清理的外部磁盘拖拽到USB…

Linux编辑器之vim的使用

文章目录 一、vim简介二、vim的基本概念三、vim的基本操作四、vim正常模式命令集移动光标删除文字复制替换撤销上一次操作更改跳至指定的行vim末行模式命令集列出行号跳到文件中的某一行查找字符保存文件离开vim 五、进阶vim玩法打开文件批量注释代码执行shell命令指定注释窗口…