Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to use shaders in custom post effects

Discussion in 'General Graphics' started by SoftwareGeezers, Apr 28, 2015.

  1. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    Standard Assets comes with a number of image effects and shaders. I'd like to be able to create a custom image effect using some of the supplied shaders, such as an effect that uses the MobileBlur shader that implements an efficient Gaussian approximation. Ultimately, I want to create my own custom glow filter with specific controls.

    I have a working custom post effect based on this tutorial : http://armedunity.com/topic/5669-pro-only-how-to-make-custom-image-effects/

    If I replace the custom shader with one of Unity's, the post effect doesn't change.

    So how do I go about integrating an existing shader with a custom post effect? Examining the included assets, I can't actually find the reference to the shaders used. That is, the standard effect BloomOptimized references fastBloomShader as a field but doesn't actually assign it a value AFAICS.
     
  2. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    No-one knows? That these shaders are locked behind Unity's image effects assets and if you want to do something novel with them, you have to create image effects from scratch (without tutorials)?

    I know how to write shaders fine - that's been taught through the learning portal. Why is there no explanation of how to 'plug' them into Image Effects? No tutorials or even documentation AFAICS.
     
  3. Deleted User

    Deleted User

    Guest

    You could add this code to your js script:

    Code (JavaScript):
    1. var mat: Material;
    2.  
    3.     function OnRenderImage(src: RenderTexture, dest: RenderTexture) {
    4.         // Copy the source Render Texture to the destination,
    5.         // applying the material along the way.
    6.         Graphics.Blit(src, dest, mat);
    7.     }
    source:
    http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnRenderImage.html

    First, make new material with applied custom image shader.
    Second, apply script into Main Camera.

    You can read this:
    http://albertshih.blogspot.com/2013/06/getting-started-with-custom-post.html

    or buy Shader Forge asset to create custom shaders in easy way
    https://www.assetstore.unity3d.com/en/#!/content/14147:
     
    SoftwareGeezers likes this.
  4. SoftwareGeezers

    SoftwareGeezers

    Joined:
    Jun 22, 2013
    Posts:
    902
    Thanks. Between your links and the original tutorial, I can see how it works now. The simple OnRenderImage function applies the shader, and you have to set up suitable parameters to pass to the shaders with simple editor interfaces and material.SetFloat() etc. calls. Also, the shaders need to be moved from Hidden/.. to somewhere else like ImageFX/.. in order to apply the shaders to a material to the camera.

    It's worth noting that these shaders don't seem to be well refined for open use. One has a redundant material parameter for example, and the MobileBlur shader appears broken, affecting only the X direction.

    And €80 for ShaderForge just to make a simple post effect for a 2D sprite-based game is a bit pricey. ;)
     
    Last edited: Apr 30, 2015
  5. varfare

    varfare

    Joined:
    Feb 12, 2013
    Posts:
    227
    Here you go. Sample Camera script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SampleImageEffect: MonoBehaviour {
    5.     public Shader m_Shader = null;
    6.     private Material m_Material;
    7.    
    8.     void Start()
    9.     {  
    10.         if (m_Shader)
    11.         {
    12.             m_Material = new Material(m_Shader);
    13.             m_Material.name = "ImageEffectMaterial";
    14.             m_Material.hideFlags = HideFlags.HideAndDontSave;
    15.         }
    16.        
    17.         else
    18.         {
    19.             Debug.LogWarning(gameObject.name + ": Shader is not assigned. Disabling image effect.", this.gameObject);
    20.             enabled = false;
    21.         }
    22.     }
    23.    
    24.     void OnRenderImage(RenderTexture src, RenderTexture dst)
    25.     {
    26.         if (m_Shader && m_Material)
    27.         {
    28.             Graphics.Blit(src, dst, m_Material);
    29.         }
    30.        
    31.         else
    32.         {
    33.             Graphics.Blit(src, dst);
    34.             Debug.LogWarning(gameObject.name + ": Shader is not assigned. Disabling image effect.", this.gameObject);
    35.             enabled = false;
    36.         }
    37.     }
    38.    
    39.     void OnDisable()
    40.     {
    41.         if (m_Material)
    42.         {
    43.             DestroyImmediate(m_Material);
    44.         }
    45.     }
    46. }
    And a sample shader for this script. It does not alter the original image at all so you won't notice any changes. You will need to modify fragment program for that.
    Code (CSharp):
    1. Shader "Hidden/SampleImageEffect" {
    2.     Properties {
    3.         _MainTex ("Screen Texture", 2D) = "white" {}
    4.     }
    5.     SubShader {
    6.     Pass {
    7.        
    8.         CGPROGRAM
    9.         #pragma vertex vert
    10.         #pragma fragment frag
    11.         #pragma fragmentoption ARB_precision_hint_fastest
    12.         #include "UnityCG.cginc"
    13.        
    14.  
    15.         sampler2D _MainTex;
    16.         float4 _MainTex_TexelSize;
    17.  
    18.         struct v2f {
    19.             float4 vertex : SV_POSITION;
    20.             float2 uv     : TEXCOORD0;
    21.         };
    22.        
    23.         v2f vert (appdata_img v) {
    24.             v2f o;
    25.             #if UNITY_UV_STARTS_AT_TOP
    26.             if (_MainTex_TexelSize.y < 0)
    27.                     v.texcoord.y = 1-v.texcoord.y;
    28.             #endif
    29.            
    30.             o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    31.             o.uv = v.texcoord;
    32.            
    33.             return o;
    34.         }
    35.        
    36.         fixed4 frag (v2f i) : COLOR
    37.         {
    38.             fixed4 tex_screen = tex2D(_MainTex, i.uv);
    39.             return tex_screen;
    40.         }
    41.        
    42.         ENDCG
    43.         }
    44.     }
    45.    
    46. }
    47.  
     
    vivianmyoung and Psyco92 like this.