diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes.meta new file mode 100644 index 000000000..c3ef039c0 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dfdd78a071ca1a04bb64c6cc41e14aa0 +folderAsset: yes +timeCreated: 1496447038 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor.meta new file mode 100644 index 000000000..80a6cfcf3 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1ad4318c20ec5674a9f4d7f786afd681 +folderAsset: yes +timeCreated: 1496449217 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor/SlotBlendModesEditor.cs b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor/SlotBlendModesEditor.cs new file mode 100644 index 000000000..199ca484d --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor/SlotBlendModesEditor.cs @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +using UnityEngine; +using UnityEditor; +using Spine.Unity.Modules; + +namespace Spine.Unity.Editor { + using Editor = UnityEditor.Editor; + + public class SlotBlendModesEditor : Editor { + + [MenuItem("CONTEXT/SkeletonRenderer/Add Slot Blend Modes Component")] + static void AddSlotBlendModesComponent (MenuCommand command) { + var skeletonRenderer = (SkeletonRenderer)command.context; + skeletonRenderer.gameObject.AddComponent(); + } + } +} + diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor/SlotBlendModesEditor.cs.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor/SlotBlendModesEditor.cs.meta new file mode 100644 index 000000000..21d0e26fe --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Editor/SlotBlendModesEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cbec7dc66dca80a419477536c23b7a0d +timeCreated: 1496449255 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAMultiply.mat b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAMultiply.mat new file mode 100644 index 000000000..28c90c143 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAMultiply.mat @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: SkeletonPMAMultiply + m_Shader: {fileID: 4800000, guid: 8bdcdc7ee298e594a9c20c61d25c33b6, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: + second: 0 + - first: + name: _Cutoff + second: 0.1 + m_Colors: + - first: + name: + second: {r: 0, g: 2.018574, b: 1e-45, a: 0.000007110106} + - first: + name: _Color + second: {r: 1, g: 1, b: 1, a: 1} diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAMultiply.mat.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAMultiply.mat.meta new file mode 100644 index 000000000..c8c803849 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAMultiply.mat.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 53bf0ab317d032d418cf1252d68f51df +timeCreated: 1496447909 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAScreen.mat b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAScreen.mat new file mode 100644 index 000000000..601f987ed --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAScreen.mat @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: SkeletonPMAScreen + m_Shader: {fileID: 4800000, guid: 4e8caa36c07aacf4ab270da00784e4d9, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: + second: 0 + - first: + name: _Cutoff + second: 0.1 + m_Colors: + - first: + name: + second: {r: 0, g: 2.018574, b: 1e-45, a: 0.000007121922} + - first: + name: _Color + second: {r: 1, g: 1, b: 1, a: 1} diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAScreen.mat.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAScreen.mat.meta new file mode 100644 index 000000000..6a1a749da --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SkeletonPMAScreen.mat.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 73f0f46d3177c614baf0fa48d646a9be +timeCreated: 1496447909 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SlotBlendModes.cs b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SlotBlendModes.cs new file mode 100644 index 000000000..632494380 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SlotBlendModes.cs @@ -0,0 +1,152 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +using System.Collections.Generic; +using UnityEngine; + +namespace Spine.Unity.Modules { + + [DisallowMultipleComponent] + public class SlotBlendModes : MonoBehaviour { + + #region Internal Material Dictionary + public struct MaterialTexturePair { + public Texture2D texture2D; + public Material material; + } + + static Dictionary materialTable; + internal static Dictionary MaterialTable { + get { + if (materialTable == null) materialTable = new Dictionary(); + return materialTable; + } + } + + internal static Material GetMaterialFor (Material materialSource, Texture2D texture) { + if (materialSource == null || texture == null) return null; + + var mt = SlotBlendModes.MaterialTable; + Material m; + var key = new MaterialTexturePair { material = materialSource, texture2D = texture }; + if (!mt.TryGetValue(key, out m)) { + m = new Material(materialSource); + m.name = "(Clone)" + texture.name + "-" + materialSource.name; + m.mainTexture = texture; + mt[key] = m; + } + + return m; + } + #endregion + + #region Inspector + public Material multiplyMaterialSource; + public Material screenMaterialSource; + + Texture2D texture; + #endregion + + public bool Applied { get; private set; } + + void Start () { + if (!Applied) Apply(); + } + + void OnDestroy () { + if (Applied) Remove(); + } + + public void Apply () { + GetTexture(); + if (texture == null) return; + + var skeletonRenderer = GetComponent(); + if (skeletonRenderer == null) return; + + var slotMaterials = skeletonRenderer.CustomSlotMaterials; + + foreach (var s in skeletonRenderer.Skeleton.Slots) { + switch (s.data.blendMode) { + case BlendMode.Multiply: + if (multiplyMaterialSource != null) slotMaterials[s] = GetMaterialFor(multiplyMaterialSource, texture); + break; + case BlendMode.Screen: + if (screenMaterialSource != null) slotMaterials[s] = GetMaterialFor(screenMaterialSource, texture); + break; + } + } + + Applied = true; + skeletonRenderer.LateUpdate(); + } + + public void Remove () { + GetTexture(); + if (texture == null) return; + + var skeletonRenderer = GetComponent(); + if (skeletonRenderer == null) return; + + var slotMaterials = skeletonRenderer.CustomSlotMaterials; + + foreach (var s in skeletonRenderer.Skeleton.Slots) { + Material m = null; + + switch (s.data.blendMode) { + case BlendMode.Multiply: + if (slotMaterials.TryGetValue(s, out m) && Material.ReferenceEquals(m, GetMaterialFor(multiplyMaterialSource, texture))) + slotMaterials.Remove(s); + break; + case BlendMode.Screen: + if (slotMaterials.TryGetValue(s, out m) && Material.ReferenceEquals(m, GetMaterialFor(screenMaterialSource, texture))) + slotMaterials.Remove(s); + break; + } + } + + Applied = false; + skeletonRenderer.LateUpdate(); + } + + public void GetTexture () { + if (texture == null) { + var sr = GetComponent(); if (sr == null) return; + var sda = sr.skeletonDataAsset; if (sda == null) return; + var aa = sda.atlasAssets[0]; if (aa == null) return; + var am = aa.materials[0]; if (am == null) return; + texture = am.mainTexture as Texture2D; + } + } + + + } +} + diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SlotBlendModes.cs.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SlotBlendModes.cs.meta new file mode 100644 index 000000000..6750f1105 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/SlotBlendModes.cs.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: f1f8243645ba2e74aa3564bd956eed89 +timeCreated: 1496794038 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: + - multiplyMaterialSource: {fileID: 2100000, guid: 53bf0ab317d032d418cf1252d68f51df, + type: 2} + - screenMaterialSource: {fileID: 2100000, guid: 73f0f46d3177c614baf0fa48d646a9be, + type: 2} + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Multiply.shader b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Multiply.shader new file mode 100644 index 000000000..26126be06 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Multiply.shader @@ -0,0 +1,101 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +// Spine/Skeleton PMA Multiply +// - single color multiply tint +// - unlit +// - Premultiplied alpha Multiply blending +// - No depth, no backface culling, no fog. +// - ShadowCaster pass + +Shader "Spine/Skeleton PMA Multiply" { + Properties { + _Color ("Tint Color", Color) = (1,1,1,1) + [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} + _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + } + + SubShader { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + LOD 100 + + Fog { Mode Off } + Cull Off + ZWrite Off + Blend DstColor OneMinusSrcAlpha + Lighting Off + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + uniform sampler2D _MainTex; + uniform float4 _Color; + + struct VertexInput { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + float4 vertexColor : COLOR; + }; + + struct VertexOutput { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 vertexColor : COLOR; + }; + + VertexOutput vert (VertexInput v) { + VertexOutput o; + o.pos = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + o.vertexColor = v.vertexColor * float4(_Color.rgb * _Color.a, _Color.a); // Combine a PMA version of _Color with vertexColor. + return o; + } + + float4 frag (VertexOutput i) : COLOR { + float4 texColor = tex2D(_MainTex, i.uv); + return (texColor * i.vertexColor); + } + ENDCG + } + + Pass { + Name "Caster" + Tags { "LightMode"="ShadowCaster" } + Offset 1, 1 + + ZWrite On + ZTest LEqual + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #pragma fragmentoption ARB_precision_hint_fastest + #include "UnityCG.cginc" + struct v2f { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + }; + + uniform float4 _MainTex_ST; + + v2f vert (appdata_base v) { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + return o; + } + + uniform sampler2D _MainTex; + uniform fixed _Cutoff; + + float4 frag (v2f i) : COLOR { + fixed4 texcol = tex2D(_MainTex, i.uv); + clip(texcol.a - _Cutoff); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } + } +} \ No newline at end of file diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Multiply.shader.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Multiply.shader.meta new file mode 100644 index 000000000..f3119889b --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Multiply.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8bdcdc7ee298e594a9c20c61d25c33b6 +timeCreated: 1496446742 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Screen.shader b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Screen.shader new file mode 100644 index 000000000..d97397036 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Screen.shader @@ -0,0 +1,99 @@ +// Spine/Skeleton PMA Multiply +// - single color multiply tint +// - unlit +// - Premultiplied alpha Multiply blending +// - No depth, no backface culling, no fog. +// - ShadowCaster pass + +Shader "Spine/Skeleton PMA Screen" { + Properties { + _Color ("Tint Color", Color) = (1,1,1,1) + [NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {} + _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1 + } + + SubShader { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + LOD 100 + + Fog { Mode Off } + Cull Off + ZWrite Off + Blend One OneMinusSrcColor + Lighting Off + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + uniform sampler2D _MainTex; + uniform float4 _Color; + + struct VertexInput { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + float4 vertexColor : COLOR; + }; + + struct VertexOutput { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 vertexColor : COLOR; + }; + + VertexOutput vert (VertexInput v) { + VertexOutput o; + o.pos = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + o.vertexColor = v.vertexColor * float4(_Color.rgb * _Color.a, _Color.a); // Combine a PMA version of _Color with vertexColor. + return o; + } + + float4 frag (VertexOutput i) : COLOR { + float4 texColor = tex2D(_MainTex, i.uv); + return (texColor * i.vertexColor); + } + ENDCG + } + + Pass { + Name "Caster" + Tags { "LightMode"="ShadowCaster" } + Offset 1, 1 + + ZWrite On + ZTest LEqual + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #pragma fragmentoption ARB_precision_hint_fastest + #include "UnityCG.cginc" + struct v2f { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + }; + + uniform float4 _MainTex_ST; + + v2f vert (appdata_base v) { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + return o; + } + + uniform sampler2D _MainTex; + uniform fixed _Cutoff; + + float4 frag (v2f i) : COLOR { + fixed4 texcol = tex2D(_MainTex, i.uv); + clip(texcol.a - _Cutoff); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } + } +} \ No newline at end of file diff --git a/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Screen.shader.meta b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Screen.shader.meta new file mode 100644 index 000000000..173ff6a26 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SlotBlendModes/Spine-Skeleton-PMA-Screen.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4e8caa36c07aacf4ab270da00784e4d9 +timeCreated: 1496448787 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: