How to render all opaque meshes with the same effect?

I have a specular outline shader that I want to be used on all opaque meshes of the scene whenever a specific camera renders. The shader is working properly when it is manually applied to some material. The shader is as follows:

Shader "Custom/Outline" {
Properties {
	_Color ("Main Color", Color) = (.5,.5,.5,1)
    _OutlineColor ("Outline Color", Color) = (1,0.5,0,1)
    _Outline ("Outline width", Range (0.0, 0.1)) = .05
	_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
	_Shininess ("Shininess", Range (0.03, 1)) = 0.078125
	_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
}

SubShader {
	Tags { "Queue"="Overlay" "RenderType"="Opaque" }
	Pass {
		Name "OUTLINE"
		Tags { "LightMode" = "Always" }
		
		Cull Off
		ZWrite Off
		// Uncomment to show outline always.
		//ZTest Always
		
		CGPROGRAM
		#pragma target 3.0
		#pragma vertex vert
		#pragma fragment frag
		
		#include "UnityCG.cginc" 
		
		struct appdata {
	    	float4 vertex : POSITION;
		    float3 normal : NORMAL;
		};
		
		struct v2f
		{
		    float4 pos : POSITION;
		    float4 color : COLOR;
		};
		
		float _Outline;
		float4 _OutlineColor;

		v2f vert(appdata v) {
		    // just make a copy of incoming vertex data but scaled according to normal direction
			v2f o;
			o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
		
			float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
			float2 offset = TransformViewToProjection(norm.xy);
		
			o.pos.xy += offset * o.pos.z * _Outline;
			o.color = _OutlineColor;
			return o;
		}
		
		float4 frag(v2f fromVert) : COLOR {
			return fromVert.color;
		}
		ENDCG
    }
    UsePass "Specular/FORWARD"
}

FallBack "Specular"
}

The camera used fot the effect has just a script component which setups the shader replacement:

using UnityEngine;
using System.Collections;

public class DetectiveEffect : MonoBehaviour {
	
	public Shader EffectShader;
	
	// Use this for initialization
	void Start () {
		this.camera.SetReplacementShader(EffectShader, "RenderType=Opaque");
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

Unfortunately, whenever I use this camera I just see the background color. Any ideas?

You’ve misunderstood the way that replacement tags in SetReplacementShader work - I had exactly the same problem, and I find the documentation not to be clear (not helped by the fact that the link to the “Rendering with Replaced Shaders” topic from the Unity - Scripting API: Camera.RenderWithShader page is borked :frowning:

Your Start() function should not specify the replacement tag value, only the key, like this:

camera.SetReplacementShader (EffectShader, "RenderType");

Then, your replacement shader, EffectShader, should contain different Subshaders with key-value tags for each RenderType that you want to replace, e.g.:

Shader "EffectShader" {
    SubShader {
        Tags { "RenderType"="Opaque" }
        Pass {
            ...
        }
    }
    SubShader {
        Tags { "RenderType"="SomethingElse" }
        Pass {
            ...
        }
    }
...
}

SetReplacementShader will look through all the objects in the scene and, instead of using their normal shader, use the first subshader which has a matching value for the specified key (e.g. in this example, any objects whose shader has Rendertype=“Opaque” tag will be replaced by first subshader in EffectShader, any objects with RenderType=“SomethingElse” shader will use second replacement subshader). Any objects whose shader does not have a matching tag value for the specified key in the replacement shader will not be rendered.

At least, that’s what I think happens - I’ve had many issues wrestling with aspects of SetReplacementShader and eventually rolled my own replacement instead. Good luck!