Unity——基于ShaderLab实现光照系统 (2)

_MainTexture_ST 控制贴图的缩放和偏移(Scale,Translate);

v2f vert(a2v v){ //uv传递给片元着色器,可以使用宏命令TRANSFORM_TEX o.uv = v.texcoord.xy * _MainTexture_ST.xy + _MainTexture_ST.zw; //o.uv = TRANSFORM_TEX(v.texcoord,_Maintexture); } fixed4 farg(v2f v) :SV_Target{ //纹理取样,表面颜色-纹素 fixed3 albedo = tex2D(_MainTexture, v.uv).rgb * _Color.rgb; //环境光*表面颜色 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz *albedo; fixed halfLambert = dot(worldNormal, worldLight) * 0.5 + 0.5; //漫反射*表面颜色 fixed3 diffuse = _LightColor0.rgb * albedo.rgb * halfLambert; } 2.法线纹理

法线计算两种方式:

将光线和观察向量变换到切线空间计算;

将切线空间下法线变换到世界空间计算;

切线空间计算由于矩阵变换在顶点着色器,计算少效率高;

由于认知,或者有其他需求我们也会在世界空间计算法线;

- 法线纹理切线空间计算 v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv.xy = v.texcoord.xy * _MainTexture_ST.xy + _MainTexture_ST.zw; //o.uv = TRANSFORM_TEX(v.texcoord,_Maintexture); o.uv.zw = TRANSFORM_TEX(v.texcoord,_BumpMap); //宏定义,求世界空间——切线空间变换矩阵rotation TANGENT_SPACE_ROTATION; o.lightDir = mul(rotation,ObjSpaceLightDir(v.vertex)).xyz; o.viewDir = mul(rotation,ObjSpaceViewDir(v.vertex)).xyz; return o; } fixed4 frag(v2f v) :SV_Target{ //切线空间-光线方向 fixed3 tangentLightDir = normalize(v.lightDir); //切线空间-观察方向 fixed3 tangentViewDir = normalize(v.viewDir); //法线贴图格式为NormalMap,使用UnpackNormal解压,取样得到切线空间下法线 fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap,v.uv.zw)); //法线缩放 tangentNormal.xy *= _BumpScale; //法线贴图压缩方法,z值可以计算得出,勾股定理,以下是简化后公式 tangentNormal.z = sqrt(1.0-saturate(dot(tangentNormal.xy,tangentNormal.xy))); ...//漫反射高光计算都使用tangentNormal } - 法线纹理世界空间计算 v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); //减少寄存器使用,xy记录主纹理uv,zw记录法线uv o.uv.xy = v.texcoord.xy * _MainTexture_ST.xy + _MainTexture_ST.zw; o.uv.zw = TRANSFORM_TEX(v.texcoord,_BumpMap); //求世界空间下法线、切线、副切线 float3 worldPos = mul(unity_ObjectToWorld,v.vertex).xyz; fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); fixed3 worldBinnormal = cross(worldNormal,worldTangent)*v.tangent.w; //法线、切线、副切线构成切线空间变换矩阵,w值trick利用存储世界坐标系顶点坐标 o.Ttow0 = float4(worldTangent.x,worldBinnormal.x,worldNormal.x,worldPos.x); o.Ttow1 = float4(worldTangent.y,worldBinnormal.y,worldNormal.y,worldPos.y); o.Ttow2 = float4(worldTangent.z,worldBinnormal.z,worldNormal.z,worldPos.z); return o; } fixed4 frag(v2f v) :SV_Target{ ... //法线贴图格式为NormalMap,使用UnpackNormal解压,取样得到切线空间法线 fixed3 tangentNormal = UnpackNormal( tex2D(_BumpMap,v.uv.zw)); //法线缩放 tangentNormal.xy *= _BumpScale; //法线贴图压缩方法,z值可以计算得出,勾股定理,以下是简化后公式 tangentNormal.z = sqrt(1.0-saturate(dot(tangentNormal.xy,tangentNormal.xy))); //矩阵变换求出世界空间法线 tangentNormal = normalize(half3(dot(v.Ttow0.xyz,tangentNormal),dot(v.Ttow1.xyz,tangentNormal),dot(v.Ttow2.xyz,tangentNormal))); ...//漫反射高光计算都使用tangentNormal }

3.渐变纹理

以上漫反射颜色都是光线颜色,或者光线颜色混合表面纹素颜色;

有时候漫反射的颜色要根据反射角大小有不同的变化,比如卡通渲染;

这就需要使用渐变纹理RampTexture;

//顶点着色器转化RampTex的uv fixed4 frag (v2f i) : SV_Target{ fixed halfLambert = 0.5 * dot(worldNormal,worldLightDir)+0.5; //根据halfLambert反射方向取样RampTex纹素 fixed3 diffuseColor = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb*_Color.rgb; fixed3 diffuse = _LightColor0.rgb * diffuseColor; }

三种不同的Ramp纹理:

4.遮罩纹理

有些部位高光效果太强,人为的希望有些部位暗一些等,可以用到遮罩纹理Mask;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgxzfy.html