Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

color replacement shader

Discussion in 'Shaders' started by felsi, Apr 16, 2015.

  1. felsi

    felsi

    Joined:
    Jul 3, 2013
    Posts:
    15
    Hello!

    I try to achieve a comic-style look with simple animations by changing the color.
    Therefor i wrote (copied) a very simple subshader with 2 textures.
    The first one is a grayscale image and the second one maps the gray-values to color-values. (y: gray-value, x:timeline)

    Code (CSharp):
    1. Shader "Cg shader using blending" {
    2.     Properties {
    3.         _MainTex ("Greyscale (R) Alpha (A)", 2D) = "white" {}
    4.         _ColorRamp ("Colour Palette", 2D) = "gray" {}
    5.         _SampleTime ("Sample Time", Float) = 0.0
    6.         }
    7.        
    8.    SubShader {
    9.       Tags { "Queue" = "Transparent" }
    10.          // draw after all opaque geometry has been drawn
    11.       Pass {
    12.          ZWrite Off // don't write to depth buffer
    13.             // in order not to occlude other objects
    14.          Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
    15.          CGPROGRAM
    16.          #pragma vertex vert
    17.          #pragma fragment frag
    18.         #pragma fragmentoption ARB_precision_hint_fastest
    19.         #include "UnityCG.cginc"
    20.      
    21.         struct v2f
    22.         {
    23.             float4  pos : SV_POSITION;
    24.             float2  uv : TEXCOORD0;
    25.         };
    26.  
    27.         v2f vert (appdata_tan v)
    28.         {
    29.             v2f o;
    30.             o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    31.             o.uv = v.texcoord.xy;
    32.             return o;
    33.         }
    34.      
    35.         sampler2D _MainTex;
    36.         sampler2D _ColorRamp;
    37.         float _SampleTime;
    38.         float4 frag(v2f i) : COLOR
    39.         {
    40.         // SURFACE COLOUR
    41.             float greyscale = tex2D(_MainTex, i.uv).r;
    42.      
    43.         // RESULT
    44.             float4 result;
    45.             result = tex2D(_ColorRamp, float2(_SampleTime, greyscale));
    46.             //result.a = tex2D(_MainTex, i.uv).a;
    47.             return result;
    48.         }
    49.          ENDCG
    50.       }
    51.    }
    52. }
    The first problem was the antialiasing of the png, which i solved.
    Unfortunately there remains an artefact between the colors.



    This is especially annoying when i use transparency or when i want to "hide" an element by using the same color...
    If anyone can give me a hint to solve this, i would be very glad.

    Thank you very much for reading this :)
     
  2. felsi

    felsi

    Joined:
    Jul 3, 2013
    Posts:
    15
    I found a solution...
    Now i use the r, g and b channels of the image to seperate the different regions.
    I want at least 6 different regions, so i use 2 textures and one for color mapping.

    Code (CSharp):
    1. Shader "ColorReplacment" {
    2.     Properties {
    3.         _ColorRamp ("Color Ramp", 2D) = "gray" {}
    4.         _MainTex1 ("Main Texture 1", 2D) = "white" {}
    5.         _MainTex2 ("Main Texture 2", 2D) = "white" {}
    6.         }
    7.      
    8.    SubShader {
    9.       Tags { "Queue" = "Transparent" }
    10.          // draw after all opaque geometry has been drawn
    11.       Pass {
    12.          //ZWrite Off
    13.        
    14.          Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
    15.          CGPROGRAM
    16.          #pragma vertex vert
    17.          #pragma fragment frag
    18.  
    19.         #include "UnityCG.cginc"
    20.  
    21.         sampler2D _MainTex1;
    22.         sampler2D _MainTex2;
    23.         sampler2D _ColorRamp;      
    24.         half _SampleTime;
    25.      
    26.         v2f_img vert(appdata_base v)
    27.         {
    28.             v2f_img o;
    29.             o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    30.             o.uv = v.texcoord.xy;
    31.             return o;
    32.         }
    33.         fixed4 frag(v2f_img i) : COLOR
    34.         {
    35.         // Surface
    36.             fixed4 main1 = tex2D(_MainTex1, i.uv);
    37.             fixed4 main2 = tex2D(_MainTex2, i.uv);
    38.      
    39.         // RESULT
    40.             fixed4 result1 = tex2D(_ColorRamp, half2(_SampleTime,half(0.0625))) * main1.r + tex2D(_ColorRamp, half2(_SampleTime,half(0.4375))) * main2.r;
    41.             fixed4 result2 = tex2D(_ColorRamp, half2(_SampleTime,half(0.1875))) * main1.g + tex2D(_ColorRamp, half2(_SampleTime,half(0.5625))) * main2.g;
    42.             fixed4 result3 = tex2D(_ColorRamp, half2(_SampleTime,half(0.3125))) * main1.b + tex2D(_ColorRamp, half2(_SampleTime,half(0.6875))) * main2.b;
    43.  
    44.             fixed4 result = result1 + result2 + result3;
    45.  
    46.             return result;
    47.         }
    48.        ENDCG
    49.    }
    50.    }
    51. }
    52.  
    53.  
    This also solved the problem with the antialiasing.
    But i guess, this is not the best solution for what i want to do.
    So, if anybody has a better approach...