Search Unity

Invert Colors Shader

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

  1. dandeentremont

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    24
    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:
    21
    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!
     
    unity_kd3c7c52OBFQmQ likes this.
  3. SevenBits

    SevenBits

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

    dandeentremont

    Joined:
    Jan 11, 2013
    Posts:
    24
    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
    TooManySugar and RaphaelBuquet like this.
  5. Play_Edu

    Play_Edu

    Joined:
    Jun 10, 2012
    Posts:
    722
    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:
    24
    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:
    24
    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,521
  10. S0ULART

    S0ULART

    Joined:
    Jun 14, 2011
    Posts:
    131
    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:
    24
    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
  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:
    605
    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,204
    @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:
    24
    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,204
    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:
    24
    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:
    24
    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:
    350
    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.         _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    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 _TintColor;
    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 * _TintColor * 2;
    46.                 o.color.rgb *=  _Glow;
    47.                 return o;
    48.             }
    49.      
    50.             fixed4 frag (v2f i) : SV_Target {
    51.                 fixed4 col = tex2D(_MainTex, i.uv) * i.color;
    52.                 return col;
    53.             }
    54.             ENDCG
    55.         }
    56.     }
    57.     FallBack "Mobile/Particles/Alpha Blended"
    58. }
    particle negative screenshot.png
     
    Last edited: Feb 23, 2018
    ArnaudValensi, Thorlar, efge and 2 others 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:
    16
    @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:
    24
    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:
    14
    @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:
    14
    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
     
  28. NicVro

    NicVro

    Joined:
    Aug 29, 2018
    Posts:
    1
    Hi @dandeentremont,

    Do you know if it's possible to apply this shader to a Sprite Renderer, and if so how should we modify the shader?

    Thanks
     
  29. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    Would it be possible to adjust this to only switch between white and black depending on the background, instead of all the colors in the world? Would make text and ui images much easier to read/see if it could change between the two without going through all the colors of the rainbow in the process
     
  30. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Not really no. Not using the blend mode technique this thread is mostly about.

    A grabpass method would work, but that'd be done completely differently. And if your background scene has a lot of high contrast detail in it, so too will the text as it's going to be choosing black or white per-pixel. Those areas will render text and UI completely illegible.

    This is why AAA games almost always have some kind of black or white background behind UI elements, or an outline.
     
  31. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    Thanks. I can see why that would look awful as well. I'll look into other solutions then :)
     
  32. AndyLangberg

    AndyLangberg

    Joined:
    Jul 6, 2018
    Posts:
    37
    Actually I have a follow up for that. I have a loading icon which can have a white background or an image behind it (depending on which menu flap is open), and I would like the icon to switch between white and black itself depending on which flap is open (Aka: White color for image flap, black color for white-background flap). Now I can do this grammatically, by switching it on the same button as the user presses, and that looks ok'ish. But it would look a lot better if it smoothly changed from one color to the next, pixel by pixel, as the flap animates its way onto the screen and underneath the loading icon, instead of this sudden and abrupt all-at-once change at the press of a button. Is this something that can be done with a Shader, or is there some other solution I'm not thinking of here?
     
  33. fjack

    fjack

    Joined:
    May 5, 2019
    Posts:
    5
    Thanks for the shader. Does anyone have any idea how to achieve a similar effect, but where the colors are only slightly inverted (i.e. the object in the foreground retains transparency). I suppose I would like the alpha channel of the _Color property to be used to decide how much to apply the effect.

    EDIT: clarity
     
  34. SatiricalSnake

    SatiricalSnake

    Joined:
    Jun 10, 2019
    Posts:
    2
    Hello, I am new to Unity. This shader is amazing but I would like to know if there is any way to keep the objects inverted while inside the mesh. This is for VRChat.
     
  35. ArnaudValensi

    ArnaudValensi

    Joined:
    Jul 22, 2015
    Posts:
    3
    It's perfect, thank you very much!
     
  36. harperrhett

    harperrhett

    Joined:
    Apr 12, 2020
    Posts:
    8
    Hi... I'm going to bump this thread, again (sorry). I'm struggling immensely to use this shader to invert the colors on a material without transparency. I see that this shader is typically used to invert colors behind an object, but what if I want to just apply it to the object itself? Thanks...

    Nevermind! I took the png I made my material out of, inverted it, and applied it to a new material. I will just use the new material instead of a shader :)
     
    Last edited: Apr 28, 2020
  37. cxode

    cxode

    Joined:
    Jun 7, 2017
    Posts:
    268
    Hello friends, if you're using SRP it's extremely easy with shader graph:



    Here's that shader applied to a UI component (RawImage) in the center of my screen.



    I've used this to make a crosshair that inverts the colors behind it, just like in Minecraft :D
     
    Chrisdbhr and TheOtherUserName like this.
  38. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Some notes on this:
    • This requires you have the opaque camera texture enabled on your pipeline asset.
    • This will only invert opaque surfaces. Transparent surfaces will either not be visible, or may appear without the color inverted if it gets sorted in front.
    • @ifurkend 's example should also "just work" in either SRP, and does not have these limitations.
     
    cxode likes this.
  39. okr765

    okr765

    Joined:
    Mar 30, 2020
    Posts:
    1
    Hello there,
    Do you know if I could make any modifications to this shader to make it compatible with Text objects? It works perfectly with Image objects, but if I apply it to text, it does not appear properly. I am not very experienced with custom shaders, so does anyone have any advice of how I would go about this?
     
  40. xator

    xator

    Joined:
    Feb 12, 2013
    Posts:
    1
    Thank you so much, spent hours trying to figure this out!
     
  41. TheAnimatedKiddo

    TheAnimatedKiddo

    Joined:
    Aug 20, 2020
    Posts:
    2
    Thank you so much! I am using this for an FPS Game that I'm making, and this is so useful. Though, will this be affected when I switch to the Lightweight Render Pipeline? I need it for Brackeys hologram shader. Thanks again!
     
  42. SkepticDude

    SkepticDude

    Joined:
    Jul 13, 2020
    Posts:
    7
    Newbie here,
    So I am using Invert shader. I have black background and two players with invert shader. Means They both are white. Now when they interact other/ partially passes through each other, then that region becomes black instead of staying white.
    I don't want to Invert already inverted shader again.
    Can anyone please help me what shader code should I use from above?
     
  43. BloomyFractal

    BloomyFractal

    Joined:
    May 8, 2021
    Posts:
    16
    Hello, I'm a beginner and I'd like to know, how do you apply this script to a sprite of an empty circle for example ?

    EDIT: Figured it out :D ! First, make a new Material folder, and create a new material (I named mine "ReverseColor"). In the Shader option at the top of the Inspector window, click the dropdown menu and search the $dd_Invert shader script. Create an object with a mesh renderer component, and in the Materials array, change the 0th element to the ReverseColor material.
     
    Last edited: Sep 23, 2022