Search Unity

  1. We've closed the job boards. If you're looking for work, or looking to hire check out Unity Connect. You can see more information here.
    Dismiss Notice
  2. Unity 2017.3 has arrived! Read about it here.
    Dismiss Notice
  3. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Invert Colors Shader

Discussion in 'Shaders' started by dandeentremont, Oct 15, 2013.

  1. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    Hey guys, I thought I'd share this simple transparent shader. It inverts the colors of anything behind the mesh to which it is applied. It also has a tint parameter. Also it works for Unity Free.

    I'm new to shaders, so if there's any way to make it more efficient, feel free to tell me!

    The .shader file is attached, but here's the code because sometimes, downloading stuff is annoying:

    Code (csharp):
    1. Shader "ddShaders/dd_Invert" {
    2. Properties
    3.     {
    4.         _Color ("Tint Color", Color) = (1,1,1,1)
    5.     }
    6.    
    7.     SubShader
    8.     {
    9.         Tags { "Queue"="Transparent" }
    10.  
    11.         Pass
    12.         {
    13.            ZWrite On
    14.            ColorMask 0
    15.         }
    16.         Blend OneMinusDstColor OneMinusSrcAlpha //invert blending, so long as FG color is 1,1,1,1
    17.         BlendOp Add
    18.        
    19.         Pass
    20.         {
    21.        
    22. CGPROGRAM
    23. #pragma vertex vert
    24. #pragma fragment frag
    25. uniform float4 _Color;
    26.  
    27. struct vertexInput
    28. {
    29.     float4 vertex: POSITION;
    30.     float4 color : COLOR;  
    31. };
    32.  
    33. struct fragmentInput
    34. {
    35.     float4 pos : SV_POSITION;
    36.     float4 color : COLOR0;
    37. };
    38.  
    39. fragmentInput vert( vertexInput i )
    40. {
    41.     fragmentInput o;
    42.     o.pos = mul(UNITY_MATRIX_MVP, i.vertex);
    43.     o.color = _Color;
    44.     return o;
    45. }
    46.  
    47. half4 frag( fragmentInput i ) : COLOR
    48. {
    49.     return i.color;
    50. }
    51.  
    52. ENDCG
    53. }
    54. }
    55. }
    56.  
     

    Attached Files:

  2. p13t3rm

    p13t3rm

    Joined:
    Nov 21, 2013
    Posts:
    5
    Hey just wanted to thank you for this as it seems no one else has.
    This shader is helping out a lot right now. Cheers!
     
  3. SevenBits

    SevenBits

    Joined:
    Dec 26, 2011
    Posts:
    1,956
    You should adjust the formatting in your embedded example. But that's just me being picky.
     
  4. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    I appreciate that, p13t3rm!

    Attached is an updated version of the shader that trims off a bunch of unnecessary code, if you are interested (also should address the formatting issue).
    Additionally, I've attached a version of the shader for use in Linear Color Space.
     

    Attached Files:

    Last edited: Jan 14, 2018 at 6:24 PM
    TooManySugar and dertyde94 like this.
  5. Play_Edu

    Play_Edu

    Joined:
    Jun 10, 2012
    Posts:
    696
    cool stuff.
     
  6. bitbutter

    bitbutter

    Joined:
    Jul 19, 2012
    Posts:
    60
    Very cool! I've been putting off learning shaders but this is almost exactly what I wanted to make.

    In case you ever feel like tinkering with it some more, a request: It'd be fantastic if there was an optional (variable) desaturation stage applied after the inverion, but before the tint was applied. If that was in there I could put off learning shaders for even longer ;)
     
  7. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    I will definitely take that challenge, but there is a strong chance it would only be possible with Pro things such as Grab Pass (I don't have Unity Pro yet)
     
    Last edited: Jan 11, 2014
  8. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    Well, after hours of tinkering, I can say a desaturation pass is beyond my abilities. The big problem is that it requires a color channel to read and mix with the other color channels, which is not something Blend does easily.


    http://forum.unity3d.com/threads/193930-Transparent-shader-that-makes-objects-behind-it-greyscale

    In the above thread, Jessy explains a process, which seems to involve storing the color channels in the alpha, and then using another pass to reveal that alpha. I CAN get a pass to work which reveals the alpha channels, but I cannot get color channels stored in the alpha in the first place.
     
  9. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,461
  10. S0ULART

    S0ULART

    Joined:
    Jun 14, 2011
    Posts:
    128
    Hello Community!

    I'm wondering how it's possible to achieve a Shader that inverts an objects color that it touches.

    _
    the problem with the shader above is, that the object (e.g. an Cube) where the shader is applied to acts like a mirror and inverts everything you look at. I want the object with the shader to be invisible and is just inverting the color of the objects thats inside it.

    My Intention is to get a similar result like in the image:
    http://www.androidshock.com/wp-content/uploads/2013/10/Paper-Sorcerer-1.jpg

    regards
    Soulart
     
  11. twbowen

    twbowen

    Joined:
    Sep 27, 2013
    Posts:
    30
    Reviving an old thread here, does anyone know if it would be possible to modify this shader to accept a texture rather than just a solid color? As in not the tint color but I'm looking to invert what's behind based on a black and white texture. So instead of a solid alpha, basically I'd like a texture alpha.
     
    Last edited: Jul 12, 2015
  12. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    Hi, twbowen. This shader should do the things you need:

    Pixels behind the white part of a texture will become inverted, while pixels behind the black part of the texture will keep their original color. It will also tint if your texture image is colorful (in fact this tinting method looks a bit better than the above shaders, IMO)

    Make note that, due to the nature of color inversion, a black-white gradient will have a solid-looking gray center.

    Code (CSharp):
    1. //ddInvertMapped shader: Daniel DeEntremont
    2. //Apply this shader to a mesh and watch all pixels behind the mesh become inverted!
    3. //Now has a texture mask input. White will invert colors behind while black remains the same.
    4. Shader "ddShaders/ddInvertMapped" {
    5.     Properties
    6.         {
    7.             _Color ("Tint Color", Color) = (1,1,1,1)
    8.             _MainTex("Main Texture", 2D) = "white"{}
    9.         }
    10.    
    11.    
    12.    
    13.         SubShader
    14.         {
    15.             Tags { "Queue"="Transparent" }
    16.      
    17.             Pass
    18.             {
    19.                ZWrite On
    20.                ColorMask 0
    21.             }
    22.        
    23.        
    24.        
    25.             Pass
    26.             {
    27.                 Blend OneMinusDstColor OneMinusSrcColor //invert blending, so long as FG color is 1,1,1,1
    28.                 BlendOp Add
    29.                 SetTexture [_MainTex]
    30.                 {
    31.                     constantColor [_Color]
    32.                     combine texture * constant
    33.                 }
    34.             }
    35.        
    36.          }//end subshader
    37. }//end shader
     

    Attached Files:

    Last edited: Jul 12, 2015
    dertyde94 likes this.
  13. ThinkertonGames

    ThinkertonGames

    Joined:
    Feb 26, 2015
    Posts:
    20
    Awesome! That's perfect, thank you so much. I was so close!
     
  14. dock

    dock

    Joined:
    Jan 2, 2008
    Posts:
    376
    This shader is excellent! Thanks so much for sharing it.

    Is there any way to make it compatible with render to texture? I can't figure it out.
     
  15. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,101
    @dandeentremont I tried to use the shader in Unity 5.2.2 and it seems like it doesn't work anymore. Is there anything that needs to change for it to work?
     
  16. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    Hi Ben BearFish,

    I just downloaded 5.2.2f1 on a macbook and the shaders seem to be running fine here.
    What kind of error messages are you getting?
     
  17. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,101
    The shader you posted in your first post doesn't seem to compile, but the later ones you posted seem to work.
     
  18. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    Even the first one seems to be working over here. Although the first time I tried, I hadn't copied the last bracket, so it did fail. Any chance something like that happened :)?
     
  19. davididev2

    davididev2

    Joined:
    Jan 25, 2016
    Posts:
    2
    Works for 2D as well. I'll put you in the credits for now as dandeentremont but I'd like to put you in as your real name. :)
     
  20. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    It's close: My real name is Daniel DeEntremont

    Thanks so much for your consideration!
     
  21. Firas24

    Firas24

    Joined:
    Jun 18, 2015
    Posts:
    4
    Hello,
    Do you have a shader that inverts colors of ui elements and sprites
    I have a 2D game where a certain part of the screen has the negative of the colors of the other part including UI and sprites.
    I'm thinking about placing a ui image with a material rendered using this negative shader above the game elements
    thanks
     
  22. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    334
    Just did my version of vertex-fragment shader. dandeentremont's legacy version (ddShaders/ddInvertMapped) actually can be revised to remove the first pass which adds an additional drawcall, but using the v-f version allows greater flexibility anyway. It also doesn't include fog like in the official Particle shaders because it seems utterly pointless for negative/inverting color effect.
    Code (CSharp):
    1. Shader "Particles/Negative" {
    2.     Properties {
    3.         _Color ("Tint Color", Color) = (1,1,1,1)
    4.         _MainTex ("Texture", 2D) = "white" {}
    5.         _Glow ("Intensity", Range(0,10)) = 1 //Allows color saturation in HDR rendering.
    6.     }
    7.     SubShader {
    8.         Tags { "Queue" = "Transparent" "PreviewType" = "Plane"}
    9.         LOD 100
    10.         Cull Off
    11.         ZWrite Off
    12.         BlendOp Add
    13.         Blend OneMinusDstColor OneMinusSrcColor //Opacity depends on grey scale. Alpha value is irrelevant, hence "alpha source" in texture properties can be "none" for maximum performance.
    14.         //AlphaToMask On //Required when using texture alpha channel for cropping.
    15.      
    16.         Pass {
    17.             CGPROGRAM
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.             #include "UnityCG.cginc"
    21.  
    22.             struct appdata {
    23.                 float4 vertex : POSITION;
    24.                 fixed4 color : COLOR;
    25.                 float2 texcoord : TEXCOORD0;
    26.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    27.             };
    28.  
    29.             struct v2f {
    30.                 float4 vertex : SV_POSITION;
    31.                 fixed4 color : COLOR;
    32.                 float2 uv : TEXCOORD0;
    33.                 UNITY_VERTEX_OUTPUT_STEREO
    34.             };
    35.          
    36.             fixed4 _Color;
    37.             sampler2D _MainTex;
    38.             float4 _MainTex_ST;
    39.             half _Glow;
    40.          
    41.             v2f vert (appdata v) {
    42.                 v2f o;
    43.                 o.vertex = UnityObjectToClipPos(v.vertex);
    44.                 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    45.                 o.color = v.color * _Color * _Glow;
    46.                 return o;
    47.             }
    48.          
    49.             fixed4 frag (v2f i) : SV_Target {
    50.                 fixed4 col = tex2D(_MainTex, i.uv) * i.color;
    51.                 return col;
    52.             }
    53.             ENDCG
    54.         }
    55.     }
    56.     FallBack "Mobile/Particles/Alpha Blended"
    57. }
    particle negative screenshot.png
     
    dertyde94 and larku like this.
  23. Noxidl

    Noxidl

    Joined:
    Mar 25, 2017
    Posts:
    1
    Just wanted to say huge thanks ! The shader is great and is just what i needed!
     
  24. aasiq

    aasiq

    Joined:
    Dec 29, 2016
    Posts:
    4
    @dandeentremont . Your invert color shader is awesome man. It even works on 2D Sprite Renderer. Instead of inverting colors, I want the objects behind it to be grayscaled. How can I achieve this??
     
  25. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    16
    This might require a more advanced shader that uses GrabPass. The reason being that desaturating requires you to be able to swizzle the RG and B channels which, to my knowledge, can't be done with simple shader blending.

    I can't try this till I get back home, but this shader in the unity docs seems to function like mine, except uses GrabPass to get the BG color:

    https://docs.unity3d.com/Manual/SL-GrabPass.html

    In that shader, if you changed the line...

    Code (CSharp):
    1. return 1 - bgcolor;
    to...

    Code (CSharp):
    1.  bgcolor.r = (bgcolor.r*0.3 + bgcolor.g*0.59 + bgcolor.b*0.11);
    2. return bgcolor.rrra;
    ...my guess is it would desaturate the background. I'll post later if it doesn't work.

    Edit: Seems to work swell.
     
    Last edited: Nov 6, 2017
  26. iTwist

    iTwist

    Joined:
    Dec 13, 2017
    Posts:
    10
    @dandeentremont

    on unity 2017.2 i get an error saying this

    Shader error in 'ddShaders/ddInvertLin': cannot implicitly convert from 'sampler2D' to 'half4' at line 60 (on d3d11)
    Compiling Vertex program
    Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_COLORSPACE_GAMMA UNITY_LIGHT_PROBE_PROXY_VOLUME

    plz help
     
  27. iTwist

    iTwist

    Joined:
    Dec 13, 2017
    Posts:
    10
    nevermind it works now after i used your mapped file and rotated my sprite on the y axis at 180 degrees for come reason it only works on one side