- Home /
 
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?
Answer by tanoshimi · Oct 24, 2013 at 06:33 AM
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 http://docs.unity3d.com/Documentation/ScriptReference/Camera.RenderWithShader.html page is borked :(
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!
Your answer
 
             Follow this Question
Related Questions
EdgeDetectEffectNormals flips camera 0 Answers
Post processing effect on depth only camera. 1 Answer
Shader to a Camera 1 Answer
Setting up a simple depth-based Shader Replacement material? 0 Answers
effect on clipping plane 1 Answer