So I’m working on a new game that’s a cross between Toca Mini and a vlog creator (editor..?), so I thought it would be fun to add some Instagram-like filters.

For this I am using Cinema Suite Inc’s Color Grading LUTs Library, which you can get in the Unity Asset Store for free, and some old-fashioned Legacy Color Correction Lookup.
This post was supposed to be a tutorial, but sadly, Legacy Image Effects are deprecated from the Asset Store, so… yuh (but if you happen to still have it from old-fashioned Standard Assets, read on).
First, I like to put all my Manager type code in its own GameObject and then attach the script to it. So, I have CameraMgr.

Button Panel is for hiding UI stuff; Camera Image Fitter and Camera Plane is for showing your device Camera (more on that in a bit); and Color Correction Lookup is for changing filters (that script is from Legacy Image Effects) and it’s attached to your MainCamera.



Code Snippets Link: https://bitbucket.org/snippets/studiosremade/EbojrA
CameraMgr.cs (Yes, some of the code are from UnityAnswers)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.ImageEffects;
public class CameraMgr : MonoBehaviour
{
public GameObject m_buttonPanel;
private bool m_isFrontFacing = false;
private WebCamDevice m_currCamera;
private WebCamDevice m_backCamera;
private WebCamDevice m_frontCamera;
private WebCamTexture m_cameraTexture;
// Source: https://answers.unity.com/questions/773464/webcamtexture-correct-resolution-and-ratio.html
public AspectRatioFitter m_cameraImageFitter;
// Image rotation
Vector3 m_camRotationVector = new Vector3(0f, 0f, 0f);
// Image uvRect
private Rect m_cameraDefaultRect = new Rect(0f, 0f, 1f, 1f);
private Rect m_cameraFixedRect = new Rect(0f, 1f, 1f, -1f);
// Image Parent's scale
private Vector3 m_cameraDefaultScale = new Vector3(1f, 1f, 1f);
private Vector3 m_cameraFixedScale = new Vector3(-1f, 1f, 1f);
public RawImage m_cameraPlane;
private string m_currFileName;
public ColorCorrectionLookup m_colorCorrectionLookup;
private void Start()
{
m_isFrontFacing = false;
StartCoroutine(SetUpCamera());
}
// Sources:
// https://docs.unity3d.com/ScriptReference/WebCamTexture-ctor.html
// https://docs.unity3d.com/ScriptReference/WebCamTexture-videoRotationAngle.html
// https://docs.unity3d.com/ScriptReference/WebCamTexture-videoVerticallyMirrored.html
private IEnumerator SetUpCamera()
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
if (!Application.HasUserAuthorization(UserAuthorization.WebCam)) yield break;
WebCamDevice[] devices = WebCamTexture.devices;
for (int i = 0; i < devices.Length; i++)
{
Debug.Log("Camera Names " + devices[i].name);
if (devices[i].isFrontFacing)
{ m_frontCamera = devices[i];
}
else
{ m_backCamera = devices[i];
}
}
m_isFrontFacing = false;
StartCoroutine(StartCamera());
}
private IEnumerator StartCamera()
{
// camera is flipped when testing with front facing camera in editor
if (Application.isEditor || m_isFrontFacing)
{ m_currCamera = m_frontCamera;
}
else
{ m_currCamera = m_backCamera;
}
m_cameraTexture = new WebCamTexture(m_currCamera.name, 1280, 720, 30);
// Sources:
// https://answers.unity.com/questions/1421387/webcamtexture-zoomed-in-on-ipad-pro.html
// https://answers.unity.com/questions/773464/webcamtexture-correct-resolution-and-ratio.html
m_cameraTexture.Play();
// Display webcam
yield return new WaitUntil(() => m_cameraTexture.width != 16 && m_cameraTexture.height != 16); // Workaround for weird bug on macOS
m_cameraPlane.texture = m_cameraTexture;
// Set camera filter modes for a smoother looking image
m_cameraPlane.texture.filterMode = FilterMode.Trilinear;
// Set AspectRatioFitter's ratio
m_cameraImageFitter.aspectRatio = (float)m_cameraTexture.width / m_cameraTexture.height;
m_cameraImageFitter.aspectMode = AspectRatioFitter.AspectMode.WidthControlsHeight;
// If you want height to control width:
/**
m_camImageFitter.aspectRatio = (float) m_cameraTexture.height / m_cameraTexture.width;
m_camImageFitter.aspectMode = AspectRatioFitter.AspectMode.HeightControlsWidth;
**/
// Rotate image to show correct orientation
m_camRotationVector.z = -m_cameraTexture.videoRotationAngle;
m_cameraPlane.rectTransform.localEulerAngles = m_camRotationVector;
// Unflip if vertically flipped
m_cameraPlane.uvRect = m_cameraTexture.videoVerticallyMirrored ? m_cameraFixedRect : m_cameraDefaultRect;
// Mirror front-facing camera's image horizontally to look more natural
if (Application.isEditor)
{ m_cameraPlane.transform.localScale = m_cameraFixedScale;
} else
{
m_cameraPlane.transform.localScale = m_currCamera.isFrontFacing ? m_cameraFixedScale : m_cameraDefaultScale;
}
}
public void ClickFlipCameraBtn()
{
StopCamera();
m_isFrontFacing = !m_isFrontFacing;
StartCoroutine(StartCamera());
}
public void StopCamera()
{ m_cameraTexture.Stop();
}
public void ClickCameraBtn()
{
HideUI();
m_currFileName = "Photo" + PlayerPrefs.GetInt("PhotoIdx", 0) + ".png";
ScreenCapture.CaptureScreenshot(m_currFileName);
PlayerPrefs.SetInt("PhotoIdx", PlayerPrefs.GetInt("PhotoIdx", 0) + 1);
Invoke("ShowUI", 0.2f);
}
public void ClickFilterBtn(FilterBtn filterBtn)
{
if (m_colorCorrectionLookup != null)
{
if (filterBtn.m_filter != null)
{
m_colorCorrectionLookup.enabled = true;
m_colorCorrectionLookup.Convert(filterBtn.m_filter, "");
}
else
{
m_colorCorrectionLookup.enabled = false;
}
}
}
private void HideUI()
{ m_buttonPanel.SetActive(false);
}
private void ShowUI()
{ m_buttonPanel.SetActive(true);
}
}
FilterBtn.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FilterBtn : Button
{
public Texture2D m_filter;
public Text m_text;
}
FilterBtnEditor.cs
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
[CustomEditor(typeof(FilterBtn))]
public class FilterBtnEditor : UnityEditor.UI.ButtonEditor
{
public override void OnInspectorGUI()
{
FilterBtn targetFilterBtn = (FilterBtn) target;
targetFilterBtn.m_filter = EditorGUILayout.ObjectField("Filter", ((FilterBtn) target).m_filter, typeof(Texture2D), true) as Texture2D;
targetFilterBtn.m_text = EditorGUILayout.ObjectField("Text", ((FilterBtn)target).m_text, typeof(Text), true) as Text;
EditorUtility.SetDirty(target);
base.OnInspectorGUI();
}
}