Unity Shader入门精要——笔记

第1篇 基础篇

第2章:渲染流水线

GPU流水线

顶点数据–> 几何阶段:(顶点着色器–> 曲面细分着色器–>几何着色器–>裁剪–>屏幕映射)–>光栅化阶段(三角形设置–>三角形遍历–>片元着色器–>逐片元操作)–>屏幕图像

顶点着色器:最基本的功能就是把模型的顶点坐标从模型空间转换到齐次裁剪坐标(通常串联成一个矩阵,即MVP矩阵)。

第4章:学习Shader所需的数学基础

数学基础

矢量减法 b-a :理解为b点相对于a点的向量,再坐标系中以a点为尾,b点为头

点积(内积):满足交换律结合律

  1. 可以用来求b在单位向量a上的投影长度
  2. 可以用来求两个向量的夹角(公式二),若结果小于0则为钝角,若结果大于0则为锐角
  3. 可以用来比较两个向量模的大小(性质三)

叉积(外积):只满足反交换律(axb=-bxa)

  1. |axb|为a和b向量构成的正方形面积,若a,b平行,则axb=0
  2. axb的结果代表两个向量的垂直向量,方向则由坐标系决定

矩阵乘法:不满足交换律,满足结合律

顶点的坐标空间变换过程

  • 第一步:将顶点坐标从模型空间变换到世界空间中,这个变换通常叫做模型变换。
  • 第二步:将顶点坐标从世界空间变换到观察空间中,这个变换通常叫做观察变换。
  • 第三步:将顶点坐标从观察空间变换到裁剪空间(齐次裁剪坐标系)中,这个变换通常叫做投影变换。
  • 第四步:将顶点坐标从裁剪空间变换到屏幕空间,这个变换通常叫做屏幕映射,齐次裁剪坐标系的顶点坐标除以w分量(齐次除法),得到归一化设备坐标(NDC),这个过程叫做归一化。再将归一化后的坐标通过屏幕映射获得屏幕上的#D像素坐标。

第2篇 初级篇

第6章:标准光照模型

环境光

c a m b i e n t = g a m b i e n t c_{ambient}=g_{ambient} cambient=gambient

自发光

c e m i s s i v e = m e m i s s i v e c_{emissive}=m_{emissive} cemissive=memissive

漫反射

兰伯特光照模型

c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) m a x ( 0 , n ^ ⋅ I ) c_{diffuse}=(c_{light}\cdot m_{diffuse})max(0,\widehat{n}\cdot I) cdiffuse=(clightmdiffuse)max(0,n I)
其中 n n n是表面法线, I I I是指向光源的单位矢量, m d i f f u s e m_{diffuse} mdiffuse是材质的漫反射颜色, c l i g h t c_{light} clight是光源颜色。为防止法线和光源方向点乘的结果为负值,使用取最大值的函数来将其截取到0,这可以防止物体被从后面来的光源照亮。

半兰伯特光照模型

广义的半兰伯特光照模型公式如下:
c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) ( α ( n ^ ⋅ I ) + β ) c_{diffuse}=(c_{light}\cdot m_{diffuse})(\alpha(\widehat{n}\cdot I)+\beta) cdiffuse=(clightmdiffuse)(α(n I)+β)
与原兰伯特模型相比,半兰伯特光照模型没有使用 m a x max max操作来防止 n n n I I I的点积为负值,而是对其结果进行了一个 α \alpha α倍的缩放再加上一个 β \beta β大小的偏移。绝大多数情况下, α \alpha α β \beta β的值均为0.5,即公式为:
c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) ( 0.5 ( n ^ ⋅ I ) + 0.5 ) c_{diffuse}=(c_{light}\cdot m_{diffuse})(0.5(\widehat{n}\cdot I)+0.5) cdiffuse=(clightmdiffuse)(0.5(n I)+0.5)
通过这样的公式,可以把 n ^ ⋅ I \widehat{n}\cdot I n I的结果范围从[-1,1]映射到[0,1]范围内,也就是说,对于模型的背光面,在原兰伯特光照模型中点积结果将映射到同一个值,即0值处;而在半兰伯特模型中,背光面也可以又明暗变化,不同的点积结果会映射到不同的值上。

需要注意的是,半兰伯特是没有任何物理依据的,它仅仅是一个视觉加强技术。

高光反射

在硬件实现时,如果摄像机和光源距离模型足够远的话,Blinn模型会快于Phong模型,这是因为,此时可以认为 v ^ \widehat{v} v I ^ \widehat{I} I 都是定值,因此 h ^ \widehat{h} h 将是一个常量。但是,当 v ^ \widehat{v} v I ^ \widehat{I} I 不是定值时,Phong模型可能反而更快一些。需要注意的是,这两种光照模型都是经验模型,也就是说,不应该认为Blinn模型是对“正确的”Phong模型的近似。实际上,在一些情况下,Blinn模型更符合实验结果。

Phong光照模型

计算反射方向:
r = 2 ( n ^ ⋅ I ) n ^ − I r=2(\widehat{n} \cdot I)\widehat{n}-I r=2(n I)n I
通过Phong模型来计算高光反射的部分:
c s p e c u l a r = ( c l i g h t ⋅ m s p e c u l a r ) m a x ( 0 , v ^ ⋅ r ) m g l o s s c_{specular}=(c_{light} \cdot m_{specular})max(0,\widehat{v} \cdot r)^{m_{gloss}} cspecular=(clightmspecular)max(0,v r)mgloss
其中 n n n是表面法线, v ^ \widehat{v} v 是视角方向, I I I是光源方向, r r r是反射方向, m g l o s s m_{gloss} mgloss是材质的光泽度,也被称为反光度。它用于控制高光区域的“亮点”有多宽, m g l o s s m_{gloss} mgloss越大,亮点就越小。 m s p e c u l a r m_{specular} mspecular是材质的高光反射颜色,它用于控制该材质对于高光反射的强度和颜色。 c l i g h t c_{light} clight则是光源的颜色和强度。同样,这里也需要防止 v ^ ⋅ r ^ \widehat{v} \cdot \widehat{r} v r 的结果为负数。

Blinn-Phong光照模型

它的基本思想是,避免计算反射方向 r ^ \widehat{r} r 。为此,Blinn模型引入了一个一个新的矢量 h ^ \widehat{h} h ,他是通过对 v ^ \widehat{v} v I ^ \widehat{I} I 的取平均后再归一化得到的。即:
h ^ = v ^ + I ^ ∣ v ^ + I ^ ∣ \widehat{h} = \frac{\widehat{v}+\widehat{I}}{\left\vert \widehat{v}+\widehat{I} \right\vert} h = v +I v +I
然后,使用 n ^ \widehat{n} n h ^ \widehat{h} h 之间的夹角进行计算,而非 v ^ \widehat{v} v r ^ \widehat{r} r 之间的夹角。
总结一下,Bilinn模型的公式如下:
c s p e c u l a r = ( c l i g h t ⋅ m s p e c u l a r ) m a x ( 0 , n ^ ⋅ h ^ ) m g l o s s c_{specular}=(c_{light} \cdot m_{specular})max(0,\widehat{n} \cdot \widehat{h})^{m_{gloss}} cspecular=(clightmspecular)max(0,n h )mgloss

Shader 常用函数

//取得小数部分  
frac(x);  //将x限制在[0,1]范围中  
saturate(x)  //返回一个布尔值,如果输入的向量的任何分量为非零,返回true,否则返回false  
any(x)  //环境光颜色
UNITY_LIGHTMODEL_AMBIENT//世界空间下的光源方向
_WorldSpaceLightPos0//光源的颜色与强度信息(注意,想要的到正确的值需要定义合适的LightMode标签)
_LightColor0//用于高光反射中计算反射方向reflectDir,CG的reflect函数的入射方向要求是由光源指向交点处的,因此需要对worldLightDir取反后再传给reflect函数
reflect(-worldLightDir, worldNormal));

第7章:基础纹理

凹凸映射

  1. 高度映射:使用一张高度纹理来模拟表面位移,得到一个修改后的法线值。
  2. 法线映射:使用一张法线纹理来直接存储表面法线。
高度纹理

高度图存储的是强度值,用于表示模型表面局部的海拔高度,颜色越浅表明该位置的表面越向外凸起,而颜色越深表明该位置越向里凹。

法线纹理

法线纹理存储的就是表面的法线方向,由于法线方向的分量范围在[-1,1],而像素的分量范围为[0,1],因此需要做一个映射:
p i x e l = n o r m a l + 1 2 pixel = \frac{normal +1}{2} pixel=2normal+1
在Shader中对法线纹理进行纹理采样后,还需要对结果进行一次反映射的过程,以得到原先的法线方向。反映射的过程实际就是使用上面映射函数的逆函数:
n o r m a l = p i x e l ∗ 2 − 1 normal=pixel*2-1 normal=pixel21

Shader 常用函数

//_MainTex_ST可以得到该纹理的缩放和平移值,_MainTex_ST.xy存储的是缩放值,_MainTex_ST.zw存储的是偏移值;首先使用缩放属性对纹理坐标进行缩放,然后再使用偏移属性对结果进行偏移。
o.uv=v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
//Unity提供了一个内置宏TRANSFORM_TEX来计算上述过程。
o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);//使用内置的UnpackNormal函数对法线进行采样和解码(需要把法线纹理的格式标识成Normal map)
fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));  
bump.xy *= _BumpScale;  
bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));

第8章:透明效果

基础概念

透明度测试:它采用一种“霸道极端”的机制,只要一个片元的透明度不满足条件(通常是小于某个阀值),那么它对应的片元就会被舍弃。被舍弃的片元将不会再进行任何处理也不会对颜色缓冲产生任何影响:否则,就会按照普通的不透明物体的处理方式来处理它,即进行深度测试、深度写入等。也就是说,透明度测试是不需要关闭深度写入的,它和其他不透明物体最大的不同就是它会根据透明度来舍弃一些片元。虽然简单,但是它产生的效果也很极端,要么完全透明,即看不到,要么完全不透明,就像不透明物体那样。
透明度混合:这种方法可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是,透明度混合需要关闭深度写入(我们下面会讲为什么需要关闭),这使得我们要非常小心物体的渲染顺序。需要注意的是,透明度混合只关闭了深度写入,但没有关闭深度测试。这意味着,当使用透明度混合渲染一个片元时,还是会比较它的深度值与当前深度缓冲中的深度值,如果它的深度值距离摄像机更远,那么就不会再进行混合操作。这一点决定了,当一个不透明物体出现在一个透明物体的前面,而我们先渲染了不透明物体,它仍然可以正常地遮挡住透明物体。也就是说,对于透明度混合来说,深度缓冲是只读的。

混合命令

//混合因子命令
Blend SrcFactor DstFactor
Blend SrcFactor DstFactor,SrcFactorA DstFactorA

进行加法时使用的混合公式:

O r g b = S r c F a c t o r × S r g b + D s t F a c t o r × D r g b O_{rgb}=SrcFactor \times S_{rgb}+DstFactor \times D_{rgb} Orgb=SrcFactor×Srgb+DstFactor×Drgb
O a = S r c F a c t o r A × S a + D s t F a c t o r A × D a O_{a}=SrcFactorA \times S_{a}+DstFactorA \times D_{a} Oa=SrcFactorA×Sa+DstFactorA×Da

混合操作

BlendOp BlendOperation//如
//将混合后的源颜色和目的颜色相加。默认的混合操作。
BlendOp Add
//将混合后的源颜色减去目的颜色。
BlendOp Sub
//将混合后的目的颜色减去源颜色。
BlendOp RevSub
//使用源颜色和目的颜色中较小的值,是逐分量比较的。
BlendOp Min
//使用源颜色和目的颜色中较大的值,是逐分量比较的。
BlendOp Max

常见的混合类型

//正常(Wormal),即透明度混合
Blend SrcAlpha OneMinusSrcAlpha//柔和相加(Soft Additive)
Blend OneMinusDstColor One//正片叠底(Multiply),即相乘
Blend DstColor Zero//两倍相柔(2x Multiply)
Blend DstColor SrcColor//变暗(Darken)
BlendOp Min
Blend One One//变亮(Lighten)
BlendOp Max
Blend One One//滤色(Screen)
Blend OneMinusDstColor One
//等同于
Blend One OneMinusSrcColor//线性减淡(Linear Dodge)
Blend One One

Shader 常用函数

//透明度测试
SubShader{Tag{//在AlphaTest渲染队列"Queue"="AlphaTest"//意味着这个SubShader不会受到投影器(Projectors)的影响"IgnoreProjector"="True"//加入提前定义的组中"RenderType"="TransparentCutout"}Pass{···}
}//透明度混合
SubShader{Tag{//在Transparent渲染队列"Queue"="Transparent"//意味着这个SubShader不会受到投影器(Projectors)的影响"IgnoreProjector"="True"//加入提前定义的组中"RenderType"="Transparent"}Pass{//关闭深度写入ZWrite Off//设置Blend的混合模式Blend SrcAlpha OneMinusSrcAlpha···}
}函数: void clip(foat4 x); void clip(float3 x); void clip(float2 x); void clip(floatl x); void clip(float x);
参数:裁剪时使用的标量或矢量条件。
描述:如果给定参数的任何一个分量是负数,就会舍弃当前像素的输出颜色。它等同于下面的代码:
void clip(float4 x)
{if( any( x < 0 ) )discard;
}//渲染命令,用于设置颜色通道的写掩码(write mask)
//当ColorMask设为0时,意味着该Pass不写入任何颜色通道,即不会输出任何颜色。
ColorMask RGB | A | 0 | 其他任何R、G、B、A的组合

第3篇 中级篇

第9章:更复杂的光照

Shader 常用函数

//阴影计算三剑客
#include "AutoLight.cginc"
//声明一个用于对阴影纹理采样的坐标,参数是下一个可用的插值寄存器的索引值
SHADOW_COORDS(2)
//在顶点着色器种计算声明的阴影纹理坐标
TRANSFER_SHADOW(o)
//在片元着色器种计算阴影值
SHADOW_ATTENUATION(i)//Unity内置的用于计算光照衰减和阴影的宏,它会将光照衰减和阴影值相乘后的结果存储到第一个参数种;第二个参数是结构体v2f;第三个参数是世界空间的坐标,它会用于计算光源空间下的坐标,再对光照衰减纹理采样来得到光照衰减。
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

第10章:高级纹理

Shader 常用函数

//Compute th reflect dir in world space  
o.worldRefl = reflect(-o.worldViewDir, o.worldNormal);//Compute the refract dir in world space  
o.worldRefr = refract(-normalize(o.worldViewDir), normalize(o.worldNormal), _RefractRatio);

第11章:让画面动起来

Shader 常用函数

//ShadowCaster Pass
Tags {"LightMode"="ShadowCaster"}#pragma multi_compile_shadowcasterstruct v2f  
{//在v2f结构体中定义阴影投射需要定义的变量V2F_SHADOW_CASTER;  
};//顶点着色器中
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);//片元着色器中,把结果输出到深度图和阴影映射纹理中
SHADOW_CASTER_FRAGMENT(i);

第4篇 高级篇

第12章:屏幕后处理效果

Shader 常用函数


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

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

相关文章

Zabbix监控应用

一.监控tomcat 1.在tomcat服务器上安装zabbix-agent服务 [rootnode2 etc]#vim zabbix_agentd.conf 94 Server192.168.240.13 #指向当前zabbix server ##### Passive checks related #被动检查相关配置### Option: ListenPort ListenPort10050 #监听端口 默认的无需修改11…

SPF配置教程:如何安全构建邮件发送策略?

SPF配置教程的步骤详解&#xff01;SPF记录配置方法策略有哪些&#xff1f; SPF通过允许域名所有者指定哪些主机可以代表该域发送邮件&#xff0c;从而减少电子邮件欺诈和垃圾邮件的风险。AokSend将详细介绍SPF配置教程&#xff0c;并指导您如何安全地构建邮件发送策略。 SPF…

《白话机器学习的数学》第4章——评估

4.1模型评估 1.由于像多重回归这样的问题会导致无法在图上展示&#xff0c;所以需要能够够定量地表示机器学习模型的精度。 4.2交叉验证 4.2.1回归问题的验证 1.把获取的全部训练数据分成两份&#xff1a;一份用于测试&#xff0c;一份用于训练。然后用前者来评估模型。 一般…

C# 数组常用遍历方式

// 假设数组Point[] points new Point[2];// 第一种遍历 forfor (int i 0; i < points.Length; i){Point p points[i];Console.WriteLine($"X{p.X},y{p.Y}");}// 第二种遍历 foreachforeach (Point p in points){Console.WriteLine($"X{p.X},y{p.Y}"…

TCP三次握手和四次挥手的理解

三次握手 第一次握手&#xff1a; 客户端发出 请求报文其中SYN应1&#xff0c;选择一个序列号x 第二次握手&#xff1a; 服务端接收到之后回复 确认报文&#xff0c;其中SYN应1&#xff0c;ACK1&#xff0c;确认号是x1&#xff0c;同时为自己初始化序列号y 第三次握手&…

spring —— AOP(前置通知)

一、pom 中需要增加的依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>6.0.2</version> </dependency> <dependency><groupId>org.springframework</g…

Hadoop架构

一、案列分析 1.1案例概述 现在已经进入了大数据(Big Data)时代&#xff0c;数以万计用户的互联网服务时时刻刻都在产生大量的交互&#xff0c;要处理的数据量实在是太大了&#xff0c;以传统的数据库技术等其他手段根本无法应对数据处理的实时性、有效性的需求。HDFS顺应时代…

ubuntu22.04,AX101网卡,打不开蓝牙

安装完ubuntu 22.04后&#xff0c;发现蓝牙可以识别&#xff0c;但是打不开。查看/var/log/dmesg日志&#xff1a; [ 2.587972] kernel: Bluetooth: hci0: Failed to load Intel firmware file intel/ibt-1040-1050.sfi (-2) [ 2.589252] kernel: Bluetooth: hci0: Fail…

Linux(CentOS)的“应用商城” —— yum

Linux&#xff08;CentOS&#xff09;的“应用商城” —— yum 关于 yum 和软件包Linux 系统&#xff08;CentOS&#xff09;的生态yum 相关操作yum 本地配置yum 安装 lrzsz.x86_64 关于 yum 和软件包 首先 yum 是软件下载安装管理的客户端&#xff0c;类似各种手机里的“应用…

WEB前端10- Fetch API(同步/异步/跨域处理)

Fetch API Fetch API 可以用来获取远程数据&#xff0c;用于在 Web 应用程序中发起和处理 HTTP 请求。它基于 Promise&#xff0c;提供了一种简单而强大的方式来处理网络通信&#xff0c;替代了传统的 XMLHttpRequest。 Promise对象 Promise 对象是 JavaScript 中处理异步操…

阿里云OSS对象存储的项目实战操作

目录 一.什么是阿里云OSS&#xff1f; 二.阿里云OSS的使用&#xff1a; 1.导入依赖到 pom.xml 配置文件&#xff1a; 2.在application.yml配置文件中配置OSS的相关信息&#xff1a; 3.在properties包下创建OSS的配置属性类来封装配置文件的配置项&#xff1a; 4.在utils包…

0723,UDP通信(聪明小辉聪明小辉),HTTP协议

我就是一个爱屋及乌的人&#xff01;&#xff01;&#xff01;&#xff01; #include "network_disk_kai.h" 昨天的epoll&#xff1a; 可恶抄错代码了 epoll_s.csockect return listenfdsetsockoptsockaddr_in bind listenfd & serveraddr…

Ubuntu 中默认的 root 用户密码

场景&#xff1a;想要切换root用户&#xff0c;发现得输入密码&#xff0c;以为是以前设置过然后一直尝试都是错误【认证失败】最后发现根本没设置过root用户&#xff0c;默认会随机生成root用户的密码&#x1f605; Ubuntu 中默认的 root 密码是随机的&#xff0c;即每次开机都…

用51单片机或者stm32能否开发机器人呢?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;能的。但是由于单片机和st…

MATLAB练习题——矩阵(2)

逻辑运算 a [5 0.2 0 -8 -0.7 ]&#xff0c;在进行逻辑运算时&#xff0c;a 相当于什么样的逻辑量。 相当于 a[1 1 0 1 1] 角度运算 在 sin(x)运算中&#xff0c;x 是角度还是弧度&#xff1f; 在 sin(x)运算中&#xff0c;x 是弧度&#xff0c;MATLAB 规定所有…

盘点2024年大家都在使用的AI智能写作工具

在科技发达的现在社会&#xff0c;AI已经悄悄的渗入我们生活的各种角落。不知道你有没有尝试过用ai智能写作来完成一些文章创作呢&#xff1f;这次我介绍几个可以提升效率的ai智能写作工具给你试试吧。 1.笔&#xff5c;灵AI写作 CSDN 传送门&#xff1a;https://ibiling.cn…

090、Python 写Excel文件及一些操作(使用xlwt库)

要写Excel文件&#xff0c;我们需要使用第三方库。 xlwt库是一个常用的写Excel的第三方库&#xff0c;它同时支持.xls和.xlsx。 要使用第三方库&#xff0c;首选需安装&#xff1a; pip install xlwt xlutils安装完成后&#xff0c;我们就可以引入库来进行相关操作了。 使用…

OpenAI发布GPT-4 Mini的深度分析及中国大模型的弯道超车机会

引言 在OpenAI封禁中国IP访问其API后&#xff0c;紧接着推出了GPT-4 Mini&#xff0c;这是一个引发广泛关注和讨论的新举措。此举不仅让人们质疑OpenAI的战略方向&#xff0c;更引发了对中国大模型是否能弯道超车的讨论。本文将详细分析GPT-4 Mini的特点、市场影响及中国大模型…

[rustlings]23_conversions

文章目录 from_into.rsfrom_str.rsas_ref_mut.rstry_from_into.rs from_into.rs // The From trait is used for value-to-value conversions. If From is // implemented, an implementation of Into is automatically provided. // You can read more about it in the docum…

谷粒商城实战笔记-50-51-商品分类的删除

文章目录 一&#xff0c;50-商品服务-API-三级分类-删除-逻辑删除1&#xff0c;逻辑删除的配置1.1 配置全局的逻辑删除规则&#xff08;可省略&#xff09;1.2 配置逻辑删除Bean&#xff08;可省略&#xff09;1.3 Bean相应字段上加上注解TableLogic 2&#xff0c;后台接口开发…