• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by DMatson · Feb 26, 2013 at 11:13 PM · shader

Gaussian Blur Shader

I'm attempting to do a 3-pass gaussian blur shader on a texture. The first pass is a horizontal blur, the second pass is a vertical blur, and the third pass is to draw the original image back on top of the two blurred versions. The result I am looking for is what I would describe as a yellow outer glow effect.

I think I am running into a problem because of my grab pass which passes the result of the first shader to the second. The second pass seems to be flipped (and smaller). If I negate the Y-value passed to tex2D() in the second pass I don't see the flipped version anymore but I also don't see the vertical blur that I'm expecting. I'm also curious as to why the background of the final texture appears to have a slight yellow tint to it (the original texture has an entirely transparent background).

What am I doing wrong?

alt text

Here is my shader code:

 Shader "Custom/GaussianBlur"
 {
     Properties
     {
         _MainTex ("Texture", 2D) = "white" { }     
     }
 
     SubShader
     {
         // Horizontal blur pass
         Pass
         {
             Blend SrcAlpha OneMinusSrcAlpha 
             Name "HorizontalBlur"
 
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag            
             #include "UnityCG.cginc"
             
             sampler2D _MainTex;
             
             struct v2f
             {
                 float4  pos : SV_POSITION;
                 float2  uv : TEXCOORD0;
             };
             
             float4 _MainTex_ST;
             
             v2f vert (appdata_base v)
             {
                 v2f o;
                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                 return o;
             }
             
             half4 frag (v2f i) : COLOR
             {
                 float blurAmount = 0.0075;
 
                 half4 sum = half4(0.0);
 
                 sum += tex2D(_MainTex, float2(i.uv.x - 5.0 * blurAmount, i.uv.y)) * 0.025;
                 sum += tex2D(_MainTex, float2(i.uv.x - 4.0 * blurAmount, i.uv.y)) * 0.05;
                 sum += tex2D(_MainTex, float2(i.uv.x - 3.0 * blurAmount, i.uv.y)) * 0.09;
                 sum += tex2D(_MainTex, float2(i.uv.x - 2.0 * blurAmount, i.uv.y)) * 0.12;
                 sum += tex2D(_MainTex, float2(i.uv.x - blurAmount, i.uv.y)) * 0.15;
                 sum += tex2D(_MainTex, float2(i.uv.x, i.uv.y)) * 0.16;
                 sum += tex2D(_MainTex, float2(i.uv.x + blurAmount, i.uv.y)) * 0.15;
                 sum += tex2D(_MainTex, float2(i.uv.x + 2.0 * blurAmount, i.uv.y)) * 0.12;
                 sum += tex2D(_MainTex, float2(i.uv.x + 3.0 * blurAmount, i.uv.y)) * 0.09;
                 sum += tex2D(_MainTex, float2(i.uv.x + 4.0 * blurAmount, i.uv.y)) * 0.05;
                 sum += tex2D(_MainTex, float2(i.uv.x + 5.0 * blurAmount, i.uv.y)) * 0.025;
 
                 sum.r = 1.0;
                 sum.g = 1.0;
                 sum.b = 0.0;
 
                 return sum;
             }
             ENDCG
         }
         
         GrabPass { }
 
         // Vertical blur pass
         Pass
         {
             Blend SrcAlpha OneMinusSrcAlpha
             Name "VerticalBlur"
                         
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag            
             #include "UnityCG.cginc"
 
             sampler2D _GrabTexture : register(s0);
 
             struct v2f 
             {
                 float4  pos : SV_POSITION;
                 float2  uv : TEXCOORD0;
             };
 
             float4 _GrabTexture_ST;
 
             v2f vert (appdata_base v)
             {
                 v2f o;
                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                 o.uv = TRANSFORM_TEX(v.texcoord, _GrabTexture);
                 return o;
             }
 
             half4 frag (v2f i) : COLOR
             {
                 float blurAmount = 0.0075;
 
                 half4 sum = half4(0.0);
 
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y - 5.0 * blurAmount)) * 0.025;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y - 4.0 * blurAmount)) * 0.05;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y - 3.0 * blurAmount)) * 0.09;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y - 2.0 * blurAmount)) * 0.12;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y - blurAmount)) * 0.15;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y)) * 0.16;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y + blurAmount)) * 0.15;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y + 2.0 * blurAmount)) * 0.12;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y + 3.0 * blurAmount)) * 0.09;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y + 4.0 * blurAmount)) * 0.05;
                 sum += tex2D(_GrabTexture, float2(i.uv.x, i.uv.y + 5.0 * blurAmount)) * 0.025;
 
                 sum.r = 1.0;
                 sum.g = 1.0;
                 sum.b = 0.0;
 
                 return sum;
             }
             ENDCG
         }
 
         // Original image pass
         Pass
         {
             ZWrite Off
              Blend SrcAlpha OneMinusSrcAlpha
 
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             #include "UnityCG.cginc"
             sampler2D _MainTex;
             struct v2f
             {
                 float4  pos : SV_POSITION;
                 float2  uv : TEXCOORD0;
                 float2 depth : TEXCOORD1;
             };
 
             float4 _MainTex_ST;
             v2f vert (appdata_base v)
             {
                 v2f o;
                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                 UNITY_TRANSFER_DEPTH(o.depth);
                 o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
                 return o;
             }
 
             half4 frag (v2f i) : COLOR
             {
                 half4 originalPixel = half4(0.0);
                 originalPixel = tex2D(_MainTex, float2(i.uv.x, i.uv.y));
 
                 return originalPixel;
             }
             ENDCG
         }
     }
 
     Fallback "VertexLit"
 }
capture.png (35.3 kB)
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Prank1710 · Sep 22, 2014 at 09:32 PM 0
Share

Were you able to solve these issues? I am having similar problems and I would love to know the solution to them.

avatar image hicks · Dec 16, 2015 at 08:56 AM 0
Share

GrabPass reads the color buffer (everything behind that object). This includes the skybox or solid color. The yellow tint should go away if you set the clear color to be fully transparent.

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by FuzzyQuills · Feb 07, 2014 at 12:22 AM

For the yellowing, it appears you have told the shader to yellow the blur in each pass. here's where you went wrong:

 sum.r = 1.0
 sum.g = 1.0
 sum.b = 0.0

For the blurring, count the code lines that do the blurring, then divide the result color by the number of lines. Example:

 sum += (whatever you do to blur the texture)
 sum = sum / (number of times you did the above)

this will give the same colour, but with blurring!

just remove those lines and the yellowing should go. as for flipped textures, i am so sure i saw something in the manual describing this issue and it having something to do with multiple renderTextures and having AA turned on. in this case, you could flip the texture using this in your vertex shader (this was taken from the unity manual):

 // On D3D when AA is used, the main texture & scene depth texture
 // will come out in different vertical orientations.
 // So flip sampling of the texture when that is the case (main texture
 // texel size will have negative Y).
 #if UNITY_UV_STARTS_AT_TOP
 if (_MainTex_TexelSize.y < 0)
         uv.y = 1-uv.y;
 #endif

Then try testing the shader. if the shader comes out right, it's fixed! hope this is useful.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by monotoan · Mar 22, 2017 at 06:39 PM

In case anyone's still looking, here's a Gaussian blur function I wrote for Unity shaders by cleaning up above code and combining it with mrharicot's gaussian blur shader on Shadertoy:

 //normpdf function gives us a Guassian distribution for each blur iteration; 
 //this is equivalent of multiplying by hard #s 0.16,0.15,0.12,0.09, etc. in code above
 float normpdf(float x, float sigma)
 {
     return 0.39894*exp(-0.5*x*x / (sigma*sigma)) / sigma;
 }

 //this is the blur function... pass in standard col derived from tex2d(_MainTex,i.uv)
 half4 blur(sampler2D tex, float2 uv,float blurAmount) {

     //get our base color...
     half4 col = tex2D(tex, uv);

     //total width/height of our blur "grid":
     const int mSize = 11;

     //this gives the number of times we'll iterate our blur on each side 
     //(up,down,left,right) of our uv coordinate;
     //NOTE that this needs to be a const or you'll get errors about unrolling for loops
     const int iter = (mSize - 1) / 2;

     //run loops to do the equivalent of what's written out line by line above
     //(number of blur iterations can be easily sized up and down this way)
     for (int i = -iter; i <= iter; ++i) {
         for (int j = -iter; j <= iter; ++j) {
             col += tex2D(tex, float2(uv.x + i * blurAmount, uv.y + j * blurAmount)) * normpdf(float(i), 7);
            }
     }

     //return blurred color
     return col/mSize;
 }


Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

14 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to force the compilation of a shader in Unity? 4 Answers

Shader Replacement Error 0 Answers

Vertex Noise Shader Mismatch on Different Computers 0 Answers

Texture2D to Texture3D 2 Answers

Unity GLSL shader - getting screen coordinates 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges