Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

2D Sprite Color Mix

Discussion in '2D' started by Grimstborith, Jun 20, 2017.

  1. Grimstborith

    Grimstborith

    Joined:
    Jun 13, 2017
    Posts:
    6
    Hello guys.

    I am trying to mix colors of different sprites when they are overlapped with each other.

    Is that possible?

    An image is attached.
     
  2. FMark92

    FMark92

    Joined:
    May 18, 2017
    Posts:
    1,243
  3. Grimstborith

    Grimstborith

    Joined:
    Jun 13, 2017
    Posts:
    6
  4. FMark92

    FMark92

    Joined:
    May 18, 2017
    Posts:
    1,243
    Are you sure you know what you want?

    You want some kind of optional color mixing on the fly. Transparancy don't do it. Shaders do it.if you think you're hot **** you can try solving it purely in monobehaviour by changing sprites during runtime, but you'll just be writing an overcomplicated shader.
     
  5. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    There's two kind of traditional color "mixing". Additive, and subtractive. Additive is easy and can be done with a small tweak to the Blend mode of the default sprite shader.

    Additive will look similarly to this:
    Capture.PNG

    To do this, create a new shader called "Sprites-Additive", and paste the following code. Then make a new material and set it to use this shader.

    This is the 5.5 default sprite shader, with one line changed to make it additive blend.
    Code (CSharp):
    1. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
    2.  
    3. Shader "Sprites/Default"
    4. {
    5.     Properties
    6.     {
    7.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    8.         _Color ("Tint", Color) = (1,1,1,1)
    9.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    10.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    11.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    12.         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
    13.         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    14.     }
    15.  
    16.     SubShader
    17.     {
    18.         Tags
    19.         {
    20.             "Queue"="Transparent"
    21.             "IgnoreProjector"="True"
    22.             "RenderType"="Transparent"
    23.             "PreviewType"="Plane"
    24.             "CanUseSpriteAtlas"="True"
    25.         }
    26.  
    27.         Cull Off
    28.         Lighting Off
    29.         ZWrite Off
    30.         Blend One One
    31.  
    32.         Pass
    33.         {
    34.         CGPROGRAM
    35.             #pragma vertex SpriteVert
    36.             #pragma fragment SpriteFrag
    37.             #pragma target 2.0
    38.             #pragma multi_compile_instancing
    39.             #pragma multi_compile _ PIXELSNAP_ON
    40.             #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    41.             #include "UnitySprites.cginc"
    42.         ENDCG
    43.         }
    44.     }
    45. }
    46.  
    Things to note:
    • Combining Red and Yellow will produce Yellow. Because (1,0,0) plus (1,1,0) will result in (1,1,0). To make orange, it requires a custom averaging blend that is both expensive and drastically more complicated.
    • This will blend your sprites with the background as well. If you only want overlaps to blend, that requires another pass in the shader, with a Stencil comparison to check for overlaps.
    I recently made a whole thread about this subject here: https://forum.unity3d.com/threads/h...prites-additively-blend-without-alpha.476763/
     
    Last edited: Jun 20, 2017
    BusyCat and Deeeds like this.
  6. Grimstborith

    Grimstborith

    Joined:
    Jun 13, 2017
    Posts:
    6
    LiterallyJeff likes this.
  7. Deeeds

    Deeeds

    Joined:
    Mar 15, 2018
    Posts:
    739
    Is this the most efficient way to apply additive blend to sprites?
     
  8. FinnTess

    FinnTess

    Joined:
    Jun 10, 2018
    Posts:
    5
    @LiterallyJeff
    Hello, in your thread: https://forum.unity3d.com/threads/h...prites-additively-blend-without-alpha.476763/ I saw that you have have been able to do this. (attached picture: "Color") Unfortunately, I know nothing about shaders, but like at all. I did tried to understand your script (the spoiler attached to this picture: "Color") but I didn't understand it and I did tried to copy paste it, but I have this result instead (In attached picture: "Bad Result"). DO you know what would cause this ?

    Hopefully you can answer me, (this thred is 3 years old haha).
     

    Attached Files:

  9. FinnTess

    FinnTess

    Joined:
    Jun 10, 2018
    Posts:
    5
    To make it easier, that's your shader that I tried to use:


    1. Shader "Custom/Sprites/ColorMixAverage"
    2. {
    3. Properties
    4. {
    5. [PerRendererData]_MainTex("Texture", 2D) = "white" {}
    6. }

    7. SubShader
    8. {
    9. Tags
    10. {
    11. "Queue" = "Transparent"
    12. "RenderType" = "Transparent"
    13. "IgnoreProjector" = "True"
    14. "PreviewType" = "Plane"
    15. "CanUseSpriteAtlas" = "True"
    16. "DisableBatching" = "True"
    17. }

    18. Cull Off
    19. Lighting Off
    20. ZWrite Off
    21. Blend SrcAlpha OneMinusSrcAlpha

    22. Pass
    23. {
    24. Stencil
    25. {
    26. Ref 0
    27. Comp Equal
    28. Pass IncrSat
    29. }


    30. CGPROGRAM
    31. #pragma vertex vert
    32. #pragma fragment frag

    33. #include "UnityCG.cginc"

    34. struct appdata
    35. {
    36. float4 vertex : POSITION;
    37. float2 uv : TEXCOORD0;
    38. float4 color: COLOR;
    39. };

    40. struct v2f
    41. {
    42. float4 vertex : SV_POSITION;
    43. float2 uv : TEXCOORD0;
    44. float4 color: COLOR;
    45. };

    46. sampler2D _MainTex;
    47. float4 _MainTex_ST;

    48. v2f vert(appdata input)
    49. {
    50. v2f output;
    51. output.vertex = UnityObjectToClipPos(input.vertex);
    52. output.uv = TRANSFORM_TEX(input.uv, _MainTex);
    53. output.color = input.color;
    54. return output;
    55. }

    56. fixed4 frag(v2f input) : SV_Target
    57. {
    58. fixed4 textureColor = tex2D(_MainTex, input.uv) * input.color;
    59. return textureColor;
    60. }
    61. ENDCG
    62. }

    63. GrabPass{"_GrabPass"}

    64. Pass
    65. {
    66. Stencil
    67. {
    68. Ref 0
    69. Comp NotEqual
    70. }

    71. CGPROGRAM
    72. #pragma vertex vert
    73. #pragma fragment frag

    74. #include "UnityCG.cginc"

    75. struct appdata
    76. {
    77. float4 vertex : POSITION;
    78. float2 uv : TEXCOORD0;
    79. float4 color : COLOR;
    80. };

    81. struct v2f
    82. {
    83. float4 vertex : SV_POSITION;
    84. float2 uv : TEXCOORD0;
    85. float4 grabPos : TEXCOORD1;
    86. float4 color : COLOR;
    87. };

    88. //https://github.com/greggman/hsva-unity/blob/master/Assets/Shaders/HSVRangeShader.shader
    89. float3 rgb2hsv(float3 c) {
    90. float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    91. float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
    92. float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));

    93. float d = q.x - min(q.w, q.y);
    94. float e = 1.0e-10;
    95. return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
    96. }

    97. //https://github.com/greggman/hsva-unity/blob/master/Assets/Shaders/HSVRangeShader.shader
    98. float3 hsv2rgb(float3 c) {
    99. c = float3(c.x, clamp(c.yz, 0.0, 1.0));
    100. float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    101. float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
    102. return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
    103. }

    104. sampler2D _MainTex;
    105. float4 _MainTex_ST;
    106. sampler2D _GrabPass;

    107. v2f vert(appdata input)
    108. {
    109. v2f output;
    110. output.vertex = UnityObjectToClipPos(input.vertex);
    111. output.uv = TRANSFORM_TEX(input.uv, _MainTex);
    112. output.grabPos = ComputeGrabScreenPos(output.vertex);
    113. output.color = input.color;
    114. return output;
    115. }

    116. fixed4 frag(v2f input) : SV_Target
    117. {
    118. float4 textureColor = tex2D(_MainTex, input.uv) * input.color;
    119. float4 backgroundColor = tex2Dproj(_GrabPass, input.grabPos);

    120. float3 textureColorHSV = rgb2hsv(textureColor);
    121. float3 backgroundColorHSV = rgb2hsv(backgroundColor);

    122. float3 averaged = (textureColorHSV + backgroundColorHSV) * 0.5f;
    123. float4 result = float4(hsv2rgb(averaged), 1.0);
    124. return result;
    125. }
    126. ENDCG
    127. }
    128. }
    129. }