Unity中URP下额外灯角度衰减
文章目录
- 前言
- 一、额外灯中聚光灯的角度衰减
- 二、AngleAttenuation函数的传入参数
-
- 1、参数:spotDirection.xyz
- 2、_AdditionalLightsSpotDir
- 3、参数:lightDirection
- 4、参数:distanceAndSpotAttenuation.zw
- 5、_AdditionalLightsAttenuation
- 三、AngleAttenuation函数的程序体
-
- 1、我们先来看一下SdotL的结果
- 2、cosOuterAngle:聚光灯外圈与聚光灯夹角的余弦值
- 3、cosInnerAngle:聚光灯内圈与聚光灯夹角角的余弦值
- 4、最后,就可以使用公式来计算了
- 5、但是,我们在程序体中,看见的却是这样一句话
- 6、最终、Unity还对其做了平方处理,目的是加强角度衰减效果
前言
在上一篇文章中,我们推导了URP下额外灯的距离衰减。
- Unity中URP下额外灯的距离衰减
在这篇文章中,我们推导一下URP下额外灯的角度衰减。角度衰减只有在聚光灯中才有用。
一、额外灯中聚光灯的角度衰减
- 衰减包括:距离衰减 和 角度衰减
- 我们这篇文章主要分析 角度衰减,角度衰减是聚光灯独有的。
AngleAttenuation1(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw);

二、AngleAttenuation函数的传入参数
- 调用
AngleAttenuation1(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw);
1、参数:spotDirection.xyz
-
该参数是通过内置变量获取的

-
该内置变量是C#提前计算好的

2、_AdditionalLightsSpotDir
- 我们来看一下C#中怎么计算得出该参数


- 一开始会赋值一个聚光灯方向默认值

- k_DefaultLightSpotDirection,默认值为(0,0,1,0)

- 非平行灯下,在对距离衰减修改后,还会判断是否是聚光灯
- 是聚光灯,则会修改聚光灯方向的默认值

- 修改时,会获取聚光灯方向,并对其取反

3、参数:lightDirection
- 之前计算出的,额外光方向的单位向量

4、参数:distanceAndSpotAttenuation.zw
- 该参数是读取的内置参数

- 该内置变量是C#提前计算好的

5、_AdditionalLightsAttenuation
- 我们来看一下C#中,怎么计算该参数



三、AngleAttenuation函数的程序体

-
角度衰减公式:
a
n
g
l
e
A
t
t
e
n
u
a
t
i
o
n
=
S
d
o
t
L
−
c
o
s
O
u
t
e
r
A
n
g
l
e
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
angleAttenuation=\frac{SdotL – cosOuterAngle} {cosInnerAngle – cosOuterAngle}
angleAttenuation=cosInnerAngle−cosOuterAngleSdotL−cosOuterAngle
-
我们先看一下这些参数分别代表什么
-
SdotL:S(聚光灯方向的相反方向)点积 L(指向聚光灯方向单位向量)
-
cosOuterAngle:聚光灯外圈与聚光灯夹角的余弦值
-
cosInnerAngle :聚光灯内圈与聚光灯夹角角的余弦值
1、我们先来看一下SdotL的结果
- 我们可以看出目标点越靠近聚光灯中心,我们的结果越趋向 1,则越亮

2、cosOuterAngle:聚光灯外圈与聚光灯夹角的余弦值
- C#中提前把角度取Unity传入的一半,然后转弧度,再计算余弦值
- 取一半的原因是,我们传入的值是需要的角的两倍



3、cosInnerAngle:聚光灯内圈与聚光灯夹角角的余弦值
- C#中提前把角度取Unity传入的一半,然后转弧度,再计算余弦值
- 取一半的原因是,我们传入的值是需要的角的两倍

- 我们主要看非特效情况下


4、最后,就可以使用公式来计算了
角度衰减公式:
a
n
g
l
e
A
t
t
e
n
u
a
t
i
o
n
=
S
d
o
t
L
−
c
o
s
O
u
t
e
r
A
n
g
l
e
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
angleAttenuation=\frac{SdotL – cosOuterAngle} {cosInnerAngle – cosOuterAngle}
angleAttenuation=cosInnerAngle−cosOuterAngleSdotL−cosOuterAngle
-
该公式其实只是起到了 平滑曲线过渡的作用

-
该公式的作用:限制最后余弦值的结果,还达到了平滑过渡的效果
-
当 targetPos 夹角大于 outerDir 的夹角时,余弦值反而小了,则取outerDir夹角余弦值来替代

-
当 targetPos 夹角小于 innerDir 的夹角时,余弦值反而大了,则取innerDir夹角余弦值来替代

5、但是,我们在程序体中,看见的却是这样一句话

- 原因在于,这是Unity为了节省性能,对该公式进行了化简
a
n
g
l
e
A
t
t
e
n
u
a
t
i
o
n
=
S
d
o
t
L
−
c
o
s
O
u
t
e
r
A
n
g
l
e
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
angleAttenuation=\frac{SdotL – cosOuterAngle} {cosInnerAngle – cosOuterAngle}
angleAttenuation=cosInnerAngle−cosOuterAngleSdotL−cosOuterAngle
=
S
d
o
t
L
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
=\frac{SdotL } {cosInnerAngle – cosOuterAngle}-\frac{cosOuterAngle} {cosInnerAngle – cosOuterAngle}
=cosInnerAngle−cosOuterAngleSdotL−cosInnerAngle−cosOuterAnglecosOuterAngle
=
S
d
o
t
L
∗
1
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
+
−
c
o
s
O
u
t
e
r
A
n
g
l
e
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
=SdotL*\frac{1} {cosInnerAngle – cosOuterAngle}+\frac{-cosOuterAngle} {cosInnerAngle – cosOuterAngle}
=SdotL∗cosInnerAngle−cosOuterAngle1+cosInnerAngle−cosOuterAngle−cosOuterAngle
- Unity在C#中,对其提前进行了计算
- 使
d
i
s
t
a
n
c
e
A
n
d
S
p
o
t
A
t
t
e
n
u
a
t
i
o
n
.
z
=
1
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
distanceAndSpotAttenuation.z=\frac{1} {cosInnerAngle – cosOuterAngle}
distanceAndSpotAttenuation.z=cosInnerAngle−cosOuterAngle1
- 使
d
i
s
t
a
n
c
e
A
n
d
S
p
o
t
A
t
t
e
n
u
a
t
i
o
n
.
w
=
−
c
o
s
O
u
t
e
r
A
n
g
l
e
c
o
s
I
n
n
e
r
A
n
g
l
e
−
c
o
s
O
u
t
e
r
A
n
g
l
e
distanceAndSpotAttenuation.w =\frac{-cosOuterAngle} {cosInnerAngle – cosOuterAngle}
distanceAndSpotAttenuation.w=cosInnerAngle−cosOuterAngle−cosOuterAngle


6、最终、Unity还对其做了平方处理,目的是加强角度衰减效果
return atten * atten;
-
平方前

-
平方后

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/5b8b7e064f.html
