Skip to content

Instantly share code, notes, and snippets.

@Stektpotet
Last active February 14, 2017 19:15
Show Gist options
  • Save Stektpotet/3a566f41d60c8952c10304b5b327a47b to your computer and use it in GitHub Desktop.
Save Stektpotet/3a566f41d60c8952c10304b5b327a47b to your computer and use it in GitHub Desktop.
WIP stuff for blending textures (SplatLayers)
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