0
\$\begingroup\$

I'm new to shaders. I am trying to combine the blur shader and the grayscale shader. Here's what I have came up with so far:

Shader "Custom/blur_and_gray" {
 Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _BumpAmt  ("Distortion", Range (0,128)) = 10
        _MainTex ("Tint Color (RGB)", 2D) = "white" {}
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _Size ("Size", Range(0, 20)) = 1
        _MainTex ("Texture", 2D) = ""

    }

    Category {

        // We must be transparent, so other objects are drawn before this one.
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque" }
     ZWrite Off
    Blend SrcAlpha OneMinusSrcAlpha  

        SubShader {

            // Horizontal blur
            GrabPass {                     
                Tags { "LightMode" = "Always" }
            }
            Pass {
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                };

                v2f vert (appdata_t v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    return o;
                }

                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                float _Size;

                half4 frag( v2f i ) : COLOR {
//                  half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
//                  return col;

                    half4 sum = half4(0,0,0,0);

                    #define GRABPIXEL(weight,kernelx) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx*_Size, i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight

                    sum += GRABPIXEL(0.05, -4.0);
                    sum += GRABPIXEL(0.09, -3.0);
                    sum += GRABPIXEL(0.12, -2.0);
                    sum += GRABPIXEL(0.15, -1.0);
                    sum += GRABPIXEL(0.18,  0.0);
                    sum += GRABPIXEL(0.15, +1.0);
                    sum += GRABPIXEL(0.12, +2.0);
                    sum += GRABPIXEL(0.09, +3.0);
                    sum += GRABPIXEL(0.05, +4.0);

                    return sum;
                }
                ENDCG
            }

            // Vertical blur
            GrabPass {                         
                Tags { "LightMode" = "Always" }
            }
            Pass {
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                };

                v2f vert (appdata_t v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    return o;
                }

                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                float _Size;

                half4 frag( v2f i ) : COLOR {
//                  half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
//                  return col;

                    half4 sum = half4(0,0,0,0);

                    #define GRABPIXEL(weight,kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely*_Size, i.uvgrab.z, i.uvgrab.w))) * weight

                    //G(X) = (1/(sqrt(2*PI*deviation*deviation))) * exp(-(x*x / (2*deviation*deviation)))

                    sum += GRABPIXEL(0.05, -4.0);
                    sum += GRABPIXEL(0.09, -3.0);
                    sum += GRABPIXEL(0.12, -2.0);
                    sum += GRABPIXEL(0.15, -1.0);
                    sum += GRABPIXEL(0.18,  0.0);
                    sum += GRABPIXEL(0.15, +1.0);
                    sum += GRABPIXEL(0.12, +2.0);
                    sum += GRABPIXEL(0.09, +3.0);
                    sum += GRABPIXEL(0.05, +4.0);

                    return sum;
                }
                ENDCG
            }

            // Distortion
            GrabPass {                         
                Tags { "LightMode" = "Always" }
            }
            Pass {
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                    float2 uvbump : TEXCOORD1;
                    float2 uvmain : TEXCOORD2;
                };

                float _BumpAmt;
                float4 _BumpMap_ST;
                float4 _MainTex_ST;

                v2f vert (appdata_t v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
                    o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
                    return o;
                }

                fixed4 _Color;
                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                sampler2D _BumpMap;
                sampler2D _MainTex;

                half4 frag( v2f i ) : COLOR {
                    // calculate perturbed coordinates
                    half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x  y without reconstructing the Z
                    float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
                    i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;

                    half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
                    half4 tint = tex2D( _MainTex, i.uvmain ) * _Color;

                    return col * tint;
                }
                ENDCG
            }

            // gray
            GrabPass {                         
                Tags {"Queue"="Transparent"}
            }Pass {
                Tags {"Queue"="Transparent"}
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                struct v2f {
                    float4 position : SV_POSITION;
                    float2 uv_mainTex : TEXCOORD;
                };

                uniform float4 _MainTex_ST;
                v2f vert(float4 position : POSITION, float2 uv : TEXCOORD0) {
                    v2f o;
                    o.position = UnityObjectToClipPos(position);
                    o.uv_mainTex = uv * _MainTex_ST.xy + _MainTex_ST.zw;
                    return o;
                }

                uniform sampler2D _MainTex;
                fixed4 frag(float2 uv_mainTex : TEXCOORD) : COLOR {
                    fixed4 mainTex = tex2D(_MainTex, uv_mainTex);
                    fixed4 fragColor;
                    fragColor.rgb = dot(mainTex.rgb, fixed3(1.222, 1.707, 1.071));
                    fragColor.a = mainTex.a;
                    return fragColor;
                }
                ENDCG
            }
        }
    }
}

The problem with this code is that it's giving me only a white texture. here are the shadera I am using BLUR

Shader "Custom/SimpleGrabPassBlur" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,1)
        _BumpAmt  ("Distortion", Range (0,128)) = 10
        _MainTex ("Tint Color (RGB)", 2D) = "white" {}
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _Size ("Size", Range(0, 20)) = 1
    }

    Category {

        // We must be transparent, so other objects are drawn before this one.
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Opaque" }


        SubShader {

            // Horizontal blur
            GrabPass {                     
                Tags { "LightMode" = "Always" }
            }
            Pass {
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                };

                v2f vert (appdata_t v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    return o;
                }

                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                float _Size;

                half4 frag( v2f i ) : COLOR {
//                  half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
//                  return col;

                    half4 sum = half4(0,0,0,0);

                    #define GRABPIXEL(weight,kernelx) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx*_Size, i.uvgrab.y, i.uvgrab.z, i.uvgrab.w))) * weight

                    sum += GRABPIXEL(0.05, -4.0);
                    sum += GRABPIXEL(0.09, -3.0);
                    sum += GRABPIXEL(0.12, -2.0);
                    sum += GRABPIXEL(0.15, -1.0);
                    sum += GRABPIXEL(0.18,  0.0);
                    sum += GRABPIXEL(0.15, +1.0);
                    sum += GRABPIXEL(0.12, +2.0);
                    sum += GRABPIXEL(0.09, +3.0);
                    sum += GRABPIXEL(0.05, +4.0);

                    return sum;
                }
                ENDCG
            }

            // Vertical blur
            GrabPass {                         
                Tags { "LightMode" = "Always" }
            }
            Pass {
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                };

                v2f vert (appdata_t v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    return o;
                }

                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                float _Size;

                half4 frag( v2f i ) : COLOR {
//                  half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
//                  return col;

                    half4 sum = half4(0,0,0,0);

                    #define GRABPIXEL(weight,kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely*_Size, i.uvgrab.z, i.uvgrab.w))) * weight

                    //G(X) = (1/(sqrt(2*PI*deviation*deviation))) * exp(-(x*x / (2*deviation*deviation)))

                    sum += GRABPIXEL(0.05, -4.0);
                    sum += GRABPIXEL(0.09, -3.0);
                    sum += GRABPIXEL(0.12, -2.0);
                    sum += GRABPIXEL(0.15, -1.0);
                    sum += GRABPIXEL(0.18,  0.0);
                    sum += GRABPIXEL(0.15, +1.0);
                    sum += GRABPIXEL(0.12, +2.0);
                    sum += GRABPIXEL(0.09, +3.0);
                    sum += GRABPIXEL(0.05, +4.0);

                    return sum;
                }
                ENDCG
            }

            // Distortion
            GrabPass {                         
                Tags { "LightMode" = "Always" }
            }
            Pass {
                Tags { "LightMode" = "Always" }

                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma fragmentoption ARB_precision_hint_fastest
                #include "UnityCG.cginc"

                struct appdata_t {
                    float4 vertex : POSITION;
                    float2 texcoord: TEXCOORD0;
                };

                struct v2f {
                    float4 vertex : POSITION;
                    float4 uvgrab : TEXCOORD0;
                    float2 uvbump : TEXCOORD1;
                    float2 uvmain : TEXCOORD2;
                };

                float _BumpAmt;
                float4 _BumpMap_ST;
                float4 _MainTex_ST;

                v2f vert (appdata_t v) {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    #if UNITY_UV_STARTS_AT_TOP
                    float scale = -1.0;
                    #else
                    float scale = 1.0;
                    #endif
                    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                    o.uvgrab.zw = o.vertex.zw;
                    o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
                    o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
                    return o;
                }

                fixed4 _Color;
                sampler2D _GrabTexture;
                float4 _GrabTexture_TexelSize;
                sampler2D _BumpMap;
                sampler2D _MainTex;

                half4 frag( v2f i ) : COLOR {
                    // calculate perturbed coordinates
                    half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x  y without reconstructing the Z
                    float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
                    i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;

                    half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
                    half4 tint = tex2D( _MainTex, i.uvmain ) * _Color;

                    return col * tint;
                }
                ENDCG
            }
        }
    }
}

GRAY SCALE

Shader "RGB -> Grey Texture/Alpha Blended" {

Properties{
    _MainTex ("Texture", 2D) = ""
}

Subshader {
    Tags {"Queue"="Transparent"}
    ZWrite Off
    Blend SrcAlpha OneMinusSrcAlpha
    Pass {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        struct v2f {
            float4 position : SV_POSITION;
            float2 uv_mainTex : TEXCOORD;
        };

        uniform float4 _MainTex_ST;
        v2f vert(float4 position : POSITION, float2 uv : TEXCOORD0) {
            v2f o;
            o.position = UnityObjectToClipPos(position);
            o.uv_mainTex = uv * _MainTex_ST.xy + _MainTex_ST.zw;
            return o;
        }

        uniform sampler2D _MainTex;
        fixed4 frag(float2 uv_mainTex : TEXCOORD) : COLOR {
            fixed4 mainTex = tex2D(_MainTex, uv_mainTex);
            fixed4 fragColor;
            fragColor.rgb = dot(mainTex.rgb, fixed3(.000, .000, .000));//(.222, .707, .071));
            fragColor.a = mainTex.a;
            return fragColor;
        }
        ENDCG
    }
}

}

The problem is that they work fine individually, but they don't when combined togheter

\$\endgroup\$
4
  • \$\begingroup\$ Are you rendering this on a full-screen quad or blit pass, or is it on a piece of geometry that might be oriented in the scene, like you're looking through a "magic window" ? The more you can tell us about the ultimate effect you want to achieve, the better we can help - otherwise we might give you correct shader code for the wrong shader for your needs. ;) \$\endgroup\$
    – DMGregory
    Nov 30, 2017 at 13:16
  • \$\begingroup\$ I would prefer the magic window solution, as I basically attached to a mash renderer and whatever the mash covers will have the sharder effect applied. \$\endgroup\$ Nov 30, 2017 at 13:27
  • \$\begingroup\$ The geometry method is really hard to implement for the blur shader (I've tried this several times even with the examples unity provides and have not gotten any useful progress). I'll take a look at the examples when I get home, I'll probably get somewhere with the full-screen effect. \$\endgroup\$ Nov 30, 2017 at 14:06
  • \$\begingroup\$ the simpleGrabPassBlur example works just fine for me, however when I added in the Grayscale pass the whole thing just wont work ..., You can comment out the //Gray pass and you can see the blur works just fine by its own \$\endgroup\$ Nov 30, 2017 at 14:09

1 Answer 1

2
\$\begingroup\$

The answer to this one was actually surprisingly easy when I've gone through all the code in that seemingly huge blur shader. The only time it ever handles colors is at the bottom, with the col parameter. All I did was add three color channels together and then divide them by three, essentially making it grayscale.

Relevant part of the shader at the end:

half4 frag( v2f i ) : COLOR {
     // calculate perturbed coordinates
     half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg; // we could optimize this by just reading the x  y without reconstructing the Z
     float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
     i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;

     half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
     half4 tint = tex2D( _MainTex, i.uvmain ) * _Color;

     /*the part that I added
     * use the first line and comment the second for faster processing
     * use the second line and comment the first for better colors */
     //col.r = (col.r + col.g + col.b) / 3; 
     col.r = (col.r * 0.2126f + col.g * 0.7152f + col.b * 0.0722f); 
     col.g = col.r;
     col.b = col.r;

     return col * tint;
}
ENDCG

The result:

hopefully my images are getting uploaded

\$\endgroup\$
5
  • 3
    \$\begingroup\$ One alteration I’d suggest: instead of just averaging the three channels, use a perceptual-luminance-preserving combination of them as described here. In other words: col.r = col.r * 0.2126 + col.g * 0.7152 + col.b * 0.0722;. You might also need to go through the gamma conversions described in the linked article—I don’t know offhand whether Unity uses linear sRGB internally already. \$\endgroup\$ Dec 4, 2017 at 22:39
  • \$\begingroup\$ thanks man ! any ideal how to become an expert on sharder ? :( \$\endgroup\$ Dec 6, 2017 at 12:14
  • \$\begingroup\$ @user1998844 Nope, I just keep tweaking some numbers and playing with variables till I get something I want to change. I wouldn't be able to write this blur shader from scratch for example. Though I'm sure you'll get there if you keep at it. \$\endgroup\$ Dec 7, 2017 at 5:05
  • 1
    \$\begingroup\$ @NoahWitherspoon after some thorough investigation (also trial and error in Unity), I've come to the conclusion that your way is much better in terms of color result. So, I'm adding that to the answer as the better way to do it. \$\endgroup\$ Dec 15, 2017 at 18:42
  • \$\begingroup\$ This can also be expressed as col.rgb = dot(col.rgb, float3(0.2126f, 0.7152f, 0.0722f)); if you like. :) \$\endgroup\$
    – DMGregory
    Dec 15, 2017 at 22:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .