BloomEffect

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Added effect amount control)
m (Text replace - "</csharp>" to "</syntaxhighlight>")
 
(5 intermediate revisions by 3 users not shown)
Line 5: Line 5:
 
Author: Jonathan Czeck (aarku)
 
Author: Jonathan Czeck (aarku)
 
==Description==
 
==Description==
This script makes areas of white alpha glow.  The amount of effect and the blurryness of the glow can be controlled by the two public variables of the script.
+
'''This script is made obsolete by the GlowEffect shipped with Unity 1.5.'''  This script makes areas of white alpha glow.  The amount of effect and the blurryness of the glow can be controlled by the two public variables of the script.
 
[[Image:OverWhelmedArenaBloom.jpg|thumb|A test of OverWhelmed Arena by Graveck Interactive showing the bloom effect.  The effect had not been tweaked and as a result there are serious graphical problems, but the bloom effect is sound.]]
 
[[Image:OverWhelmedArenaBloom.jpg|thumb|A test of OverWhelmed Arena by Graveck Interactive showing the bloom effect.  The effect had not been tweaked and as a result there are serious graphical problems, but the bloom effect is sound.]]
  
Line 16: Line 16:
  
 
==C# - BloomEffect.cs==
 
==C# - BloomEffect.cs==
<csharp>using UnityEngine;
+
<syntaxhighlight lang="csharp">using UnityEngine;
 
using System.Collections;
 
using System.Collections;
  
Line 85: Line 85:
 
     // Function that actually renders the screenspace passes, offsetting the texture coordinates
 
     // Function that actually renders the screenspace passes, offsetting the texture coordinates
 
     // based one the size of the screen.
 
     // based one the size of the screen.
     public static void FourTapCone (RenderTexture source, Rect sourceRect, RenderTexture dest, Rect destRect) {
+
     public static void FourTapCone (RenderTexture source, Rect sourceRect, RenderTexture dest, Rect destRect, int iteration) {
  
 
         RenderTexture.active = dest;
 
         RenderTexture.active = dest;
 
         source.SetGlobalShaderProperty ("__RenderTex");
 
         source.SetGlobalShaderProperty ("__RenderTex");
  
         float offsetX = .5F / (float)source.width;
+
         float offsetX = (.5F+iteration) / (float)source.width;
         float offsetY = .5F / (float)source.height;
+
         float offsetY = (.5F+iteration) / (float)source.height;
 +
       
 
         GL.PushMatrix ();
 
         GL.PushMatrix ();
 
         GL.LoadOrtho ();     
 
         GL.LoadOrtho ();     
Line 188: Line 189:
 
         for(int i = 0; i < blurLevels; i++) {
 
         for(int i = 0; i < blurLevels; i++) {
 
             if(oddEven) {
 
             if(oddEven) {
                 FourTapCone (buffer, new Rect (0,0,1,1), buffer2, new Rect (0,0,1,1));
+
                 FourTapCone (buffer, new Rect (0,0,1,1), buffer2, new Rect (0,0,1,1), i);
 
                 oddEven = false;
 
                 oddEven = false;
 
             } else {
 
             } else {
                 FourTapCone (buffer2, new Rect (0,0,1,1), buffer, new Rect (0,0,1,1));
+
                 FourTapCone (buffer2, new Rect (0,0,1,1), buffer, new Rect (0,0,1,1), i);
 
                 oddEven = true;
 
                 oddEven = true;
 
             }
 
             }
Line 223: Line 224:
 
     }
 
     }
  
}</csharp>
+
}</syntaxhighlight>

Latest revision as of 20:44, 10 January 2012

Author: Jonathan Czeck (aarku)

[edit] Description

This script is made obsolete by the GlowEffect shipped with Unity 1.5. This script makes areas of white alpha glow. The amount of effect and the blurryness of the glow can be controlled by the two public variables of the script.

A test of OverWhelmed Arena by Graveck Interactive showing the bloom effect. The effect had not been tweaked and as a result there are serious graphical problems, but the bloom effect is sound.

[edit] Usage

This script (and all image effects) use render textures by need and therefore require Unity Pro. There isn't a way around this!

Set your scene view to show the alpha channel of your scene. This is a menu in your scene view. Then, set up your scene so that areas you want to glow are white and areas that you do not want to glow are black, and anywhere inbetween. For most shaders, you can alter this by either including an alpha channel in your texture, or by altering the material's main color's alpha. Some shaders will even put the specular highlights (gloss) in the alpha, so that glints of light will glow. This should work with most if not all of the regular default shaders, but that does not seem to be the case as of Unity 1.2.2. Make sure to also set the alpha of the tint color in your skybox to an appropriate value. This means that you can even change the amount of skybox glow at runtime just like "Shadow Of The Colossus"!

When you are done setting up your scene, attach this script to your main camera. Adjust the number of blurs to match the performance you want and the effect you want. The more iterations the more computation it takes. It is usually fill rate limited.

[edit] C# - BloomEffect.cs

using UnityEngine;
using System.Collections;
 
// This class implements a bloom effect.
// It is based off of OTEE's BlurEffect.cs
// It uses texture combiners, so it should run on older gfx. cards too.
// It is based on a four tap cone kernel.
[AddComponentMenu("Image Effects/Bloom")]
public class BloomEffect : MonoBehaviour {
 
    /// 0 to 1... the amount of bloom effect
    public float bloomAmount = 1F;
 
    /// How many levels of blurryness we want
    public int blurLevels = 2;
 
    static Material m_BloomMaterial = null;
    protected static Material bloomMaterial {
        get {
            if (m_BloomMaterial == null) 
                m_BloomMaterial = new Material (
                    "Shader \"Bloom Combine Shader\" {" +
                    "   Properties { _Color (\"Bloom Amount\", Color) = (1,1,1,1) }" +
                    "   SubShader { Pass {" +
                    "       ZTest Always Cull Off ZWrite Off" +
                    "       Blend SrcAlpha One" +
                    "       SetTexture [__RenderTex] {" +
                    "           constantColor [_Color]" +
                    "           combine constant * texture QUAD" +
                    "}}}}"
            );
            return m_BloomMaterial;
        } 
    }
 
    /// The blur shader material.
    static Material m_BlurMaterial = null;  
    protected static Material blurMaterial {
        get {
            if (m_BlurMaterial == null) 
                m_BlurMaterial = new Material (
                "Shader \"ConeTab\" {\n"    +
                "   SubShader { Pass {\n" +
                "       ZTest Always Cull Off ZWrite Off\n" +
                "       SetTexture [__RenderTex] { combine texture * constant alpha " +
                "           constantColor (0,0,0,0.25) } \n"    +
                "       SetTexture [__RenderTex] { combine texture * constant + previous " +
                "           constantColor (0,0,0,0.25) }\n" +
                "       SetTexture [__RenderTex] { combine texture * constant + previous " +
                "           constantColor (0,0,0,0.25) }\n" +
                "       SetTexture [__RenderTex] { combine texture * constant + previous " +
                "           constantColor (0,0,0,0.25) }\n" +
                "   }}\n"    +
                "}"
            );
            return m_BlurMaterial;
        } 
    }
 
    protected void Start()
    {
        // Disable the image effect if the shader can't
        // run on the users graphics card
        if (!blurMaterial.shader.isSupported)
            enabled = false;
    }
 
    // Function that actually renders the screenspace passes, offsetting the texture coordinates
    // based one the size of the screen.
    public static void FourTapCone (RenderTexture source, Rect sourceRect, RenderTexture dest, Rect destRect, int iteration) {
 
        RenderTexture.active = dest;
        source.SetGlobalShaderProperty ("__RenderTex");
 
        float offsetX = (.5F+iteration) / (float)source.width;
        float offsetY = (.5F+iteration) / (float)source.height;
 
        GL.PushMatrix ();
        GL.LoadOrtho ();    
 
        for (int i = 0; i < blurMaterial.passCount; i++) {
            blurMaterial.SetPass (i);
 
            GL.Begin (GL.QUADS);
            GL.MultiTexCoord2 (0, sourceRect.xMin - offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMin + offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMin + offsetX,    sourceRect.yMin + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMin - offsetX,    sourceRect.yMin + offsetY);
            GL.Vertex3 (destRect.xMin,destRect.yMin, .1f);
 
            GL.MultiTexCoord2 (0, sourceRect.xMax - offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMax + offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMax + offsetX,    sourceRect.yMin + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMax - offsetX,    sourceRect.yMin + offsetY);
            GL.Vertex3 (destRect.xMax,destRect.yMin, .1f);
 
            GL.MultiTexCoord2 (0, sourceRect.xMax - offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMax + offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMax + offsetX,    sourceRect.yMax + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMax - offsetX,    sourceRect.yMax + offsetY);
            GL.Vertex3 (destRect.xMax,destRect.yMax,.1f);
 
            GL.MultiTexCoord2 (0, sourceRect.xMin - offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMin + offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMin + offsetX,    sourceRect.yMax + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMin - offsetX,    sourceRect.yMax + offsetY);
            GL.Vertex3 (destRect.xMin,destRect.yMax,.1f);
            GL.End();
 
        }
        GL.PopMatrix ();
 
    }
 
    // Downsamples the texture to a quarter resolution.
    static void DownSample4x (RenderTexture source, Rect sourceRect, RenderTexture dest, Rect destRect) {
 
        //if (dest.width * (destRect.xMax - destRect.xMin) *4 != source.width * (sourceRect.xMax - sourceRect.xMin))
        //  Debug.Log ("Warning: DownSample4x called with non-matching rectangles");
        RenderTexture.active = dest;
        source.SetGlobalShaderProperty ("__RenderTex");
 
        float offsetX = 1F / (float)source.width;
        float offsetY = 1F / (float)source.height;
 
        GL.PushMatrix ();
        GL.LoadOrtho ();        
        for (int i = 0; i < blurMaterial.passCount; i++) {
            blurMaterial.SetPass (i);
 
            GL.Begin (GL.QUADS);
            GL.MultiTexCoord2 (0, sourceRect.xMin - offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMin + offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMin + offsetX,    sourceRect.yMin + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMin - offsetX,    sourceRect.yMin + offsetY);
            GL.Vertex3 (destRect.xMin,destRect.yMin, .1f);
 
            GL.MultiTexCoord2 (0, sourceRect.xMax - offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMax + offsetX,    sourceRect.yMin - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMax + offsetX,    sourceRect.yMin + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMax - offsetX,    sourceRect.yMin + offsetY);
            GL.Vertex3 (destRect.xMax,destRect.yMin, .1f);
 
            GL.MultiTexCoord2 (0, sourceRect.xMax - offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMax + offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMax + offsetX,    sourceRect.yMax + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMax - offsetX,    sourceRect.yMax + offsetY);
            GL.Vertex3 (destRect.xMax,destRect.yMax,.1f);
 
            GL.MultiTexCoord2 (0, sourceRect.xMin - offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (1, sourceRect.xMin + offsetX,    sourceRect.yMax - offsetY);
            GL.MultiTexCoord2 (2, sourceRect.xMin + offsetX,    sourceRect.yMax + offsetY); 
            GL.MultiTexCoord2 (3, sourceRect.xMin - offsetX,    sourceRect.yMax + offsetY);
            GL.Vertex3 (destRect.xMin,destRect.yMax,.1f);
            GL.End();
        }
        GL.PopMatrix ();
    }
 
    // Update is called once per frame
    void OnRenderImage (RenderTexture source, RenderTexture destination) {      
        RenderTexture buffer = RenderTexture.GetTemporary(source.width/4, source.height/4, 0);
        RenderTexture buffer2 = RenderTexture.GetTemporary(source.width/4, source.height/4, 0);
 
        // Blur the source image. Since blurring is an expensive process, we want to do it at
        // quater resolution.
        // Copy the main screen image into an image at half size
        DownSample4x (source, new Rect (0,0,1,1), buffer, new Rect (0,0,1,1));  
 
        // Blur the image by running the FourTapCone function on it i = blurLevels numbers of time.
        bool oddEven = true;
        for(int i = 0; i < blurLevels; i++) {
            if(oddEven) {
                FourTapCone (buffer, new Rect (0,0,1,1), buffer2, new Rect (0,0,1,1), i);
                oddEven = false;
            } else {
                FourTapCone (buffer2, new Rect (0,0,1,1), buffer, new Rect (0,0,1,1), i);
                oddEven = true;
            }
        }
        ImageEffects.Blit(source,destination);
 
        //bloomAmount = Mathf.Clamp01(bloomAmount);
        bloomMaterial.color = new Color(1F, 1F, 1F, bloomAmount);
 
        if(oddEven)
            BlitBloom(buffer, destination);
        else
            BlitBloom(buffer2, destination);
 
        RenderTexture.ReleaseTemporary(buffer);
        RenderTexture.ReleaseTemporary(buffer2);
    }
 
    public void BlitBloom (RenderTexture source, RenderTexture dest)
    {
        // Make the destination texture the target for all rendering
        RenderTexture.active = dest;        
        // Assign the source texture to a property from a shader
        source.SetGlobalShaderProperty ("__RenderTex"); 
        // Set up the simple Matrix
        GL.PushMatrix ();
        GL.LoadOrtho ();
        bloomMaterial.SetPass (0);
        ImageEffects.DrawGrid(1,1);
        GL.PopMatrix ();
    }
 
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox