// Amplify Color - Advanced Color Grading for Unity Pro
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>

using UnityEngine;
using System.Collections;

[RequireComponent( typeof( Camera ) )]
public class RenderColorMask : MonoBehaviour
{
	public Camera maskCamera;
	public LayerMask layerMask;
	public bool invertMask;
	public bool debug;

	private int width, height;
	private RenderTexture maskTexture;
	private Shader colorMaskShader;
	private Shader colorMaskShaderAlpha;

	void Start()
	{
		colorMaskShader = Shader.Find( "Hidden/ColorMaskShader" );
		colorMaskShaderAlpha = Shader.Find( "Hidden/ColorMaskShaderAlpha" );

		UpdateRenderTextures();
		UpdateCameraProperties();
	}

	void Update()
	{
		UpdateRenderTextures();
		UpdateCameraProperties();
	}

	void UpdateRenderTextures()
	{
		int w = ( int ) ( GetComponent<Camera>().pixelWidth + 0.5f );
		int h = ( int ) ( GetComponent<Camera>().pixelHeight + 0.5f );

		if ( width != w || height != h )
		{
			width = w;
			height = h;

			if ( maskTexture != null )
				DestroyImmediate( maskTexture );

			maskTexture = new RenderTexture( width, height, 24, RenderTextureFormat.Default, RenderTextureReadWrite.Linear ) { hideFlags = HideFlags.HideAndDontSave, name = "MaskTexture" };
			maskTexture.antiAliasing = ( QualitySettings.antiAliasing > 0 ) ? QualitySettings.antiAliasing : 1;
			maskTexture.Create();
		}

		if ( GetComponent<Camera>() != null )
			GetComponent<Camera>().GetComponent<AmplifyColorEffect>().MaskTexture = maskTexture;
	}

	void UpdateCameraProperties()
	{
		maskCamera.CopyFrom( GetComponent<Camera>() );
		maskCamera.targetTexture = maskTexture;
		maskCamera.clearFlags = CameraClearFlags.Nothing;
		maskCamera.renderingPath = RenderingPath.VertexLit;
		maskCamera.pixelRect = new Rect( 0, 0, width, height );
		maskCamera.depthTextureMode = DepthTextureMode.None;
		maskCamera.hdr = false;
		maskCamera.enabled = false;
	}

	void Render( Shader shader )
	{
		// Render all objects, except ColorMask layer
		Shader.SetGlobalColor( "_COLORMASK_Color", invertMask ? Color.black : Color.white );
		maskCamera.cullingMask = ~layerMask;
		maskCamera.RenderWithShader( shader, "RenderType" );

		// Render only ColorMask layer
		Shader.SetGlobalColor( "_COLORMASK_Color", invertMask ? Color.white : Color.black );
		maskCamera.cullingMask = layerMask;
		maskCamera.RenderWithShader( shader, "RenderType" );
	}

	void OnPreRender()
	{
		RenderBuffer prevColor = Graphics.activeColorBuffer;
		RenderBuffer prevDepth = Graphics.activeDepthBuffer;

		Graphics.SetRenderTarget( maskTexture );
		GL.Clear( true, true, invertMask ? Color.black : Color.white );

		// Render Opaque objects
		Render( colorMaskShader );

		// Render Transparent objects
		Render( colorMaskShaderAlpha );

		Graphics.SetRenderTarget( prevColor, prevDepth );
	}

	void OnGUI()
	{
		if ( debug )
			GUI.DrawTexture( new Rect( 0, 0, Screen.width, Screen.height ), maskTexture );
	}
}
