ImageEffectOpaque renders too late in builds (ok in editor)

Hello,

I have a project using the old post process v1 stack and the legacy standard assets edge detection shader. It generally works fine, except we have one problem with the edge detection script rendering on top of fog. (Unity version 2018.4.2f1)

It appears that after the game is built, the edge detection script is running too late in the process. Its OnRenderImage function is tagged with [ImageEffectOpaque], and runs appropriately in editor – but in a build it runs too late.

As we are nearing ship, we would like to make a minimal set of changes in order to resolve the problem. Anyone have any tips?

PS - here is the edge detection script for ease of reference:

using System;
using UnityEngine;

namespace UnityStandardAssets.ImageEffects
{
    [ExecuteInEditMode]
    [RequireComponent (typeof (Camera))]
    [AddComponentMenu ("Image Effects/Edge Detection/Edge Detection")]
    public class EdgeDetection : PostEffectsBase
    {
        public enum EdgeDetectMode
        {
            TriangleDepthNormals = 0,
            RobertsCrossDepthNormals = 1,
            SobelDepth = 2,
            SobelDepthThin = 3,
            TriangleLuminance = 4,
        }


        public EdgeDetectMode mode = EdgeDetectMode.SobelDepthThin;
        public float sensitivityDepth = 1.0f;
        public float sensitivityNormals = 1.0f;
        public float lumThreshold = 0.2f;
        public float edgeExp = 1.0f;
        public float sampleDist = 1.0f;
        public float edgesOnly = 0.0f;
        public Color edgesOnlyBgColor = Color.white;

        public Shader edgeDetectShader;
        private Material edgeDetectMaterial = null;
        private EdgeDetectMode oldMode = EdgeDetectMode.SobelDepthThin;


        public override bool CheckResources ()
        {
            CheckSupport (true);

            edgeDetectMaterial = CheckShaderAndCreateMaterial (edgeDetectShader,edgeDetectMaterial);
            if (mode != oldMode)
                SetCameraFlag ();

            oldMode = mode;

            if (!isSupported)
                ReportAutoDisable ();
            return isSupported;
        }


        new void Start ()
        {
            oldMode    = mode;
        }

        void SetCameraFlag ()
        {
            if (mode == EdgeDetectMode.SobelDepth || mode == EdgeDetectMode.SobelDepthThin)
                GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
            else if (mode == EdgeDetectMode.TriangleDepthNormals || mode == EdgeDetectMode.RobertsCrossDepthNormals)
                GetComponent<Camera>().depthTextureMode |= DepthTextureMode.DepthNormals;
        }

        void OnEnable ()
        {
            SetCameraFlag();
        }

        [ImageEffectOpaque]
        void OnRenderImage (RenderTexture source, RenderTexture destination)
        {
            if (CheckResources () == false)
            {
                Graphics.Blit (source, destination);
                return;
            }

            Vector2 sensitivity = new Vector2 (sensitivityDepth, sensitivityNormals);
            edgeDetectMaterial.SetVector ("_Sensitivity", new Vector4 (sensitivity.x, sensitivity.y, 1.0f, sensitivity.y));
            edgeDetectMaterial.SetFloat ("_BgFade", edgesOnly);
            edgeDetectMaterial.SetFloat ("_SampleDistance", sampleDist);
            edgeDetectMaterial.SetVector ("_BgColor", edgesOnlyBgColor);
            edgeDetectMaterial.SetFloat ("_Exponent", edgeExp);
            edgeDetectMaterial.SetFloat ("_Threshold", lumThreshold);

            Graphics.Blit (source, destination, edgeDetectMaterial, (int) mode);
        }
    }
}

I know it has been over a year but I ran into the same issue with Unity 2018.4.36f and found a solution.

Builds with high managed stripping level have this issue but builds with a low managed stripping level would not have this issue.

It seems the ImageEffectOpaque attribute is being stripped.

The best solution would be to make sure the attribute is not stripped using a link.xml file. I am still figuring out how to do this.

this linker file worked for me:

<linker>
<assembly fullname="UnityEngine.CoreModule">
<type fullname="UnityEngine.ImageEffectOpaque" preserve="all"/>
</assembly>
</linker>