Last active
December 22, 2017 12:39
-
-
Save JLChnToZ/c2642b5c2edd05db28a27e83f149d440 to your computer and use it in GitHub Desktop.
Unity rendering post processor which corrects the color with a color matrix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| [ExecuteInEditMode, RequireComponent(typeof(Camera))] | |
| public class ColorMatrixCorrection: MonoBehaviour { | |
| public Matrix4x4 colorMatrix = Matrix4x4.identity; | |
| public Vector4 baseColor; | |
| private Material material; | |
| private void Awake() { | |
| material = new Material(Shader.Find("Hidden/ColorMatrixCorrection")); | |
| } | |
| private void OnDestroy() { | |
| if(material) { | |
| if(Application.isPlaying) | |
| Destroy(material); | |
| else | |
| DestroyImmediate(material); | |
| } | |
| } | |
| private void OnRenderImage(RenderTexture source, RenderTexture destination) { | |
| material.SetMatrix("_ColorMatrix", colorMatrix); | |
| material.SetVector("_BaseColor", baseColor); | |
| Graphics.Blit(source, destination, material); | |
| } | |
| public static Matrix4x4 InvertMatrix { | |
| get { | |
| return new Matrix4x4 { | |
| m00 = -1, m11 = -1, m22 = -1, m33 = 1, | |
| m30 = 1, m31 = 1, m32 = 1 | |
| }; | |
| } | |
| } | |
| public static Matrix4x4 BrightnessMatrix(float b) { | |
| return new Matrix4x4 { | |
| m00 = 1, m11 = 1, m22 = 1, m33 = 1, | |
| m30 = b, m31 = b, m32 = b | |
| }; | |
| } | |
| public static Matrix4x4 ContrastMatrix(float c) { | |
| float t = (1 - c) / 2; | |
| return new Matrix4x4 { | |
| m00 = c, m11 = c, m22 = c, m33 = 1, | |
| m30 = t, m31 = t, m32 = t | |
| }; | |
| } | |
| public static Matrix4x4 SaturationMatrix(float s) { | |
| const float lumR = 0.3086F; | |
| const float lumG = 0.6094F; | |
| const float lumB = 0.0820F; | |
| float sr = (1 - s) * lumR; | |
| float sg = (1 - s) * lumG; | |
| float sb = (1 - s) * lumB; | |
| return new Matrix4x4 { | |
| m00 = sr + s, m01 = sr, m02 = sr, | |
| m10 = sg, m11 = sg + s, m12 = sg, | |
| m20 = sb, m21 = sb, m22 = sb + s, | |
| m33 = 1, | |
| }; | |
| } | |
| } | |
| public static class Matrix4x4Helper { | |
| public static Matrix4x4 Strengh(this Matrix4x4 m, float s) { | |
| return Lerp(Matrix4x4.identity, m, s); | |
| } | |
| public static Matrix4x4 Lerp(Matrix4x4 a, Matrix4x4 b, float t) { | |
| return new Matrix4x4 { | |
| m00 = Mathf.LerpUnclamped(a.m00, b.m00, t), | |
| m01 = Mathf.LerpUnclamped(a.m01, b.m01, t), | |
| m02 = Mathf.LerpUnclamped(a.m02, b.m02, t), | |
| m03 = Mathf.LerpUnclamped(a.m03, b.m03, t), | |
| m10 = Mathf.LerpUnclamped(a.m10, b.m10, t), | |
| m11 = Mathf.LerpUnclamped(a.m11, b.m11, t), | |
| m12 = Mathf.LerpUnclamped(a.m12, b.m12, t), | |
| m13 = Mathf.LerpUnclamped(a.m13, b.m13, t), | |
| m20 = Mathf.LerpUnclamped(a.m20, b.m20, t), | |
| m21 = Mathf.LerpUnclamped(a.m21, b.m21, t), | |
| m22 = Mathf.LerpUnclamped(a.m22, b.m22, t), | |
| m23 = Mathf.LerpUnclamped(a.m23, b.m23, t), | |
| m30 = Mathf.LerpUnclamped(a.m30, b.m30, t), | |
| m31 = Mathf.LerpUnclamped(a.m31, b.m31, t), | |
| m32 = Mathf.LerpUnclamped(a.m32, b.m32, t), | |
| m33 = Mathf.LerpUnclamped(a.m33, b.m33, t) | |
| }; | |
| } | |
| public static Matrix4x4 Add(this Matrix4x4 a, Matrix4x4 b) { | |
| return new Matrix4x4 { | |
| m00 = a.m00 + b.m00, | |
| m01 = a.m01 + b.m01, | |
| m02 = a.m02 + b.m02, | |
| m03 = a.m03 + b.m03, | |
| m10 = a.m10 + b.m10, | |
| m11 = a.m11 + b.m11, | |
| m12 = a.m12 + b.m12, | |
| m13 = a.m13 + b.m13, | |
| m20 = a.m20 + b.m20, | |
| m21 = a.m21 + b.m21, | |
| m22 = a.m22 + b.m22, | |
| m23 = a.m23 + b.m23, | |
| m30 = a.m30 + b.m30, | |
| m31 = a.m31 + b.m31, | |
| m32 = a.m32 + b.m32, | |
| m33 = a.m33 + b.m33, | |
| }; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Shader "Hidden/ColorMatrixCorrection" { | |
| Properties { | |
| _MainTex ("Base (RGB)", 2D) = "white" {} | |
| } | |
| SubShader { | |
| Cull Off | |
| ZWrite Off | |
| ZTest Always | |
| Pass { | |
| CGPROGRAM | |
| #pragma vertex vert_img | |
| #pragma fragment frag | |
| #include "UnityCG.cginc" | |
| uniform sampler2D _MainTex; | |
| uniform fixed4x4 _ColorMatrix; | |
| uniform fixed4 _BaseColor; | |
| fixed4 frag(v2f_img i): COLOR { | |
| return mul(tex2D(_MainTex, i.uv), _ColorMatrix) + _BaseColor; | |
| } | |
| ENDCG | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| using UnityEditor; | |
| [CustomPropertyDrawer(typeof(Matrix4x4))] | |
| class MatrixDrawer: PropertyDrawer { | |
| static Rect GetRelativeRect(Rect original, float row) { | |
| return new Rect(original.x, original.y + EditorGUIUtility.singleLineHeight * row, original.width, EditorGUIUtility.singleLineHeight); | |
| } | |
| static readonly GUIContent[] rowContent = new[] { new GUIContent("0"), new GUIContent("1"), new GUIContent("2"), new GUIContent("3") }; | |
| static readonly GUIContent emptySpaceContent = new GUIContent(" "); | |
| readonly SerializedProperty[] sp = new SerializedProperty[4]; | |
| readonly float[] values = new float[4]; | |
| void OnGUIRow(Rect position, SerializedProperty property, int row, GUIContent label) { | |
| int i; | |
| for(i = 0; i < 4; i++) { | |
| sp[i] = property.FindPropertyRelative(string.Format("e{0}{1}", row, i)); | |
| values[i] = sp[i].floatValue; | |
| } | |
| EditorGUI.BeginChangeCheck(); | |
| EditorGUI.MultiFloatField(GetRelativeRect(position, row), label, rowContent, values); | |
| if(!EditorGUI.EndChangeCheck()) return; | |
| for(i = 0; i < 4; i++) | |
| sp[i].floatValue = values[i]; | |
| } | |
| public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { | |
| EditorGUI.BeginProperty(position, label, property); | |
| OnGUIRow(position, property, 0, label); | |
| OnGUIRow(position, property, 1, emptySpaceContent); | |
| OnGUIRow(position, property, 2, emptySpaceContent); | |
| OnGUIRow(position, property, 3, emptySpaceContent); | |
| EditorGUI.EndProperty(); | |
| } | |
| public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { | |
| return EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 4 : 5); | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
The color matrix maps the color channel like this:
Result:
R' = R * Rr + G * Gr + B * Br + WrG' = R * Rg + G * Gg + B * Bg + WgB' = R * Rb + G * Gb + B * Bb + WbUnlike implementations in other platform/frameworks, the alpha channel will not be affected or involved in the calculation, also the fourth column of the matrix is unused. Have a remind that because of this limitation, the functionality of fifth row in most implementations (which will add/subtract a constant value after multiplication) will be in the fourth row here, which have values
Wr,WgandWbmentioned in the table above.Example
Black and white (Gray scale):
Inverted color:
Other references