Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

I have misunderstood the concept of shader replacement. The replacementTag value of

SetReplacementShader(shader: Shader, replacementTag: string): void;

must be the tag type only. Then, in the replacement shader I have to set the tag value that I want to replace, as I did before. Any material with this value in the tag will use the replacement shader instead when rendered by the camera with the effect script attached and enabled. The final code of the effect script became:

using UnityEngine;
using System.Collections;

    public class DetectiveEffect : MonoBehaviour {

    public Shader EffectShader;

    // Use this for initialization
    void Start () {
        //Notice the "RenderType" tag here.
        this.camera.SetReplacementShader(EffectShader, "RenderType"); 
    }

    // Update is called once per frame
    void Update () {
    }
}

The shader code did not changed. But notice where the tag is set.

//...

SubShader {
Tags { "Queue"="Overlay" "RenderType"="Opaque" }
Pass {

//...

In my case, any material with a shader with the RenderType tag equals Opaque will be replaced by my shader when rendered by my effect camera.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.