UnityShader凹凸感

1、_TexelSize:纹理以这个为后缀, 后2个则是像素的数量如256x128。那么后2个就是256和128。而前两个值为x = 1/256, y = 1 / 128

2、有限差分近似

image.png


根据这个图来理解编写,利用两点之间切线表示其深度

void InitializeFragmentNormal(inout Interpolator i){
    float2 delta = float2(_HeightMap_TexelSize.x, 0); //如何贴图为256x128的 那么delta = 1 / 256
    float h1 = tex2D(_HeightMap, i.uv); //普通采样
    float h2 = tex2D(_HeightMap, i.uv + delta); //向后挪一个像素采样
    // y结合上图, 会发现是斜率
    //i.normal = float3(1, (h2-h1)/delta.x, 0); 
    或者 i.normal = float3(delta.x, h2-h1, 0);
    i.normal = normalize(i.normal);
}

注意此时得到是切线, 并不是真正的法线, 而是切线,也就是图中红色的部分
真正的法线绕旋z轴90度i.normal = float3(h1-h2, 1, 0);
这个旋转怎么理解?
得到的这个切线由于delta很小可以理解为(0, h2-h1, 0),然后右乘z轴旋转的旋转矩阵,其中旋转角度为90度。最终得到(h1-h2, 0, 0),而y轴变成了1,是为了让没有那么明显的差异感,进行了缩放。

3、中心差法:教程中提到了中心差法:
其实就是不在原来的顶点处直接取值为h1,而是向后偏移原来的一般。但是x的总距离是没有变化的

//中心差法
    float2 delta = float2(_HeightMap_TexelSize.x * 0.5, 0);
    float h1 = tex2D(_HeightMap, i.uv - delta);
    float h2 = tex2D(_HeightMap, i.uv + delta);
    i.normal = float3(h1 - h2, 1, 0);

效果是更好与高度场对齐, 并不会改变形状注意:此时是x轴向维度的, 并没有y轴维度的

4、添加uv中的v的维度,此时平面时yz面

//另一个维度
    float2 deltaV = float2(0, _HeightMap_TexelSize.y * 0.5);
    float v1 = tex2D(_HeightMap, i.uv - deltaV);
    float v2 = tex2D(_HeightMap, i.uv + deltaV);
    //切线为 float3(0, v2-v1, deltaV) =>(缩放) float3(0, v2-v1, 1)
    //绕x轴转-90度, 这里右乘的是x轴旋转矩阵
    float3(0, 1, v1-v2)
    i.normal = float3(0, 1, v1-v2);

5、通过UV2个维度的切线构造生产法向量

float3 tu = float3(1, h2-h1, 0); //u切线
    float3 tv = float3(0, v2-v1, 1); //v 方向的切线
    //通过叉乘 可以确定垂直于这2条切线的向量 从而成为法向量
    i.normal = cross(tv, tu);

注意:tv和tu两个不能互换, 因为叉乘有2个方向

6、法线贴图
假如有多个纹理图,我们需要进行差分近似采样就需要进行多次,这样很浪费。所以我们将纹理图设置为Normal Map,并勾选Create From Grayscale应用。将得到法线贴图(法线贴图为什么是便蓝色的?因为其将向上的向量存储在z变量,对应RGB中的Blue颜色)

7、使用法线贴图

//非DXT5 移动端
    i.normal = tex2D(_NormalMap, i.uv).xyz * 2 - 1;  //将其归一至 -1 ~ 1
    i.normal = i.normal.xzy; //zy交换
//支持DXT5
    i.normal.xy = tex2D(_NormalMap, i.uv).wy * 2 - 1;  //DXT5只用2个通道存储,x存储在a通道, y存储在y
    //根据上图,法线是单位向量,所有距离是1,可以通过xy计算出z
    i.normal.z = sqrt(1 - saturate(dot(i.normal.xy, i.normal.xy)));
    i.normal = i.normal.xzy;

8、缩放凹凸 向上的向量存储在z方向向量中,所以我们可以缩放xy从而达到缩放z的效果

// _BumpScale = 0时平面将会变得平坦, 越大将会越凹凸
    i.normal.xy = tex2D(_NormalMap, i.uv).wy * 2 - 1;  //将其归一至 -1 ~ 1
    i.normal.xy = _BumpScale * i.normal.xy;

其中Unity自带函数

//使用unity自带的函数 进行法线纹理的解码和缩放
    i.normal = UnpackScaleNormal(tex2D(_NormalMap, i.uv), _BumpScale);
    i.normal = i.normal.xzy;

9、细节法线

同样细节法线和普通法线纹理差不多,只是利用细节uv进行采样而已
    //细节法线贴图
    i.normal = UnpackScaleNormal(tex2D(_DetailNormalMap, i.uv.zw), _DetailBumpScale);

10、融合法线:BlendNormals可以将2个法线混合,并且使用的是泛白混合(原理用得到了再看原理)

//细节法线贴图
    float3 detailNormal = UnpackScaleNormal(tex2D(_DetailNormalMap, i.uv.zw), _DetailBumpScale);
    i.normal = BlendNormals(mainNormal, detailNormal);
    i.normal = i.normal.xzy;
    
    // i.normal = normalize(i.normal);

此处连接切线空间文章

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Shader中的水转折效果是一种用于模拟水面倒影的视觉效果。在实现水转折效果的过程中,我们需要使用顶点和片元着色器来修改渲染管线的行为。 首先,我们需要通过顶点着色器将水面的顶点位置传递给片元着色器。在片元着色器中,我们可以根据顶点位置计算出水面对光线的折射向量。这个向量是一个颜色值,代表了水面在该点上的倒影颜色。 接下来,为了实现水的水波效果,我们可以使用一些数学函数来对水面进行扰动。这可以通过使用时间函数、噪声函数或其他算法来实现。这些扰动可以在水面上产生波纹效果,增加水的真实感。 另外,我们还可以使用法线贴图来模拟水面的细节。法线贴图包含了每个像素点的法线向量信息,可以模拟出水面的凹凸不平的部分。将法线贴图与倒影颜色相结合,可以更加真实地渲染出水面的效果。 最后,为了增加水面的光泽感,我们可以使用反射效果。通过使用 Unity 的反射函数,我们可以将水面反射周围环境的颜色和物体。这样,水面就可以在特定角度下反射出周围环境的场景,增加水的真实感和光泽感。 综上所述,Unity Shader中的水转折效果是通过修改渲染管线的方式来实现的。通过计算顶点位置、使用数学函数产生水波效果、使用法线贴图模拟水面细节,以及使用反射函数增加光泽感,可以让水看起来更加真实和绚丽。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值