This shader adds a post processor effect, on Windows/Editor it works, but on Android it does not appear. Just nothing, everything works, but the effect does not appear.
Shader "Custom/Highlight" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Main Texture", 2D) = "black" {}
_OccludeMap ("Occlusion Map", 2D) = "black" {}
}
SubShader {
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
// OVERLAY GLOW
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _OccludeMap;
fixed4 _Color;
fixed4 frag(v2f_img IN) : COLOR
{
fixed3 overCol = tex2D(_OccludeMap, IN.uv).r * _Color.rgb * _Color.a;
return tex2D (_MainTex, IN.uv) + fixed4(overCol, 1.0);
}
ENDCG
}
// OVERLAY SOLID
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _OccludeMap;
fixed4 _Color;
fixed4 frag(v2f_img IN) : COLOR
{
fixed4 mCol = tex2D (_MainTex, IN.uv);
fixed oCol = tex2D (_OccludeMap, IN.uv).r;
fixed solid = step (1.0 - _Color.a, oCol);
return mCol + solid * fixed4(_Color.rgb, 1.0);
}
ENDCG
}
// OCCLUSION
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _OccludeMap;
fixed frag(v2f_img IN) : COLOR
{
return tex2D (_MainTex, IN.uv).r - tex2D(_OccludeMap, IN.uv).r;
}
ENDCG
}
Pass {
Tags {"RenderType"="Opaque"}
ZWrite On
ZTest LEqual
Fog { Mode Off }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 v:POSITION) : POSITION {
return mul (UNITY_MATRIX_MVP, v);
}
fixed frag() : COLOR {
return 1.0;
}
ENDCG
}
Pass {
Tags {"Queue"="Transparent"}
Cull Back
Lighting Off
ZWrite Off
ZTest LEqual
ColorMask RGBA
Blend OneMinusDstColor One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _CameraDepthTexture;
struct v2f {
float4 vertex : POSITION;
float4 projPos : TEXCOORD1;
};
v2f vert( float4 v : POSITION ) {
v2f o;
o.vertex = mul( UNITY_MATRIX_MVP, v );
o.projPos = ComputeScreenPos(o.vertex);
return o;
}
fixed frag( v2f i ) : COLOR {
float depthVal = LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r);
float zPos = i.projPos.z;
return step( zPos, depthVal );
}
ENDCG
}
}
}
This works perfectly for a Windows build/Editor, but NOT in on an Android device/Emulator; it works via Unity Remote 4.
C# Script that uses it:
using UnityEngine;
using System.Collections.Generic;
using UnityStandardAssets.ImageEffects;
using UnityEngine.Rendering;
[RequireComponent(typeof(Camera))]
public class HighlightsPostEffect : MonoBehaviour
{
#region enums
public enum HighlightType
{
Glow = 0,
Solid = 1
}
public enum SortingType
{
Overlay = 3,
DepthFilter = 4
}
public enum FillType
{
Fill,
Outline
}
public enum RTResolution
{
Quarter = 4,
Half = 2,
Full = 1
}
#endregion
#region public vars
public HighlightType m_selectionType = HighlightType.Glow;
public SortingType m_sortingType = SortingType.DepthFilter;
public FillType m_fillType = FillType.Outline;
public RTResolution m_resolution = RTResolution.Full;
public string m_occludeesTag = "Occludee";
public string m_occludersTag = "Occluder";
public Color m_highlightColor = new Color(1f, 0f, 0f, 0.65f);
public Shader m_highlightShader;
#endregion
#region private field
private BlurOptimized m_blur;
private Renderer[] highlightObjects;
private Renderer[] m_occluders = null;
private Material m_highlightMaterial;
private CommandBuffer m_renderBuffer;
private int m_RTWidth = 512;
private int m_RTHeight = 512;
#endregion
private void Awake()
{
CreateBuffers();
CreateMaterials();
SetOccluderObjects();
//m_blur = gameObject.AddComponent<BlurOptimized>();
m_blur = gameObject.GetComponent<BlurOptimized>();
m_blur.enabled = false;
GameObject[] occludees = GameObject.FindGameObjectsWithTag(m_occludeesTag);
highlightObjects = new Renderer[occludees.Length];
for( int i = 0; i < occludees.Length; i++ )
highlightObjects _= occludees*.GetComponent<Renderer>();*_
* m_RTWidth = (int) (Screen.width / (float) m_resolution);
m_RTHeight = (int) (Screen.height / (float) m_resolution);
_ }_
_ private void CreateBuffers()_
_ {_
m_renderBuffer = new CommandBuffer();
_ }_
_ private void ClearCommandBuffers()_
_ {_
m_renderBuffer.Clear();
_ }*_
* private void CreateMaterials()*
* {*
* m_highlightMaterial = new Material( m_highlightShader );
_ }_
_ private void SetOccluderObjects()_
_ {_
if( string.IsNullOrEmpty(m_occludersTag) )
_ return;*_
* GameObject occluderGOs = GameObject.FindGameObjectsWithTag(m_occludersTag);*
* List occluders = new List();*
* foreach( GameObject go in occluderGOs )*
* {*
* Renderer renderer = go.GetComponent();*
* if( renderer != null )*
* occluders.Add( renderer );*
* }*
* m_occluders = occluders.ToArray();
_ }*_
* private void RenderHighlights( RenderTexture rt)*
* {*
* if( highlightObjects == null )*
* return;*
* RenderTargetIdentifier rtid = new RenderTargetIdentifier(rt);*
* m_renderBuffer.SetRenderTarget( rtid );
_ for(int i = 0; i < highlightObjects.Length; i++)_
_ {_
_ if( highlightObjects == null )
continue;*_
m_renderBuffer.DrawRenderer( highlightObjects*, m_highlightMaterial, 0, (int) m_sortingType );
_ }
RenderTexture.active = rt;_
Graphics.ExecuteCommandBuffer(m_renderBuffer);
_ RenderTexture.active = null;
}*_
* private void RenderOccluders( RenderTexture rt)*
* {*
* if( m_occluders == null )
_ return;
RenderTargetIdentifier rtid = new RenderTargetIdentifier(rt);_
m_renderBuffer.SetRenderTarget( rtid );
m_renderBuffer.Clear();*
* foreach(Renderer renderer in m_occluders)
_ { _
m_renderBuffer.DrawRenderer( renderer, m_highlightMaterial, 0, (int) m_sortingType );
_ }
RenderTexture.active = rt;_
Graphics.ExecuteCommandBuffer(m_renderBuffer);
_ RenderTexture.active = null;
}
/// Final image composing.
/// 1. Renders all the highlight objects either with Overlay shader or DepthFilter*
* /// 2. Downsamples and blurs the result image using standard BlurOptimized image effect*
* /// 3. Renders occluders to the same render texture*
* /// 4. Substracts the occlusion map from the blurred image, leaving the highlight area*
* /// 5. Renders the result image over the main camera’s G-Buffer*
* private void OnRenderImage( RenderTexture source, RenderTexture destination )
{
RenderTexture highlightRT;_
RenderTexture.active = highlightRT = RenderTexture.GetTemporary(m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8 );
_ GL.Clear(true, true, Color.clear);
RenderTexture.active = null;
ClearCommandBuffers();
RenderHighlights(highlightRT);_
RenderTexture blurred = RenderTexture.GetTemporary( m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8 );
m_blur.OnRenderImage( highlightRT, blurred );*
* RenderOccluders(highlightRT);*
* if( m_fillType == FillType.Outline )
_ {_
RenderTexture occluded = RenderTexture.GetTemporary( m_RTWidth, m_RTHeight, 0, RenderTextureFormat.R8);
_ // Excluding the original image from the blurred image, leaving out the areal alone*
* m_highlightMaterial.SetTexture("OccludeMap", highlightRT);
Graphics.Blit( blurred, occluded, m_highlightMaterial, 2 );
m_highlightMaterial.SetTexture("OccludeMap", occluded);*
* RenderTexture.ReleaseTemporary(occluded);*
* }
else*
* {_
m_highlightMaterial.SetTexture("OccludeMap", blurred);*
* }_
m_highlightMaterial.SetColor("Color", m_highlightColor);
Graphics.Blit (source, destination, m_highlightMaterial, (int) m_selectionType);*
* RenderTexture.ReleaseTemporary(blurred);
RenderTexture.ReleaseTemporary(highlightRT);
}
public void RefreshHighlight()
{
//CreateBuffers();
//CreateMaterials();
SetOccluderObjects();_
//m_blur = gameObject.AddComponent();
//m_blur.enabled = false;
GameObject[] occludees = GameObject.FindGameObjectsWithTag(m_occludeesTag);
highlightObjects = new Renderer[occludees.Length];
for (int i = 0; i < occludees.Length; i++)
highlightObjects _= occludees.GetComponent();
m_RTWidth = (int)(Screen.width / (float)m_resolution);
m_RTHeight = (int)(Screen.height / (float)m_resolution);
}
}*_