Last active
February 14, 2017 19:15
-
-
Save Stektpotet/3a566f41d60c8952c10304b5b327a47b to your computer and use it in GitHub Desktop.
WIP stuff for blending textures (SplatLayers)
This file contains 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 System; | |
using System.Collections.Generic; | |
using UnityEngine; | |
namespace LowPolySystems | |
{ | |
[System.Serializable] | |
[CreateAssetMenu( fileName = "default blends", menuName = "wat")] | |
public class BlendMode : ScriptableObject | |
{ | |
public Color this[Color a, Color b] { get { return blend(a, b); } } | |
private Func<Color, Color, Color> blend; | |
public BlendMode(Func<Color, Color, Color> blend) | |
{ | |
this.blend = blend; | |
} | |
public static readonly BlendMode NORMAL = new BlendMode((a, b) => Normal(a, b)); | |
public static readonly BlendMode MULTIPLY = new BlendMode((a, b) => Multiply(a, b)); | |
public static readonly BlendMode SCREEN = new BlendMode((a, b) => Screen(a, b)); | |
public static readonly BlendMode OVERLAY = new BlendMode((a, b) => Overlay(a, b)); | |
public static readonly BlendMode DIVIDE = new BlendMode((a, b) => Divide(a, b)); | |
public static readonly BlendMode ADD = new BlendMode((a, b) => Add(a, b)); | |
public static readonly BlendMode SUBTRACT = new BlendMode((a, b) => Subtract(a, b)); | |
public static readonly BlendMode DIFFERENCE = new BlendMode((a, b) => Difference(a, b)); | |
public static readonly BlendMode DARKEN = new BlendMode((a, b) => Darken(a, b)); | |
public static readonly BlendMode LIGHTEN = new BlendMode((a, b) => Lighten(a, b)); | |
private static Color Normal(Color a, Color b) | |
{ return (a * a.a + b * b.a * (1.0f - a.a)) / (a.a + b.a * 1.0f - a.a); } | |
private static Color Multiply(Color a, Color b) | |
{ return a * b; } | |
private static Color Screen(Color a, Color b) | |
{ return Inverse(Multiply(Inverse(a), Inverse(b))); } | |
private static Color Overlay(Color a, Color b) | |
{ return (a.grayscale < 0.5f) ? 2 * Multiply(a, b) : Inverse(2 * Inverse(a) * Inverse(b)); } | |
private static Color Divide(Color a, Color b) | |
{ return new Color(a.r / b.r, a.g / b.g, a.b / b.b, a.a / b.a); } | |
private static Color Add(Color a, Color b) | |
{ return (a + b); } | |
private static Color Subtract(Color a, Color b) | |
{ return a - b; } | |
private static Color Difference(Color a, Color b) | |
{ return b - a; } | |
private static Color Darken(Color a, Color b) | |
{ return new Color(Mathf.Min(a.r, b.r), Mathf.Min(a.g, b.g), Mathf.Min(a.b, b.b), Mathf.Min(a.a, b.a)); } | |
private static Color Lighten(Color a, Color b) | |
{ return new Color(Mathf.Max(a.r, b.r), Mathf.Max(a.g, b.g), Mathf.Max(a.b, b.b), Mathf.Max(a.a, b.a)); } | |
//Utility | |
private static Color Inverse(Color c) { return Color.white - c; } | |
} | |
[System.Serializable] | |
public class SplatLayer | |
{ | |
public Texture2D m_layerTexture; | |
public int width { get { return m_layerTexture.width; } } | |
public int height{ get { return m_layerTexture.height; } } | |
private Color this[int x,int y] { | |
get { return m_layerTexture.GetPixel(x, y); } | |
set { m_layerTexture.SetPixel(x, y, value); } | |
} | |
public BlendMode blendMode; | |
public SplatLayer(int width, int height) | |
{ m_layerTexture = new Texture2D(width, height,TextureFormat.RGBA32,false); | |
} | |
public SplatLayer Blend(SplatLayer over) { return Blend(over, blendMode); } | |
public SplatLayer Blend(SplatLayer over, BlendMode mode) | |
{ | |
SplatLayer result = new SplatLayer(width, height); | |
for (int y = 0; y < height; y++) | |
{ | |
for (int x = 0; x < width; x++) | |
{ | |
result[x, y] = mode[this[x, y], over[x, y]]; | |
} | |
} | |
result.m_layerTexture.Apply(); | |
return result; | |
} | |
//expressions based on blendmode naming | |
public static SplatLayer operator &(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.NORMAL); } | |
public static SplatLayer operator +(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.ADD); } | |
public static SplatLayer operator -(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.SUBTRACT); } | |
public static SplatLayer operator /(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.DIVIDE); } | |
public static SplatLayer operator *(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.MULTIPLY); } | |
public static SplatLayer operator <(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.DARKEN); } | |
public static SplatLayer operator >(SplatLayer a, SplatLayer b) | |
{ return a.Blend(b, BlendMode.LIGHTEN); } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment