Search Unity

World Space Three texture blend

Discussion in 'Shaders' started by mattimus, Feb 13, 2013.

  1. mattimus

    mattimus

    Joined:
    Mar 8, 2008
    Posts:
    576
    I'm trying to make a 3 texture blend that tiles in world space. I've got a surface shader that tiles in world space, and I found a 3 texture blend fragment shader, but I don't know enough about cg shaders to combine them.

    Code (csharp):
    1.     Shader "WorldSpace" {
    2.     Properties {
    3.       _MainTex ("Texture", 2D) = "white" {}
    4.       _ScaleX ("Scale X", float) = 1.0
    5.       _ScaleY ("Scale Y", float) = 1.0
    6.     }
    7. SubShader {
    8.       Tags { "RenderType" = "Opaque" }
    9.       CGPROGRAM
    10.       #pragma surface surf Lambert
    11.       struct Input {
    12.           float2 uv_MainTex;
    13.           float3 worldPos;
    14.           float3 worldNormal; INTERNAL_DATA
    15.       };
    16.       sampler2D _MainTex;
    17.      
    18.       half _ScaleX;
    19.       half _ScaleY;
    20.      
    21.       void surf (Input IN, inout SurfaceOutput o) {
    22.         float3 correctWorldNormal = WorldNormalVector(IN, float3( 0, 0, 1 ) );
    23.         float2 uv = IN.worldPos.xz;
    24.                            
    25.         if( abs( correctWorldNormal.x ) > 0.5 ) uv = IN.worldPos.yz;
    26.         if( abs( correctWorldNormal.z ) > 0.5 ) uv = IN.worldPos.xz;
    27.      
    28.         uv.x *= _ScaleX;
    29.         uv.y *= _ScaleY;
    30.         o.Albedo = tex2D (_MainTex, uv).rgb;
    31.       }
    32.       ENDCG
    33.     }
    34.     Fallback "Diffuse"
    35.   }
    Code (csharp):
    1.     Shader "TriBlend" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (1,1,1,1)
    4.         _MainTex ("Mixing Mask (RGBA)", 2D) = "white" {}
    5.         _Tex1 ("Color 1 (RGB)", 2D) = "grey" {}
    6.         _Tex2 ("Color 2 (RGB)", 2D) = "grey" {}
    7.         _Tex3 ("Color 3 (RGB)", 2D) = "grey" {}
    8.        
    9.     }
    10.     SubShader {
    11.         Pass {
    12.             Blend SrcAlpha OneMinusSrcAlpha
    13.             Lighting On
    14.            
    15.             Material {
    16.                 Diffuse [_Color]
    17.                 Ambient [_Color]
    18.             }
    19.        
    20.     CGPROGRAM
    21. // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
    22. #pragma exclude_renderers gles
    23.     // profiles arbfp1
    24.     #pragma fragment frag
    25.      
    26.     // fragmentoption ARB_fog_exp2
    27.      
    28.     sampler2D _Tex1 : register(s0);
    29.     sampler2D _Tex2 : register(s1);
    30.     sampler2D _Tex3 : register(s2);
    31.     sampler2D _MainTex : register(s3);
    32.      
    33.     struct v2f {
    34.         float4 uv[5] : TEXCOORD0;
    35.         float4 diffuse : COLOR;
    36.     };
    37.      
    38.     half4 frag( v2f i ) : COLOR
    39.     {
    40.         // get the four layer colors
    41.         half4 color1 = tex2D( _Tex1, i.uv[0].xy );
    42.         half4 color2 = tex2D( _Tex2, i.uv[1].xy );
    43.         half4 color3 = tex2D( _Tex3, i.uv[2].xy );
    44.         // get the mixing mask texture
    45.         half4 mask = tex2D( _MainTex, i.uv[3].xy );
    46.         // mix the four layers
    47.         half4 color = color1 * mask.r + color2 * mask.g + color3 * mask.b;
    48.         //multiply and double by the lighting
    49.         return color * i.diffuse * 2.0;
    50.     }
    51.     ENDCG
    52.             SetTexture[_MainTex] {}
    53.             SetTexture[_MainTex2] {}
    54.             SetTexture[_MainTex3] {}
    55.             SetTexture[_Mask] {}
    56.         }
    57.     }
    58.     FallBack " VertexLit", 1
    59.     }
     
  2. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
  3. mattimus

    mattimus

    Joined:
    Mar 8, 2008
    Posts:
    576
    Not quite what I'm looking for. The shader you linked blends textures based on their surface normal. I'm looking to blend based on an RGB mask.
     
  4. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    You give the answer yourself, make a mask texture with red green and blue parts with uv stretching to the edges then use this
    half4 color = color1 * mask.r + color2 * mask.g + color3 * mask.b;
    to add each colors on your second uv set which is based on world position.
     
  5. mattimus

    mattimus

    Joined:
    Mar 8, 2008
    Posts:
    576
    Ok, let's try this again. In my original post, there are two shaders.

    Shader #1 tiles a single texture in world space.


    Shader #2 is a typical 3 texture blend with an RGB mask that tiles in UV space.




    What I am trying to figure out is how to combine the two in order to make a three texture blend that tiles in world space.
     
  6. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    as i explained, you do everything in your first shader except that you save the o.Albedo part into 3 different texture fetches using the world uv.
    Then you use the logic of this line of code found in your second shader:
    half4 color = color1 * mask.r + color2 * mask.g + color3 * mask.b;

    and mix 3 different textures with the mask textures rgb channels (o.Albedo = my new mixed color) and there you have what you require.
     
  7. mattimus

    mattimus

    Joined:
    Mar 8, 2008
    Posts:
    576
    The good news is that I managed to get it working. Thanks aubergine.

    The bad news is that objects with this shader are rendering with two draw calls per object and are not being batched. My scene's draw call count has exploded to a degree that is about 20x too high for mobile platforms.

    Code (csharp):
    1.     Shader "Custom/WorldTriMasked" {
    2.     Properties {
    3.       _MainTex ("Texture", 2D) = "white" {}
    4.       _ScaleX ("Scale X", float) = 1.0
    5.       _ScaleY ("Scale Y", float) = 1.0
    6.       _Tex1 ("Color 1 (RGB)", 2D) = "grey" {}
    7.       _Tex2 ("Color 2 (RGB)", 2D) = "grey" {}
    8.       _Tex3 ("Color 3 (RGB)", 2D) = "grey" {}
    9.     }
    10. SubShader {
    11.       Tags { "RenderType" = "Opaque" }
    12.       CGPROGRAM
    13.       #pragma surface surf Lambert
    14.      
    15.       struct Input {
    16.           float2 uv_MainTex;
    17.           float3 worldPos;
    18.           float3 worldNormal; INTERNAL_DATA
    19.       };
    20.      
    21.       sampler2D _MainTex;
    22.       sampler2D _Tex1;
    23.       sampler2D _Tex2;
    24.       sampler2D _Tex3;
    25.      
    26.       half _ScaleX;
    27.       half _ScaleY;
    28.      
    29.       void surf (Input IN, inout SurfaceOutput o) {
    30.         float3 correctWorldNormal = WorldNormalVector(IN, float3( 0, 0, 1 ) );
    31.         float2 uv = IN.worldPos.xz;
    32.      
    33.         uv.x *= _ScaleX;
    34.         uv.y *= _ScaleY;
    35.        
    36.         half4 color1 = tex2D( _Tex1, uv );
    37.         half4 color2 = tex2D( _Tex2, uv );
    38.         half4 color3 = tex2D( _Tex3, uv );
    39.        
    40.         half4 mask = tex2D( _MainTex, IN.uv_MainTex );
    41.        
    42.         o.Albedo = color1 * mask.r + color2 * mask.g + color3 * mask.b;
    43.       }
    44.       ENDCG
    45.     }
    46.     Fallback "Diffuse"
    47.   }
     
  8. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    Not batching is not related to your shader which looks good, but probably you using different textures for different objects and/or somewhere in your code you mess with individual material but not sharedMaterial.
     
  9. Mireneye

    Mireneye

    Joined:
    Apr 14, 2016
    Posts:
    2
    First and foremost thanks for this snippet of code, I've learned a lot tonight just by looking at it! =)
    A bit of a necropost, but I've shaved off a lot of things that I did not need. Now what I'd like is to add normal mapping to it.. How can I archive that?

    Code (CSharp):
    1.     Shader "Custom/TriWorld" {
    2.     Properties {
    3.       _Color ("Main Color", Color) = (1,1,1,1)
    4.       _MainTex ("Diffuse Texture", 2D) = "white" {}
    5.       _BumpMap ("NormalMap", 2D) = "bump" {}
    6.       _BaseScale ("BaseScale", Vector) = (1,1,1,0)
    7.     }
    8. SubShader {
    9.       Tags { "RenderType" = "Opaque" }
    10.       CGPROGRAM
    11.       #pragma surface surf Lambert
    12.    
    13.       struct Input {
    14.           float3 worldPos;
    15.           float3 worldNormal; INTERNAL_DATA
    16.           float3 vertColors;
    17.  
    18.       };
    19.  
    20.         void vert (inout appdata_full v, out Input o)
    21.         {
    22.             o.vertColors = abs(v.normal);
    23.         }
    24.    
    25.       sampler2D _MainTex;
    26.       sampler2D _BumpMap;
    27.       fixed4 _Color;
    28.       float3 _BaseScale;
    29.  
    30. void surf (Input IN, inout SurfaceOutput o) {
    31.     fixed4 texXY = tex2D(_MainTex, IN.worldPos.xy * _BaseScale.z);
    32.     fixed4 texXZ = tex2D(_MainTex, IN.worldPos.xz * _BaseScale.y);
    33.     fixed4 texYZ = tex2D(_MainTex, IN.worldPos.yz * _BaseScale.x);
    34.         fixed3 mask = fixed3(
    35.         dot (IN.worldNormal, fixed3(0,0,1)),
    36.         dot (IN.worldNormal, fixed3(0,1,0)),
    37.         dot (IN.worldNormal, fixed3(1,0,0)));
    38.     fixed4 tex = texXY * abs(mask.x) +texXZ * abs(mask.y) +texYZ * abs(mask.z);
    39.     fixed4 c = tex * _Color;
    40.  
    41.             float3 uv = IN.worldPos.xyz;
    42.  
    43.             half4 x = tex2D(_BumpMap, uv.zy);
    44.             half4 y = tex2D(_BumpMap, uv.zx);
    45.             half4 z = tex2D(_BumpMap, uv.xy);
    46.             half4 n = float4(1,1,1,1);
    47.             n = lerp(n,x,IN.vertColors.r);
    48.             n = lerp(n,y,IN.vertColors.g);
    49.             n = lerp(n,z,IN.vertColors.b);
    50.  
    51.                      o.Albedo = c.rgb;
    52.                      o.Normal = UnpackNormal(n);
    53.  
    54.       }
    55.       ENDCG
    56.     }
    57.     Fallback "Diffuse"
    58.   }
    Current result is just plain black. With no regard to the Albedo or anything.. just pure dark.
     
    Last edited: Apr 14, 2016