Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • 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
1
Question by jrc03c · Oct 20, 2015 at 06:58 PM · shadersimage effectscameras

Chain multiple custom camera image effects?

UPDATE: I've added the shader code to the post. Sorry that it makes the post so long!

I wrote my own custom camera image effects. Individually, they work great. Unfortunately, if I add more than two to the camera, only the last effect is applied. I pored over the documentation for OnRenderImage (link), which says this:

When there are multiple image filters attached to the camera, they process image sequentially, by passing first filter's destination as the source to the next filter.

But for some reason, this isn't working for me. Can you think of any reasons why I can't chain my custom effects together? I've posted the source for the C# scripts below. (NOTE: I also tried inheriting my scripts from the ImageEffectBase class in the UnityStandardAssets.ImageEffects namespace, but it didn't fix anything.) Thanks!

JoshImageEffect.cs (base class)

 using UnityEngine;
 using System.Collections;
 
 public class JoshImageEffect : MonoBehaviour {
     public Shader shader;
 
     protected Material _material;
     protected Material material{
         get {
             if (!_material) _material = new Material(shader);
             return _material;
         }
     }
 
     void OnDisable(){
         Destroy(material);
     }
 
     public virtual void OnRenderImage(RenderTexture src, RenderTexture dst){
         Graphics.Blit(src, dst, material);
     }
 }

TintImageEffect.cs (inherits from JoshImageEffect)

 using UnityEngine;
 using System.Collections;
 
 public class TintImageEffect : JoshImageEffect {
     public Color tint;
     public float intensity;
 
     void Awake(){
         material.SetColor("_Tint", tint);
         material.SetFloat("_Intensity", intensity);
     }
 }

PixellatorImageEffect.cs (inherits from JoshImageEffect)

 using UnityEngine;
 using System.Collections;
 
 public class PixellatorImageEffect : JoshImageEffect {
     public Vector2 grid;
 
     void Awake(){
         material.SetVector("_Grid", new Vector4(grid.x, grid.y, 0, 0));
     }
 }

GhostImageEffect.cs (inherits from JoshImageEffect)

 using UnityEngine;
 using System.Collections;
 
 public class GhostImageEffect : JoshImageEffect {
     public int iterations;
     public float radius;
     public float timeScale;
     public float shadowBrightness;
     public float overallBrightness;
 
     void Awake(){
         material.SetFloat("_Iterations", iterations);
         material.SetFloat("_Radius", radius);
         material.SetFloat("_TimeScale", timeScale);
         material.SetFloat("_ShadowBrightness", shadowBrightness);
         material.SetFloat("_Brightness", overallBrightness);
     }
 }

TintShader.shader

 Shader "Custom/TintShader" {
     Properties {
         _MainTex ("Texture", 2D) = "white" {}
         _Tint ("Tint", Color) = (1, 1, 1, 1)
         _Intensity ("Intensity", Float) = 0.1
     }
     
     SubShader {
         Pass {
             CGPROGRAM
             
             #pragma vertex vert_img
             #pragma fragment frag
             #include "UnityCG.cginc"
             
             uniform sampler2D _MainTex;
             uniform float4 _Tint;
             uniform float _Intensity;
             
             float4 frag(v2f_img i) : COLOR {
                 float4 col = tex2D(_MainTex, i.uv);
                 return lerp(col, _Tint, _Intensity);
             }
             
             ENDCG
         }
     }
     
     FallBack Off
 }

PixellatorShader.shader

 Shader "Custom/PixellatorShader" {
     Properties {
         _MainTex ("Texture", 2D) = "white" {}
         _Grid ("Grid", Vector) = (0.02, 0.02, 0, 0)
     }
     
     SubShader {
         Pass {
             CGPROGRAM
             
             #pragma vertex vert_img
             #pragma fragment frag
             #include "UnityCG.cginc"
             
             uniform sampler2D _MainTex;
             uniform float4 _Grid;
             
             float4 frag(v2f_img i) : COLOR{
                 float u = ((i.uv.x / _Grid.x) - fmod(i.uv.x, _Grid.x)/(_Grid.x)) * _Grid.x;
                 float v = ((i.uv.y / _Grid.y) - fmod(i.uv.y, _Grid.y)/(_Grid.y)) * _Grid.y;
                 float4 col = tex2D(_MainTex, float2(u, v));
                 return col;
             }
             
             ENDCG
         }
     }
 }

GhostShader.shader

 Shader "Custom/GhostShader" {
     Properties {
         _MainTex ("Main Texture", 2D) = "white" {}
         _Iterations ("Iterations", Float) = 10
         _Radius ("Radius", Float) = 0.01
         _TimeScale ("Time Scale", Float) = 0.1
         _ShadowBrightness ("Shadow Brightness", Float) = 500
         _Brightness ("Overall Brightness", Float) = 0.5
     }
     
     SubShader {
         Pass {
             CGPROGRAM
             
             #pragma vertex vert_img
             #pragma fragment frag
             #include "UnityCG.cginc"
             
             uniform sampler2D _MainTex;
             uniform float _Iterations;
             uniform float _Radius;
             uniform float _TimeScale;
             uniform float _ShadowBrightness;
             uniform float _Brightness;
             
             float4 frag(v2f_img i) : COLOR {
                 float4 col = tex2D(_MainTex, i.uv);
                 
                 for (int c=0; c<_Iterations; c++){
                     float x = _Time.y * _TimeScale + c;
                     float xOffset = sin(x*x*x + x*x + x) * _Radius;
                     float yOffset = sin(x*x*x - x*x - x) * _Radius;
                     float2 off = float2(xOffset, yOffset);
                     col += mul(tex2D(_MainTex, i.uv + off), _ShadowBrightness * pow(length(off), 2));
                 }
                 
                 return mul(col, _Brightness);
             }
             
             ENDCG
         }
     }
     
     FallBack Off
 }

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 Bunny83 · Oct 20, 2015 at 07:22 PM 0
Share

Since you have your shader as public variable, are you sure you assigned the correct shader for each image effect? Tried Debug.Log() inside your OnRenderImage callback? You could print the classname to see which one are actually called:

 Debug.Log("ImageEffect: " + GetType().Name);

I don't see a reason why it shouldn't work. If all your images effects are executed the problem is more likely in your shader code which you haven't posted.

avatar image jrc03c Bunny83 · Oct 20, 2015 at 08:19 PM 0
Share

I have now double-checked that I have the right shaders in the right scripts. That does not seem to be the source of the problem.

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Oct 20, 2015 at 08:00 PM

As said in my comment there has to be something wrong with your shaders. I just created two simple shaders, one that inverts the colors (the unaltered image-effect- template shader) and one that simply adds a bit red to the whole color. I also created a script which basically is identical to your "JoshImageEffect" script.

I attached this script two times to my camera and set my two shaders in the public variables. The resulting image has inverted colors and a red touch.

If i swap the two instances (I moved the second one up in the context menu) I get inverted colors and a blue-green touch instead since the red touch is added first and then the colors are inverted. So on my side it works as it should.

edit

So after a long try and error session it turns out that the shader were missing those important settings in the subshader:

 // the culling isn't that important.
 Cull Off
 ZWrite Off
 ZTest Always

More details in the comments below ^^.

Comment
Add comment · Show 9 · 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 jrc03c · Oct 20, 2015 at 08:18 PM 0
Share

As I said in my question, the scripts work for two effects, but not for more. Did you try more than two? Also, I've posted the shader code; maybe you can help me spot errors there.

avatar image Bunny83 jrc03c · Oct 21, 2015 at 12:18 AM 0
Share

Well, i just added 4 scripts (though just with the two test shaders) and all 4 are working as expected. I can even enable / disable them and rearrange the order at runtime and get the expected result.

However i exchanged 2 of my shaders with your pixellator and the ghost shader. So i have those effects:

  • color invert

  • add 0.5 red

  • pixellator

  • ghost

This works fine. However If i disable the first one strange things happens. Basically all effects have no effect except the last one. But additionally the image is flipped upside down. It get's even stranger ^^. If i also disable the second effect the remaining two start working again and the image is up right. If i enable the first one again only the last one works and the image is flipped again.

If the first two are enabled i can properly disable the last two and get the correct result. This almost "feels" like some sort if internal bitmask madness which goes horrible wrong at some point. Everything seems to depend on the 3rd image effect if i disable it i can set any combination on the others without problems.

It get's totally messed up with 5 effects:

  • color invert

  • add 0.5 red

  • second add 0.5 red

  • ghost

  • pixellator

If all are enabled, only the color invert, one of the "add red" and the pixellator works. The second red and the ghost shader do not work. Now it get's funny: If i disable the ghost shader all effects are working (except the ghost of course). Same when i disable the pixellator. So with all i mean the second "add red" is now working as well....

I think i will setup some simple, easy to follow example project and file a bug report. This feature seems to be completely broken ^^.

I've found those issues which might be related:

https://issuetracker.unity3d.com/issues/screen-flips-upside-down-with-non-native-full-screen-resolution

http://issuetracker.unity3d.com/issues/bad-rendering-in-editor-when-disabling-slash-enabling-the-image-effect-script

If the first link applies to our problem, it might be already fixed in the next release. However since that's the only issues i've found it looks like they don't have enough data to reproduce the problem. So sending in more bug reports certainly will help. If you send a bug report you might want to include a link to your question here.

avatar image Bunny83 jrc03c · Oct 21, 2015 at 12:35 AM 0
Share

Just added a Debug.Log to the "OnRenderImage" callback and it looks like all 5 are called in my last test. So even they are called and execute the Blit some don't work in some cases...

avatar image Bunny83 jrc03c · Oct 21, 2015 at 01:34 AM 0
Share

Apart from all the bugs in Unity, there are some improvements in your shaders. In the pixellator you can simply do:

 float u = (i.uv.x  - fmod(i.uv.x, _Grid.x) );
 float v = (i.uv.y  - fmod(i.uv.y, _Grid.y) );

All the dividing and multiplying cancels out.

In your ghost shader i'm not sure why you use the "mul" operator which is a matrix multiplication. You treat your color vector as a 4x1 matrix and multiply it with a 1x1 matrix to get back a 1x4 matrix. I'm not sure if that has an impact on performance but i simply haven't ever seen someone using it for vector scaling. You can ins$$anonymous$$d simply multiply them together. Also "pow" is one of the most expensive function. It might have a shortcut for the power of 2 but since you just want to square the length or a vector you can simply do a "dot" with itself that gives you the squared length:

 col += tex2D(_$$anonymous$$ainTex, i.uv + off) * _ShadowBrightness * dot(off, off);
 // ...
 return col * _Brightness;

Show more comments
avatar image jrc03c · Oct 25, 2015 at 01:18 PM 0
Share

Dang, @Bunny83! Thanks for going to so much trouble! I'll have some free time later today and I'll try out your stuff. Thanks!

avatar image jrc03c · Oct 27, 2015 at 03:50 PM 0
Share

Yes, it was the culling and depth-testing and -writing that were the problem! Thanks!

avatar image Andrew-Le · Jun 02, 2019 at 04:47 PM 0
Share

Hi! I have the same problems. I write 2 image effects script, use OnPreRender & OnPostRender, attached to the main camera. Which one has a higher order in inspector won't be triggered? How could you solve the problems? Thanks!

avatar image Bunny83 Andrew-Le · Jun 03, 2019 at 12:14 AM 0
Share

Have you actually read the last bit in my answer?

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.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Blacksmith Atmospheric Scattering failing in Unity 5.5 2 Answers

How to get picked worldposition to clipspace, in fragment shader? (Image effect shader) 0 Answers

Is it possible to create a scrolling texture as an image effect (shader)? 2 Answers

Image Effects in URP (Shadergraph) 1 Answer

How to Partially Blur an Object 0 Answers


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