7.2.2 法线纹理的使用

7.2.2 法线纹理的使用

Shader "Custom/chap7.2.2/normal map in world space"
{
    Properties
    {
        _MainTex("Main Texture", 2D) = "White" {}
        _BumpMap("normal map", 2D) = "bump" {} // 使用内置的 bump 作为初始值(模型自带的法线纹理)
        _BumpScale("bump scale", Float) = 1.0 // 控制发现纹理的影响程度
        _Color ("Color Tint", Color) = (1.0,1.0,1.0,1.0) 
    }
    SubShader
    {
        pass {
            Tags { "RenderPipeLine"="UniversalRenderPipeline"  "RenderType"="Opaque" "LightMode"="UniversalForward"}

            HLSLPROGRAM
    
            #pragma vertex vert
            #pragma fragment frag
    
            // 使用urp光照文件
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl"

            CBUFFER_START(UnityPerMaterial)
            sampler2D _MainTex;
            sampler2D _BumpMap;

            float4 _MainTex_ST;  // 纹理的 scale 和 transform 属性 xy->scale, zw -> transform
            float4 _BumpMap_ST;
            float4 _Color;
            float _BumpScale;
            CBUFFER_END

            struct a2v { 
                float4 vertex: POSITION; // 必须要定义的
                float3 normal: NORMAL;   // 法线
                float4 uv_MainTex: TEXCOORD0;
                float4 uv_BumpTex: TEXCOORD1;
                float4 tangent: TANGENT; // 切线
            };
    
            struct v2f {
                float4 pos: SV_POSITION; // 必须要定义的
                float2 uv_MainTex:TEXCOORD0;
                float2 uv_BumpTex:TEXCOORD1;
                float4 TW1:TEXCOORD2;
                float4 TW2:TEXCOORD3;
                float4 TW3:TEXCOORD4;
            };
    
            v2f vert(a2v v) {
                v2f o; 
                 // 裁剪坐标
                o.pos = TransformObjectToHClip(v.vertex);
                // 世界坐标下的法线
                float3 worldNormal = TransformObjectToWorldNormal(v.normal); 
                // 世界坐标下的切线
                float3 worldTangent = TransformObjectToWorldDir(v.tangent); 
                // 记住副切线这里要乘以切线的 w 分量, 副切线垂直于法线和切线, 使用叉积可以获取
                float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;  
                 // 由于没有使用高光,这里其实没啥作用,还是带上去
                float3 worldPos = TransformObjectToWorld(v.vertex.xyz);

                o.uv_MainTex = TRANSFORM_TEX(v.uv_MainTex, _MainTex); // 纹理uv
                o.uv_BumpTex = TRANSFORM_TEX(v.uv_MainTex, _BumpMap); // 纹理uv

                // 因此前三列就是就是切线空间到世界空间的转换矩阵, 最后一列代表的是未纹理世界坐标
                o.TW1 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                o.TW2 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                o.TW3 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                return o;
            }
    
            float4 frag(v2f i) : SV_Target {
                // 获取到切线转换到世界坐标的矩阵
                float3x3 TW = float3x3(i.TW1.xyz,i.TW2.xyz,i.TW3.xyz); 
                // 世界坐标
                float3 worldPos = half3(i.TW1.w,i.TW2.w,i.TW3.w); 

                // 对法线纹理进行采样
                float4 normalTex = tex2D(_BumpMap, i.uv_BumpTex);
                // 将法线纹理从 0,1 重新变成 -1,1;
                float3 bump = UnpackNormal(normalTex);
                // 让法线的影响程度受到 _BumpScale大小 的影响
                bump.xy *= _BumpScale;  
                //这个z的计算是因为法线仅存储x和y信息,而z可以由x^2 + y^2 + z^2 = 1反推出来。(法线是单位矢量)
                bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
                 //将切线空间中的法线转换到世界空间中
                bump = mul(TW,bump);

                // 计算纹理颜色
                float3 albedo = tex2D(_MainTex, i.uv_MainTex);
                Light light = GetMainLight();
                // 获取灯光世界方向
                float3 worldLightDir = TransformObjectToWorldDir(light.direction);
                float3 ambient = _GlossyEnvironmentColor.xyz * albedo; // 环境的颜色
                // 漫反射颜色 -> 这里的法线使用切线法线代替原有的法线。
                float3 diffuse = LightingLambert(light.color.rgb, worldLightDir, bump) * albedo; 

                return float4(ambient + diffuse, 1.0);
            }
    
            ENDHLSL
        }
    }
}


  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值