Skip to content

Instantly share code, notes, and snippets.

@JLChnToZ
Last active December 22, 2017 12:39
Show Gist options
  • Select an option

  • Save JLChnToZ/c2642b5c2edd05db28a27e83f149d440 to your computer and use it in GitHub Desktop.

Select an option

Save JLChnToZ/c2642b5c2edd05db28a27e83f149d440 to your computer and use it in GitHub Desktop.
Unity rendering post processor which corrects the color with a color matrix.
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,
};
}
}
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
}
}
}
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);
}
}
@JLChnToZ

JLChnToZ commented Oct 11, 2016

Copy link
Copy Markdown
Author

Usage

The color matrix maps the color channel like this:

Output R G B A
R Rr Rg Rb -
G Gr Gg Gb -
B Br Bg Bb -
- Wr Wg Wb -

Result:
R' = R * Rr + G * Gr + B * Br + Wr
G' = R * Rg + G * Gg + B * Bg + Wg
B' = R * Rb + G * Gb + B * Bb + Wb

Unlike 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, Wg and Wb mentioned in the table above.

Example

Black and white (Gray scale):

R G B A
0.33 0.33 0.33 0
0.59 0.59 0.59 0
0.11 0.11 0.11 0
0 0 0 0

Inverted color:

R G B A
-1 0 0 0
0 -1 0 0
0 0 -1 0
1 1 1 0

Demonstration

Other references

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment