Unity3D ShaderLab压缩混合纹理贴图
纹理可以用于存储大量的数据,我们可以把多个图像打包存储在单一的RGBA纹理上,然后通过着色器代码提取这些元素,
我们就可以使用每个图片的RGBA通道的讯息作为一个独立的纹理。
这种使用场景特别是在地面的混合着色上有着很明显的优势,下面我们就来说说 怎么构建一个常用的四纹理混合着色器。
那么请县创建一个shader和材质球吧。下面我们直接开始:
1,修改Properties
{ //设置GUI; _MainTint("Diffuse Tint",Color)=(1,1,1,1) _ColorA("Terrain Color A",Color)=(1,1,1,1) _ColorB("Terrain Color B",Color)=(1,1,1,1) _RTexture("Red Channel Texture",2D)="" _GTexture("Green Channel Texture",2D)="" _BTexture("Blue Channel Texture",2D)="" _ATexture("Alpha Channel Texture",2D)="" _BlendTexture("Blend Texture",2D)="" }
2,SubShader申明变量
#pragma surface surf Lambert //变量; float4 _MainTint; float4 _ColorA; float4 _ColorB; sampler2D _RTexture; sampler2D _GTexture; sampler2D _BTexture; sampler2D _ATexture; sampler2D _BlendTexture;
3,修改Input结构
struct Input { float2 uv_RTexture; float2 uv_GTexture; float2 uv_BTexture; float2 uv_ATexture; float2 uv_BlendTexture; };
4,修改无敌的surf函数
void surf (Input IN, inout SurfaceOutput o) { //得到纹理讯息; float4 blendData = tex2D(_BlendTexture,IN.uv_BlendTexture); float4 rTexData = tex2D(_RTexture,IN.uv_RTexture); float4 gTexData = tex2D(_GTexture,IN.uv_GTexture); float4 bTexData = tex2D(_BTexture,IN.uv_BTexture); float4 aTexData = tex2D(_ATexture,IN.uv_ATexture); //进行纹理混合; float4 finalColor; finalColor = lerp(rTexData,gTexData,blendData.g); finalColor = lerp(finalColor,bTexData,blendData.b); finalColor = lerp(finalColor,aTexData,blendData.a); finalColor.a=1; //计算色调; float4 terrainLayers = lerp(_ColorA,_ColorB,blendData.r)*2; finalColor *= terrainLayers; finalColor = saturate(finalColor); //half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = finalColor.rgb*_MainTint.rgb; o.Alpha = finalColor.a; }
////////////////////////////////////////////////////
以上就是我们的混合纹理Shader全部步骤。
我们在unity中直接看看效果吧。
上面用到了lerp(a,b,f)。如果我们想得到1和2之间的中间值,我们可以将lerp函数的第三个函数赋值为0.5,他将会返回1.5,
这个函数很适合混合纹理,因为在一个RGBA纹理中单个通道的值就是单精度浮点值,通常值范围是0~1之间。
我们将提供的草地纹理 泥土纹理以及混合纹理的红色通道3个值作为lerp函数参数,这样我们得到物体表面每个像素值均为正确的混合颜色。
code start-------------------------------------------------------------------------------
Shader "91YGame/TextureBlend" { Properties { //设置GUI; _MainTint("Diffuse Tint",Color)=(1,1,1,1) _ColorA("Terrain Color A",Color)=(1,1,1,1) _ColorB("Terrain Color B",Color)=(1,1,1,1) _RTexture("Red Channel Texture",2D)="" _GTexture("Green Channel Texture",2D)="" _BTexture("Blue Channel Texture",2D)="" _ATexture("Alpha Channel Texture",2D)="" _BlendTexture("Blend Texture",2D)="" } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert //变量; float4 _MainTint; float4 _ColorA; float4 _ColorB; sampler2D _RTexture; sampler2D _GTexture; sampler2D _BTexture; sampler2D _ATexture; sampler2D _BlendTexture; struct Input { float2 uv_RTexture; float2 uv_GTexture; float2 uv_BTexture; float2 uv_ATexture; float2 uv_BlendTexture; }; void surf (Input IN, inout SurfaceOutput o) { //得到纹理讯息; float4 blendData = tex2D(_BlendTexture,IN.uv_BlendTexture); float4 rTexData = tex2D(_RTexture,IN.uv_RTexture); float4 gTexData = tex2D(_GTexture,IN.uv_GTexture); float4 bTexData = tex2D(_BTexture,IN.uv_BTexture); float4 aTexData = tex2D(_ATexture,IN.uv_ATexture); //进行纹理混合; float4 finalColor; finalColor = lerp(rTexData,gTexData,blendData.g); finalColor = lerp(finalColor,bTexData,blendData.b); finalColor = lerp(finalColor,aTexData,blendData.a); finalColor.a=1.0; //计算色调; float4 terrainLayers = lerp(_ColorA,_ColorB,blendData.r)*2; finalColor *= terrainLayers; finalColor = saturate(finalColor); //half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = finalColor.rgb*_MainTint.rgb; o.Alpha = finalColor.a; } ENDCG } FallBack "Diffuse" }
code end--------------------------------------------------------------------------------