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(); } }