Shader纹理坐标

基础纹理

在计算漫反射时使用纹理中的像素值。

v2f vert(a2v v) {
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);                                
    o.worldNormal = UnityObjectToWorldNormal(v.normal);                                
    o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;                             
    o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;  
    return o;
}
fixed4 frag(v2f i) : SV_Target {
    fixed3 worldNormal = normalize(i.worldNormal);
    fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
    fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;    
    fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));  
    fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
    fixed3 halfDir = normalize(worldLightDir + viewDir);
    fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
    return fixed4(ambient + diffuse + specular, 1.0);
 }                        

普通纹理

凹凸纹理(Bump Mapping)

两种主要的方法:高度纹理、法线纹理

高度纹理

模拟表面位移,得到一个修改后的法线值,存储的是强度值。

法线纹理

 直接存储表面法线。
 法线方向的分量范围:[-1,1],像素的分量范围:[0,1]。所以,要进行映射,通常采用:pixel = (normal+1)/2。

两种空间存储法线

分别是模型空间的法线纹理、切线空间的法线纹理。
两种各有好处,模型空间的法线纹理中不同的法线方向就使用不同的颜色,更符合人类的直观认识,并且很直观、易调整。但是,我们使用切线空间下的法线纹理更多一些,主要因为自由度很高,法线不局限于模型。可进行uv动画,可以重用法线纹理,可压缩等优点。(前两点已经可以让用户坚定的选择切线空间~)

切线空间中计算

首先,在顶点着色器中计算切线空间下的光照和视角方向,所以这里需要知道从模型空间到切线空间的变换矩阵。

v2f vert(a2v v){
    //UNITY提供一个内置宏TANGENT_SPACE_ROTATION(在unity.cginc)中被定义
    //可以帮助我们直接计算得到rotation
    TANGENT_SPACE_ROTATION;
    o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex).xyz);
    o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
    //也可以自己手动计算变换矩阵rotation,和上述实现的功能是一样的
    float3 binormal = cross(normalize(v.normal), normalize(v.tangent.xyz)) * v.tangent.w;
    float3*3 rotation = float3*3(v.tangent.xyz, binormal, v.normal);
}

接着,在片元着色器中采样得到切线空间下的法线方向,再在切线空间下进行关注光照计算。
最后返回即可。

                        v2f vert(a2v v) {
                                v2f o;
                                o.pos = UnityObjectToClipPos(v.vertex);                             
                                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                                o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
                                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
                                fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
                                fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
                                float3x3 worldToTangent = float3x3(worldTangent, worldBinormal, worldNormal);
                                o.lightDir = mul(worldToTangent, WorldSpaceLightDir(v.vertex));
                                o.viewDir = mul(worldToTangent, WorldSpaceViewDir(v.vertex));
                                return o;
                        }
                        
                        fixed4 frag(v2f i) : SV_Target {                                
                                fixed3 tangentLightDir = normalize(i.lightDir);
                                fixed3 tangentViewDir = normalize(i.viewDir);
                                fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw);
                                fixed3 tangentNormal; 
                                tangentNormal = UnpackNormal(packedNormal);
                                tangentNormal.xy *= _BumpScale;
                                tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));                               
                                fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
                                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
                                fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
                                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss);
                                return fixed4(ambient + diffuse + specular, 1.0);
                        }

在这里插入图片描述

世界空间中计算

- 在顶点着色器中,计算从切线空间到世界空间的变换矩阵。
- 在片元着色器中,计算在世界空间下的光照计算。
v2f vert(a2v v) {
                                v2f o;
                                o.pos = UnityObjectToClipPos(v.vertex);
                                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                                o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
                                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
                                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
                                fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
                                fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 
                                o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                                o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                                o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
                                return o;
                        }
                        
                        fixed4 frag(v2f i) : SV_Target {              
                                float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
                                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                                fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
                                bump.xy *= _BumpScale;
                                bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
                                bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));                             
                                fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
                                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));
                                fixed3 halfDir = normalize(lightDir + viewDir);
                                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);              
                                return fixed4(ambient + diffuse + specular, 1.0);
                        }

[图片]

渐变纹理

核心思想是使用渐变纹理控制漫反射光照的结果,可以使用这种方法来完成一些卡通风格的效果。

v2f vert(a2v v) {
                                v2f o;
                                o.pos = UnityObjectToClipPos(v.vertex);
                                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                                o.uv = TRANSFORM_TEX(v.texcoord, _RampTex);
                                return o;
                        }
                        
                        fixed4 frag(v2f i) : SV_Target {
                                fixed3 worldNormal = normalize(i.worldNormal);
                                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                                fixed halfLambert  = 0.5 * dot(worldNormal, worldLightDir) + 0.5;
                                fixed3 diffuseColor = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb * _Color.rgb;
                                fixed3 diffuse = _LightColor0.rgb * diffuseColor;
                                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                                fixed3 halfDir = normalize(worldLightDir + viewDir);
                                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
                                return fixed4(ambient + diffuse + specular, 1.0);
                        }

遮罩纹理

为更加精准的控制模型的各种性质,我们使用遮罩纹理。简而言之即允许我们使用遮罩纹理“保护”某些区域不被修改。
流程:通过采样得到遮罩纹理的像素值,使用其中某些通道的值和某些属性相乘。(当通道值为0时,该区域可以不受这种属性的影响)

v2f vert(a2v v) {
                                v2f o;
                                o.pos = UnityObjectToClipPos(v.vertex);
                                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                                TANGENT_SPACE_ROTATION;
                                o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
                                o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
                                return o;
                        }
                        
                        fixed4 frag(v2f i) : SV_Target {
                                 fixed3 tangentLightDir = normalize(i.lightDir);
                                fixed3 tangentViewDir = normalize(i.viewDir);
                                fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uv));
                                tangentNormal.xy *= _BumpScale;
                                tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
                                fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
                                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
                                 fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
                                 fixed specularMask = tex2D(_SpecularMask, i.uv).r * _SpecularScale;
                                 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss) * specularMask;
                                return fixed4(ambient + diffuse + specular, 1.0);
                        }

[图片]
希望这篇文章对大家有所帮助!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值