Search Unity

Camera that only sees 1 specific color

Discussion in 'Image Effects' started by Amuscaria, Oct 26, 2017.

  1. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    I'm new to unity and have to use it for a school project. I was wondering if there is a way to make the camera see only 1 color, while rendering everything else black. I've been looking thru documentation on Camera Textures, but I'm not sure what specific terminology I need to look up for the effect I want. Refer to the attached image:

    upload_2017-10-26_12-31-37.png

    The left is what the camera sees now. How do I make it so it only sees the magenta (255,0,255)? Is this even possible?

    Thanks in advance.
     
  2. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    If you're on a Desktop platform, the easiest way is to create simple post processing shader that just discards (paints black) all the pixels that are different from what you need.
     
  3. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    Yeah, that's chroma keying. (except in your case you'd take the inverse of it, discarding that the chroma filter matches).
    Take a look at how Open Broadcaster Software does it, they code is open source.
    Pretty sure that can easily be done in a post processing step.
     
  4. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    I am on PC, yes. I'll google those. Thanks all! :D
     
  5. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    After looking at some examples of Chromakey shaders, I tried my hand at writing once myself, just the reversed. But it's not working (get a black screen). I have this script on my camera that's supposed to use the camera's view as the texture:

    Code (csharp):
    1.  
    2. [ExecuteInEditMode]
    3. public class CameraTexture : MonoBehaviour
    4. {
    5.     public Material EffectMaterial;
    6.  
    7.     void OnRenderImage(RenderTexture src, RenderTexture dst)
    8.     {
    9.         Graphics.Blit(src, dst, EffectMaterial);
    10.     }
    11. }
    12.  
    here is the shader that's supposed to ignore all colors that isn't rgb(1,0,1):

    Code (csharp):
    1.  
    2.  
    3. Shader "Custom/ColorPicker"
    4. {
    5.      Properties {
    6.         _Color ("Color", Color) = (1,1,1,1)      
    7.          _VisableColor ("Visable Color", Color) = (1,0,1,1) //Sets the color that the camera picks up
    8.          _MainTex ("Albedo (RGB)", 2D) = "red" {}
    9.      }
    10.  
    11.      SubShader
    12.      {
    13.          Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    14.      
    15.          CGPROGRAM
    16.          #pragma surface surf Lambert alpha
    17.  
    18.          sampler2D _MainTex;
    19.  
    20.          struct Input
    21.          {
    22.              float2 uv_MainTex;
    23.          };
    24.  
    25.          fixed4 _VisableColor;
    26.  
    27.          void surf (Input IN, inout SurfaceOutput o)
    28.          {
    29.              half4 c = tex2D(_MainTex, IN.uv_MainTex); // Read color from the texture
    30.              half4 output_col = c;
    31.  
    32.               //ignores all colors that isn't pure megenta (1,0,1)
    33.              if(output_col.r != _VisableColor.r && output_col.g != _VisableColor.g && output_col.b != _VisableColor.b)
    34.                  discard;          
    35.          
    36.              //output albedo and alpha just like a normal shader
    37.              o.Albedo = output_col.rgb;
    38.              o.Alpha = output_col.a;
    39.          }
    40.          ENDCG
    41.      }
    42.      FallBack "Diffuse"
    43. }
    44.  
    I'm sure that the color i'm trying to pick is (1,0,1) from using the color pick to test the values. I've also placed the correct material with the shader onto the camera script. What am I doing wrong here? Thanks in advance. :)
     
    Last edited: Oct 27, 2017
  6. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    I rewrote the shader and its working a lot better now, but still having some strange problems:

    Code (csharp):
    1.  
    2.  
    3. Shader "Custom/ColorPicker"
    4. {
    5.     Properties
    6.     {
    7.         _MainTex ("Texture", 2D) = "white" {}
    8.         _VisableColor ("Visable Color", Color) = (1,0,1,1)
    9.     }
    10.     SubShader
    11.     {
    12.         // No culling or depth
    13.         Cull Off ZWrite Off ZTest Always
    14.  
    15.         Pass
    16.         {
    17.             CGPROGRAM
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.            
    21.             #include "UnityCG.cginc"
    22.  
    23.             struct appdata
    24.             {
    25.                 float4 vertex : POSITION;
    26.                 float2 uv : TEXCOORD0;
    27.             };
    28.  
    29.             struct v2f
    30.             {
    31.                 float2 uv : TEXCOORD0;
    32.                 float4 vertex : SV_POSITION;
    33.             };
    34.  
    35.             v2f vert (appdata v)
    36.             {
    37.                 v2f o;
    38.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    39.                 o.uv = v.uv;
    40.                 return o;
    41.             }
    42.            
    43.             sampler2D _MainTex;
    44.             float4 _VisableColor;
    45.  
    46.             float4 frag (v2f i) : SV_Target
    47.             {
    48.                 float4 col = tex2D(_MainTex, i.uv);
    49.  
    50.                 if(col.r != _VisableColor.r && col.g != _VisableColor.g && col.b != _VisableColor.b)
    51.                 discard;          
    52.  
    53.                 return col;
    54.             }
    55.             ENDCG
    56.         }
    57.     }
    58. }
    59.  
    It does pick out the magenta from the camera, but if I move the camera, the magenta sections of the previous instant sticks around. Not sure what is up, but it's in the right direction. :)
     
  7. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    Modified the code a bit. Replaced the frag function with this:

    Code (csharp):
    1.  
    2. float4 frag (v2f i) : SV_Target
    3.             {
    4.                 float4 col = tex2D(_MainTex, i.uv);
    5.                
    6.                 if((col.r != _VisableColor.r) && (col.g != _VisableColor.g) && (col.b != _VisableColor.b))
    7.                 col -= float4 (1,1,1,1); //sets all non-magenta pixels to invisible
    8.  
    9.                 if((col.r == _VisableColor.r) && (col.g == _VisableColor.g) && (col.b == _VisableColor.b))
    10.                 col += float4 (1,1,1,1); //sets all magenta pixels to white
    11.  
    12.                 return col;
    13.             }
    14.  
    Which works a lot better. And works the way I want if not for the light in the scene. If I delete the light, it works high. But if I leave the light in, it renders the highlights on top of the image, which is not what I want. Here's what I mean:

    upload_2017-10-27_11-24-55.png

    The left is what I want, and what I get when the light is off. But if I have the light on, when I get the right. I'm assuming it has something to do with the rendering queue, but am unsure. An ideas? Thanks.
     
  8. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    Do you have several cameras rendering? Or do you have just one?
     
  9. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    Two cameras right now. One normal camera for the overiew, and just 1 camera to see the cross section with the special reverse-chroma key shader as well. I managed to bypass the problem by just having a set of invisible models that can only be see by the second camera that has no light. Which is what I want. Here's what I have currently, and its working decently:

     
    Last edited: Oct 30, 2017
  10. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    So you actually need to display intersections between models?
     
  11. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    Yup. That's what I'm using to generate the stencil looking fake ultrasound image. I don't know of any other way to make a intersection come up. If there is a better way, lemme know, but this is all I can figure out for now, and it seems to be "good enough".

    BTW, related to this school project. Is it possible use 2 mouse at the same time in Unity to control the same object? If so, how would I map the buttons in script? How would I differentiate between the two?
     
  12. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    I'm pretty sure I've seen a lot of these intersection shaders already, but a quick search didn't yield any usable results. Try searching for "Unity intersection shader" or something like that.

    I'm not sure that this is even possible on Windows. If you connect two mice to the same PC, they will both control the same cursor, so Windows thinks that those two mice are just one mouse. So there's nothing Unity-specific here, if something needs to be researched, it's the OS in the first place.
    I think gamepad (Xbox360 one or basically any USB-Wireless gamepad) may be better for controlling something in your project, and it (as well as OS itself) supports several gamepads simultaneously.
     
    Last edited: Oct 31, 2017
  13. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    Ah ok. Thanks for the heads up. Guess I'll just stick with the keyboard and get a mouse with more than 3 buttons.
     
  14. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
  15. Amuscaria

    Amuscaria

    Joined:
    May 30, 2017
    Posts:
    55
    That's actually what I'm using, lol, just modified a bit.

    Another question. Is it possible to overlay the render from 1 camera ontop of another with additive rendering. Would I need a shader for that, or is there a easier way?

    EDIT: I think I cna just use 2 cameras, render out 2 cameraTextures, and then use a shader to additively combined them onto a third camera. At least that's the logic. Hope I'm going in the right direction.
     
    Last edited: Oct 31, 2017