Unity 渲染教程(06):凹凸度(2)

2025-04-30

1 n ormal = float3(1, h

2 - h1, 0);

缩放后的高度。

这开始看起来不错,但光照是错误的。太黑了。这是因为我们直接使用切线向量作为法线向量。要将切线向量转为向上的法线向量,我们必须围绕Z轴旋转切线向量90°。

1 n ormal = float3(h1 - h2, 1, 0);

使用实际的法线向量。

这个向量旋转是如何工作的?

你可以通过交换向量的X和Y分量,并翻转新的X分量的符号,来对一个二维向量做一个逆时针90°的旋转。这样我们就得到了。

对一个二维向量做一个逆时针90°的旋转。

1.5中心差分 我们使用有限差分近似法来创建法向量。具体地做法是,通过使用正向差分法。我们选取一点,然后沿着一个方向来确定斜率。我们得到的结果就是法线在该方向上的偏移。为了获得更好的法线近似,我们可以在两个方向上偏移采样点。这将线性近似集中在当前点上,并且被称为中心差分法。 这将导数函数更改为 。

1 2 3 4 5 6 7 float2 delta = float2(_HeightMap_TexelSize.x * 0.5, 0);

float h1 = tex2D(_HeightMap, i.uv - delta);

float h2 = tex2D(_HeightMap, i.uv + delta);

normal = float3(h1 - h2, 1, 0);

这会轻微地移动凹凸度贴图,因此它们可以更好地与高度字段对准。除此之外,它们的形状没有发生改变。

1.6同时使用两个维度

我们创建的法线只考虑了沿U 方向的变化。我们一直使用函数f

(u ,v )相对于u 轴的偏导数。这就是f'u (u ,v ),或简称f'u 。我们还可以通过使用f'v 沿着V 方向创建法线。 在这种情况下,切向量为而法线向量是。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 float2 du = float2(_HeightMap_TexelSize.x * 0.5, 0);

float u1 = tex2D(_HeightMap, i.uv - du);

float u2 = tex2D(_HeightMap, i.uv + du);

i.normal = float3(u1 - u2, 1, 0);

float2 dv = float2(0, _HeightMap_TexelSize.y * 0.5);

float v1 = tex2D(_HeightMap, i.uv - dv);

float v2 = tex2D(_HeightMap, i.uv + dv);

i.normal = float3(0, 1, v1 - v2);

normal = normalize(i.normal);

沿着V 方向的法线。

我们现在可以访问沿着U 方向和V 方向的切线。总之,这些向量描述了在我们的片段所在处的高度场的表面。通过计算它们的叉积,我们找到二维高度场的法向量。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 float2 du = float2(_HeightMap_TexelSize.x * 0.5, 0);

float u1 = tex2D(_HeightMap, i.uv - du);

float u2 = tex2D(_HeightMap, i.uv + du);

float3 tu = float3(1, u2 - u1, 0);

float2 dv = float2(0, _HeightMap_TexelSize.y * 0.5);

float v1 = tex2D(_HeightMap, i.uv - dv);

float v2 = tex2D(_HeightMap, i.uv + dv);

float3 tv = float3(0, v2 - v1, 1);

i.normal = cross(tv, tu);

i.normal = normalize(i.normal);

完整的法线的效果。

什么是叉积?

两个向量之间的叉积在几何上定义为A×B = || A || || B || sin(θ)N。这里N 是垂直于包含A向量和B向量的平面的单位矢量。所以N是我们想要的法线向量。

||A || || B || sinθ这个部分缩放这个向量。它就像点积,除了它包含矢量之间的角度的正弦,而不是余弦之外。如果两个向量都是单位长度,并且它们之间的角度是90°,则结果是1。由于很可能不是这种情况,因此我们必须对叉积运算的结

果进行归一化。只要矢量之间的角度不是0°和180°,这个方法就有效,因为如果矢量之间的角度是0°和180°的话,正弦为零。

在代数上,对于三维向量,叉积被定义为。

1 f loat crossProduct = v1.yzx * v2.zxy - v1.zxy * v2.yzx;

在视觉上,产生的矢量的绝对量值对应于可以用两个矢量形成的平行四边形的表面积。

叉积。

需要注意的是,A×B = -B×A。这意味着结果的方向取决于向量的顺序。因为我们想要我们的向量指向上,我们必须使用cross(ty,tx),而不是cross(tx,ty)。

当你用切线向量计算叉积的时候,你会看到

。因此,我们可以直接构造向量,而不必依赖于叉积函数。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 void InitializeFragmentNormal(inout Interpolators i) {

float2 du = float2(_HeightMap_TexelSize.x * 0.5, 0);

float u1 = tex2D(_HeightMap, i.uv - du);

float u2 = tex2D(_HeightMap, i.uv + du);

// float3 tu = float3(1, u2 - u1, 0);

float2 dv = float2(0, _HeightMap_TexelSize.y * 0.5);

float v1 = tex2D(_HeightMap, i.uv - dv);

float v2 = tex2D(_HeightMap, i.uv + dv);

// float3 tv = float3(0, v2 - v1, 1);

// i.normal = cross(tv, tu);

i.normal = float3(u1 - u2, 1, v1 - v2);

i.normal = normalize(i.normal);

}

2 法线贴图

当凹凸贴图起作用的时候,我们必须执行多个纹理采样和有限差分计算。这似乎是一种浪费,因为最终的法线向量应该总是相同的。为什么所有这些工作每帧都要做一次?我们可以只做一次,并将得到的法线向量存储在纹理上。 这是否与纹理过滤相冲突?

双线性滤波和三线性滤波将在法线向量之间进行混合,就像法线在三角形内部进行内插值一样。因此,我们必须对采样的法线进行归一化。

你还必须确保每个mipmap包含有效的法线。你不能简单地对纹理进行缩样,就好像它包含颜色数据一样。矢量也必须被归一化。Unity会负责这个事情。这意味着我们需要一个法线贴图。我可以提供一个,但我们可以让Unity为我们做这个工作。将高度贴图的纹理类型更改为法线贴图。Unity自动切换纹理以使用三线性滤波,并假设我们想使用灰度图像数据来生成法线贴图。这正是我们想要的,但我们要将凹凸度更改为更低的值,如0.05。

从高度数据生成法线向量。

应用导入设置以后,Unity 将计算法线贴图。原始高度图仍然存在,但Unity 内部使用的是生成的贴图。

像我们在将法线可视化为颜色时所做的那样,它们必须进行调整以适应0-1范围内。 因此它们被存储为N + 12。 这表明平坦区域将呈现浅绿色。然而,它们看起来是浅蓝色的。这是因为法线贴图最常见的约定是将向上方向存储在Z 分量中。所以从Unity 的角度来看,Y 坐标和Z 坐标是交换的。

对法线贴图进行采样

因为法线贴图与高度图完全不同,请相应地重命名着色器属性。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Properties {

_Tint ("Tint", Color) = (1, 1, 1, 1)

_MainTex ("Albedo", 2D) = "white" {}

[NoScaleOffset] _NormalMap ("Normals", 2D) = "bump" {}

// [NoScaleOffset] _HeightMap ("Heights", 2D) = "gray" {}

[Gamma] _Metallic ("Metallic", Range(0, 1)) = 0

_Smoothness ("Smoothness", Range(0, 1)) = 0.1

}


Unity 渲染教程(06):凹凸度(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:[标准楷体]汉字偏旁部首表田字格练习字帖82718

相关阅读
本类排行
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 7

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xuecool-com QQ:370150219