Search Unity

Unity Multi - Material Triplanar Texturing

Discussion in 'Editor & General Support' started by entro_p, Mar 15, 2014.

  1. entro_p

    entro_p

    Joined:
    Mar 9, 2014
    Posts:
    36
    Hello everyone!

    I'm working on a multi-material, triplanar textured voxel terrain.
    First off, I cannot use vertex painting, I need quite a lot of different materials ( 10 - 20 ).

    So, basically every vertex got a material id, the material id determines which texture to use, usually you would get a mix of 3 material ids in the surface shader and no way to get the correct texture.
    I already fixed that:
    Code (csharp):
    1.  
    2. struct Vertex{
    3.         ...
    4.     float3 material;
    5.     float3 alpha;  
    6. };
    7.  
    Every vertex contains 3 materials (it's own and the 2 of the other vertices in the triangle).
    The float3 alpha contains blending 'helpers': the vertex' own material is marked with 1, the other two are 0.
    Code (csharp):
    1.  
    2. v.material = {1, 2, 1};
    3. v.alpha = {1, 0, 0};
    4.  
    This way I can access the original material of each of the three vertices in the surface shader by dividing material by alpha.

    So far so good, I already did that once in XNA and just had to translate it.
    Triplanar texturing also was no problem, lots of resources out there.

    So, here's the problem: Whenever I use a material with an ID higher than 1 the shader somehow mixes the material and all materials with a lower id, also sometimes they seem not to blend:


    In this case the material in that sphere things is 3, however stone (2) and grass (1) also show up.

    Here is my shader code:

    Code (csharp):
    1.  
    2. Shader "MoleEngine.Unity/Multi Material Shader" {
    3. Properties {
    4.     _DiffuseColor ("Diffuse Color", Color) = (1,1,1,1)
    5.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
    6.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    7.     _BlendRange ("Blend Range", Range(0, 1)) = 0.2
    8.    
    9.     _MainTex ("Texture 1", 2D) = "white" {}
    10.     _MainTex2 ("Texture 2", 2D) = "white" {}
    11.     _MainTex3 ("Texture 3", 2D) = "white" {}
    12.     _MainTex4 ("Texture 4", 2D) = "white" {}
    13. }
    14. SubShader {
    15.     Tags { "RenderType"="Opaque" }
    16.     LOD 600
    17.    
    18. CGPROGRAM
    19. #pragma surface surf BlinnPhong vertex:vert
    20. #pragma target 3.0
    21. #pragma glsl
    22. #include "UnityCG.cginc"
    23.  
    24.  
    25. fixed4 _DiffuseColor;
    26. half _Shininess;
    27. half _BlendRange;
    28. sampler2D _MainTex;
    29. sampler2D _MainTex2;
    30. sampler2D _MainTex3;
    31. sampler2D _MainTex4;
    32.  
    33. struct Input {
    34.     float2 topUVs; 
    35.     float4 sideUVs;
    36.     float3 normal;
    37.     float3 material;
    38.     float3 alpha;  
    39. };
    40.  
    41. float4 _MainTex_ST;
    42. float4 _MainTex2_ST;
    43. float4 _MainTex3_ST;
    44. float4 _MainTex4_ST;
    45.  
    46. void vert(inout appdata_full v, out Input o)
    47. {
    48.     #if defined(SHADER_API_D3D11) || defined(SHADER_API_D3D11_9X)
    49.         UNITY_INITIALIZE_OUTPUT(Input,o);
    50.     #endif
    51.  
    52.     //Triplanar Weights: Done
    53.     o.normal = abs(v.normal);
    54.     half m = max(o.normal.x, max(o.normal.y, o.normal.z));
    55.     o.normal.x *= (o.normal.x == m ? 1 : _BlendRange);
    56.     o.normal.y *= (o.normal.y == m ? 1 : _BlendRange);
    57.     o.normal.z *= (o.normal.z == m ? 1 : _BlendRange);
    58.     o.normal = saturate(o.normal); 
    59.     o.normal /= (o.normal.x + o.normal.y + o.normal.z).xxx;
    60.    
    61.     //Triplanar UVs: DONE
    62.     o.topUVs.xy = TRANSFORM_TEX(v.vertex.yz, _MainTex);
    63.     o.sideUVs.xy = TRANSFORM_TEX(v.vertex.xz, _MainTex);
    64.     o.sideUVs.zw = TRANSFORM_TEX(v.vertex.xy, _MainTex);
    65.    
    66.     //material data
    67.     o.alpha = v.color.rgb;
    68.     o.material = float3(v.color.a, v.texcoord1.x, v.texcoord1.y);
    69. }
    70.  
    71. float4 getTexture(float m, float2 coord1, float2 coord2, float2 coord3, float3 weights)
    72. {
    73.     float4 c1, c2, c3;
    74.  
    75.     if(m > 0.5f  m < 1.5f)
    76.     {
    77.         c1 = tex2D(_MainTex, coord1);
    78.         c2 = tex2D(_MainTex, coord2);
    79.         c3 = tex2D(_MainTex, coord3);
    80.     }
    81.     else if(m > 1.5f  m < 2.5f)
    82.     {
    83.         c1 = tex2D(_MainTex2, coord1);
    84.         c2 = tex2D(_MainTex2, coord2);
    85.         c3 = tex2D(_MainTex2, coord3);
    86.     }
    87.     else if(m > 2.5f  m < 3.5f)
    88.     {
    89.         c1 = tex2D(_MainTex3, coord1);
    90.         c2 = tex2D(_MainTex3, coord2);
    91.         c3 = tex2D(_MainTex3, coord3);
    92.     }
    93.     else
    94.     {
    95.         c1 = tex2D(_MainTex4, coord1);
    96.         c2 = tex2D(_MainTex4, coord2);
    97.         c3 = tex2D(_MainTex4, coord3);
    98.     }
    99.  
    100.     return
    101.         c1.xyzw * weights.xxxx +
    102.         c2.xyzw * weights.yyyy +
    103.         c3.xyzw * weights.zzzz;
    104. }
    105.  
    106. void surf (Input IN, inout SurfaceOutput o)
    107. {
    108.     //Triplanar Weights: DONE
    109.     float3 weights = IN.normal;
    110.  
    111.     //Triplanar UVs: DONE
    112.     float2 coord1 = IN.topUVs;
    113.     float2 coord2 = IN.sideUVs.xy;
    114.     float2 coord3 = IN.sideUVs.zw;
    115.    
    116.     float4 tex1 = getTexture(IN.material.x, coord1, coord2, coord3, weights);
    117.     float4 tex2 = getTexture(IN.material.y, coord1, coord2, coord3, weights);
    118.     float4 tex3 = getTexture(IN.material.z, coord1, coord2, coord3, weights);
    119.     half4 col = tex1 * IN.alpha.x + tex2 * IN.alpha.y + tex3 * IN.alpha.z;
    120.  
    121.     o.Albedo = col.rgb * _DiffuseColor.rgb;
    122.     o.Gloss = col.a;
    123.     o.Alpha = o.Gloss * _DiffuseColor.a;
    124.     o.Specular = _Shininess;
    125. }
    126. ENDCG
    127. }
    128.  
    129. FallBack "Bumped Specular"
    130. }
    131.  
    I experimented for two days using different approaches but nothing ever worked (while the very same shader works fine in XNA (which is basically DirectX 9).

    Does anyone have an idea what the issue may be?

    Thanks in advance!

    Best regards,
    entro-p
     
  2. entro_p

    entro_p

    Joined:
    Mar 9, 2014
    Posts:
    36
    Update:
    I did not solve the problem itself, however I managed a workaround by using an adapted vertex painting shader.

    For anyone who may be interested:
    Code (csharp):
    1.  
    2. Shader "MoleEngine.Unity/VertexPainting.MultiMaterial.Advanced" {
    3. Properties {
    4.     _DiffuseColor ("Diffuse Color", Color) = (1,1,1,1)
    5.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
    6.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    7.     _Blend ("Blend Area", Range(0, 1)) = 0.2
    8.    
    9.     _DiffuseTexture ("Texture 1", 2D) = "white" {}
    10.     _DiffuseTexture2 ("Texture 2", 2D) = "white" {}
    11.     _DiffuseTexture3 ("Texture 3", 2D) = "white" {}
    12.     _DiffuseTexture4 ("Texture 4", 2D) = "white" {}
    13.     _DiffuseTexture5 ("Texture 5", 2D) = "white" {}
    14.     _DiffuseTexture6 ("Texture 6", 2D) = "white" {}
    15.     _DiffuseTexture7 ("Texture 7", 2D) = "white" {}
    16.     _DiffuseTexture8 ("Texture 8", 2D) = "white" {}
    17.     _DiffuseTexture9 ("Texture 9", 2D) = "white" {}
    18.     _DiffuseTexture10 ("Texture 10", 2D) = "white" {}
    19.     _DiffuseTexture11 ("Texture 11", 2D) = "white" {}
    20.     _DiffuseTexture12 ("Texture 12", 2D) = "white" {}
    21. }
    22. SubShader {
    23.     Tags { "RenderType"="Opaque" }
    24.     LOD 600
    25.    
    26. CGPROGRAM
    27. #pragma surface surf BlinnPhong vertex:vert
    28. #pragma target 3.0
    29. #pragma glsl
    30. #include "UnityCG.cginc"
    31.  
    32. fixed4 _DiffuseColor;
    33. half _Shininess;
    34. half _Blend;
    35. sampler2D _DiffuseTexture;
    36. sampler2D _DiffuseTexture2;
    37. sampler2D _DiffuseTexture3;
    38. sampler2D _DiffuseTexture4;
    39. sampler2D _DiffuseTexture5;
    40. sampler2D _DiffuseTexture6;
    41. sampler2D _DiffuseTexture7;
    42. sampler2D _DiffuseTexture8;
    43. sampler2D _DiffuseTexture9;
    44. sampler2D _DiffuseTexture10;
    45. sampler2D _DiffuseTexture11;
    46. sampler2D _DiffuseTexture12;
    47.  
    48. struct Input {
    49.     float2 top;
    50.     float4 sides;
    51.     float4 color : COLOR;  
    52.     float4 color2;
    53.     float4 color3;
    54.     float3 normal;     
    55. };
    56.  
    57. float4 _DiffuseTexture_ST;
    58. float4 _DiffuseTexture2_ST;
    59. float4 _DiffuseTexture3_ST;
    60. float4 _DiffuseTexture4_ST;
    61. float4 _DiffuseTexture5_ST;
    62. float4 _DiffuseTexture6_ST;
    63. float4 _DiffuseTexture7_ST;
    64. float4 _DiffuseTexture8_ST;
    65. float4 _DiffuseTexture9_ST;
    66. float4 _DiffuseTexture10_ST;
    67. float4 _DiffuseTexture11_ST;
    68. float4 _DiffuseTexture12_ST;
    69.  
    70. float mant(float f)
    71. {
    72.     return f - floor(f);
    73. }
    74.  
    75. void vert(inout appdata_full v, out Input o)
    76. {
    77.     #if defined(SHADER_API_D3D11) || defined(SHADER_API_D3D11_9X)
    78.         UNITY_INITIALIZE_OUTPUT(Input,o);
    79.     #endif
    80.    
    81.     o.normal = abs(v.normal);
    82.     half m = max(o.normal.x, max(o.normal.y, o.normal.z));
    83.     o.normal.x *= (o.normal.x == m ? 1 : _Blend);
    84.     o.normal.y *= (o.normal.y == m ? 1 : _Blend);
    85.     o.normal.z *= (o.normal.z == m ? 1 : _Blend);
    86.     o.normal = saturate(o.normal); 
    87.     o.normal /= (o.normal.x + o.normal.y + o.normal.z).xxx;
    88.  
    89.     o.top.xy = TRANSFORM_TEX(v.vertex.xz, _DiffuseTexture);
    90.     o.sides.xy = TRANSFORM_TEX(v.vertex.zy, _DiffuseTexture);
    91.     o.sides.zw = TRANSFORM_TEX(v.vertex.xy, _DiffuseTexture);
    92.    
    93.     o.color.r = floor(v.color.r);
    94.     o.color.g = floor(v.color.g);
    95.     o.color.b = floor(v.color.b);
    96.     o.color.a = floor(v.color.a);
    97.     o.color2.r = mant(v.color.r) * 10;
    98.     o.color2.g = mant(v.color.g) * 10;
    99.     o.color2.b = mant(v.color.b) * 10;
    100.     o.color2.a = mant(v.color.a) * 10;
    101.     o.color3.r = mant(mant(v.color.r) * 10) * 10;
    102.     o.color3.g = mant(mant(v.color.g) * 10) * 10;
    103.     o.color3.b = mant(mant(v.color.b) * 10) * 10;
    104.     o.color3.a = mant(mant(v.color.a) * 10) * 10;
    105. }
    106.  
    107.  
    108. void surf (Input IN, inout SurfaceOutput o) {
    109.     fixed4 tex1 = tex2D(_DiffuseTexture, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture, IN.sides.zw) * IN.normal.z;
    110.     fixed4 tex2 = tex2D(_DiffuseTexture2, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture2, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture2, IN.sides.zw) * IN.normal.z;
    111.     fixed4 tex3 = tex2D(_DiffuseTexture3, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture3, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture3, IN.sides.zw) * IN.normal.z;
    112.     fixed4 tex4 = tex2D(_DiffuseTexture4, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture4, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture4, IN.sides.zw) * IN.normal.z;
    113.     fixed4 tex5 = tex2D(_DiffuseTexture5, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture5, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture5, IN.sides.zw) * IN.normal.z;
    114.     fixed4 tex6 = tex2D(_DiffuseTexture6, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture6, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture6, IN.sides.zw) * IN.normal.z;
    115.     fixed4 tex7 = tex2D(_DiffuseTexture7, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture7, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture7, IN.sides.zw) * IN.normal.z;
    116.     fixed4 tex8 = tex2D(_DiffuseTexture8, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture8, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture8, IN.sides.zw) * IN.normal.z;
    117.     fixed4 tex9 = tex2D(_DiffuseTexture9, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture9, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture9, IN.sides.zw) * IN.normal.z;
    118.     fixed4 tex10 = tex2D(_DiffuseTexture10, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture10, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture10, IN.sides.zw) * IN.normal.z;
    119.     fixed4 tex11 = tex2D(_DiffuseTexture11, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture11, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture11, IN.sides.zw) * IN.normal.z;
    120.     fixed4 tex12 = tex2D(_DiffuseTexture12, IN.sides.xy) * IN.normal.x + tex2D(_DiffuseTexture12, IN.top.xy) * IN.normal.y + tex2D(_DiffuseTexture12, IN.sides.zw) * IN.normal.z;
    121.  
    122.     half4 col =
    123.         tex1  * IN.color.r +
    124.         tex2  * IN.color.g +
    125.         tex3  * IN.color.b +
    126.         tex4  * IN.color.a +
    127.         tex5  * IN.color2.r +
    128.         tex6  * IN.color2.g +
    129.         tex7  * IN.color2.b +
    130.         tex8  * IN.color2.a +
    131.         tex9  * IN.color3.r +
    132.         tex10 * IN.color3.g +
    133.         tex11 * IN.color3.b +
    134.         tex12 * IN.color3.a;
    135.                
    136.     o.Albedo = col.rgb * _DiffuseColor.rgb;
    137.     o.Gloss = col.a;
    138.     o.Alpha = o.Gloss * _DiffuseColor.a;
    139.     o.Specular = _Shininess;
    140. }
    141. ENDCG
    142. }
    143.  
    144. FallBack "Bumped Specular"
    145. }