Search Unity

Blending 2 textures and color.

Discussion in 'Shaders' started by TIGGYsmalls, Jul 19, 2013.

  1. TIGGYsmalls

    TIGGYsmalls

    Joined:
    Jan 10, 2013
    Posts:
    38
    Code (csharp):
    1. Shader "Custom/IlumBlend2" {
    2.  
    3. Properties {
    4.     _Color ("Color Tint (A = Opacity)", Color) = (1,1,1,1)
    5.     _Texture1 ("Texture1", 2D) = ""
    6.     _Texture2 ("Texture2", 2D) = ""
    7. }
    8. Category {
    9.     Material {
    10.        Ambient[_Color]
    11.        Diffuse[_Color]
    12.     }
    13.    
    14.     SubShader {
    15.    
    16.     Pass {
    17.        Lighting On
    18.        SetTexture[_Texture1]
    19.        SetTexture[_Texture2] {
    20.          ConstantColor(1,1,1,0.5)
    21.          Combine texture Lerp(constant) previous
    22.        }
    23.        SetTexture[_] {Combine previous * primary Double}
    24.     }}
    25.  
    26. }
    27.  
    28. }
    Code (csharp):
    1. Shader "Custom/IlumBlend" {
    2.  
    3.      
    4.  
    5.     Properties {
    6.  
    7.             _Color ("Color (RGB)", Color) = (1,1,1,1)
    8.             _Texture1 ("Texture1 (RGB) Texture", 2D) = "white" {}
    9.             _Texture2 ("Texture2 (RGB) Texture", 2D) = "white" {}
    10.      }
    11.  
    12.         SubShader {
    13.         Pass {
    14.             Lighting On
    15.  
    16.             SetTexture [_Texture1] {
    17.             constantColor [_Color]
    18.                 Combine Constant Lerp(texture) previous
    19.             }
    20.              SetTexture [_Texture2]{
    21.                 Combine texture Lerp(texture) previous, previous
    22.                
    23.             }
    24.  
    25.         }
    26.  
    27.     }
    28.  
    29. }
    Right, I've made these 2 very simple shaders, nether of which work. I just want to combine 2 textures and a color.

    What am I doing wrong?
     
  2. TIGGYsmalls

    TIGGYsmalls

    Joined:
    Jan 10, 2013
    Posts:
    38
    Been messing about with them but I still haven't gotten what I wanted. I know what I want to achieve is easy, I just cant do it.
     
  3. groovounet

    groovounet

    Unity Technologies

    Joined:
    Jul 15, 2013
    Posts:
    16
    You really need to need to give more detail about what you are trying to archive here. Texture combiners are configurable so you can accomplish a lot of different things with them.

    Have a look at http://docs.unity3d.com/Documentation/Components/SL-SetTexture.html for details about texture combiners.

    Code (csharp):
    1.  
    2. SetTexture[_Texture2] {
    3.          ConstantColor(1,1,1,0.5)
    4.          Combine texture Lerp(constant) previous
    5. }
    6.  
    What this code do is using the color outputted by the previous SetTexture and linearly interpolate it with the color of _Texture2 using the alpha value set to ConstantColor which is 0.5.

    That is: result = previous * 0.5 + texture * (1.0 - 0.5)
    So in this present case, you average the color of the two textures.

    On your second case:
    Code (csharp):
    1.  
    2.             SetTexture [_Texture1] {
    3.                 constantColor [_Color]
    4.                 Combine Constant Lerp(texture) previous
    5.             }
    6.  
    7.              SetTexture [_Texture2]{
    8.                 Combine texture Lerp(texture) previous, previous
    9.             }
    10.  
    You are using "previous" without setting any texture before. Hence previous will behave as if you had set primary and use the lighting calculation because Lighting is turned on.

    I suspect that what you are trying to do it to generate an output color so that you have as much of _Texture1, _Texture2 and _Color, in others words you want to average your three colors which is not the kind of things combiners can really do.
    That would be equivalent to do the following logical operation: primary * (_Texture1 + _Texture2 + _Color) * 0.33
    If you really want to do that I recommend to use real shader code.
     
  4. TIGGYsmalls

    TIGGYsmalls

    Joined:
    Jan 10, 2013
    Posts:
    38
    $Example.jpg

    How do you define the new texture then?

    And why doesn't this work?

    Code (csharp):
    1.  SetTexture [_Texture1] {
    2.                 SetTexture [_Texture2]
    3.                 Combine texture Lerp(texture) previous
    4.             }
    5.              constantColor [_Color]{
    6.                 Combine Constant Lerp(texture) previous, previous
    7.             }
     
  5. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    635
    To color the grey and white areas, you'll want to multiply with the color, in stead of adding it.
    By the way, it helps to be more specific about how something doesn't work (are you getting errors? Is the image completely black? Or purple perhaps?)

    I can't tell you how to write pure shaderlab though, I rarely ever use it. Cg can be a lot easier to read.
     
  6. groovounet

    groovounet

    Unity Technologies

    Joined:
    Jul 15, 2013
    Posts:
    16
    Actually following the order of operations given by TIGGYsmalls, the two black textures needs to be added and then that result need to be multiply by the color. Other operations and order could also give you the expected result.

    You can't write code creating a hierarchy of SetTexture
    Code (csharp):
    1.  
    2.  SetTexture [_Texture1] {
    3.  
    4.                 SetTexture [_Texture2]
    5.  
    6.                 Combine texture Lerp(texture) previous
    7.  
    8.             }
    9.  
    10.              constantColor [_Color]{
    11.  
    12.                 Combine Constant Lerp(texture) previous, previous
    13.  
    14.             }
    15.  
    The reason is that texture combiners are a deprecated GPU hardware feature released in 2000 with GeForce 2 through the OpenGL extension GL_NV_register_combiners and standardise in 2001 with GL_ARB_texture_env_combine http://www.opengl.org/registry/specs/ARB/texture_env_combine.txt. That was the time of fixed function GPUs where we could do very little. Eventually all this became obsolete in 2002 with the release for Radeon 9700 which introduced shader programming. That was also a feature of OpenGL ES 1.x used by mobile but these were removed in OpenGL ES 2.0 in 2007.

    Bottom line: Texture combiners are very limited so really you should use shaders.which will allow you to combine your texture exactly the way you want. To help you transitioning from combiners to shaders you can have a look at this OpenGL wiki page. http://www.opengl.org/wiki/Texture_Combiners It shows the higher simplicity of shaders overs combiners.
     
    Last edited: Aug 1, 2013
  7. TIGGYsmalls

    TIGGYsmalls

    Joined:
    Jan 10, 2013
    Posts:
    38
    $Preview.jpg

    This is what I'm getting.

    It may be limited but I know it should work because its been done here:

    http://answers.unity3d.com/questions/377481/2-texture-blend-shader.html

    In my first example have tried editing this down to remove the _blend function but I either get full black, the pink error texture or just 1 texture mixing with the _color. I know it doesn't need to be complicated but I just don't get how to do it. Its the ConstantColor() that seems to break it.
     
  8. groovounet

    groovounet

    Unity Technologies

    Joined:
    Jul 15, 2013
    Posts:
    16
    And what's the code for this result?
     
  9. groovounet

    groovounet

    Unity Technologies

    Joined:
    Jul 15, 2013
    Posts:
    16
    Here you are multiplying your color and the first texture. Then you are adding the second color.

    You need to add your two textures and then multiply your color.

    The link you are giving as nothing to do with what you do. What the developer does, it's blending/interpolating two textures using an alpha value stored in the _Blend property.

    If you prefer using texture combiners, you are free to do that so you need to read the documentation about it: http://docs.unity3d.com/Documentation/Components/SL-SetTexture.html

    When considering each operation, you need to remember that the inputs are interpreted as normalized color. If the texture is all red storing effectively "255, 0, 0, 255", you should view it as "1.0, 0.0, 0.0, 1.0". Hence once you multiply red(1.0, 0.0, 0.0, 1.0) by white(1.0, 1.0, 1.0, 1.0) you get red. If you add red and white you get (2.0, 1.0, 1.0, 2.0) which is clamp to white(1.0, 1.0, 1.0, 1.0).
     
  10. TIGGYsmalls

    TIGGYsmalls

    Joined:
    Jan 10, 2013
    Posts:
    38
    Ok, I just searched for the terms you talked about and found this thread:

    http://forum.unity3d.com/threads/153042-Multiplication-shaders-for-textures-on-3D-models

    Code (csharp):
    1. Shader "Custom/IlumBlend"
    2.  
    3. {  
    4.  
    5.     Properties
    6.     {
    7.         _MainColor ("Color", Color) = (1,1,1,1)
    8.         _Texture1 ("Texture1 (RGB) Texture", 2D) = "white" {}
    9.         _Texture2 ("Texture1 (RGB) Texture", 2D) = "white" {}
    10.     }
    11.  
    12.  
    13.     SubShader
    14.     {
    15.         Tags { "RenderType"="Opaque" }
    16.         LOD 250
    17.         CGPROGRAM
    18.  
    19.         #pragma surface surf Lambert
    20.         fixed4 _MainColor;
    21.         sampler2D _Texture1;
    22.         sampler2D _Texture2;
    23.         struct Input
    24.         {
    25.             float2 uv_Texture1;
    26.             float2 uv_Texture2;
    27.         };
    28.  
    29.         void surf (Input IN, inout SurfaceOutput o)
    30.  
    31.         {
    32.  
    33.             fixed4 main = tex2D(_Texture1, IN.uv_Texture1);
    34.             half4 team = tex2D(_Texture2, IN.uv_Texture2);
    35.  
    36.             main.rgb = lerp (team.rgb, main.rgb, main.a);
    37.             main *= _MainColor;
    38.             o.Albedo = main.rgb;
    39.  
    40.         }
    41.  
    42.         ENDCG
    43.  
    44.     }
    45.  
    46. }
    There must be one line I can put in and it'll work like any other self illuminating shader?
     
  11. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    635
    That shader doesn't work like a self-illumination shader yet because it only writes to o.Albedo. If you just want to directly output color without lighting, you can write to o.Emission.

    Although, if you don't need lighting at all, you might want to look into using basic vertex+fragment shaders, since surface shaders create a whole lot of code dedicated to lighting that you would not need.
     
  12. TIGGYsmalls

    TIGGYsmalls

    Joined:
    Jan 10, 2013
    Posts:
    38
    I'm not smart enough for that. This works, so it's fine.

    Thank you.