3
\$\begingroup\$

I am trying to make a shader that applies a black image with 50% transparency to the entire screen, with the exception of a designated area. I am starting by just trying to apply a shader to the entire screen. So I am using the default ImageEffect Shader.

This is my before and after when applying my shader, which should invert everything. It inverts everything except for the Balmer's Peak, which is a Unity Image:

Before:

enter image description here

After:

enter image description here

Example of what I am going for:

enter image description here

I attached a script using OnRenderImage to the Camera, and the attached material is being applied to everything in sight, except the UI. What can I do to make my material applied to everything on the screen, including the UI?

I am new to shaders, so this may seem like a bit of a dumb question. But I am not sure what direction I should be headed. Here are my scripts, although I did not really change anything from what Unity provided me:

Script attached to camera:

using UnityEngine;

public class ButtonHighlight : MonoBehaviour
{
    [Tooltip("Material which is to be applied")]
    [SerializeField]
    private Material material;

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Graphics.Blit(source, material);
    }
}

Shader attached to material above:

Shader "Magic/Magic Shader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                // just invert the colors
                col = 1 - col;
                return col;
            }
            ENDCG
        }
    }
}

What is the correct approach to apply a shader to the entire screen? (Keeping in mind, that the purpose is to add a filter to most, but not all, of the screen.)

\$\endgroup\$

1 Answer 1

7
\$\begingroup\$

The default behavior for Unity's UI is to draw after the post-processing effects have been applied. This is dictated by the Render Mode setting on your scene's Canvas object.

Switch the Render Mode to Screen Space - Camera, and drag your scene's main camera into the Render Camera property (which will appear when you change the render mode). Now your canvas's UI will draw before that camera's post-processing.

There's more information about render modes in the Unity documentation about Canvas.

\$\endgroup\$

You must log in to answer this question.

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