提交Spine插件
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdfae2bc4b385b84eb4f5f6855d0f991
|
||||
folderAsset: yes
|
||||
timeCreated: 1537527020
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,263 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
|
||||
//[CreateAssetMenu(menuName = "Spine/SkeletonData Modifiers/Animation Match", order = 200)]
|
||||
public class AnimationMatchModifierAsset : SkeletonDataModifierAsset {
|
||||
|
||||
public bool matchAllAnimations = true;
|
||||
|
||||
public override void Apply (SkeletonData skeletonData) {
|
||||
if (matchAllAnimations)
|
||||
AnimationTools.MatchAnimationTimelines(skeletonData.animations, skeletonData);
|
||||
}
|
||||
|
||||
public static class AnimationTools {
|
||||
|
||||
#region Filler Timelines
|
||||
/// <summary>
|
||||
/// Matches the animation timelines across the given set of animations.
|
||||
/// This allows unkeyed properties to assume setup pose when animations are naively mixed using Animation.Apply.
|
||||
/// </summary>
|
||||
/// <param name="animations">An enumerable collection animations whose timelines will be matched.</param>
|
||||
/// <param name="skeletonData">The SkeletonData where the animations belong.</param>
|
||||
public static void MatchAnimationTimelines (IEnumerable<Spine.Animation> animations, SkeletonData skeletonData) {
|
||||
if (animations == null) return;
|
||||
if (skeletonData == null) throw new System.ArgumentNullException("skeletonData", "Timelines can't be matched without a SkeletonData source.");
|
||||
|
||||
// Build a reference collection of timelines to match
|
||||
// and a collection of dummy timelines that can be used to fill-in missing items.
|
||||
var timelineDictionary = new Dictionary<int, Spine.Timeline>();
|
||||
foreach (var animation in animations) {
|
||||
foreach (var timeline in animation.timelines) {
|
||||
if (timeline is EventTimeline) continue;
|
||||
|
||||
int propertyID = timeline.PropertyId;
|
||||
if (!timelineDictionary.ContainsKey(propertyID)) {
|
||||
timelineDictionary.Add(propertyID, GetFillerTimeline(timeline, skeletonData));
|
||||
}
|
||||
}
|
||||
}
|
||||
var idsToMatch = new List<int>(timelineDictionary.Keys);
|
||||
|
||||
// For each animation in the list, check for and add missing timelines.
|
||||
var currentAnimationIDs = new HashSet<int>();
|
||||
foreach (var animation in animations) {
|
||||
currentAnimationIDs.Clear();
|
||||
foreach (var timeline in animation.timelines) {
|
||||
if (timeline is EventTimeline) continue;
|
||||
currentAnimationIDs.Add(timeline.PropertyId);
|
||||
}
|
||||
|
||||
var animationTimelines = animation.timelines;
|
||||
foreach (int propertyID in idsToMatch) {
|
||||
if (!currentAnimationIDs.Contains(propertyID))
|
||||
animationTimelines.Add(timelineDictionary[propertyID]);
|
||||
}
|
||||
}
|
||||
|
||||
// These are locals, but sometimes Unity's GC does weird stuff. So let's clean up.
|
||||
timelineDictionary.Clear();
|
||||
timelineDictionary = null;
|
||||
idsToMatch.Clear();
|
||||
idsToMatch = null;
|
||||
currentAnimationIDs.Clear();
|
||||
currentAnimationIDs = null;
|
||||
}
|
||||
|
||||
static Timeline GetFillerTimeline (Timeline timeline, SkeletonData skeletonData) {
|
||||
int propertyID = timeline.PropertyId;
|
||||
int tt = propertyID >> 24;
|
||||
var timelineType = (TimelineType)tt;
|
||||
|
||||
switch (timelineType) {
|
||||
// Bone
|
||||
case TimelineType.Rotate:
|
||||
return GetFillerTimeline((RotateTimeline)timeline, skeletonData);
|
||||
case TimelineType.Translate:
|
||||
return GetFillerTimeline((TranslateTimeline)timeline, skeletonData);
|
||||
case TimelineType.Scale:
|
||||
return GetFillerTimeline((ScaleTimeline)timeline, skeletonData);
|
||||
case TimelineType.Shear:
|
||||
return GetFillerTimeline((ShearTimeline)timeline, skeletonData);
|
||||
|
||||
// Slot
|
||||
case TimelineType.Attachment:
|
||||
return GetFillerTimeline((AttachmentTimeline)timeline, skeletonData);
|
||||
case TimelineType.Color:
|
||||
return GetFillerTimeline((ColorTimeline)timeline, skeletonData);
|
||||
case TimelineType.TwoColor:
|
||||
return GetFillerTimeline((TwoColorTimeline)timeline, skeletonData);
|
||||
case TimelineType.Deform:
|
||||
return GetFillerTimeline((DeformTimeline)timeline, skeletonData);
|
||||
|
||||
// Skeleton
|
||||
case TimelineType.DrawOrder:
|
||||
return GetFillerTimeline((DrawOrderTimeline)timeline, skeletonData);
|
||||
|
||||
// IK Constraint
|
||||
case TimelineType.IkConstraint:
|
||||
return GetFillerTimeline((IkConstraintTimeline)timeline, skeletonData);
|
||||
|
||||
// TransformConstraint
|
||||
case TimelineType.TransformConstraint:
|
||||
return GetFillerTimeline((TransformConstraintTimeline)timeline, skeletonData);
|
||||
|
||||
// Path Constraint
|
||||
case TimelineType.PathConstraintPosition:
|
||||
return GetFillerTimeline((PathConstraintPositionTimeline)timeline, skeletonData);
|
||||
case TimelineType.PathConstraintSpacing:
|
||||
return GetFillerTimeline((PathConstraintSpacingTimeline)timeline, skeletonData);
|
||||
case TimelineType.PathConstraintMix:
|
||||
return GetFillerTimeline((PathConstraintMixTimeline)timeline, skeletonData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static RotateTimeline GetFillerTimeline (RotateTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new RotateTimeline(1);
|
||||
t.boneIndex = timeline.boneIndex;
|
||||
t.SetFrame(0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TranslateTimeline GetFillerTimeline (TranslateTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new TranslateTimeline(1);
|
||||
t.boneIndex = timeline.boneIndex;
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ScaleTimeline GetFillerTimeline (ScaleTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new ScaleTimeline(1);
|
||||
t.boneIndex = timeline.boneIndex;
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ShearTimeline GetFillerTimeline (ShearTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new ShearTimeline(1);
|
||||
t.boneIndex = timeline.boneIndex;
|
||||
t.SetFrame(0, 0, 0, 0);
|
||||
return t;
|
||||
}
|
||||
|
||||
static AttachmentTimeline GetFillerTimeline (AttachmentTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new AttachmentTimeline(1);
|
||||
t.slotIndex = timeline.slotIndex;
|
||||
var slotData = skeletonData.slots.Items[t.slotIndex];
|
||||
t.SetFrame(0, 0, slotData.attachmentName);
|
||||
return t;
|
||||
}
|
||||
|
||||
static ColorTimeline GetFillerTimeline (ColorTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new ColorTimeline(1);
|
||||
t.slotIndex = timeline.slotIndex;
|
||||
var slotData = skeletonData.slots.Items[t.slotIndex];
|
||||
t.SetFrame(0, 0, slotData.r, slotData.g, slotData.b, slotData.a);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TwoColorTimeline GetFillerTimeline (TwoColorTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new TwoColorTimeline(1);
|
||||
t.slotIndex = timeline.slotIndex;
|
||||
var slotData = skeletonData.slots.Items[t.slotIndex];
|
||||
t.SetFrame(0, 0, slotData.r, slotData.g, slotData.b, slotData.a, slotData.r2, slotData.g2, slotData.b2);
|
||||
return t;
|
||||
}
|
||||
|
||||
static DeformTimeline GetFillerTimeline (DeformTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new DeformTimeline(1);
|
||||
t.slotIndex = timeline.slotIndex;
|
||||
t.attachment = timeline.attachment;
|
||||
|
||||
if (t.attachment.IsWeighted()) {
|
||||
t.SetFrame(0, 0, new float[t.attachment.vertices.Length]);
|
||||
} else {
|
||||
t.SetFrame(0, 0, t.attachment.vertices.Clone() as float[]);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static DrawOrderTimeline GetFillerTimeline (DrawOrderTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new DrawOrderTimeline(1);
|
||||
t.SetFrame(0, 0, null); // null means use setup pose in DrawOrderTimeline.Apply.
|
||||
return t;
|
||||
}
|
||||
|
||||
static IkConstraintTimeline GetFillerTimeline (IkConstraintTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new IkConstraintTimeline(1);
|
||||
var ikConstraintData = skeletonData.ikConstraints.Items[timeline.ikConstraintIndex];
|
||||
t.SetFrame(0, 0, ikConstraintData.mix, ikConstraintData.bendDirection, ikConstraintData.compress, ikConstraintData.stretch);
|
||||
return t;
|
||||
}
|
||||
|
||||
static TransformConstraintTimeline GetFillerTimeline (TransformConstraintTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new TransformConstraintTimeline(1);
|
||||
var data = skeletonData.transformConstraints.Items[timeline.transformConstraintIndex];
|
||||
t.SetFrame(0, 0, data.rotateMix, data.translateMix, data.scaleMix, data.shearMix);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintPositionTimeline GetFillerTimeline (PathConstraintPositionTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new PathConstraintPositionTimeline(1);
|
||||
var data = skeletonData.pathConstraints.Items[timeline.pathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.position);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintSpacingTimeline GetFillerTimeline (PathConstraintSpacingTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new PathConstraintSpacingTimeline(1);
|
||||
var data = skeletonData.pathConstraints.Items[timeline.pathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.spacing);
|
||||
return t;
|
||||
}
|
||||
|
||||
static PathConstraintMixTimeline GetFillerTimeline (PathConstraintMixTimeline timeline, SkeletonData skeletonData) {
|
||||
var t = new PathConstraintMixTimeline(1);
|
||||
var data = skeletonData.pathConstraints.Items[timeline.pathConstraintIndex];
|
||||
t.SetFrame(0, 0, data.rotateMix, data.translateMix);
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df7d457928e0f4041a439f9847f72290
|
||||
timeCreated: 1537527074
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
AnimationMatchModifierAsset
|
||||
===========================
|
||||
|
||||
This is a SkeletonDataModifierAsset. Add it to a SkeletonDataAsset to apply its effects when its SkeletonData is loaded.
|
||||
|
||||
AnimationMatchModifierAsset processes animations so that their timelines match. This allows them to function with naive Animation Apply systems such as SkeletonMecanim without the need for autoreset functionality.
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4436c0c78cc5ee469089ed864f4e1ea
|
||||
timeCreated: 1537528259
|
||||
licenseType: Pro
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: df7d457928e0f4041a439f9847f72290, type: 3}
|
||||
m_Name: Default Match All Animations
|
||||
m_EditorClassIdentifier:
|
||||
matchAllAnimations: 1
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8623082208cae724e88314ec951691e1
|
||||
timeCreated: 1537527914
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f601b524e4da4704a9e0f6b7e05d6ca6
|
||||
folderAsset: yes
|
||||
timeCreated: 1478437840
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8dd46dbf979fcb7459246cd37aad09ef
|
||||
timeCreated: 1478437807
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86b1ae3ec8681c646aea49654969b73c
|
||||
folderAsset: yes
|
||||
timeCreated: 1455492474
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,248 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
public class BoundingBoxFollower : MonoBehaviour {
|
||||
internal static bool DebugMessages = true;
|
||||
|
||||
#region Inspector
|
||||
public SkeletonRenderer skeletonRenderer;
|
||||
[SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
|
||||
public string slotName;
|
||||
public bool isTrigger;
|
||||
public bool clearStateOnDisable = true;
|
||||
#endregion
|
||||
|
||||
Slot slot;
|
||||
BoundingBoxAttachment currentAttachment;
|
||||
string currentAttachmentName;
|
||||
PolygonCollider2D currentCollider;
|
||||
|
||||
public readonly Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
|
||||
public readonly Dictionary<BoundingBoxAttachment, string> nameTable = new Dictionary<BoundingBoxAttachment, string>();
|
||||
|
||||
public Slot Slot { get { return slot; } }
|
||||
public BoundingBoxAttachment CurrentAttachment { get { return currentAttachment; } }
|
||||
public string CurrentAttachmentName { get { return currentAttachmentName; } }
|
||||
public PolygonCollider2D CurrentCollider { get { return currentCollider; } }
|
||||
public bool IsTrigger { get { return isTrigger; } }
|
||||
|
||||
void Start () {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
if (skeletonRenderer != null) {
|
||||
skeletonRenderer.OnRebuild -= HandleRebuild;
|
||||
skeletonRenderer.OnRebuild += HandleRebuild;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void HandleRebuild (SkeletonRenderer sr) {
|
||||
//if (BoundingBoxFollower.DebugMessages) Debug.Log("Skeleton was rebuilt. Repopulating BoundingBoxFollower.");
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize and instantiate the BoundingBoxFollower colliders. This is method checks if the BoundingBoxFollower has already been initialized for the skeleton instance and slotName and prevents overwriting unless it detects a new setup.</summary>
|
||||
public void Initialize (bool overwrite = false) {
|
||||
if (skeletonRenderer == null)
|
||||
return;
|
||||
|
||||
skeletonRenderer.Initialize(false);
|
||||
|
||||
if (string.IsNullOrEmpty(slotName))
|
||||
return;
|
||||
|
||||
// Don't reinitialize if the setup did not change.
|
||||
if (!overwrite
|
||||
&&
|
||||
colliderTable.Count > 0 && slot != null // Slot is set and colliders already populated.
|
||||
&&
|
||||
skeletonRenderer.skeleton == slot.Skeleton // Skeleton object did not change.
|
||||
&&
|
||||
slotName == slot.data.name // Slot object did not change.
|
||||
)
|
||||
return;
|
||||
|
||||
DisposeColliders();
|
||||
|
||||
var skeleton = skeletonRenderer.skeleton;
|
||||
slot = skeleton.FindSlot(slotName);
|
||||
int slotIndex = skeleton.FindSlotIndex(slotName);
|
||||
|
||||
if (slot == null) {
|
||||
if (BoundingBoxFollower.DebugMessages)
|
||||
Debug.LogWarning(string.Format("Slot '{0}' not found for BoundingBoxFollower on '{1}'. (Previous colliders were disposed.)", slotName, this.gameObject.name));
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.gameObject.activeInHierarchy) {
|
||||
foreach (var skin in skeleton.Data.Skins)
|
||||
AddSkin(skin, slotIndex);
|
||||
|
||||
if (skeleton.skin != null)
|
||||
AddSkin(skeleton.skin, slotIndex);
|
||||
}
|
||||
|
||||
if (BoundingBoxFollower.DebugMessages) {
|
||||
bool valid = colliderTable.Count != 0;
|
||||
if (!valid) {
|
||||
if (this.gameObject.activeInHierarchy)
|
||||
Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
|
||||
else
|
||||
Debug.LogWarning("Bounding Box Follower tried to rebuild as a prefab.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddSkin (Skin skin, int slotIndex) {
|
||||
if (skin == null) return;
|
||||
var attachmentNames = new List<string>();
|
||||
skin.FindNamesForSlot(slotIndex, attachmentNames);
|
||||
|
||||
foreach (var skinKey in attachmentNames) {
|
||||
var attachment = skin.GetAttachment(slotIndex, skinKey);
|
||||
var boundingBoxAttachment = attachment as BoundingBoxAttachment;
|
||||
|
||||
if (BoundingBoxFollower.DebugMessages && attachment != null && boundingBoxAttachment == null)
|
||||
Debug.Log("BoundingBoxFollower tried to follow a slot that contains non-boundingbox attachments: " + slotName);
|
||||
|
||||
if (boundingBoxAttachment != null) {
|
||||
if (!colliderTable.ContainsKey(boundingBoxAttachment)) {
|
||||
var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(boundingBoxAttachment, slot, gameObject, isTrigger);
|
||||
|
||||
bbCollider.enabled = false;
|
||||
bbCollider.hideFlags = HideFlags.NotEditable;
|
||||
bbCollider.isTrigger = IsTrigger;
|
||||
colliderTable.Add(boundingBoxAttachment, bbCollider);
|
||||
nameTable.Add(boundingBoxAttachment, skinKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (clearStateOnDisable)
|
||||
ClearState();
|
||||
}
|
||||
|
||||
public void ClearState () {
|
||||
if (colliderTable != null)
|
||||
foreach (var col in colliderTable.Values)
|
||||
col.enabled = false;
|
||||
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
currentCollider = null;
|
||||
}
|
||||
|
||||
void DisposeColliders () {
|
||||
var colliders = GetComponents<PolygonCollider2D>();
|
||||
if (colliders.Length == 0) return;
|
||||
|
||||
if (Application.isEditor) {
|
||||
if (Application.isPlaying) {
|
||||
foreach (var c in colliders) {
|
||||
if (c != null)
|
||||
Destroy(c);
|
||||
}
|
||||
} else {
|
||||
foreach (var c in colliders)
|
||||
if (c != null)
|
||||
DestroyImmediate(c);
|
||||
}
|
||||
} else {
|
||||
foreach (PolygonCollider2D c in colliders)
|
||||
if (c != null)
|
||||
Destroy(c);
|
||||
}
|
||||
|
||||
slot = null;
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
currentCollider = null;
|
||||
colliderTable.Clear();
|
||||
nameTable.Clear();
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
if (slot != null && slot.Attachment != currentAttachment)
|
||||
MatchAttachment(slot.Attachment);
|
||||
}
|
||||
|
||||
/// <summary>Sets the current collider to match attachment.</summary>
|
||||
/// <param name="attachment">If the attachment is not a bounding box, it will be treated as null.</param>
|
||||
void MatchAttachment (Attachment attachment) {
|
||||
var bbAttachment = attachment as BoundingBoxAttachment;
|
||||
|
||||
if (BoundingBoxFollower.DebugMessages && attachment != null && bbAttachment == null)
|
||||
Debug.LogWarning("BoundingBoxFollower tried to match a non-boundingbox attachment. It will treat it as null.");
|
||||
|
||||
if (currentCollider != null)
|
||||
currentCollider.enabled = false;
|
||||
|
||||
if (bbAttachment == null) {
|
||||
currentCollider = null;
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
} else {
|
||||
PolygonCollider2D foundCollider;
|
||||
colliderTable.TryGetValue(bbAttachment, out foundCollider);
|
||||
if (foundCollider != null) {
|
||||
currentCollider = foundCollider;
|
||||
currentCollider.enabled = true;
|
||||
currentAttachment = bbAttachment;
|
||||
currentAttachmentName = nameTable[bbAttachment];
|
||||
} else {
|
||||
currentCollider = null;
|
||||
currentAttachment = bbAttachment;
|
||||
currentAttachmentName = null;
|
||||
if (BoundingBoxFollower.DebugMessages) Debug.LogFormat("Collider for BoundingBoxAttachment named '{0}' was not initialized. It is possibly from a new skin. currentAttachmentName will be null. You may need to call BoundingBoxFollower.Initialize(overwrite: true);", bbAttachment.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0317ee9ba6e1b1e49a030268e026d372
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7236dbdc6a4e5a4989483dac97aee0b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,211 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
#define SPINE_OPTIONAL_MATERIALOVERRIDE
|
||||
|
||||
// Contributed by: Lost Polygon
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
public class SkeletonRendererCustomMaterials : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
public SkeletonRenderer skeletonRenderer;
|
||||
[SerializeField] protected List<SlotMaterialOverride> customSlotMaterials = new List<SlotMaterialOverride>();
|
||||
[SerializeField] protected List<AtlasMaterialOverride> customMaterialOverrides = new List<AtlasMaterialOverride>();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void Reset () {
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
|
||||
// Populate atlas list
|
||||
if (skeletonRenderer != null && skeletonRenderer.skeletonDataAsset != null) {
|
||||
var atlasAssets = skeletonRenderer.skeletonDataAsset.atlasAssets;
|
||||
|
||||
var initialAtlasMaterialOverrides = new List<AtlasMaterialOverride>();
|
||||
foreach (AtlasAssetBase atlasAsset in atlasAssets) {
|
||||
foreach (Material atlasMaterial in atlasAsset.Materials) {
|
||||
var atlasMaterialOverride = new AtlasMaterialOverride {
|
||||
overrideDisabled = true,
|
||||
originalMaterial = atlasMaterial
|
||||
};
|
||||
|
||||
initialAtlasMaterialOverrides.Add(atlasMaterialOverride);
|
||||
}
|
||||
}
|
||||
|
||||
customMaterialOverrides = initialAtlasMaterialOverrides;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
void SetCustomSlotMaterials () {
|
||||
if (skeletonRenderer == null) {
|
||||
Debug.LogError("skeletonRenderer == null");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < customSlotMaterials.Count; i++) {
|
||||
SlotMaterialOverride slotMaterialOverride = customSlotMaterials[i];
|
||||
if (slotMaterialOverride.overrideDisabled || string.IsNullOrEmpty(slotMaterialOverride.slotName))
|
||||
continue;
|
||||
|
||||
Slot slotObject = skeletonRenderer.skeleton.FindSlot(slotMaterialOverride.slotName);
|
||||
skeletonRenderer.CustomSlotMaterials[slotObject] = slotMaterialOverride.material;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveCustomSlotMaterials () {
|
||||
if (skeletonRenderer == null) {
|
||||
Debug.LogError("skeletonRenderer == null");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < customSlotMaterials.Count; i++) {
|
||||
SlotMaterialOverride slotMaterialOverride = customSlotMaterials[i];
|
||||
if (string.IsNullOrEmpty(slotMaterialOverride.slotName))
|
||||
continue;
|
||||
|
||||
Slot slotObject = skeletonRenderer.skeleton.FindSlot(slotMaterialOverride.slotName);
|
||||
|
||||
Material currentMaterial;
|
||||
if (!skeletonRenderer.CustomSlotMaterials.TryGetValue(slotObject, out currentMaterial))
|
||||
continue;
|
||||
|
||||
// Do not revert the material if it was changed by something else
|
||||
if (currentMaterial != slotMaterialOverride.material)
|
||||
continue;
|
||||
|
||||
skeletonRenderer.CustomSlotMaterials.Remove(slotObject);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCustomMaterialOverrides () {
|
||||
if (skeletonRenderer == null) {
|
||||
Debug.LogError("skeletonRenderer == null");
|
||||
return;
|
||||
}
|
||||
|
||||
#if SPINE_OPTIONAL_MATERIALOVERRIDE
|
||||
for (int i = 0; i < customMaterialOverrides.Count; i++) {
|
||||
AtlasMaterialOverride atlasMaterialOverride = customMaterialOverrides[i];
|
||||
if (atlasMaterialOverride.overrideDisabled)
|
||||
continue;
|
||||
|
||||
skeletonRenderer.CustomMaterialOverride[atlasMaterialOverride.originalMaterial] = atlasMaterialOverride.replacementMaterial;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RemoveCustomMaterialOverrides () {
|
||||
if (skeletonRenderer == null) {
|
||||
Debug.LogError("skeletonRenderer == null");
|
||||
return;
|
||||
}
|
||||
|
||||
#if SPINE_OPTIONAL_MATERIALOVERRIDE
|
||||
for (int i = 0; i < customMaterialOverrides.Count; i++) {
|
||||
AtlasMaterialOverride atlasMaterialOverride = customMaterialOverrides[i];
|
||||
Material currentMaterial;
|
||||
|
||||
if (!skeletonRenderer.CustomMaterialOverride.TryGetValue(atlasMaterialOverride.originalMaterial, out currentMaterial))
|
||||
continue;
|
||||
|
||||
// Do not revert the material if it was changed by something else
|
||||
if (currentMaterial != atlasMaterialOverride.replacementMaterial)
|
||||
continue;
|
||||
|
||||
skeletonRenderer.CustomMaterialOverride.Remove(atlasMaterialOverride.originalMaterial);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// OnEnable applies the overrides at runtime, and when the editor loads.
|
||||
void OnEnable () {
|
||||
if (skeletonRenderer == null)
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
|
||||
if (skeletonRenderer == null) {
|
||||
Debug.LogError("skeletonRenderer == null");
|
||||
return;
|
||||
}
|
||||
|
||||
skeletonRenderer.Initialize(false);
|
||||
SetCustomMaterialOverrides();
|
||||
SetCustomSlotMaterials();
|
||||
}
|
||||
|
||||
// OnDisable removes the overrides at runtime, and in the editor when the component is disabled or destroyed.
|
||||
void OnDisable () {
|
||||
if (skeletonRenderer == null) {
|
||||
Debug.LogError("skeletonRenderer == null");
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveCustomMaterialOverrides();
|
||||
RemoveCustomSlotMaterials();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct SlotMaterialOverride : IEquatable<SlotMaterialOverride> {
|
||||
public bool overrideDisabled;
|
||||
|
||||
[SpineSlot]
|
||||
public string slotName;
|
||||
public Material material;
|
||||
|
||||
public bool Equals (SlotMaterialOverride other) {
|
||||
return overrideDisabled == other.overrideDisabled && slotName == other.slotName && material == other.material;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct AtlasMaterialOverride : IEquatable<AtlasMaterialOverride> {
|
||||
public bool overrideDisabled;
|
||||
public Material originalMaterial;
|
||||
public Material replacementMaterial;
|
||||
|
||||
public bool Equals (AtlasMaterialOverride other) {
|
||||
return overrideDisabled == other.overrideDisabled && originalMaterial == other.originalMaterial && replacementMaterial == other.replacementMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26947ae098a8447408d80c0c86e35b48
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
SkeletonRendererCustomMaterials by LostPolygon
|
||||
===============================
|
||||
This is a basic serialization and inspector implementation for custom material overrides for SkeletonRenderer and its derived classes (SkeletonAnimation, SkeletonAnimator).
|
||||
|
||||
## How to use
|
||||
Right-click on your SkeletonRenderer and select "Add Basic Serialized Custom Materials". This will add and initialize the SkeletonRendererCustomMaterials to the same object.
|
||||
|
||||
You can use this to store material override settings for SkeletonRenderer instances/prefabs so they will be applied automatically when your scene starts or when the prefab is instantiated.
|
||||
|
||||
This script is not intended for use with code.
|
||||
To dynamically set materials for your SkeletonRenderer through code, you can directly access `SkeletonRenderer.CustomMaterialOverride` for material array overrides and `SkeletonRenderer.CustomSlotMaterials` for slot material overrides.
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d4db6c367e463c4cb5566afc490163c
|
||||
timeCreated: 1460572571
|
||||
licenseType: Free
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
5
Assets/Spine/Runtime/spine-unity/Modules/Ghost.meta
Normal file
5
Assets/Spine/Runtime/spine-unity/Modules/Ghost.meta
Normal file
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13193c9d213765f4c85f4c1faa615711
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0cee0de78cef7440ae0b5aac39ae971
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,67 @@
|
||||
// - Unlit + no shadow
|
||||
// - Premultiplied Alpha Blending (One OneMinusSrcAlpha)
|
||||
// - Double-sided, no depth
|
||||
|
||||
Shader "Spine/Special/SkeletonGhost" {
|
||||
Properties {
|
||||
_Color ("Main Color", Color) = (1,1,1,1)
|
||||
[NoScaleOffset] _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
|
||||
_TextureFade ("Texture Fade Out", Range(0,1)) = 0
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
SubShader {
|
||||
Tags {
|
||||
"Queue"="Transparent"
|
||||
"IgnoreProjector"="False"
|
||||
"RenderType"="Transparent"
|
||||
}
|
||||
Fog { Mode Off }
|
||||
Blend One OneMinusSrcAlpha
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
fixed4 _Color;
|
||||
fixed _TextureFade;
|
||||
|
||||
struct VertexInput {
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
VertexOutput vert (VertexInput v) {
|
||||
VertexOutput o;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.uv;
|
||||
o.color = v.color;
|
||||
return o;
|
||||
}
|
||||
|
||||
fixed4 frag (VertexOutput i) : COLOR {
|
||||
fixed4 tc = tex2D(_MainTex, i.uv);
|
||||
tc = fixed4(max(_TextureFade, tc.r), max(_TextureFade, tc.g), max(_TextureFade, tc.b), tc.a);
|
||||
return tc * ((i.color * _Color) * tc.a);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3873d4699ee8a4b4da8fa6b8c229b94d
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
201
Assets/Spine/Runtime/spine-unity/Modules/Ghost/SkeletonGhost.cs
Normal file
201
Assets/Spine/Runtime/spine-unity/Modules/Ghost/SkeletonGhost.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonGhost : MonoBehaviour {
|
||||
// Internal Settings
|
||||
const HideFlags GhostHideFlags = HideFlags.HideInHierarchy;
|
||||
const string GhostingShaderName = "Spine/Special/SkeletonGhost";
|
||||
|
||||
[Header("Animation")]
|
||||
public bool ghostingEnabled = true;
|
||||
[Tooltip("The time between invididual ghost pieces being spawned.")]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("spawnRate")]
|
||||
public float spawnInterval = 1f/30f;
|
||||
[Tooltip("Maximum number of ghosts that can exist at a time. If the fade speed is not fast enough, the oldest ghost will immediately disappear to enforce the maximum number.")]
|
||||
public int maximumGhosts = 10;
|
||||
public float fadeSpeed = 10;
|
||||
|
||||
[Header("Rendering")]
|
||||
public Shader ghostShader;
|
||||
public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
|
||||
[Tooltip("Remember to set color alpha to 0 if Additive is true")]
|
||||
public bool additive = true;
|
||||
[Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
|
||||
[Range(0, 1)]
|
||||
public float textureFade = 1;
|
||||
|
||||
[Header("Sorting")]
|
||||
public bool sortWithDistanceOnly;
|
||||
public float zOffset = 0f;
|
||||
|
||||
float nextSpawnTime;
|
||||
SkeletonGhostRenderer[] pool;
|
||||
int poolIndex = 0;
|
||||
SkeletonRenderer skeletonRenderer;
|
||||
MeshRenderer meshRenderer;
|
||||
MeshFilter meshFilter;
|
||||
|
||||
readonly Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
|
||||
|
||||
void Start () {
|
||||
Initialize(false);
|
||||
}
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (pool == null || overwrite) {
|
||||
if (ghostShader == null)
|
||||
ghostShader = Shader.Find(GhostingShaderName);
|
||||
|
||||
skeletonRenderer = GetComponent<SkeletonRenderer>();
|
||||
meshFilter = GetComponent<MeshFilter>();
|
||||
meshRenderer = GetComponent<MeshRenderer>();
|
||||
nextSpawnTime = Time.time + spawnInterval;
|
||||
pool = new SkeletonGhostRenderer[maximumGhosts];
|
||||
for (int i = 0; i < maximumGhosts; i++) {
|
||||
GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
|
||||
pool[i] = go.GetComponent<SkeletonGhostRenderer>();
|
||||
go.SetActive(false);
|
||||
go.hideFlags = GhostHideFlags;
|
||||
}
|
||||
|
||||
var skeletonAnimation = skeletonRenderer as Spine.Unity.IAnimationStateComponent;
|
||||
if (skeletonAnimation != null)
|
||||
skeletonAnimation.AnimationState.Event += OnEvent;
|
||||
}
|
||||
}
|
||||
|
||||
//SkeletonAnimation
|
||||
/*
|
||||
* Int Value: 0 sets ghostingEnabled to false, 1 sets ghostingEnabled to true
|
||||
* Float Value: Values greater than 0 set the spawnRate equal the float value
|
||||
* String Value: Pass RGBA hex color values in to set the color property. IE: "A0FF8BFF"
|
||||
*/
|
||||
void OnEvent (Spine.TrackEntry trackEntry, Spine.Event e) {
|
||||
if (e.Data.Name.Equals("Ghosting", System.StringComparison.Ordinal)) {
|
||||
ghostingEnabled = e.Int > 0;
|
||||
if (e.Float > 0)
|
||||
spawnInterval = e.Float;
|
||||
|
||||
if (!string.IsNullOrEmpty(e.stringValue))
|
||||
this.color = HexToColor(e.String);
|
||||
}
|
||||
}
|
||||
|
||||
//SkeletonAnimator
|
||||
//SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled. Be sure not to set anything other than the Int param in Spine or String will take priority.
|
||||
void Ghosting (float val) {
|
||||
ghostingEnabled = val > 0;
|
||||
}
|
||||
|
||||
void Update () {
|
||||
if (!ghostingEnabled)
|
||||
return;
|
||||
|
||||
if (Time.time >= nextSpawnTime) {
|
||||
GameObject go = pool[poolIndex].gameObject;
|
||||
|
||||
Material[] materials = meshRenderer.sharedMaterials;
|
||||
for (int i = 0; i < materials.Length; i++) {
|
||||
var originalMat = materials[i];
|
||||
Material ghostMat;
|
||||
if (!materialTable.ContainsKey(originalMat)) {
|
||||
ghostMat = new Material(originalMat) {
|
||||
shader = ghostShader,
|
||||
color = Color.white
|
||||
};
|
||||
|
||||
if (ghostMat.HasProperty("_TextureFade"))
|
||||
ghostMat.SetFloat("_TextureFade", textureFade);
|
||||
|
||||
materialTable.Add(originalMat, ghostMat);
|
||||
} else {
|
||||
ghostMat = materialTable[originalMat];
|
||||
}
|
||||
|
||||
materials[i] = ghostMat;
|
||||
}
|
||||
|
||||
var goTransform = go.transform;
|
||||
goTransform.parent = transform;
|
||||
|
||||
pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
|
||||
|
||||
goTransform.localPosition = new Vector3(0f, 0f, zOffset);
|
||||
goTransform.localRotation = Quaternion.identity;
|
||||
goTransform.localScale = Vector3.one;
|
||||
|
||||
goTransform.parent = null;
|
||||
|
||||
poolIndex++;
|
||||
|
||||
if (poolIndex == pool.Length)
|
||||
poolIndex = 0;
|
||||
|
||||
nextSpawnTime = Time.time + spawnInterval;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (pool != null) {
|
||||
for (int i = 0; i < maximumGhosts; i++)
|
||||
if (pool[i] != null) pool[i].Cleanup();
|
||||
}
|
||||
|
||||
foreach (var mat in materialTable.Values)
|
||||
Destroy(mat);
|
||||
}
|
||||
|
||||
//based on UnifyWiki http://wiki.unity3d.com/index.php?title=HexConverter
|
||||
static Color32 HexToColor (string hex) {
|
||||
const System.Globalization.NumberStyles HexNumber = System.Globalization.NumberStyles.HexNumber;
|
||||
|
||||
if (hex.Length < 6)
|
||||
return Color.magenta;
|
||||
|
||||
hex = hex.Replace("#", "");
|
||||
byte r = byte.Parse(hex.Substring(0, 2), HexNumber);
|
||||
byte g = byte.Parse(hex.Substring(2, 2), HexNumber);
|
||||
byte b = byte.Parse(hex.Substring(4, 2), HexNumber);
|
||||
byte a = 0xFF;
|
||||
if (hex.Length == 8)
|
||||
a = byte.Parse(hex.Substring(6, 2), HexNumber);
|
||||
|
||||
return new Color32(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02f2fa991881c6d419500ccc40ad443f
|
||||
timeCreated: 1431858330
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- ghostShader: {fileID: 4800000, guid: 3873d4699ee8a4b4da8fa6b8c229b94d, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,128 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
public class SkeletonGhostRenderer : MonoBehaviour {
|
||||
static readonly Color32 TransparentBlack = new Color32(0, 0, 0, 0);
|
||||
const string colorPropertyName = "_Color";
|
||||
|
||||
float fadeSpeed = 10;
|
||||
Color32 startColor;
|
||||
MeshFilter meshFilter;
|
||||
MeshRenderer meshRenderer;
|
||||
|
||||
MaterialPropertyBlock mpb;
|
||||
int colorId;
|
||||
|
||||
void Awake () {
|
||||
meshRenderer = gameObject.AddComponent<MeshRenderer>();
|
||||
meshFilter = gameObject.AddComponent<MeshFilter>();
|
||||
|
||||
colorId = Shader.PropertyToID(colorPropertyName);
|
||||
mpb = new MaterialPropertyBlock();
|
||||
}
|
||||
|
||||
public void Initialize (Mesh mesh, Material[] materials, Color32 color, bool additive, float speed, int sortingLayerID, int sortingOrder) {
|
||||
StopAllCoroutines();
|
||||
|
||||
gameObject.SetActive(true);
|
||||
meshRenderer.sharedMaterials = materials;
|
||||
meshRenderer.sortingLayerID = sortingLayerID;
|
||||
meshRenderer.sortingOrder = sortingOrder;
|
||||
meshFilter.sharedMesh = Instantiate(mesh);
|
||||
startColor = color;
|
||||
mpb.SetColor(colorId, color);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
fadeSpeed = speed;
|
||||
|
||||
if (additive)
|
||||
StartCoroutine(FadeAdditive());
|
||||
else
|
||||
StartCoroutine(Fade());
|
||||
}
|
||||
|
||||
IEnumerator Fade () {
|
||||
Color32 c = startColor;
|
||||
Color32 black = SkeletonGhostRenderer.TransparentBlack;
|
||||
|
||||
float t = 1f;
|
||||
for (float hardTimeLimit = 5f; hardTimeLimit > 0; hardTimeLimit -= Time.deltaTime) {
|
||||
c = Color32.Lerp(black, startColor, t);
|
||||
mpb.SetColor(colorId, c);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
t = Mathf.Lerp(t, 0, Time.deltaTime * fadeSpeed);
|
||||
if (t <= 0)
|
||||
break;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
IEnumerator FadeAdditive () {
|
||||
Color32 c = startColor;
|
||||
Color32 black = SkeletonGhostRenderer.TransparentBlack;
|
||||
|
||||
float t = 1f;
|
||||
|
||||
for (float hardTimeLimit = 5f; hardTimeLimit > 0; hardTimeLimit -= Time.deltaTime) {
|
||||
c = Color32.Lerp(black, startColor, t);
|
||||
mpb.SetColor(colorId, c);
|
||||
meshRenderer.SetPropertyBlock(mpb);
|
||||
|
||||
t = Mathf.Lerp(t, 0, Time.deltaTime * fadeSpeed);
|
||||
if (t <= 0)
|
||||
break;
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public void Cleanup () {
|
||||
if (meshFilter != null && meshFilter.sharedMesh != null)
|
||||
Destroy(meshFilter.sharedMesh);
|
||||
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58e3a9b80754b7545a1dff4d8475b51f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
5
Assets/Spine/Runtime/spine-unity/Modules/Ragdoll.meta
Normal file
5
Assets/Spine/Runtime/spine-unity/Modules/Ragdoll.meta
Normal file
@@ -0,0 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90af663b37d994841b7ac03ae30fe2a9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
@@ -0,0 +1,404 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRagdoll : MonoBehaviour {
|
||||
static Transform parentSpaceHelper;
|
||||
|
||||
#region Inspector
|
||||
[Header("Hierarchy")]
|
||||
[SpineBone]
|
||||
public string startingBoneName = "";
|
||||
[SpineBone]
|
||||
public List<string> stopBoneNames = new List<string>();
|
||||
|
||||
[Header("Parameters")]
|
||||
public bool applyOnStart;
|
||||
[Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
|
||||
public bool disableIK = true;
|
||||
public bool disableOtherConstraints = false;
|
||||
[Space(18)]
|
||||
[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
|
||||
public bool pinStartBone;
|
||||
[Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
|
||||
public bool enableJointCollision;
|
||||
public bool useGravity = true;
|
||||
[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
|
||||
public float thickness = 0.125f;
|
||||
[Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
|
||||
public float rotationLimit = 20;
|
||||
public float rootMass = 20;
|
||||
[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float massFalloffFactor = 0.4f;
|
||||
[Tooltip("The layer assigned to all of the rigidbody parts.")]
|
||||
public int colliderLayer = 0;
|
||||
[Range(0, 1)]
|
||||
public float mix = 1;
|
||||
#endregion
|
||||
|
||||
ISkeletonAnimation targetSkeletonComponent;
|
||||
Skeleton skeleton;
|
||||
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
||||
Transform ragdollRoot;
|
||||
public Rigidbody RootRigidbody { get; private set; }
|
||||
public Bone StartingBone { get; private set; }
|
||||
Vector3 rootOffset;
|
||||
public Vector3 RootOffset { get { return this.rootOffset; } }
|
||||
bool isActive;
|
||||
public bool IsActive { get { return this.isActive; } }
|
||||
|
||||
IEnumerator Start () {
|
||||
if (parentSpaceHelper == null) {
|
||||
parentSpaceHelper = (new GameObject("Parent Space Helper")).transform;
|
||||
parentSpaceHelper.hideFlags = HideFlags.HideInHierarchy;
|
||||
}
|
||||
|
||||
targetSkeletonComponent = GetComponent<SkeletonRenderer>() as ISkeletonAnimation;
|
||||
if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible.");
|
||||
skeleton = targetSkeletonComponent.Skeleton;
|
||||
|
||||
if (applyOnStart) {
|
||||
yield return null;
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
#region API
|
||||
public Rigidbody[] RigidbodyArray {
|
||||
get {
|
||||
if (!isActive)
|
||||
return new Rigidbody[0];
|
||||
|
||||
var rigidBodies = new Rigidbody[boneTable.Count];
|
||||
int i = 0;
|
||||
foreach (Transform t in boneTable.Values) {
|
||||
rigidBodies[i] = t.GetComponent<Rigidbody>();
|
||||
i++;
|
||||
}
|
||||
|
||||
return rigidBodies;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 EstimatedSkeletonPosition {
|
||||
get { return RootRigidbody.position - rootOffset; }
|
||||
}
|
||||
|
||||
/// <summary>Instantiates the ragdoll simulation and applies its transforms to the skeleton.</summary>
|
||||
public void Apply () {
|
||||
isActive = true;
|
||||
mix = 1;
|
||||
|
||||
StartingBone = skeleton.FindBone(startingBoneName);
|
||||
RecursivelyCreateBoneProxies(StartingBone);
|
||||
|
||||
RootRigidbody = boneTable[StartingBone].GetComponent<Rigidbody>();
|
||||
RootRigidbody.isKinematic = pinStartBone;
|
||||
RootRigidbody.mass = rootMass;
|
||||
var boneColliders = new List<Collider>();
|
||||
foreach (var pair in boneTable) {
|
||||
var b = pair.Key;
|
||||
var t = pair.Value;
|
||||
Transform parentTransform;
|
||||
boneColliders.Add(t.GetComponent<Collider>());
|
||||
if (b == StartingBone) {
|
||||
ragdollRoot = new GameObject("RagdollRoot").transform;
|
||||
ragdollRoot.SetParent(transform, false);
|
||||
if (b == skeleton.RootBone) { // RagdollRoot is skeleton root.
|
||||
ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b));
|
||||
} else {
|
||||
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b.Parent));
|
||||
}
|
||||
parentTransform = ragdollRoot;
|
||||
rootOffset = t.position - transform.position;
|
||||
} else {
|
||||
parentTransform = boneTable[b.Parent];
|
||||
}
|
||||
|
||||
// Add joint and attach to parent.
|
||||
var rbParent = parentTransform.GetComponent<Rigidbody>();
|
||||
if (rbParent != null) {
|
||||
var joint = t.gameObject.AddComponent<HingeJoint>();
|
||||
joint.connectedBody = rbParent;
|
||||
Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
|
||||
localPos.x *= 1;
|
||||
joint.connectedAnchor = localPos;
|
||||
joint.axis = Vector3.forward;
|
||||
|
||||
joint.GetComponent<Rigidbody>().mass = joint.connectedBody.mass * massFalloffFactor;
|
||||
joint.limits = new JointLimits {
|
||||
min = -rotationLimit,
|
||||
max = rotationLimit,
|
||||
};
|
||||
joint.useLimits = true;
|
||||
joint.enableCollision = enableJointCollision;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore collisions among bones.
|
||||
for (int x = 0; x < boneColliders.Count; x++) {
|
||||
for (int y = 0; y < boneColliders.Count; y++) {
|
||||
if (x == y) continue;
|
||||
Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy existing override-mode SkeletonUtilityBones.
|
||||
var utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
if (utilityBones.Length > 0) {
|
||||
var destroyedUtilityBoneNames = new List<string>();
|
||||
foreach (var ub in utilityBones) {
|
||||
if (ub.mode == SkeletonUtilityBone.Mode.Override) {
|
||||
destroyedUtilityBoneNames.Add(ub.gameObject.name);
|
||||
Destroy(ub.gameObject);
|
||||
}
|
||||
}
|
||||
if (destroyedUtilityBoneNames.Count > 0) {
|
||||
string msg = "Destroyed Utility Bones: ";
|
||||
for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
|
||||
msg += destroyedUtilityBoneNames[i];
|
||||
if (i != destroyedUtilityBoneNames.Count - 1) {
|
||||
msg += ",";
|
||||
}
|
||||
}
|
||||
Debug.LogWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable skeleton constraints.
|
||||
if (disableIK) {
|
||||
var ikConstraints = skeleton.IkConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++)
|
||||
ikConstraints.Items[i].mix = 0;
|
||||
}
|
||||
|
||||
if (disableOtherConstraints) {
|
||||
var transformConstraints = skeleton.transformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
transformConstraints.Items[i].rotateMix = 0;
|
||||
transformConstraints.Items[i].scaleMix = 0;
|
||||
transformConstraints.Items[i].shearMix = 0;
|
||||
transformConstraints.Items[i].translateMix = 0;
|
||||
}
|
||||
|
||||
var pathConstraints = skeleton.pathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
pathConstraints.Items[i].rotateMix = 0;
|
||||
pathConstraints.Items[i].translateMix = 0;
|
||||
}
|
||||
}
|
||||
|
||||
targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
/// <summary>Transitions the mix value from the current value to a target value.</summary>
|
||||
public Coroutine SmoothMix (float target, float duration) {
|
||||
return StartCoroutine(SmoothMixCoroutine(target, duration));
|
||||
}
|
||||
|
||||
IEnumerator SmoothMixCoroutine (float target, float duration) {
|
||||
float startTime = Time.time;
|
||||
float startMix = mix;
|
||||
while (mix > 0) {
|
||||
skeleton.SetBonesToSetupPose();
|
||||
mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the transform world position while preserving the ragdoll parts world position.</summary>
|
||||
public void SetSkeletonPosition (Vector3 worldPosition) {
|
||||
if (!isActive) {
|
||||
Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - transform.position;
|
||||
transform.position = worldPosition;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
t.position -= offset;
|
||||
|
||||
UpdateSpineSkeleton(null);
|
||||
skeleton.UpdateWorldTransform();
|
||||
}
|
||||
|
||||
/// <summary>Removes the ragdoll instance and effect from the animated skeleton.</summary>
|
||||
public void Remove () {
|
||||
isActive = false;
|
||||
foreach (var t in boneTable.Values)
|
||||
Destroy(t.gameObject);
|
||||
|
||||
Destroy(ragdollRoot.gameObject);
|
||||
|
||||
boneTable.Clear();
|
||||
targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
public Rigidbody GetRigidbody (string boneName) {
|
||||
var bone = skeleton.FindBone(boneName);
|
||||
return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent<Rigidbody>() : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
void RecursivelyCreateBoneProxies (Bone b) {
|
||||
string boneName = b.data.name;
|
||||
if (stopBoneNames.Contains(boneName))
|
||||
return;
|
||||
|
||||
var boneGameObject = new GameObject(boneName);
|
||||
boneGameObject.layer = colliderLayer;
|
||||
Transform t = boneGameObject.transform;
|
||||
boneTable.Add(b, t);
|
||||
|
||||
t.parent = transform;
|
||||
t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.shearX);
|
||||
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
|
||||
|
||||
// MITCH: You left "todo: proper ragdoll branching"
|
||||
var colliders = AttachBoundingBoxRagdollColliders(b);
|
||||
if (colliders.Count == 0) {
|
||||
float length = b.Data.Length;
|
||||
if (length == 0) {
|
||||
var ball = boneGameObject.AddComponent<SphereCollider>();
|
||||
ball.radius = thickness * 0.5f;
|
||||
} else {
|
||||
var box = boneGameObject.AddComponent<BoxCollider>();
|
||||
box.size = new Vector3(length, thickness, thickness);
|
||||
box.center = new Vector3(length * 0.5f, 0);
|
||||
}
|
||||
}
|
||||
var rb = boneGameObject.AddComponent<Rigidbody>();
|
||||
rb.constraints = RigidbodyConstraints.FreezePositionZ;
|
||||
|
||||
foreach (Bone child in b.Children)
|
||||
RecursivelyCreateBoneProxies(child);
|
||||
}
|
||||
|
||||
void UpdateSpineSkeleton (ISkeletonAnimation skeletonRenderer) {
|
||||
bool flipX = skeleton.ScaleX < 0;
|
||||
bool flipY = skeleton.ScaleY < 0;
|
||||
bool flipXOR = flipX ^ flipY;
|
||||
bool flipOR = flipX || flipY;
|
||||
|
||||
foreach (var pair in boneTable) {
|
||||
var b = pair.Key;
|
||||
var t = pair.Value;
|
||||
bool isStartingBone = b == StartingBone;
|
||||
Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[b.Parent];
|
||||
Vector3 parentTransformWorldPosition = parentTransform.position;
|
||||
Quaternion parentTransformWorldRotation = parentTransform.rotation;
|
||||
|
||||
parentSpaceHelper.position = parentTransformWorldPosition;
|
||||
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
||||
parentSpaceHelper.localScale = parentTransform.localScale;
|
||||
|
||||
Vector3 boneWorldPosition = t.position;
|
||||
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
||||
|
||||
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
||||
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
||||
|
||||
if (flipOR) {
|
||||
if (isStartingBone) {
|
||||
if (flipX) boneLocalPosition.x *= -1f;
|
||||
if (flipY) boneLocalPosition.y *= -1f;
|
||||
|
||||
boneLocalRotation = boneLocalRotation * (flipXOR ? -1f : 1f);
|
||||
if (flipX) boneLocalRotation += 180;
|
||||
} else {
|
||||
if (flipXOR) {
|
||||
boneLocalRotation *= -1f;
|
||||
boneLocalPosition.y *= -1f; // wtf??
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.x = Mathf.Lerp(b.x, boneLocalPosition.x, mix);
|
||||
b.y = Mathf.Lerp(b.y, boneLocalPosition.y, mix);
|
||||
b.rotation = Mathf.Lerp(b.rotation, boneLocalRotation, mix);
|
||||
//b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix);
|
||||
}
|
||||
}
|
||||
|
||||
List<Collider> AttachBoundingBoxRagdollColliders (Bone b) {
|
||||
const string AttachmentNameMarker = "ragdoll";
|
||||
var colliders = new List<Collider>();
|
||||
|
||||
Transform t = boneTable[b];
|
||||
GameObject go = t.gameObject;
|
||||
var skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
|
||||
|
||||
var attachments = new List<Attachment>();
|
||||
foreach (Slot s in skeleton.Slots) {
|
||||
if (s.Bone == b) {
|
||||
skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
|
||||
foreach (var a in attachments) {
|
||||
var bbAttachment = a as BoundingBoxAttachment;
|
||||
if (bbAttachment != null) {
|
||||
if (!a.Name.ToLower().Contains(AttachmentNameMarker))
|
||||
continue;
|
||||
|
||||
var bbCollider = go.AddComponent<BoxCollider>();
|
||||
var bounds = SkeletonUtility.GetBoundingBoxBounds(bbAttachment, thickness);
|
||||
bbCollider.center = bounds.center;
|
||||
bbCollider.size = bounds.size;
|
||||
colliders.Add(bbCollider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
static float GetPropagatedRotation (Bone b) {
|
||||
Bone parent = b.Parent;
|
||||
float a = b.AppliedRotation;
|
||||
while (parent != null) {
|
||||
a += parent.AppliedRotation;
|
||||
parent = parent.parent;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
public class LayerFieldAttribute : PropertyAttribute {}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 373527d2bf3351348b9fcc499ce9ea23
|
||||
timeCreated: 1430552693
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,415 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
// Contributed by: Mitch Thompson
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRagdoll2D : MonoBehaviour {
|
||||
static Transform parentSpaceHelper;
|
||||
|
||||
#region Inspector
|
||||
[Header("Hierarchy")]
|
||||
[SpineBone]
|
||||
public string startingBoneName = "";
|
||||
[SpineBone]
|
||||
public List<string> stopBoneNames = new List<string>();
|
||||
|
||||
[Header("Parameters")]
|
||||
public bool applyOnStart;
|
||||
[Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
|
||||
public bool disableIK = true;
|
||||
public bool disableOtherConstraints = false;
|
||||
[Space]
|
||||
[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
|
||||
public bool pinStartBone;
|
||||
public float gravityScale = 1;
|
||||
[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
|
||||
public float thickness = 0.125f;
|
||||
[Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
|
||||
public float rotationLimit = 20;
|
||||
public float rootMass = 20;
|
||||
[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
|
||||
[Range(0.01f, 1f)]
|
||||
public float massFalloffFactor = 0.4f;
|
||||
[Tooltip("The layer assigned to all of the rigidbody parts.")]
|
||||
[SkeletonRagdoll.LayerField]
|
||||
public int colliderLayer = 0;
|
||||
[Range(0, 1)]
|
||||
public float mix = 1;
|
||||
#endregion
|
||||
|
||||
ISkeletonAnimation targetSkeletonComponent;
|
||||
Skeleton skeleton;
|
||||
Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
|
||||
Transform ragdollRoot;
|
||||
public Rigidbody2D RootRigidbody { get; private set; }
|
||||
public Bone StartingBone { get; private set; }
|
||||
Vector2 rootOffset;
|
||||
public Vector3 RootOffset { get { return this.rootOffset; } }
|
||||
bool isActive;
|
||||
public bool IsActive { get { return this.isActive; } }
|
||||
|
||||
IEnumerator Start () {
|
||||
if (parentSpaceHelper == null) {
|
||||
parentSpaceHelper = (new GameObject("Parent Space Helper")).transform;
|
||||
}
|
||||
|
||||
targetSkeletonComponent = GetComponent<SkeletonRenderer>() as ISkeletonAnimation;
|
||||
if (targetSkeletonComponent == null) Debug.LogError("Attached Spine component does not implement ISkeletonAnimation. This script is not compatible.");
|
||||
skeleton = targetSkeletonComponent.Skeleton;
|
||||
|
||||
if (applyOnStart) {
|
||||
yield return null;
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
#region API
|
||||
public Rigidbody2D[] RigidbodyArray {
|
||||
get {
|
||||
if (!isActive)
|
||||
return new Rigidbody2D[0];
|
||||
|
||||
var rigidBodies = new Rigidbody2D[boneTable.Count];
|
||||
int i = 0;
|
||||
foreach (Transform t in boneTable.Values) {
|
||||
rigidBodies[i] = t.GetComponent<Rigidbody2D>();
|
||||
i++;
|
||||
}
|
||||
|
||||
return rigidBodies;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 EstimatedSkeletonPosition {
|
||||
get { return this.RootRigidbody.position - rootOffset; }
|
||||
}
|
||||
|
||||
/// <summary>Instantiates the ragdoll simulation and applies its transforms to the skeleton.</summary>
|
||||
public void Apply () {
|
||||
isActive = true;
|
||||
mix = 1;
|
||||
|
||||
Bone startingBone = this.StartingBone = skeleton.FindBone(startingBoneName);
|
||||
RecursivelyCreateBoneProxies(startingBone);
|
||||
|
||||
RootRigidbody = boneTable[startingBone].GetComponent<Rigidbody2D>();
|
||||
RootRigidbody.isKinematic = pinStartBone;
|
||||
RootRigidbody.mass = rootMass;
|
||||
var boneColliders = new List<Collider2D>();
|
||||
foreach (var pair in boneTable) {
|
||||
var b = pair.Key;
|
||||
var t = pair.Value;
|
||||
Transform parentTransform;
|
||||
boneColliders.Add(t.GetComponent<Collider2D>());
|
||||
if (b == startingBone) {
|
||||
ragdollRoot = new GameObject("RagdollRoot").transform;
|
||||
ragdollRoot.SetParent(transform, false);
|
||||
if (b == skeleton.RootBone) { // RagdollRoot is skeleton root.
|
||||
ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b));
|
||||
} else {
|
||||
ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
|
||||
ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetPropagatedRotation(b.Parent));
|
||||
}
|
||||
parentTransform = ragdollRoot;
|
||||
rootOffset = t.position - transform.position;
|
||||
} else {
|
||||
parentTransform = boneTable[b.Parent];
|
||||
}
|
||||
|
||||
// Add joint and attach to parent.
|
||||
var rbParent = parentTransform.GetComponent<Rigidbody2D>();
|
||||
if (rbParent != null) {
|
||||
var joint = t.gameObject.AddComponent<HingeJoint2D>();
|
||||
joint.connectedBody = rbParent;
|
||||
Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
|
||||
joint.connectedAnchor = localPos;
|
||||
|
||||
joint.GetComponent<Rigidbody2D>().mass = joint.connectedBody.mass * massFalloffFactor;
|
||||
joint.limits = new JointAngleLimits2D {
|
||||
min = -rotationLimit,
|
||||
max = rotationLimit
|
||||
};
|
||||
joint.useLimits = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore collisions among bones.
|
||||
for (int x = 0; x < boneColliders.Count; x++) {
|
||||
for (int y = 0; y < boneColliders.Count; y++) {
|
||||
if (x == y) continue;
|
||||
Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy existing override-mode SkeletonUtility bones.
|
||||
var utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
|
||||
if (utilityBones.Length > 0) {
|
||||
var destroyedUtilityBoneNames = new List<string>();
|
||||
foreach (var ub in utilityBones) {
|
||||
if (ub.mode == SkeletonUtilityBone.Mode.Override) {
|
||||
destroyedUtilityBoneNames.Add(ub.gameObject.name);
|
||||
Destroy(ub.gameObject);
|
||||
}
|
||||
}
|
||||
if (destroyedUtilityBoneNames.Count > 0) {
|
||||
string msg = "Destroyed Utility Bones: ";
|
||||
for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
|
||||
msg += destroyedUtilityBoneNames[i];
|
||||
if (i != destroyedUtilityBoneNames.Count - 1) {
|
||||
msg += ",";
|
||||
}
|
||||
}
|
||||
Debug.LogWarning(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable skeleton constraints.
|
||||
if (disableIK) {
|
||||
var ikConstraints = skeleton.IkConstraints;
|
||||
for (int i = 0, n = ikConstraints.Count; i < n; i++)
|
||||
ikConstraints.Items[i].mix = 0;
|
||||
}
|
||||
|
||||
if (disableOtherConstraints) {
|
||||
var transformConstraints = skeleton.transformConstraints;
|
||||
for (int i = 0, n = transformConstraints.Count; i < n; i++) {
|
||||
transformConstraints.Items[i].rotateMix = 0;
|
||||
transformConstraints.Items[i].scaleMix = 0;
|
||||
transformConstraints.Items[i].shearMix = 0;
|
||||
transformConstraints.Items[i].translateMix = 0;
|
||||
}
|
||||
|
||||
var pathConstraints = skeleton.pathConstraints;
|
||||
for (int i = 0, n = pathConstraints.Count; i < n; i++) {
|
||||
pathConstraints.Items[i].rotateMix = 0;
|
||||
pathConstraints.Items[i].translateMix = 0;
|
||||
}
|
||||
}
|
||||
|
||||
targetSkeletonComponent.UpdateWorld += UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
/// <summary>Transitions the mix value from the current value to a target value.</summary>
|
||||
public Coroutine SmoothMix (float target, float duration) {
|
||||
return StartCoroutine(SmoothMixCoroutine(target, duration));
|
||||
}
|
||||
|
||||
IEnumerator SmoothMixCoroutine (float target, float duration) {
|
||||
float startTime = Time.time;
|
||||
float startMix = mix;
|
||||
while (mix > 0) {
|
||||
skeleton.SetBonesToSetupPose();
|
||||
mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Set the transform world position while preserving the ragdoll parts world position.</summary>
|
||||
public void SetSkeletonPosition (Vector3 worldPosition) {
|
||||
if (!isActive) {
|
||||
Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - transform.position;
|
||||
transform.position = worldPosition;
|
||||
foreach (Transform t in boneTable.Values)
|
||||
t.position -= offset;
|
||||
|
||||
UpdateSpineSkeleton(null);
|
||||
skeleton.UpdateWorldTransform();
|
||||
}
|
||||
|
||||
/// <summary>Removes the ragdoll instance and effect from the animated skeleton.</summary>
|
||||
public void Remove () {
|
||||
isActive = false;
|
||||
foreach (var t in boneTable.Values)
|
||||
Destroy(t.gameObject);
|
||||
|
||||
Destroy(ragdollRoot.gameObject);
|
||||
boneTable.Clear();
|
||||
targetSkeletonComponent.UpdateWorld -= UpdateSpineSkeleton;
|
||||
}
|
||||
|
||||
public Rigidbody2D GetRigidbody (string boneName) {
|
||||
var bone = skeleton.FindBone(boneName);
|
||||
return (bone != null && boneTable.ContainsKey(bone)) ? boneTable[bone].GetComponent<Rigidbody2D>() : null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>Generates the ragdoll simulation's Transform and joint setup.</summary>
|
||||
void RecursivelyCreateBoneProxies (Bone b) {
|
||||
string boneName = b.data.name;
|
||||
if (stopBoneNames.Contains(boneName))
|
||||
return;
|
||||
|
||||
var boneGameObject = new GameObject(boneName);
|
||||
boneGameObject.layer = this.colliderLayer;
|
||||
Transform t = boneGameObject.transform;
|
||||
boneTable.Add(b, t);
|
||||
|
||||
t.parent = transform;
|
||||
t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
|
||||
t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX - b.shearX);
|
||||
t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0);
|
||||
|
||||
// MITCH: You left "todo: proper ragdoll branching"
|
||||
var colliders = AttachBoundingBoxRagdollColliders(b, boneGameObject, skeleton, this.gravityScale);
|
||||
if (colliders.Count == 0) {
|
||||
float length = b.data.length;
|
||||
if (length == 0) {
|
||||
var circle = boneGameObject.AddComponent<CircleCollider2D>();
|
||||
circle.radius = thickness * 0.5f;
|
||||
} else {
|
||||
var box = boneGameObject.AddComponent<BoxCollider2D>();
|
||||
box.size = new Vector2(length, thickness);
|
||||
box.offset = new Vector2(length * 0.5f, 0); // box.center in UNITY_4
|
||||
}
|
||||
}
|
||||
|
||||
var rb = boneGameObject.GetComponent<Rigidbody2D>();
|
||||
if (rb == null) rb = boneGameObject.AddComponent<Rigidbody2D>();
|
||||
rb.gravityScale = this.gravityScale;
|
||||
|
||||
foreach (Bone child in b.Children)
|
||||
RecursivelyCreateBoneProxies(child);
|
||||
}
|
||||
|
||||
/// <summary>Performed every skeleton animation update to translate Unity Transforms positions into Spine bone transforms.</summary>
|
||||
void UpdateSpineSkeleton (ISkeletonAnimation animatedSkeleton) {
|
||||
bool flipX = skeleton.ScaleX < 0;
|
||||
bool flipY = skeleton.ScaleY < 0;
|
||||
bool flipXOR = flipX ^ flipY;
|
||||
bool flipOR = flipX || flipY;
|
||||
var startingBone = this.StartingBone;
|
||||
|
||||
foreach (var pair in boneTable) {
|
||||
var b = pair.Key;
|
||||
var t = pair.Value;
|
||||
bool isStartingBone = (b == startingBone);
|
||||
Transform parentTransform = isStartingBone ? ragdollRoot : boneTable[b.Parent];
|
||||
Vector3 parentTransformWorldPosition = parentTransform.position;
|
||||
Quaternion parentTransformWorldRotation = parentTransform.rotation;
|
||||
|
||||
parentSpaceHelper.position = parentTransformWorldPosition;
|
||||
parentSpaceHelper.rotation = parentTransformWorldRotation;
|
||||
parentSpaceHelper.localScale = parentTransform.localScale;
|
||||
|
||||
Vector3 boneWorldPosition = t.position;
|
||||
Vector3 right = parentSpaceHelper.InverseTransformDirection(t.right);
|
||||
|
||||
Vector3 boneLocalPosition = parentSpaceHelper.InverseTransformPoint(boneWorldPosition);
|
||||
float boneLocalRotation = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
|
||||
if (flipOR) {
|
||||
if (isStartingBone) {
|
||||
if (flipX) boneLocalPosition.x *= -1f;
|
||||
if (flipY) boneLocalPosition.y *= -1f;
|
||||
|
||||
boneLocalRotation = boneLocalRotation * (flipXOR ? -1f : 1f);
|
||||
if (flipX) boneLocalRotation += 180;
|
||||
} else {
|
||||
if (flipXOR) {
|
||||
boneLocalRotation *= -1f;
|
||||
boneLocalPosition.y *= -1f; // wtf??
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.x = Mathf.Lerp(b.x, boneLocalPosition.x, mix);
|
||||
b.y = Mathf.Lerp(b.y, boneLocalPosition.y, mix);
|
||||
b.rotation = Mathf.Lerp(b.rotation, boneLocalRotation, mix);
|
||||
//b.AppliedRotation = Mathf.Lerp(b.AppliedRotation, boneLocalRotation, mix);
|
||||
}
|
||||
}
|
||||
|
||||
static List<Collider2D> AttachBoundingBoxRagdollColliders (Bone b, GameObject go, Skeleton skeleton, float gravityScale) {
|
||||
const string AttachmentNameMarker = "ragdoll";
|
||||
var colliders = new List<Collider2D>();
|
||||
var skin = skeleton.Skin ?? skeleton.Data.DefaultSkin;
|
||||
|
||||
var attachments = new List<Attachment>();
|
||||
foreach (Slot slot in skeleton.Slots) {
|
||||
if (slot.bone == b) {
|
||||
skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(slot), attachments);
|
||||
|
||||
bool bbAttachmentAdded = false;
|
||||
foreach (var a in attachments) {
|
||||
var bbAttachment = a as BoundingBoxAttachment;
|
||||
if (bbAttachment != null) {
|
||||
if (!a.Name.ToLower().Contains(AttachmentNameMarker))
|
||||
continue;
|
||||
|
||||
bbAttachmentAdded = true;
|
||||
var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(bbAttachment, slot, go, isTrigger: false);
|
||||
colliders.Add(bbCollider);
|
||||
}
|
||||
}
|
||||
|
||||
if (bbAttachmentAdded)
|
||||
SkeletonUtility.AddBoneRigidbody2D(go, isKinematic: false, gravityScale: gravityScale);
|
||||
}
|
||||
}
|
||||
|
||||
return colliders;
|
||||
}
|
||||
|
||||
static float GetPropagatedRotation (Bone b) {
|
||||
Bone parent = b.Parent;
|
||||
float a = b.AppliedRotation;
|
||||
while (parent != null) {
|
||||
a += parent.AppliedRotation;
|
||||
parent = parent.parent;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static Vector3 FlipScale (bool flipX, bool flipY) {
|
||||
return new Vector3(flipX ? -1f : 1f, flipY ? -1f : 1f, 1f);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnDrawGizmosSelected () {
|
||||
if (isActive) {
|
||||
Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
|
||||
Vector3 newTransformPos = RootRigidbody.position - rootOffset;
|
||||
Gizmos.DrawLine(transform.position, newTransformPos);
|
||||
Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e74a49a26242a214d9084fde00bfe3ab
|
||||
timeCreated: 1431497383
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Spine/Runtime/spine-unity/Modules/Shaders.meta
Normal file
9
Assets/Spine/Runtime/spine-unity/Modules/Shaders.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e6a65e2576c5b74dabb05c3d3fc2ae4
|
||||
folderAsset: yes
|
||||
timeCreated: 1479258132
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
// - Unlit
|
||||
// - Premultiplied Alpha Blending (Optional straight alpha input)
|
||||
// - Double-sided, no depth
|
||||
|
||||
Shader "Spine/Skeleton Fill" {
|
||||
Properties {
|
||||
_FillColor ("FillColor", Color) = (1,1,1,1)
|
||||
_FillPhase ("FillPhase", Range(0, 1)) = 0
|
||||
[NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {}
|
||||
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
SubShader {
|
||||
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
|
||||
Blend One OneMinusSrcAlpha
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
Lighting Off
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
float4 _FillColor;
|
||||
float _FillPhase;
|
||||
|
||||
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 = (VertexOutput)0;
|
||||
o.uv = v.uv;
|
||||
o.vertexColor = v.vertexColor;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag (VertexOutput i) : COLOR {
|
||||
float4 rawColor = tex2D(_MainTex,i.uv);
|
||||
float finalAlpha = (rawColor.a * i.vertexColor.a);
|
||||
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
rawColor.rgb *= rawColor.a;
|
||||
#endif
|
||||
|
||||
float3 finalColor = lerp((rawColor.rgb * i.vertexColor.rgb), (_FillColor.rgb * finalAlpha), _FillPhase); // make sure to PMA _FillColor.
|
||||
return fixed4(finalColor, finalAlpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
Name "Caster"
|
||||
Tags { "LightMode"="ShadowCaster" }
|
||||
Offset 1, 1
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
|
||||
Fog { Mode Off }
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
fixed _Cutoff;
|
||||
|
||||
struct VertexOutput {
|
||||
V2F_SHADOW_CASTER;
|
||||
float2 uv : TEXCOORD1;
|
||||
};
|
||||
|
||||
VertexOutput vert (appdata_base v) {
|
||||
VertexOutput o;
|
||||
o.uv = v.texcoord;
|
||||
TRANSFER_SHADOW_CASTER(o)
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag (VertexOutput i) : COLOR {
|
||||
fixed4 texcol = tex2D(_MainTex, i.uv);
|
||||
clip(texcol.a - _Cutoff);
|
||||
SHADOW_CASTER_FRAGMENT(i)
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
FallBack "Diffuse"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45495790b394f894a967dbf44489b57b
|
||||
timeCreated: 1492385797
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
// Spine/Skeleton Tint
|
||||
// - Two color tint
|
||||
// - unlit
|
||||
// - Premultiplied alpha blending (Optional straight alpha input)
|
||||
// - No depth, no backface culling, no fog.
|
||||
|
||||
Shader "Spine/Skeleton Tint" {
|
||||
Properties {
|
||||
_Color ("Tint Color", Color) = (1,1,1,1)
|
||||
_Black ("Black Point", Color) = (0,0,0,0)
|
||||
[NoScaleOffset] _MainTex ("MainTex", 2D) = "black" {}
|
||||
[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
|
||||
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
|
||||
|
||||
Fog { Mode Off }
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
Blend One OneMinusSrcAlpha
|
||||
Lighting Off
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
float4 _Color;
|
||||
float4 _Black;
|
||||
|
||||
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);
|
||||
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
texColor.rgb *= texColor.a;
|
||||
#endif
|
||||
|
||||
return (texColor * i.vertexColor) + float4(((1-texColor.rgb) * _Black.rgb * texColor.a*_Color.a*i.vertexColor.a), 0);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
Name "Caster"
|
||||
Tags { "LightMode"="ShadowCaster" }
|
||||
Offset 1, 1
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
|
||||
Fog { Mode Off }
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
fixed _Cutoff;
|
||||
|
||||
struct VertexOutput {
|
||||
V2F_SHADOW_CASTER;
|
||||
float2 uv : TEXCOORD1;
|
||||
};
|
||||
|
||||
VertexOutput vert (appdata_base v) {
|
||||
VertexOutput o;
|
||||
o.uv = v.texcoord;
|
||||
TRANSFER_SHADOW_CASTER(o)
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag (VertexOutput i) : COLOR {
|
||||
fixed4 texcol = tex2D(_MainTex, i.uv);
|
||||
clip(texcol.a - _Cutoff);
|
||||
SHADOW_CASTER_FRAGMENT(i)
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 522f03282fd79be47b306e2ef4b593fd
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
// - Unlit
|
||||
// - Premultiplied Alpha Blending (Optional straight alpha input)
|
||||
// - Double-sided, no depth
|
||||
|
||||
Shader "Spine/Special/Skeleton Grayscale" {
|
||||
Properties {
|
||||
_GrayPhase ("Phase", Range(0, 1)) = 1
|
||||
[NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {}
|
||||
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
SubShader {
|
||||
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
|
||||
Blend One OneMinusSrcAlpha
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
Lighting Off
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
float _GrayPhase;
|
||||
|
||||
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 = (VertexOutput)0;
|
||||
o.uv = v.uv;
|
||||
o.vertexColor = v.vertexColor;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag (VertexOutput i) : COLOR {
|
||||
float4 rawColor = tex2D(_MainTex,i.uv);
|
||||
float finalAlpha = (rawColor.a * i.vertexColor.a);
|
||||
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
rawColor.rgb *= rawColor.a;
|
||||
#endif
|
||||
|
||||
rawColor.rgb *= i.vertexColor.rgb;
|
||||
|
||||
float3 finalColor = lerp(rawColor.rgb, dot(rawColor.rgb, float3(0.3, 0.59, 0.11)), _GrayPhase);
|
||||
return fixed4(finalColor, finalAlpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
Name "Caster"
|
||||
Tags { "LightMode"="ShadowCaster" }
|
||||
Offset 1, 1
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
|
||||
Fog { Mode Off }
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
fixed _Cutoff;
|
||||
|
||||
struct VertexOutput {
|
||||
V2F_SHADOW_CASTER;
|
||||
float2 uv : TEXCOORD1;
|
||||
};
|
||||
|
||||
VertexOutput vert (appdata_base v) {
|
||||
VertexOutput o;
|
||||
o.uv = v.texcoord;
|
||||
TRANSFER_SHADOW_CASTER(o)
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag (VertexOutput i) : SV_Target {
|
||||
fixed4 texcol = tex2D(_MainTex, i.uv);
|
||||
clip(texcol.a - _Cutoff);
|
||||
SHADOW_CASTER_FRAGMENT(i)
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
FallBack "Diffuse"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea7e7c05f36541b4bb280f98ebda8ba1
|
||||
timeCreated: 1492385797
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a831a8ed72a588a48b2fb892e7f37371
|
||||
folderAsset: yes
|
||||
timeCreated: 1479419399
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b6fb48f295cd8248a7566315212a3c2
|
||||
folderAsset: yes
|
||||
timeCreated: 1494092464
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef SHADER_MATHS_INCLUDED
|
||||
#define SHADER_MATHS_INCLUDED
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Maths functions
|
||||
//
|
||||
|
||||
inline half3 safeNormalize(half3 inVec)
|
||||
{
|
||||
half dp3 = max(0.001f, dot(inVec, inVec));
|
||||
return inVec * rsqrt(dp3);
|
||||
}
|
||||
|
||||
inline float dotClamped(float3 a, float3 b)
|
||||
{
|
||||
#if (SHADER_TARGET < 30 || defined(SHADER_API_PS3))
|
||||
return saturate(dot(a, b));
|
||||
#else
|
||||
return max(0.0h, dot(a, b));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline float oneDividedBy(float value)
|
||||
{
|
||||
//Catches NANs
|
||||
float sign_value = sign(value);
|
||||
float sign_value_squared = sign_value*sign_value;
|
||||
return sign_value_squared / ( value + sign_value_squared - 1.0);
|
||||
}
|
||||
|
||||
inline half pow5 (half x)
|
||||
{
|
||||
return x*x*x*x*x;
|
||||
}
|
||||
|
||||
inline float4 quat_from_axis_angle(float3 axis, float angleRadians)
|
||||
{
|
||||
float4 qr;
|
||||
float half_angle = (angleRadians * 0.5);
|
||||
qr.x = axis.x * sin(half_angle);
|
||||
qr.y = axis.y * sin(half_angle);
|
||||
qr.z = axis.z * sin(half_angle);
|
||||
qr.w = cos(half_angle);
|
||||
return qr;
|
||||
}
|
||||
|
||||
inline float3 rotate_vertex_position(float3 position, float3 axis, float angleRadians)
|
||||
{
|
||||
float4 q = quat_from_axis_angle(axis, angleRadians);
|
||||
float3 v = position.xyz;
|
||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
|
||||
}
|
||||
|
||||
float3 EncodeFloatRGB(float value)
|
||||
{
|
||||
const float max24int = 256*256*256-1;
|
||||
float3 decomp = floor( value * float3( max24int/(256*256), max24int/256, max24int ) ) / 255.0;
|
||||
decomp.z -= decomp.y * 256.0;
|
||||
decomp.y -= decomp.x * 256.0;
|
||||
return decomp;
|
||||
}
|
||||
|
||||
float DecodeFloatRGB(float3 decomp)
|
||||
{
|
||||
return dot( decomp.xyz, float3( 255.0/256, 255.0/(256*256), 255.0/(256*256*256) ) );
|
||||
}
|
||||
|
||||
#endif // SHADER_MATHS_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1de23de2025abe4a84ff2edd3f24491
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,474 @@
|
||||
// Upgrade NOTE: upgraded instancing buffer 'PerDrawSprite' to new syntax.
|
||||
|
||||
#ifndef SHADER_SHARED_INCLUDED
|
||||
#define SHADER_SHARED_INCLUDED
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#ifdef UNITY_INSTANCING_ENABLED
|
||||
|
||||
UNITY_INSTANCING_BUFFER_START(PerDrawSprite)
|
||||
// SpriteRenderer.Color while Non-Batched/Instanced.
|
||||
fixed4 unity_SpriteRendererColorArray[UNITY_INSTANCED_ARRAY_SIZE];
|
||||
// this could be smaller but that's how bit each entry is regardless of type
|
||||
float4 unity_SpriteFlipArray[UNITY_INSTANCED_ARRAY_SIZE];
|
||||
UNITY_INSTANCING_BUFFER_END(PerDrawSprite)
|
||||
|
||||
#define _RendererColor unity_SpriteRendererColorArray[unity_InstanceID]
|
||||
#define _Flip unity_SpriteFlipArray[unity_InstanceID]
|
||||
|
||||
#endif // instancing
|
||||
|
||||
CBUFFER_START(UnityPerDrawSprite)
|
||||
#ifndef UNITY_INSTANCING_ENABLED
|
||||
fixed4 _RendererColor;
|
||||
float4 _Flip;
|
||||
#endif
|
||||
float _EnableExternalAlpha;
|
||||
CBUFFER_END
|
||||
|
||||
////////////////////////////////////////
|
||||
// Space functions
|
||||
//
|
||||
|
||||
inline float4 calculateWorldPos(float4 vertex)
|
||||
{
|
||||
return mul(unity_ObjectToWorld, vertex);
|
||||
}
|
||||
|
||||
inline float4 calculateLocalPos(float4 vertex)
|
||||
{
|
||||
#ifdef UNITY_INSTANCING_ENABLED
|
||||
vertex.xy *= _Flip.xy;
|
||||
#endif
|
||||
|
||||
float4 pos = UnityObjectToClipPos(vertex);
|
||||
|
||||
#ifdef PIXELSNAP_ON
|
||||
pos = UnityPixelSnap(pos);
|
||||
#endif
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
inline half3 calculateWorldNormal(float3 normal)
|
||||
{
|
||||
return UnityObjectToWorldNormal(normal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Normal map functions
|
||||
//
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
|
||||
uniform sampler2D _BumpMap;
|
||||
uniform half _BumpScale;
|
||||
|
||||
half3 UnpackScaleNormal(half4 packednormal, half bumpScale)
|
||||
{
|
||||
#if defined(UNITY_NO_DXT5nm)
|
||||
return packednormal.xyz * 2 - 1;
|
||||
#else
|
||||
half3 normal;
|
||||
normal.xy = (packednormal.wy * 2 - 1);
|
||||
#if (SHADER_TARGET >= 30)
|
||||
// SM2.0: instruction count limitation
|
||||
// SM2.0: normal scaler is not supported
|
||||
normal.xy *= bumpScale;
|
||||
#endif
|
||||
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
|
||||
return normal;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline half3 calculateWorldTangent(float4 tangent)
|
||||
{
|
||||
return UnityObjectToWorldDir(tangent);
|
||||
}
|
||||
|
||||
inline half3 calculateWorldBinormal(half3 normalWorld, half3 tangentWorld, float tangentSign)
|
||||
{
|
||||
//When calculating the binormal we have to flip it when the mesh is scaled negatively.
|
||||
//Normally this would just be unity_WorldTransformParams.w but this isn't set correctly by Unity for its SpriteRenderer meshes so get from objectToWorld matrix scale instead.
|
||||
half worldTransformSign = sign(unity_ObjectToWorld[0][0] * unity_ObjectToWorld[1][1] * unity_ObjectToWorld[2][2]);
|
||||
half sign = tangentSign * worldTransformSign;
|
||||
return cross(normalWorld, tangentWorld) * sign;
|
||||
}
|
||||
|
||||
inline half3 calculateNormalFromBumpMap(float2 texUV, half3 tangentWorld, half3 binormalWorld, half3 normalWorld)
|
||||
{
|
||||
half3 localNormal = UnpackScaleNormal(tex2D(_BumpMap, texUV), _BumpScale);
|
||||
half3x3 rotation = half3x3(tangentWorld, binormalWorld, normalWorld);
|
||||
half3 normal = normalize(mul(localNormal, rotation));
|
||||
return normal;
|
||||
}
|
||||
|
||||
#endif // _NORMALMAP
|
||||
|
||||
////////////////////////////////////////
|
||||
// Blending functions
|
||||
//
|
||||
|
||||
inline fixed4 calculateLitPixel(fixed4 texureColor, fixed4 color, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHABLEND_ON)
|
||||
//Normal Alpha
|
||||
finalPixel.a = texureColor.a * color.a;
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * (lighting * finalPixel.a);
|
||||
#elif defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= lighting * color.a;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= lighting;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * lighting * 2.0f;
|
||||
finalPixel.a = color.a * texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f * color;
|
||||
finalPixel.rgb *= lighting * color.a;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= lighting * finalPixel.a;
|
||||
#else
|
||||
//Opaque
|
||||
finalPixel.a = 1;
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * lighting;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculateLitPixel(fixed4 texureColor, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHABLEND_ON)
|
||||
//Normal Alpha
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel.rgb = texureColor.rgb * (lighting * finalPixel.a);
|
||||
#elif defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= lighting;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= lighting;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * lighting * 2.0f;
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f;
|
||||
finalPixel.rgb *= lighting;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= lighting * finalPixel.a;
|
||||
#else
|
||||
//Opaque
|
||||
finalPixel.a = 1;
|
||||
finalPixel.rgb = texureColor.rgb * lighting;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculateAdditiveLitPixel(fixed4 texureColor, fixed4 color, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHABLEND_ON) || defined(_MULTIPLYBLEND) || defined(_MULTIPLYBLEND_X2) || defined(_ADDITIVEBLEND) || defined(_ADDITIVEBLEND_SOFT)
|
||||
//Normal Alpha, Additive and Multiply modes
|
||||
finalPixel.rgb = (texureColor.rgb * lighting * color.rgb) * (texureColor.a * color.a);
|
||||
finalPixel.a = 1.0;
|
||||
#elif defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel.rgb = texureColor.rgb * lighting * color.rgb * color.a;
|
||||
finalPixel.a = 1.0;
|
||||
#else
|
||||
//Opaque
|
||||
finalPixel.rgb = texureColor.rgb * lighting * color.rgb;
|
||||
finalPixel.a = 1.0;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculateAdditiveLitPixel(fixed4 texureColor, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHABLEND_ON) || defined(_MULTIPLYBLEND) || defined(_MULTIPLYBLEND_X2) || defined(_ADDITIVEBLEND) || defined(_ADDITIVEBLEND_SOFT)
|
||||
//Normal Alpha, Additive and Multiply modes
|
||||
finalPixel.rgb = (texureColor.rgb * lighting) * texureColor.a;
|
||||
finalPixel.a = 1.0;
|
||||
#else
|
||||
//Pre multiplied alpha and Opaque
|
||||
finalPixel.rgb = texureColor.rgb * lighting;
|
||||
finalPixel.a = 1.0;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculatePixel(fixed4 texureColor, fixed4 color) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHABLEND_ON)
|
||||
//Normal Alpha
|
||||
finalPixel.a = texureColor.a * color.a;
|
||||
finalPixel.rgb = (texureColor.rgb * color.rgb) * finalPixel.a;
|
||||
#elif defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= color.a;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = color * texureColor;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * 2.0f;
|
||||
finalPixel.a = color.a * texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f * color;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = color * texureColor;
|
||||
finalPixel.rgb *= finalPixel.a;
|
||||
#else
|
||||
//Opaque
|
||||
finalPixel.a = 1;
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculatePixel(fixed4 texureColor) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHABLEND_ON)
|
||||
//Normal Alpha
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel.rgb = texureColor.rgb * finalPixel.a;
|
||||
#elif defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = texureColor;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * 2.0f;
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= finalPixel.a;
|
||||
#else
|
||||
//Opaque
|
||||
finalPixel.a = 1;
|
||||
finalPixel.rgb = texureColor.rgb;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Alpha Clipping
|
||||
//
|
||||
|
||||
#if defined(_ALPHA_CLIP)
|
||||
|
||||
uniform fixed _Cutoff;
|
||||
|
||||
#define ALPHA_CLIP(pixel, color) clip((pixel.a * color.a) - _Cutoff);
|
||||
|
||||
#else
|
||||
|
||||
#define ALPHA_CLIP(pixel, color)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
// Color functions
|
||||
//
|
||||
|
||||
uniform fixed4 _Color;
|
||||
|
||||
inline fixed4 calculateVertexColor(fixed4 color)
|
||||
{
|
||||
return color * _Color;
|
||||
}
|
||||
|
||||
#if defined(_COLOR_ADJUST)
|
||||
|
||||
uniform float _Hue;
|
||||
uniform float _Saturation;
|
||||
uniform float _Brightness;
|
||||
uniform fixed4 _OverlayColor;
|
||||
|
||||
float3 rgb2hsv(float3 c)
|
||||
{
|
||||
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
|
||||
float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
float3 hsv2rgb(float3 c)
|
||||
{
|
||||
c = float3(c.x, clamp(c.yz, 0.0, 1.0));
|
||||
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
inline fixed4 adjustColor(fixed4 color)
|
||||
{
|
||||
float3 hsv = rgb2hsv(color.rgb);
|
||||
|
||||
hsv.x += _Hue;
|
||||
hsv.y *= _Saturation;
|
||||
hsv.z *= _Brightness;
|
||||
|
||||
color.rgb = hsv2rgb(hsv);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#define COLORISE(pixel) pixel.rgb = lerp(pixel.rgb, _OverlayColor.rgb, _OverlayColor.a * pixel.a);
|
||||
#define COLORISE_ADDITIVE(pixel) pixel.rgb = ((1.0-_OverlayColor.a) * pixel.rgb);
|
||||
|
||||
#else // !_COLOR_ADJUST
|
||||
|
||||
#define COLORISE(pixel)
|
||||
#define COLORISE_ADDITIVE(pixel)
|
||||
|
||||
#endif // !_COLOR_ADJUST
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fog
|
||||
//
|
||||
|
||||
#if defined(_FOG) && (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
|
||||
|
||||
inline fixed4 applyFog(fixed4 pixel, float1 fogCoord)
|
||||
{
|
||||
#if defined(_ADDITIVEBLEND) || defined(_ADDITIVEBLEND_SOFT)
|
||||
//In additive mode blend from clear to black based on luminance
|
||||
float luminance = pixel.r * 0.3 + pixel.g * 0.59 + pixel.b * 0.11;
|
||||
fixed4 fogColor = lerp(fixed4(0,0,0,0), fixed4(0,0,0,1), luminance);
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//In multiplied mode fade to white based on inverse luminance
|
||||
float luminance = pixel.r * 0.3 + pixel.g * 0.59 + pixel.b * 0.11;
|
||||
fixed4 fogColor = lerp(fixed4(1,1,1,1), fixed4(0,0,0,0), luminance);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//In multipliedx2 mode fade to grey based on inverse luminance
|
||||
float luminance = pixel.r * 0.3 + pixel.g * 0.59 + pixel.b * 0.11;
|
||||
fixed4 fogColor = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), fixed4(0,0,0,0), luminance);
|
||||
#elif defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
|
||||
//In alpha blended modes blend to fog color based on pixel alpha
|
||||
fixed4 fogColor = lerp(fixed4(0,0,0,0), unity_FogColor, pixel.a);
|
||||
#else
|
||||
//In opaque mode just return fog color;
|
||||
fixed4 fogColor = unity_FogColor;
|
||||
#endif
|
||||
|
||||
UNITY_APPLY_FOG_COLOR(fogCoord, pixel, fogColor);
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
#define APPLY_FOG(pixel, input) pixel = applyFog(pixel, input.fogCoord);
|
||||
|
||||
#define APPLY_FOG_ADDITIVE(pixel, input) \
|
||||
UNITY_APPLY_FOG_COLOR(input.fogCoord, pixel.rgb, fixed4(0,0,0,0)); // fog towards black in additive pass
|
||||
|
||||
#else
|
||||
|
||||
#define APPLY_FOG(pixel, input)
|
||||
#define APPLY_FOG_ADDITIVE(pixel, input)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
// Texture functions
|
||||
//
|
||||
|
||||
uniform sampler2D _MainTex;
|
||||
|
||||
#if ETC1_EXTERNAL_ALPHA
|
||||
//External alpha texture for ETC1 compression
|
||||
uniform sampler2D _AlphaTex;
|
||||
#endif //ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#if _TEXTURE_BLEND
|
||||
uniform sampler2D _BlendTex;
|
||||
uniform float _BlendAmount;
|
||||
|
||||
inline fixed4 calculateBlendedTexturePixel(float2 texcoord)
|
||||
{
|
||||
return (1.0-_BlendAmount) * tex2D(_MainTex, texcoord) + _BlendAmount * tex2D(_BlendTex, texcoord);
|
||||
}
|
||||
#endif // _TEXTURE_BLEND
|
||||
|
||||
inline fixed4 calculateTexturePixel(float2 texcoord)
|
||||
{
|
||||
fixed4 pixel;
|
||||
|
||||
#if _TEXTURE_BLEND
|
||||
pixel = calculateBlendedTexturePixel(texcoord);
|
||||
#else
|
||||
pixel = tex2D(_MainTex, texcoord);
|
||||
#endif // !_TEXTURE_BLEND
|
||||
|
||||
#if ETC1_EXTERNAL_ALPHA
|
||||
fixed4 alpha = tex2D (_AlphaTex, texcoord);
|
||||
pixel.a = lerp (pixel.a, alpha.r, _EnableExternalAlpha);
|
||||
#endif
|
||||
|
||||
#if defined(_COLOR_ADJUST)
|
||||
pixel = adjustColor(pixel);
|
||||
#endif // _COLOR_ADJUST
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
uniform fixed4 _MainTex_ST;
|
||||
|
||||
inline float2 calculateTextureCoord(float4 texcoord)
|
||||
{
|
||||
return TRANSFORM_TEX(texcoord, _MainTex);
|
||||
}
|
||||
|
||||
#endif // SHADER_SHARED_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c18c5cab567666f4d8c5b2bd4e61390b
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,200 @@
|
||||
#ifndef SPRITE_LIGHTING_INCLUDED
|
||||
#define SPRITE_LIGHTING_INCLUDED
|
||||
|
||||
//Check for using mesh normals
|
||||
#if !defined(_FIXED_NORMALS_VIEWSPACE) && !defined(_FIXED_NORMALS_VIEWSPACE_BACKFACE) && !defined(_FIXED_NORMALS_MODELSPACE) && !defined(_FIXED_NORMALS_MODELSPACE_BACKFACE)
|
||||
#define MESH_NORMALS
|
||||
#endif
|
||||
|
||||
//Check for fixing backfacing tangents
|
||||
#if defined(_FIXED_NORMALS_VIEWSPACE_BACKFACE) || defined(_FIXED_NORMALS_MODELSPACE_BACKFACE)
|
||||
#define FIXED_NORMALS_BACKFACE_RENDERING
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex structs
|
||||
//
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
float4 color : COLOR;
|
||||
#if defined(MESH_NORMALS)
|
||||
float3 normal : NORMAL;
|
||||
#endif // _FIXED_NORMALS
|
||||
#if defined(_NORMALMAP)
|
||||
float4 tangent : TANGENT;
|
||||
#endif // _NORMALMAP
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Normal functions
|
||||
//
|
||||
|
||||
uniform float4 _FixedNormal = float4(0, 0, 1, 1);
|
||||
|
||||
inline float3 getFixedNormal()
|
||||
{
|
||||
return _FixedNormal.xyz;
|
||||
}
|
||||
|
||||
inline float calculateBackfacingSign(float3 worldPos)
|
||||
{
|
||||
//If we're using fixed normals and mesh is facing away from camera, flip tangentSign
|
||||
//Unity uses a left handed coordinate system so camera always looks down the negative z axis
|
||||
float3 cameraForward = float3(0,0,-1);
|
||||
float3 meshWorldForward = mul((float3x3)unity_ObjectToWorld, cameraForward);
|
||||
float3 toCamera = _WorldSpaceCameraPos - worldPos;
|
||||
return sign(dot(toCamera, meshWorldForward));
|
||||
}
|
||||
|
||||
inline half3 calculateSpriteWorldNormal(VertexInput vertex, float backFaceSign)
|
||||
{
|
||||
#if defined(MESH_NORMALS)
|
||||
|
||||
return calculateWorldNormal(vertex.normal);
|
||||
|
||||
#else // !MESH_NORMALS
|
||||
|
||||
float3 normal = getFixedNormal();
|
||||
|
||||
#if defined(_FIXED_NORMALS_VIEWSPACE) || defined(_FIXED_NORMALS_VIEWSPACE_BACKFACE)
|
||||
//View space fixed normal
|
||||
//Rotate fixed normal by inverse view matrix to convert the fixed normal into world space
|
||||
float3x3 invView = transpose((float3x3)UNITY_MATRIX_V);
|
||||
return normalize(mul(invView, normal));
|
||||
#else
|
||||
//Model space fixed normal.
|
||||
#if defined(FIXED_NORMALS_BACKFACE_RENDERING)
|
||||
//If back face rendering is enabled and the sprite is facing away from the camera (ie we're rendering the backface) then need to flip the normal
|
||||
normal *= backFaceSign;
|
||||
#endif
|
||||
return calculateWorldNormal(normal);
|
||||
#endif
|
||||
|
||||
#endif // !MESH_NORMALS
|
||||
}
|
||||
|
||||
inline half3 calculateSpriteViewNormal(VertexInput vertex, float backFaceSign)
|
||||
{
|
||||
#if defined(MESH_NORMALS)
|
||||
|
||||
return normalize(mul((float3x3)UNITY_MATRIX_IT_MV, vertex.normal));
|
||||
|
||||
#else // !MESH_NORMALS
|
||||
|
||||
float3 normal = getFixedNormal();
|
||||
|
||||
#if defined(_FIXED_NORMALS_VIEWSPACE) || defined(_FIXED_NORMALS_VIEWSPACE_BACKFACE)
|
||||
//View space fixed normal
|
||||
return normal;
|
||||
#else
|
||||
//Model space fixed normal
|
||||
#if defined(FIXED_NORMALS_BACKFACE_RENDERING)
|
||||
//If back face rendering is enabled and the sprite is facing away from the camera (ie we're rendering the backface) then need to flip the normal
|
||||
normal *= backFaceSign;
|
||||
#endif
|
||||
return normalize(mul((float3x3)UNITY_MATRIX_IT_MV, normal));
|
||||
#endif
|
||||
|
||||
#endif // !MESH_NORMALS
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Normal map functions
|
||||
//
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
|
||||
inline half3 calculateSpriteWorldBinormal(VertexInput vertex, half3 normalWorld, half3 tangentWorld, float backFaceSign)
|
||||
{
|
||||
float tangentSign = vertex.tangent.w;
|
||||
|
||||
#if defined(FIXED_NORMALS_BACKFACE_RENDERING)
|
||||
tangentSign *= backFaceSign;
|
||||
#endif
|
||||
|
||||
return calculateWorldBinormal(normalWorld, tangentWorld, tangentSign);
|
||||
}
|
||||
|
||||
#endif // _NORMALMAP
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Diffuse ramp functions
|
||||
//
|
||||
|
||||
//Disable for softer, more traditional diffuse ramping
|
||||
#define HARD_DIFFUSE_RAMP
|
||||
|
||||
uniform sampler2D _DiffuseRamp;
|
||||
|
||||
inline fixed3 calculateDiffuseRamp(float ramp)
|
||||
{
|
||||
return tex2D(_DiffuseRamp, float2(ramp, ramp)).rgb;
|
||||
}
|
||||
|
||||
inline fixed3 calculateRampedDiffuse(fixed3 lightColor, float attenuation, float angleDot)
|
||||
{
|
||||
float d = angleDot * 0.5 + 0.5;
|
||||
#if defined(HARD_DIFFUSE_RAMP)
|
||||
half3 ramp = calculateDiffuseRamp(d * attenuation * 2);
|
||||
return lightColor * ramp;
|
||||
#else
|
||||
half3 ramp = calculateDiffuseRamp(d);
|
||||
return lightColor * ramp * (attenuation * 2);
|
||||
#endif
|
||||
}
|
||||
#endif // _DIFFUSE_RAMP
|
||||
|
||||
////////////////////////////////////////
|
||||
// Rim Lighting functions
|
||||
//
|
||||
|
||||
#ifdef _RIM_LIGHTING
|
||||
|
||||
uniform float _RimPower;
|
||||
uniform fixed4 _RimColor;
|
||||
|
||||
inline fixed3 applyRimLighting(fixed3 posWorld, fixed3 normalWorld, fixed4 pixel) : SV_Target
|
||||
{
|
||||
fixed3 viewDir = normalize(_WorldSpaceCameraPos - posWorld);
|
||||
float invDot = 1.0 - saturate(dot(normalWorld, viewDir));
|
||||
float rimPower = pow(invDot, _RimPower);
|
||||
float rim = saturate(rimPower * _RimColor.a);
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
rim = calculateDiffuseRamp(rim).r;
|
||||
#endif
|
||||
|
||||
return lerp(pixel.rgb, _RimColor.xyz * pixel.a, rim);
|
||||
}
|
||||
|
||||
#endif //_RIM_LIGHTING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Emission functions
|
||||
//
|
||||
|
||||
#ifdef _EMISSION
|
||||
|
||||
uniform sampler2D _EmissionMap;
|
||||
uniform fixed4 _EmissionColor;
|
||||
uniform float _EmissionPower;
|
||||
|
||||
|
||||
#define APPLY_EMISSION(diffuse, uv) diffuse += tex2D(_EmissionMap, uv).rgb * _EmissionColor.rgb * _EmissionPower;
|
||||
#define APPLY_EMISSION_SPECULAR(pixel, uv) pixel.rgb += (tex2D(_EmissionMap, uv).rgb * _EmissionColor.rgb * _EmissionPower) * pixel.a;
|
||||
|
||||
#else //!_EMISSION
|
||||
|
||||
#define APPLY_EMISSION(diffuse, uv)
|
||||
#define APPLY_EMISSION_SPECULAR(pixel, uv)
|
||||
|
||||
#endif //!_EMISSION
|
||||
|
||||
#endif // SPRITE_LIGHTING_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cfb891658099ca4bb0c9544c08e60f9
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,252 @@
|
||||
#ifndef SPRITE_PIXEL_LIGHTING_INCLUDED
|
||||
#define SPRITE_PIXEL_LIGHTING_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
#include "SpriteLighting.cginc"
|
||||
#include "SpriteSpecular.cginc"
|
||||
#include "AutoLight.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Defines
|
||||
//
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex output struct
|
||||
//
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
#define _VERTEX_LIGHTING_INDEX TEXCOORD5
|
||||
#define _LIGHT_COORD_INDEX_0 6
|
||||
#define _LIGHT_COORD_INDEX_1 7
|
||||
#define _FOG_COORD_INDEX 8
|
||||
#else
|
||||
#define _VERTEX_LIGHTING_INDEX TEXCOORD3
|
||||
#define _LIGHT_COORD_INDEX_0 4
|
||||
#define _LIGHT_COORD_INDEX_1 5
|
||||
#define _FOG_COORD_INDEX 6
|
||||
#endif // _NORMALMAP
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 posWorld : TEXCOORD1;
|
||||
half3 normalWorld : TEXCOORD2;
|
||||
#if defined(_NORMALMAP)
|
||||
half3 tangentWorld : TEXCOORD3;
|
||||
half3 binormalWorld : TEXCOORD4;
|
||||
#endif // _NORMALMAP
|
||||
fixed3 vertexLighting : _VERTEX_LIGHTING_INDEX;
|
||||
LIGHTING_COORDS(_LIGHT_COORD_INDEX_0, _LIGHT_COORD_INDEX_1)
|
||||
#if defined(_FOG)
|
||||
UNITY_FOG_COORDS(_FOG_COORD_INDEX)
|
||||
#endif // _FOG
|
||||
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Light calculations
|
||||
//
|
||||
|
||||
uniform fixed4 _LightColor0;
|
||||
|
||||
inline fixed3 calculateLightDiffuse(VertexOutput input, float3 normalWorld, inout fixed4 albedo)
|
||||
{
|
||||
//For directional lights _WorldSpaceLightPos0.w is set to zero
|
||||
float3 lightWorldDirection = normalize(_WorldSpaceLightPos0.xyz - input.posWorld.xyz * _WorldSpaceLightPos0.w);
|
||||
|
||||
float attenuation = LIGHT_ATTENUATION(input);
|
||||
float angleDot = max(0, dot(normalWorld, lightWorldDirection));
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
fixed3 lightDiffuse = calculateRampedDiffuse(_LightColor0.rgb, attenuation, angleDot);
|
||||
#else
|
||||
fixed3 lightDiffuse = _LightColor0.rgb * (attenuation * angleDot);
|
||||
#endif // _DIFFUSE_RAMP
|
||||
|
||||
return lightDiffuse;
|
||||
}
|
||||
|
||||
inline float3 calculateNormalWorld(VertexOutput input)
|
||||
{
|
||||
#if defined(_NORMALMAP)
|
||||
return calculateNormalFromBumpMap(input.texcoord, input.tangentWorld, input.binormalWorld, input.normalWorld);
|
||||
#else
|
||||
return input.normalWorld;
|
||||
#endif
|
||||
}
|
||||
|
||||
fixed3 calculateVertexLighting(float3 posWorld, float3 normalWorld)
|
||||
{
|
||||
fixed3 vertexLighting = fixed3(0,0,0);
|
||||
|
||||
#ifdef VERTEXLIGHT_ON
|
||||
//Get approximated illumination from non-important point lights
|
||||
vertexLighting = Shade4PointLights ( unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
|
||||
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
|
||||
unity_4LightAtten0, posWorld, normalWorld) * 0.5;
|
||||
#endif
|
||||
|
||||
return vertexLighting;
|
||||
}
|
||||
|
||||
fixed3 calculateAmbientLight(half3 normalWorld)
|
||||
{
|
||||
#if defined(_SPHERICAL_HARMONICS)
|
||||
fixed3 ambient = ShadeSH9(half4(normalWorld, 1.0));
|
||||
#else
|
||||
fixed3 ambient = unity_AmbientSky.rgb;
|
||||
#endif
|
||||
return ambient;
|
||||
}
|
||||
|
||||
#if defined(SPECULAR)
|
||||
|
||||
fixed4 calculateSpecularLight(SpecularCommonData s, float3 viewDir, float3 normal, float3 lightDir, float3 lightColor, half3 ambient)
|
||||
{
|
||||
SpecularLightData data = calculatePhysicsBasedSpecularLight (s.specColor, s.oneMinusReflectivity, s.smoothness, normal, viewDir, lightDir, lightColor, ambient, unity_IndirectSpecColor.rgb);
|
||||
fixed4 pixel = calculateLitPixel(fixed4(s.diffColor, s.alpha), data.lighting);
|
||||
pixel.rgb += data.specular * s.alpha;
|
||||
return pixel;
|
||||
}
|
||||
|
||||
fixed4 calculateSpecularLightAdditive(SpecularCommonData s, float3 viewDir, float3 normal, float3 lightDir, float3 lightColor)
|
||||
{
|
||||
SpecularLightData data = calculatePhysicsBasedSpecularLight (s.specColor, s.oneMinusReflectivity, s.smoothness, normal, viewDir, lightDir, lightColor, half3(0,0,0), half3(0,0,0));
|
||||
fixed4 pixel = calculateAdditiveLitPixel(fixed4(s.diffColor, s.alpha), data.lighting);
|
||||
pixel.rgb += data.specular * s.alpha;
|
||||
return pixel;
|
||||
}
|
||||
|
||||
#endif //SPECULAR
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
VertexOutput vert(VertexInput v)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||
|
||||
output.pos = calculateLocalPos(v.vertex);
|
||||
output.color = calculateVertexColor(v.color);
|
||||
output.texcoord = calculateTextureCoord(v.texcoord);
|
||||
output.posWorld = calculateWorldPos(v.vertex);
|
||||
|
||||
float backFaceSign = 1;
|
||||
#if defined(FIXED_NORMALS_BACKFACE_RENDERING)
|
||||
backFaceSign = calculateBackfacingSign(output.posWorld.xyz);
|
||||
#endif
|
||||
|
||||
output.normalWorld = calculateSpriteWorldNormal(v, backFaceSign);
|
||||
output.vertexLighting = calculateVertexLighting(output.posWorld, output.normalWorld);
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
output.tangentWorld = calculateWorldTangent(v.tangent);
|
||||
output.binormalWorld = calculateSpriteWorldBinormal(v, output.normalWorld, output.tangentWorld, backFaceSign);
|
||||
#endif
|
||||
|
||||
TRANSFER_VERTEX_TO_FRAGMENT(output)
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_TRANSFER_FOG(output,output.pos);
|
||||
#endif // _FOG
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment programs
|
||||
//
|
||||
|
||||
fixed4 fragBase(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord);
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
//Get normal direction
|
||||
fixed3 normalWorld = calculateNormalWorld(input);
|
||||
|
||||
//Get Ambient diffuse
|
||||
fixed3 ambient = calculateAmbientLight(normalWorld);
|
||||
|
||||
|
||||
#if defined(SPECULAR)
|
||||
|
||||
//For directional lights _WorldSpaceLightPos0.w is set to zero
|
||||
float3 lightWorldDirection = normalize(_WorldSpaceLightPos0.xyz - input.posWorld.xyz * _WorldSpaceLightPos0.w);
|
||||
float attenuation = LIGHT_ATTENUATION(input);
|
||||
|
||||
//Returns pixel lit by light, texture color should inlcluded alpha
|
||||
half3 viewDir = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
|
||||
fixed4 pixel = calculateSpecularLight(getSpecularData(input.texcoord.xy, texureColor, input.color), viewDir, normalWorld, lightWorldDirection, _LightColor0.rgb * attenuation, ambient + input.vertexLighting);
|
||||
|
||||
APPLY_EMISSION_SPECULAR(pixel, input.texcoord)
|
||||
|
||||
#else
|
||||
|
||||
//Get primary pixel light diffuse
|
||||
fixed3 diffuse = calculateLightDiffuse(input, normalWorld, texureColor);
|
||||
|
||||
//Combine along with vertex lighting for the base lighting pass
|
||||
fixed3 lighting = ambient + diffuse + input.vertexLighting;
|
||||
|
||||
APPLY_EMISSION(lighting, input.texcoord)
|
||||
|
||||
fixed4 pixel = calculateLitPixel(texureColor, input.color, lighting);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_RIM_LIGHTING)
|
||||
pixel.rgb = applyRimLighting(input.posWorld, normalWorld, pixel);
|
||||
#endif
|
||||
|
||||
COLORISE(pixel)
|
||||
APPLY_FOG(pixel, input)
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
fixed4 fragAdd(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord);
|
||||
|
||||
#if defined(_COLOR_ADJUST)
|
||||
texureColor = adjustColor(texureColor);
|
||||
#endif // _COLOR_ADJUST
|
||||
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
//Get normal direction
|
||||
fixed3 normalWorld = calculateNormalWorld(input);
|
||||
|
||||
#if defined(SPECULAR)
|
||||
|
||||
//For directional lights _WorldSpaceLightPos0.w is set to zero
|
||||
float3 lightWorldDirection = normalize(_WorldSpaceLightPos0.xyz - input.posWorld.xyz * _WorldSpaceLightPos0.w);
|
||||
float attenuation = LIGHT_ATTENUATION(input);
|
||||
|
||||
half3 viewDir = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
|
||||
fixed4 pixel = calculateSpecularLightAdditive(getSpecularData(input.texcoord.xy, texureColor, input.color), viewDir, normalWorld, lightWorldDirection, _LightColor0.rgb * attenuation);
|
||||
|
||||
#else
|
||||
|
||||
//Get light diffuse
|
||||
fixed3 lighting = calculateLightDiffuse(input, normalWorld, texureColor);
|
||||
fixed4 pixel = calculateAdditiveLitPixel(texureColor, input.color, lighting);
|
||||
|
||||
#endif
|
||||
|
||||
COLORISE_ADDITIVE(pixel)
|
||||
APPLY_FOG_ADDITIVE(pixel, input)
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
|
||||
#endif // SPRITE_PIXEL_LIGHTING_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ffc57e05c42ec748838bea0a3aff9f9
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef SPRITE_SHADOWS_INCLUDED
|
||||
#define SPRITE_SHADOWS_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex structs
|
||||
//
|
||||
|
||||
struct vertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct vertexOutput
|
||||
{
|
||||
V2F_SHADOW_CASTER;
|
||||
float2 texcoord : TEXCOORD1;
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
vertexOutput vert(vertexInput v)
|
||||
{
|
||||
vertexOutput o;
|
||||
TRANSFER_SHADOW_CASTER(o)
|
||||
o.texcoord = calculateTextureCoord(v.texcoord);
|
||||
return o;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment program
|
||||
//
|
||||
|
||||
|
||||
uniform fixed _ShadowAlphaCutoff;
|
||||
|
||||
fixed4 frag(vertexOutput IN) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(IN.texcoord);
|
||||
clip(texureColor.a - _ShadowAlphaCutoff);
|
||||
|
||||
SHADOW_CASTER_FRAGMENT(IN)
|
||||
}
|
||||
|
||||
#endif // SPRITE_SHADOWS_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7dbdfb1f55ee26459284220ad6d5bc4
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,246 @@
|
||||
#ifndef SPRITE_SPECULAR_INCLUDED
|
||||
#define SPRITE_SPECULAR_INCLUDED
|
||||
|
||||
#include "ShaderMaths.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Specular functions
|
||||
//
|
||||
|
||||
#if defined(_SPECULAR) || defined(_SPECULAR_GLOSSMAP)
|
||||
|
||||
#define SPECULAR
|
||||
|
||||
|
||||
//ALL THESE FUNCTIONS ARE TAKEN AND ADAPTED FROM UNITY'S OWN PHYSICS BASED STANDARD SHADER
|
||||
|
||||
uniform float _Metallic;
|
||||
uniform float _Glossiness;
|
||||
uniform float _GlossMapScale;
|
||||
uniform sampler2D _MetallicGlossMap;
|
||||
|
||||
struct SpecularLightData
|
||||
{
|
||||
half3 lighting;
|
||||
half3 specular;
|
||||
};
|
||||
|
||||
struct SpecularCommonData
|
||||
{
|
||||
half3 diffColor, specColor;
|
||||
// Note: smoothness & oneMinusReflectivity for optimization purposes, mostly for DX9 SM2.0 level.
|
||||
// Most of the math is being done on these (1-x) values, and that saves a few precious ALU slots.
|
||||
half oneMinusReflectivity, smoothness;
|
||||
half alpha;
|
||||
};
|
||||
|
||||
inline half2 getMetallicGloss(float2 uv)
|
||||
{
|
||||
half2 mg;
|
||||
|
||||
#ifdef _SPECULAR_GLOSSMAP
|
||||
mg = tex2D(_MetallicGlossMap, uv).ra;
|
||||
mg.g *= _GlossMapScale;
|
||||
#else
|
||||
mg.r = _Metallic;
|
||||
mg.g = _Glossiness;
|
||||
#endif
|
||||
|
||||
return mg;
|
||||
}
|
||||
|
||||
inline half getOneMinusReflectivityFromMetallic(half metallic)
|
||||
{
|
||||
// We'll need oneMinusReflectivity, so
|
||||
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic)
|
||||
// store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then
|
||||
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
|
||||
// = alpha - metallic * alpha
|
||||
half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
|
||||
return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
|
||||
}
|
||||
|
||||
inline SpecularCommonData getSpecularData(float2 uv, half4 texureColor, fixed4 color)
|
||||
{
|
||||
half2 metallicGloss = getMetallicGloss(uv);
|
||||
half metallic = metallicGloss.x;
|
||||
half smoothness = metallicGloss.y; // this is 1 minus the square root of real roughness m.
|
||||
|
||||
fixed4 albedo = calculatePixel(texureColor, color);
|
||||
|
||||
half3 specColor = lerp (unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
|
||||
half oneMinusReflectivity = getOneMinusReflectivityFromMetallic(metallic);
|
||||
half3 diffColor = albedo * oneMinusReflectivity;
|
||||
|
||||
SpecularCommonData o = (SpecularCommonData)0;
|
||||
o.diffColor = diffColor;
|
||||
o.specColor = specColor;
|
||||
o.oneMinusReflectivity = oneMinusReflectivity;
|
||||
o.smoothness = smoothness;
|
||||
|
||||
#if defined(_ALPHAPREMULTIPLY_ON) && (SHADER_TARGET >= 30)
|
||||
// Reflectivity 'removes' from the rest of components, including Transparency
|
||||
// outAlpha = 1-(1-alpha)*(1-reflectivity) = 1-(oneMinusReflectivity - alpha*oneMinusReflectivity) =
|
||||
// = 1-oneMinusReflectivity + alpha*oneMinusReflectivity
|
||||
//o.alpha = 1-oneMinusReflectivity + albedo.a*oneMinusReflectivity;
|
||||
o.alpha = albedo.a;
|
||||
#else
|
||||
o.alpha = albedo.a;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
inline half SmoothnessToPerceptualRoughness(half smoothness)
|
||||
{
|
||||
return (1 - smoothness);
|
||||
}
|
||||
|
||||
inline half PerceptualRoughnessToRoughness(half perceptualRoughness)
|
||||
{
|
||||
return perceptualRoughness * perceptualRoughness;
|
||||
}
|
||||
|
||||
// Ref: http://jcgt.org/published/0003/02/03/paper.pdf
|
||||
inline half SmithJointGGXVisibilityTerm (half NdotL, half NdotV, half roughness)
|
||||
{
|
||||
#if 0
|
||||
// Original formulation:
|
||||
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
|
||||
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
|
||||
// G = 1 / (1 + lambda_v + lambda_l);
|
||||
|
||||
// Reorder code to be more optimal
|
||||
half a = roughness;
|
||||
half a2 = a * a;
|
||||
|
||||
half lambdaV = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2);
|
||||
half lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
|
||||
|
||||
// Simplify visibility term: (2.0f * NdotL * NdotV) / ((4.0f * NdotL * NdotV) * (lambda_v + lambda_l + 1e-5f));
|
||||
return 0.5f / (lambdaV + lambdaL + 1e-5f); // This function is not intended to be running on Mobile,
|
||||
// therefore epsilon is smaller than can be represented by half
|
||||
#else
|
||||
// Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough)
|
||||
half a = roughness;
|
||||
half lambdaV = NdotL * (NdotV * (1 - a) + a);
|
||||
half lambdaL = NdotV * (NdotL * (1 - a) + a);
|
||||
|
||||
return 0.5f / (lambdaV + lambdaL + 1e-5f);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline half GGXTerm (half NdotH, half roughness)
|
||||
{
|
||||
half a2 = roughness * roughness;
|
||||
half d = (NdotH * a2 - NdotH) * NdotH + 1.0f; // 2 mad
|
||||
return UNITY_INV_PI * a2 / (d * d + 1e-7f); // This function is not intended to be running on Mobile,
|
||||
// therefore epsilon is smaller than what can be represented by half
|
||||
}
|
||||
|
||||
inline half3 FresnelTerm (half3 F0, half cosA)
|
||||
{
|
||||
half t = pow5 (1 - cosA); // ala Schlick interpoliation
|
||||
return F0 + (1-F0) * t;
|
||||
}
|
||||
|
||||
inline half3 FresnelLerp (half3 F0, half F90, half cosA)
|
||||
{
|
||||
half t = pow5 (1 - cosA); // ala Schlick interpoliation
|
||||
return lerp (F0, F90, t);
|
||||
}
|
||||
|
||||
// Note: Disney diffuse must be multiply by diffuseAlbedo / PI. This is done outside of this function.
|
||||
inline half DisneyDiffuse(half NdotV, half NdotL, half LdotH, half perceptualRoughness)
|
||||
{
|
||||
half fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
|
||||
// Two schlick fresnel term
|
||||
half lightScatter = (1 + (fd90 - 1) * pow5(1 - NdotL));
|
||||
half viewScatter = (1 + (fd90 - 1) * pow5(1 - NdotV));
|
||||
|
||||
return lightScatter * viewScatter;
|
||||
}
|
||||
|
||||
// Main Physically Based BRDF
|
||||
// Derived from Disney work and based on Torrance-Sparrow micro-facet model
|
||||
//
|
||||
// BRDF = kD / pi + kS * (D * V * F) / 4
|
||||
// I = BRDF * NdotL
|
||||
//
|
||||
// * NDF (depending on UNITY_BRDF_GGX):
|
||||
// a) Normalized BlinnPhong
|
||||
// b) GGX
|
||||
// * Smith for Visiblity term
|
||||
// * Schlick approximation for Fresnel
|
||||
SpecularLightData calculatePhysicsBasedSpecularLight(half3 specColor, half oneMinusReflectivity, half smoothness, half3 normal, half3 viewDir, half3 lightdir, half3 lightColor, half3 indirectDiffuse, half3 indirectSpecular)
|
||||
{
|
||||
half perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
|
||||
half3 halfDir = safeNormalize (lightdir + viewDir);
|
||||
|
||||
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
|
||||
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
|
||||
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
|
||||
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
|
||||
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
|
||||
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
|
||||
#define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0
|
||||
|
||||
#if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
|
||||
// The amount we shift the normal toward the view vector is defined by the dot product.
|
||||
half shiftAmount = dot(normal, viewDir);
|
||||
normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
|
||||
// A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
|
||||
//normal = normalize(normal);
|
||||
|
||||
half nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
|
||||
#else
|
||||
half nv = abs(dot(normal, viewDir)); // This abs allow to limit artifact
|
||||
#endif
|
||||
|
||||
half nl = saturate(dot(normal, lightdir));
|
||||
half nh = saturate(dot(normal, halfDir));
|
||||
|
||||
half lv = saturate(dot(lightdir, viewDir));
|
||||
half lh = saturate(dot(lightdir, halfDir));
|
||||
|
||||
// Diffuse term
|
||||
half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;
|
||||
|
||||
// Specular term
|
||||
// HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
|
||||
// BUT 1) that will make shader look significantly darker than Legacy ones
|
||||
// and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
|
||||
half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
|
||||
half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
|
||||
half D = GGXTerm (nh, roughness);
|
||||
|
||||
half specularTerm = V*D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later
|
||||
|
||||
# ifdef UNITY_COLORSPACE_GAMMA
|
||||
specularTerm = sqrt(max(1e-4h, specularTerm));
|
||||
# endif
|
||||
|
||||
// specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
|
||||
specularTerm = max(0, specularTerm * nl);
|
||||
|
||||
// surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
|
||||
half surfaceReduction;
|
||||
# ifdef UNITY_COLORSPACE_GAMMA
|
||||
surfaceReduction = 1.0 - 0.28f * roughness * perceptualRoughness; // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
|
||||
# else
|
||||
surfaceReduction = 1.0 / (roughness*roughness + 1.0); // fade \in [0.5;1]
|
||||
# endif
|
||||
|
||||
// To provide true Lambert lighting, we need to be able to kill specular completely.
|
||||
specularTerm *= any(specColor) ? 1.0 : 0.0;
|
||||
|
||||
half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
|
||||
|
||||
SpecularLightData outData = (SpecularLightData)0;
|
||||
outData.lighting = indirectDiffuse + lightColor * diffuseTerm;
|
||||
outData.specular = (specularTerm * lightColor * FresnelTerm (specColor, lh)) + (surfaceReduction * indirectSpecular * FresnelLerp (specColor, grazingTerm, nv));
|
||||
return outData;
|
||||
}
|
||||
|
||||
#endif // _SPECULAR && _SPECULAR_GLOSSMAP
|
||||
|
||||
#endif // SPRITE_SPECULAR_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f195336fc94457241a37a0aa85923681
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef SPRITE_UNLIT_INCLUDED
|
||||
#define SPRITE_UNLIT_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex structs
|
||||
//
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
#if defined(_FOG)
|
||||
UNITY_FOG_COORDS(1)
|
||||
#endif // _FOG
|
||||
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
VertexOutput vert(VertexInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||
|
||||
output.pos = calculateLocalPos(input.vertex);
|
||||
output.texcoord = calculateTextureCoord(input.texcoord);
|
||||
output.color = calculateVertexColor(input.color);
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_TRANSFER_FOG(output,output.pos);
|
||||
#endif // _FOG
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment program
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
fixed4 frag(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
fixed4 pixel = calculatePixel(texureColor, input.color);
|
||||
|
||||
COLORISE(pixel)
|
||||
APPLY_FOG(pixel, input)
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
#endif // SPRITE_UNLIT_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 072e7b07ec7fb1346a9dcd3bcbbb7111
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,474 @@
|
||||
#ifndef SPRITE_VERTEX_LIGHTING_INCLUDED
|
||||
#define SPRITE_VERTEX_LIGHTING_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
#include "SpriteLighting.cginc"
|
||||
#include "SpriteSpecular.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Defines
|
||||
//
|
||||
|
||||
//Define to use spot lights (more expensive)
|
||||
#define SPOT_LIGHTS
|
||||
|
||||
//Have to process lighting per pixel if using normal maps or a diffuse ramp or rim lighting or specular
|
||||
#if defined(_NORMALMAP) || defined(_DIFFUSE_RAMP) || defined(_RIM_LIGHTING) || defined(SPECULAR)
|
||||
#define PER_PIXEL_LIGHTING
|
||||
#endif
|
||||
|
||||
//Turn off bump mapping and diffuse ramping on older shader models as they dont support needed number of outputs
|
||||
#if defined(PER_PIXEL_LIGHTING) && (SHADER_TARGET < 30)
|
||||
#undef PER_PIXEL_LIGHTING
|
||||
#undef _NORMALMAP
|
||||
#undef _DIFFUSE_RAMP
|
||||
#undef _RIM_LIGHTING
|
||||
#endif
|
||||
|
||||
//In D3D9 only have a max of 9 TEXCOORD so can't have diffuse ramping or fog or rim lighting if processing lights per pixel
|
||||
#if defined(SHADER_API_D3D9) && defined(PER_PIXEL_LIGHTING)
|
||||
#if defined(_NORMALMAP)
|
||||
#undef _DIFFUSE_RAMP
|
||||
#undef _FOG
|
||||
#undef _RIM_LIGHTING
|
||||
#elif defined(_DIFFUSE_RAMP)
|
||||
#undef _FOG
|
||||
#undef _RIM_LIGHTING
|
||||
#elif defined(_RIM_LIGHTING)
|
||||
#undef _FOG
|
||||
#undef _DIFFUSE_RAMP
|
||||
#else
|
||||
#undef _DIFFUSE_RAMP
|
||||
#undef _RIM_LIGHTING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
#if defined(_NORMALMAP) && defined(_DIFFUSE_RAMP)
|
||||
#define ATTENUATIONS TEXCOORD9
|
||||
#if defined(_RIM_LIGHTING)
|
||||
#define _POS_WORLD_INDEX TEXCOORD10
|
||||
#define _FOG_COORD_INDEX 11
|
||||
#else
|
||||
#define _FOG_COORD_INDEX 10
|
||||
#endif
|
||||
#elif defined(_NORMALMAP) != defined(_DIFFUSE_RAMP)
|
||||
#define ATTENUATIONS TEXCOORD8
|
||||
#if defined(_RIM_LIGHTING)
|
||||
#define _POS_WORLD_INDEX TEXCOORD9
|
||||
#define _FOG_COORD_INDEX 10
|
||||
#else
|
||||
#define _FOG_COORD_INDEX 9
|
||||
#endif
|
||||
#else //!_DIFFUSE_RAMP && !_NORMALMAP
|
||||
#if defined(_RIM_LIGHTING)
|
||||
#define _POS_WORLD_INDEX TEXCOORD8
|
||||
#define _FOG_COORD_INDEX 9
|
||||
#else
|
||||
#define _FOG_COORD_INDEX 8
|
||||
#endif
|
||||
#endif
|
||||
#else //!PER_PIXEL_LIGHTING
|
||||
#define _FOG_COORD_INDEX 2
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex output struct
|
||||
//
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float3 texcoord : TEXCOORD0;
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
half4 VertexLightInfo0 : TEXCOORD1;
|
||||
half4 VertexLightInfo1 : TEXCOORD2;
|
||||
half4 VertexLightInfo2 : TEXCOORD3;
|
||||
half4 VertexLightInfo3 : TEXCOORD4;
|
||||
half4 VertexLightInfo4 : TEXCOORD5;
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
half4 normalWorld : TEXCOORD6;
|
||||
half4 tangentWorld : TEXCOORD7;
|
||||
half4 binormalWorld : TEXCOORD8;
|
||||
#else
|
||||
half3 normalWorld : TEXCOORD6;
|
||||
half3 VertexLightInfo5 : TEXCOORD7;
|
||||
#endif
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
half4 LightAttenuations : ATTENUATIONS;
|
||||
#endif
|
||||
#if defined(_RIM_LIGHTING)
|
||||
float4 posWorld : _POS_WORLD_INDEX;
|
||||
#endif
|
||||
|
||||
#else //!PER_PIXEL_LIGHTING
|
||||
|
||||
half3 FullLighting : TEXCOORD1;
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_FOG_COORDS(_FOG_COORD_INDEX)
|
||||
#endif // _FOG
|
||||
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Light calculations
|
||||
//
|
||||
|
||||
struct VertexLightInfo
|
||||
{
|
||||
half3 lightDirection;
|
||||
fixed3 lightColor;
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
float attenuation;
|
||||
#endif // _DIFFUSE_RAMP
|
||||
};
|
||||
|
||||
inline VertexLightInfo getVertexLightAttenuatedInfo(int index, float3 viewPos)
|
||||
{
|
||||
VertexLightInfo lightInfo;
|
||||
|
||||
//For directional lights unity_LightPosition.w is set to zero
|
||||
lightInfo.lightDirection = unity_LightPosition[index].xyz - viewPos.xyz * unity_LightPosition[index].w;
|
||||
float lengthSq = dot(lightInfo.lightDirection, lightInfo.lightDirection);
|
||||
|
||||
// don't produce NaNs if some vertex position overlaps with the light
|
||||
lengthSq = max(lengthSq, 0.000001);
|
||||
|
||||
lightInfo.lightDirection *= rsqrt(lengthSq);
|
||||
|
||||
float attenuation = 1.0 / (1.0 + lengthSq * unity_LightAtten[index].z);
|
||||
|
||||
#if defined(SPOT_LIGHTS)
|
||||
//Spot light attenuation - for non-spot lights unity_LightAtten.x is set to -1 and y is set to 1
|
||||
{
|
||||
float rho = max (0, dot(lightInfo.lightDirection, unity_SpotDirection[index].xyz));
|
||||
float spotAtt = (rho - unity_LightAtten[index].x) * unity_LightAtten[index].y;
|
||||
attenuation *= saturate(spotAtt);
|
||||
}
|
||||
#endif // SPOT_LIGHTS
|
||||
|
||||
//If using a diffuse ramp texture then need to pass through the lights attenuation, otherwise premultiply the light color with it
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
lightInfo.lightColor = unity_LightColor[index].rgb;
|
||||
lightInfo.attenuation = attenuation;
|
||||
#else
|
||||
lightInfo.lightColor = unity_LightColor[index].rgb * attenuation;
|
||||
#endif // _DIFFUSE_RAMP
|
||||
|
||||
return lightInfo;
|
||||
}
|
||||
|
||||
fixed3 calculateAmbientLight(half3 normalWorld)
|
||||
{
|
||||
#if defined(_SPHERICAL_HARMONICS)
|
||||
|
||||
//Magic constants used to tweak ambient to approximate pixel shader spherical harmonics
|
||||
static const fixed3 worldUp = fixed3(0,1,0);
|
||||
static const float skyGroundDotMul = 2.5;
|
||||
static const float minEquatorMix = 0.5;
|
||||
static const float equatorColorBlur = 0.33;
|
||||
|
||||
float upDot = dot(normalWorld, worldUp);
|
||||
|
||||
//Fade between a flat lerp from sky to ground and a 3 way lerp based on how bright the equator light is.
|
||||
//This simulates how directional lights get blurred using spherical harmonics
|
||||
|
||||
//Work out color from ground and sky, ignoring equator
|
||||
float adjustedDot = upDot * skyGroundDotMul;
|
||||
fixed3 skyGroundColor = lerp(unity_AmbientGround, unity_AmbientSky, saturate((adjustedDot + 1.0) * 0.5));
|
||||
|
||||
//Work out equator lights brightness
|
||||
float equatorBright = saturate(dot(unity_AmbientEquator.rgb, unity_AmbientEquator.rgb));
|
||||
|
||||
//Blur equator color with sky and ground colors based on how bright it is.
|
||||
fixed3 equatorBlurredColor = lerp(unity_AmbientEquator, saturate(unity_AmbientEquator + unity_AmbientGround + unity_AmbientSky), equatorBright * equatorColorBlur);
|
||||
|
||||
//Work out 3 way lerp inc equator light
|
||||
fixed3 equatorColor = lerp(equatorBlurredColor, unity_AmbientGround, -upDot) * step(upDot, 0) + lerp(equatorBlurredColor, unity_AmbientSky, upDot) * step(0, upDot);
|
||||
|
||||
//Mix the two colors together based on how bright the equator light is
|
||||
return lerp(skyGroundColor, equatorColor, saturate(equatorBright + minEquatorMix));
|
||||
|
||||
#else // !_SPHERICAL_HARMONICS
|
||||
|
||||
//Flat ambient is just the sky color
|
||||
return unity_AmbientSky.rgb;
|
||||
|
||||
#endif // !_SPHERICAL_HARMONICS
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Light Packing Functions
|
||||
//
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
|
||||
inline fixed3 calculateLightDiffuse(fixed3 lightColor, half3 viewNormal, half3 lightViewDir, float attenuation)
|
||||
{
|
||||
float angleDot = max(0, dot(viewNormal, lightViewDir));
|
||||
fixed3 lightDiffuse = calculateRampedDiffuse(lightColor, attenuation, angleDot);
|
||||
return lightDiffuse;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline fixed3 calculateLightDiffuse(fixed3 attenuatedLightColor, half3 viewNormal, half3 lightViewDir)
|
||||
{
|
||||
float angleDot = max(0, dot(viewNormal, lightViewDir));
|
||||
fixed3 lightDiffuse = attenuatedLightColor * angleDot;
|
||||
|
||||
return lightDiffuse;
|
||||
}
|
||||
|
||||
#endif // _NORMALMAP
|
||||
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
#define VERTEX_LIGHT_0_DIR VertexLightInfo0.xyz
|
||||
#define VERTEX_LIGHT_0_R VertexLightInfo4.x
|
||||
#define VERTEX_LIGHT_0_G VertexLightInfo4.y
|
||||
#define VERTEX_LIGHT_0_B VertexLightInfo4.z
|
||||
|
||||
#define VERTEX_LIGHT_1_DIR VertexLightInfo1.xyz
|
||||
#define VERTEX_LIGHT_1_R VertexLightInfo0.w
|
||||
#define VERTEX_LIGHT_1_G VertexLightInfo1.w
|
||||
#define VERTEX_LIGHT_1_B VertexLightInfo2.w
|
||||
|
||||
#define VERTEX_LIGHT_2_DIR VertexLightInfo2.xyz
|
||||
#define VERTEX_LIGHT_2_R VertexLightInfo3.w
|
||||
#define VERTEX_LIGHT_2_G VertexLightInfo4.w
|
||||
#define VERTEX_LIGHT_2_B texcoord.z
|
||||
|
||||
#define VERTEX_LIGHT_3_DIR VertexLightInfo3.xyz
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
#define VERTEX_LIGHT_3_R normalWorld.w
|
||||
#define VERTEX_LIGHT_3_G tangentWorld.w
|
||||
#define VERTEX_LIGHT_3_B binormalWorld.w
|
||||
#else
|
||||
#define VERTEX_LIGHT_3_R VertexLightInfo5.x
|
||||
#define VERTEX_LIGHT_3_G VertexLightInfo5.y
|
||||
#define VERTEX_LIGHT_3_B VertexLightInfo5.z
|
||||
#endif
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
|
||||
#define LIGHT_DIFFUSE_ATTEN_0 LightAttenuations.x
|
||||
#define LIGHT_DIFFUSE_ATTEN_1 LightAttenuations.y
|
||||
#define LIGHT_DIFFUSE_ATTEN_2 LightAttenuations.z
|
||||
#define LIGHT_DIFFUSE_ATTEN_3 LightAttenuations.w
|
||||
|
||||
#define PACK_VERTEX_LIGHT_DIFFUSE(index, output, lightInfo) \
|
||||
{ \
|
||||
output.LIGHT_DIFFUSE_ATTEN_##index = lightInfo.attenuation; \
|
||||
}
|
||||
|
||||
#define ADD_VERTEX_LIGHT_DIFFUSE(index, diffuse, input, lightColor, viewNormal, lightViewDir) \
|
||||
{ \
|
||||
diffuse += calculateLightDiffuse(lightColor, viewNormal, lightViewDir, input.LIGHT_DIFFUSE_ATTEN_##index); \
|
||||
}
|
||||
#else
|
||||
#define PACK_VERTEX_LIGHT_DIFFUSE(index, output, lightInfo)
|
||||
#define ADD_VERTEX_LIGHT_DIFFUSE(index, diffuse, input, lightColor, viewNormal, lightViewDir) \
|
||||
{ \
|
||||
diffuse += calculateLightDiffuse(lightColor, viewNormal, lightViewDir); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PACK_VERTEX_LIGHT(index, output, viewPos) \
|
||||
{ \
|
||||
VertexLightInfo lightInfo = getVertexLightAttenuatedInfo(index, viewPos); \
|
||||
output.VERTEX_LIGHT_##index##_DIR = lightInfo.lightDirection; \
|
||||
output.VERTEX_LIGHT_##index##_R = lightInfo.lightColor.r; \
|
||||
output.VERTEX_LIGHT_##index##_G = lightInfo.lightColor.g; \
|
||||
output.VERTEX_LIGHT_##index##_B = lightInfo.lightColor.b; \
|
||||
PACK_VERTEX_LIGHT_DIFFUSE(index, output, lightInfo); \
|
||||
}
|
||||
|
||||
#define ADD_VERTEX_LIGHT(index, input, viewNormal, diffuse) \
|
||||
{ \
|
||||
half3 lightViewDir = input.VERTEX_LIGHT_##index##_DIR; \
|
||||
fixed3 lightColor = fixed3(input.VERTEX_LIGHT_##index##_R, input.VERTEX_LIGHT_##index##_G, input.VERTEX_LIGHT_##index##_B); \
|
||||
ADD_VERTEX_LIGHT_DIFFUSE(index, diffuse, input, lightColor, viewNormal, lightViewDir) \
|
||||
}
|
||||
|
||||
#if defined(SPECULAR)
|
||||
|
||||
#define ADD_VERTEX_LIGHT_SPEC(index, input, viewNormal, specData, combinedLightData, indirectDiffuse, indirectSpecular) \
|
||||
{ \
|
||||
half3 lightViewDir = input.VERTEX_LIGHT_##index##_DIR; \
|
||||
fixed3 lightColor = fixed3(input.VERTEX_LIGHT_##index##_R, input.VERTEX_LIGHT_##index##_G, input.VERTEX_LIGHT_##index##_B); \
|
||||
SpecularLightData lightData = calculatePhysicsBasedSpecularLight(specData.specColor, specData.oneMinusReflectivity, specData.smoothness, viewNormal, fixed3(0,0,1), lightViewDir, lightColor, indirectDiffuse, indirectSpecular); \
|
||||
combinedLightData.lighting += lightData.lighting; \
|
||||
combinedLightData.specular += lightData.specular; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else //!PER_PIXEL_LIGHTING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex Only Functions
|
||||
//
|
||||
|
||||
inline fixed3 calculateLightDiffuse(int index, float3 viewPos, half3 viewNormal)
|
||||
{
|
||||
VertexLightInfo lightInfo = getVertexLightAttenuatedInfo(index, viewPos);
|
||||
float angleDot = max(0, dot(viewNormal, lightInfo.lightDirection));
|
||||
return lightInfo.lightColor * angleDot;
|
||||
}
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
VertexOutput vert(VertexInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
UNITY_SETUP_INSTANCE_ID(input);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||
|
||||
output.pos = calculateLocalPos(input.vertex);
|
||||
output.color = calculateVertexColor(input.color);
|
||||
output.texcoord = float3(calculateTextureCoord(input.texcoord), 0);
|
||||
|
||||
float3 viewPos = UnityObjectToViewPos(input.vertex); //float3 viewPos = mul(UNITY_MATRIX_MV, input.vertex); //
|
||||
#if defined(FIXED_NORMALS_BACKFACE_RENDERING) || defined(_RIM_LIGHTING)
|
||||
float4 powWorld = calculateWorldPos(input.vertex);
|
||||
#endif
|
||||
|
||||
float backFaceSign = 1;
|
||||
#if defined(FIXED_NORMALS_BACKFACE_RENDERING)
|
||||
backFaceSign = calculateBackfacingSign(powWorld.xyz);
|
||||
#endif
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
#if defined(_RIM_LIGHTING)
|
||||
output.posWorld = powWorld;
|
||||
#endif
|
||||
|
||||
PACK_VERTEX_LIGHT(0, output, viewPos)
|
||||
PACK_VERTEX_LIGHT(1, output, viewPos)
|
||||
PACK_VERTEX_LIGHT(2, output, viewPos)
|
||||
PACK_VERTEX_LIGHT(3, output, viewPos)
|
||||
|
||||
output.normalWorld.xyz = calculateSpriteWorldNormal(input, backFaceSign);
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
output.tangentWorld.xyz = calculateWorldTangent(input.tangent);
|
||||
output.binormalWorld.xyz = calculateSpriteWorldBinormal(input, output.normalWorld, output.tangentWorld, backFaceSign);
|
||||
#endif
|
||||
|
||||
#else // !PER_PIXEL_LIGHTING
|
||||
|
||||
//Just pack full lighting
|
||||
float3 viewNormal = calculateSpriteViewNormal(input, backFaceSign);
|
||||
//Get Ambient diffuse
|
||||
float3 normalWorld = calculateSpriteWorldNormal(input, backFaceSign);
|
||||
fixed3 ambient = calculateAmbientLight(normalWorld);
|
||||
|
||||
fixed3 diffuse = calculateLightDiffuse(0, viewPos, viewNormal);
|
||||
diffuse += calculateLightDiffuse(1, viewPos, viewNormal);
|
||||
diffuse += calculateLightDiffuse(2, viewPos, viewNormal);
|
||||
diffuse += calculateLightDiffuse(3, viewPos, viewNormal);
|
||||
|
||||
output.FullLighting = ambient + diffuse;
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_TRANSFER_FOG(output, output.pos);
|
||||
#endif // _FOG
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment program
|
||||
//
|
||||
|
||||
fixed4 frag(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
half3 normalWorld = calculateNormalFromBumpMap(input.texcoord.xy, input.tangentWorld.xyz, input.binormalWorld.xyz, input.normalWorld.xyz);
|
||||
#else
|
||||
half3 normalWorld = input.normalWorld.xyz;
|
||||
#endif
|
||||
|
||||
//Get Ambient diffuse
|
||||
fixed3 ambient = calculateAmbientLight(normalWorld);
|
||||
|
||||
half3 normalView = normalize(mul((float3x3)UNITY_MATRIX_V, normalWorld));
|
||||
|
||||
#if defined(SPECULAR)
|
||||
|
||||
SpecularCommonData specData = getSpecularData(input.texcoord.xy, texureColor, input.color);
|
||||
|
||||
SpecularLightData combinedLightData = (SpecularLightData)0;
|
||||
ADD_VERTEX_LIGHT_SPEC(0, input, normalView, specData, combinedLightData, ambient, unity_IndirectSpecColor.rgb)
|
||||
ADD_VERTEX_LIGHT_SPEC(1, input, normalView, specData, combinedLightData, fixed3(0,0,0), fixed3(0,0,0))
|
||||
ADD_VERTEX_LIGHT_SPEC(2, input, normalView, specData, combinedLightData, fixed3(0,0,0), fixed3(0,0,0))
|
||||
ADD_VERTEX_LIGHT_SPEC(3, input, normalView, specData, combinedLightData, fixed3(0,0,0), fixed3(0,0,0))
|
||||
|
||||
fixed4 pixel = calculateLitPixel(fixed4(specData.diffColor, specData.alpha), combinedLightData.lighting);
|
||||
pixel.rgb += combinedLightData.specular * specData.alpha;
|
||||
|
||||
APPLY_EMISSION_SPECULAR(pixel, input.texcoord)
|
||||
|
||||
#else
|
||||
|
||||
//Find vertex light diffuse
|
||||
fixed3 diffuse = fixed3(0,0,0);
|
||||
|
||||
//Add each vertex light to diffuse
|
||||
ADD_VERTEX_LIGHT(0, input, normalView, diffuse)
|
||||
ADD_VERTEX_LIGHT(1, input, normalView, diffuse)
|
||||
ADD_VERTEX_LIGHT(2, input, normalView, diffuse)
|
||||
ADD_VERTEX_LIGHT(3, input, normalView, diffuse)
|
||||
|
||||
fixed3 lighting = ambient + diffuse;
|
||||
|
||||
APPLY_EMISSION(lighting, input.texcoord.xy)
|
||||
|
||||
fixed4 pixel = calculateLitPixel(texureColor, input.color, lighting);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_RIM_LIGHTING)
|
||||
pixel.rgb = applyRimLighting(input.posWorld, normalWorld, pixel);
|
||||
#endif
|
||||
|
||||
#else // !PER_PIXEL_LIGHTING
|
||||
|
||||
APPLY_EMISSION(input.FullLighting, input.texcoord.xy)
|
||||
|
||||
fixed4 pixel = calculateLitPixel(texureColor, input.color, input.FullLighting);
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
COLORISE(pixel)
|
||||
APPLY_FOG(pixel, input)
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
#endif // SPRITE_VERTEX_LIGHTING_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c739dcf9dbcab944898d0b796e11afb9
|
||||
timeCreated: 1494092582
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,522 @@
|
||||
Shader "Hidden/Sprite-CameraDepthNormalsTexture" {
|
||||
|
||||
// Use this shader to render a DepthNormals texture for a camera with correct sprite normals (using camera.RenderWithShader with replacement tag "RenderType")
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _FixedNormal;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteViewSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = getFixedNormal();
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteModelSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
float3 worldPos = mul(unity_ObjectToWorld, v.vertex);
|
||||
float3 normal = getFixedNormal();
|
||||
//Only do this if backface is enabled :/
|
||||
normal *= calculateBackfacingSign(worldPos.xyz);
|
||||
//
|
||||
o.nz.xyz = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, normal));
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = -COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.nz.xyz = float3(0,0,1);
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4794ea6b2d07cc546ba97a809b5f9ada
|
||||
timeCreated: 1494092583
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,518 @@
|
||||
Shader "Hidden/Sprite-CameraDepthTexture" {
|
||||
|
||||
// Use this shader to render a Depth texture for a camera with soft edged Sprites (using camera.RenderWithShader with replacement tag "RenderType")
|
||||
// Note the depth is encoded into the pixels RGB not the full RGBA (alpha is needed for blending)
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), alpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteViewSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), alpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteModelSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), alpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f768a57e040cc48489ad8c7392a31154
|
||||
timeCreated: 1494092586
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,522 @@
|
||||
Shader "Hidden/Sprite-CameraNormalsTexture" {
|
||||
|
||||
// Use this shader to render a Normals texture for a camera with correct sprite normals (using camera.RenderWithShader with replacement tag "RenderType")
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _FixedNormal;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteViewSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = getFixedNormal();
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteModelSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
float3 worldPos = mul(unity_ObjectToWorld, v.vertex);
|
||||
float3 normal = getFixedNormal();
|
||||
//Only do this if backface is enabled :/
|
||||
normal *= calculateBackfacingSign(worldPos.xyz);
|
||||
//
|
||||
o.nz.xyz = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, normal));
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = -COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.nz.xyz = float3(0,0,1);
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 537141eca02c6df4bb8b4f77567e9de2
|
||||
timeCreated: 1494092584
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
Contributed by ToddRivers
|
||||
|
||||
# Unity Sprite Shaders
|
||||
An Uber Shader specialised for rendering Sprites in Unity.
|
||||
Even though it's designed for Sprites it can be used for a whole range of uses. It supports a wide range of optional shader features that won't effect performance unless they are used.
|
||||
It also supports per-pixel effects such as normal maps and diffuse ramping whilst using Vertex Lit rendering.
|
||||
|
||||
### Lighting
|
||||
The shaders support lighting using both Forward Rendering and Vertex Lit Rendering.
|
||||
Forward rendering is more accurate but is slower and crucially means the sprite has to write to depth using alpha clipping to avoid overdraw.
|
||||
Vertex lit means all lighting can be done in one pass meaning full alpha can be used.
|
||||
|
||||
### Normal Mapping
|
||||
Normals maps are supported in both lighting modes (in Vertex Lit rendering data for normal mapping is packed into texture channels and then processed per pixel).
|
||||
|
||||
### Blend Modes
|
||||
Easily switch between blend modes including pre-multiplied alpha, additive, multiply etc.
|
||||
|
||||
### Rim Lighting
|
||||
Camera-space rim lighting is supported in both lighting modes.
|
||||
|
||||
### Diffuse Ramp
|
||||
A ramp texture is optionally supported for toon shading effects.
|
||||
|
||||
### Shadows
|
||||
Shadows are supported using alpha clipping.
|
||||
|
||||
### Gradient based Ambient lighting
|
||||
Both lighting modes support using a gradient for ambient light. In Vertex Lit mode the Spherical Harmonics is approximated from the ground, equator and sky colors.
|
||||
|
||||
### Emission Map
|
||||
An optional emission map is supported.
|
||||
|
||||
### Camera Space Normals
|
||||
As sprites are 2d their normals will always be constant. The shaders allow you to define a fixed normal in camera space rather than pass through mesh normals.
|
||||
This not only saves vertex throughput but means lighting looks less 'flat' for rendering sprites with a perspective camera.
|
||||
|
||||
### Color Adjustment
|
||||
The shaders allow optional adjustment of hue / saturation and brightness as well as applying a solid color overlay effect for flashing a sprite to a solid color (eg. for damage effects).
|
||||
|
||||
### Fog
|
||||
Fog is optionally supported
|
||||
|
||||
|
||||
## To Use
|
||||
On your object's material click the drop down for shader and select Spine\Sprite\Pixel Lit, Vertex Lit or Unlit.
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cecd0ea162097a94c89a97af6baf0a66
|
||||
timeCreated: 1479457854
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,363 @@
|
||||
#ifndef SHADER_SHARED_INCLUDED
|
||||
#define SHADER_SHARED_INCLUDED
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Space functions
|
||||
//
|
||||
|
||||
inline float4 calculateWorldPos(float4 vertex)
|
||||
{
|
||||
return mul(unity_ObjectToWorld, vertex);
|
||||
}
|
||||
|
||||
inline float4 calculateLocalPos(float4 vertex)
|
||||
{
|
||||
return UnityObjectToClipPos(vertex);
|
||||
}
|
||||
|
||||
inline half3 calculateWorldNormal(float3 normal)
|
||||
{
|
||||
return UnityObjectToWorldNormal(normal);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Maths functions
|
||||
//
|
||||
|
||||
inline float dotClamped(float3 a, float3 b)
|
||||
{
|
||||
#if (SHADER_TARGET < 30 || defined(SHADER_API_PS3))
|
||||
return saturate(dot(a, b));
|
||||
#else
|
||||
return max(0.0h, dot(a, b));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline float oneDividedBy(float value)
|
||||
{
|
||||
//Catches NANs
|
||||
float sign_value = sign(value);
|
||||
float sign_value_squared = sign_value*sign_value;
|
||||
return sign_value_squared / ( value + sign_value_squared - 1.0);
|
||||
}
|
||||
|
||||
inline float4 quat_from_axis_angle(float3 axis, float angleRadians)
|
||||
{
|
||||
float4 qr;
|
||||
float half_angle = (angleRadians * 0.5);
|
||||
qr.x = axis.x * sin(half_angle);
|
||||
qr.y = axis.y * sin(half_angle);
|
||||
qr.z = axis.z * sin(half_angle);
|
||||
qr.w = cos(half_angle);
|
||||
return qr;
|
||||
}
|
||||
|
||||
inline float3 rotate_vertex_position(float3 position, float3 axis, float angleRadians)
|
||||
{
|
||||
float4 q = quat_from_axis_angle(axis, angleRadians);
|
||||
float3 v = position.xyz;
|
||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Normal map functions
|
||||
//
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
|
||||
uniform sampler2D _BumpMap;
|
||||
|
||||
inline half3 calculateWorldTangent(float4 tangent)
|
||||
{
|
||||
return UnityObjectToWorldDir(tangent);
|
||||
}
|
||||
|
||||
inline half3 calculateWorldBinormal(half3 normalWorld, half3 tangentWorld, float tangentW)
|
||||
{
|
||||
// For odd-negative scale transforms we need to flip the binormal
|
||||
return cross(normalWorld, tangentWorld.xyz) * tangentW * unity_WorldTransformParams.w;
|
||||
}
|
||||
|
||||
inline half3 calculateNormalFromBumpMap(float2 texUV, half3 tangentWorld, half3 binormalWorld, half3 normalWorld)
|
||||
{
|
||||
half3 localNormal = UnpackNormal(tex2D(_BumpMap, texUV));
|
||||
half3x3 rotation = half3x3(tangentWorld, binormalWorld, normalWorld);
|
||||
half3 normal = normalize(mul(localNormal, rotation));
|
||||
return normal;
|
||||
}
|
||||
|
||||
#endif // _NORMALMAP
|
||||
|
||||
////////////////////////////////////////
|
||||
// Blending functions
|
||||
//
|
||||
|
||||
inline fixed4 calculateLitPixel(fixed4 texureColor, fixed4 color, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= lighting * color.a;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = color * texureColor;
|
||||
finalPixel.rgb *= lighting;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * lighting * 2.0f;
|
||||
finalPixel.a = color.a * texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f * color;
|
||||
finalPixel.rgb *= lighting * color.a;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= lighting * finalPixel.a;
|
||||
#else
|
||||
finalPixel.a = texureColor.a * color.a;
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * (lighting * finalPixel.a);
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculateLitPixel(fixed4 texureColor, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= lighting;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= lighting;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * lighting * 2.0f;
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f;
|
||||
finalPixel.rgb *= lighting;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= lighting * finalPixel.a;
|
||||
#else
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel.rgb = texureColor.rgb * (lighting * finalPixel.a);
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculateAdditiveLitPixel(fixed4 texureColor, fixed4 color, fixed3 lighting) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel.rgb = texureColor.rgb * lighting * color.rgb * color.a;
|
||||
finalPixel.a = 1.0;
|
||||
#else
|
||||
//All other alpha
|
||||
finalPixel.rgb = (texureColor.rgb * lighting * color.rgb) * (texureColor.a * color.a);
|
||||
finalPixel.a = 1.0;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculatePixel(fixed4 texureColor, fixed4 color) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor * color;
|
||||
finalPixel.rgb *= color.a;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = color * texureColor;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * color.rgb * 2.0f;
|
||||
finalPixel.a = color.a * texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f * color;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = color * texureColor;
|
||||
finalPixel.rgb *= finalPixel.a;
|
||||
#else
|
||||
//Standard alpha
|
||||
finalPixel.a = texureColor.a * color.a;
|
||||
finalPixel.rgb = (texureColor.rgb * color.rgb) * finalPixel.a;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
inline fixed4 calculatePixel(fixed4 texureColor) : SV_Target
|
||||
{
|
||||
fixed4 finalPixel;
|
||||
|
||||
#if defined(_ALPHAPREMULTIPLY_ON)
|
||||
//Pre multiplied alpha
|
||||
finalPixel = texureColor;
|
||||
#elif defined(_MULTIPLYBLEND)
|
||||
//Multiply
|
||||
finalPixel = texureColor;
|
||||
finalPixel = lerp(fixed4(1,1,1,1), finalPixel, finalPixel.a);
|
||||
#elif defined(_MULTIPLYBLEND_X2)
|
||||
//Multiply x2
|
||||
finalPixel.rgb = texureColor.rgb * 2.0f;
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel = lerp(fixed4(0.5f,0.5f,0.5f,0.5f), finalPixel, finalPixel.a);
|
||||
#elif defined(_ADDITIVEBLEND)
|
||||
//Additive
|
||||
finalPixel = texureColor * 2.0f;
|
||||
#elif defined(_ADDITIVEBLEND_SOFT)
|
||||
//Additive soft
|
||||
finalPixel = texureColor;
|
||||
finalPixel.rgb *= finalPixel.a;
|
||||
#else
|
||||
//Standard alpha
|
||||
finalPixel.a = texureColor.a;
|
||||
finalPixel.rgb = texureColor.rgb * finalPixel.a;
|
||||
#endif
|
||||
|
||||
return finalPixel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Alpha Clipping
|
||||
//
|
||||
|
||||
#if defined(_ALPHA_CLIP)
|
||||
|
||||
uniform fixed _Cutoff;
|
||||
|
||||
#define ALPHA_CLIP(pixel, color) clip((pixel.a * color.a) - _Cutoff);
|
||||
|
||||
#else
|
||||
|
||||
#define ALPHA_CLIP(pixel, color)
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
// Color functions
|
||||
//
|
||||
|
||||
uniform fixed4 _Color;
|
||||
|
||||
inline fixed4 calculateVertexColor(fixed4 color)
|
||||
{
|
||||
return color * _Color;
|
||||
}
|
||||
|
||||
#if defined(_COLOR_ADJUST)
|
||||
|
||||
uniform float _Hue;
|
||||
uniform float _Saturation;
|
||||
uniform float _Brightness;
|
||||
uniform fixed4 _OverlayColor;
|
||||
|
||||
float3 rgb2hsv(float3 c)
|
||||
{
|
||||
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
|
||||
float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
float3 hsv2rgb(float3 c)
|
||||
{
|
||||
c = float3(c.x, clamp(c.yz, 0.0, 1.0));
|
||||
float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
inline fixed4 adjustColor(fixed4 color)
|
||||
{
|
||||
float3 hsv = rgb2hsv(color.rgb);
|
||||
|
||||
hsv.x += _Hue;
|
||||
hsv.y *= _Saturation;
|
||||
hsv.z *= _Brightness;
|
||||
|
||||
color.rgb = hsv2rgb(hsv);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#define COLORISE(pixel) pixel.rgb = lerp(pixel.rgb, _OverlayColor.rgb, _OverlayColor.a * pixel.a);
|
||||
#define COLORISE_ADDITIVE(pixel) pixel.rgb = ((1.0-_OverlayColor.a) * pixel.rgb);
|
||||
|
||||
#else // !_COLOR_ADJUST
|
||||
|
||||
#define COLORISE(pixel)
|
||||
#define COLORISE_ADDITIVE(pixel)
|
||||
|
||||
#endif // !_COLOR_ADJUST
|
||||
|
||||
////////////////////////////////////////
|
||||
// Texture functions
|
||||
//
|
||||
|
||||
uniform sampler2D _MainTex;
|
||||
|
||||
#if _TEXTURE_BLEND
|
||||
uniform sampler2D _BlendTex;
|
||||
uniform float _BlendAmount;
|
||||
|
||||
fixed4 calculateBlendedTexturePixel(float2 texcoord)
|
||||
{
|
||||
return (1.0-_BlendAmount) * tex2D(_MainTex, texcoord) + _BlendAmount * tex2D(_BlendTex, texcoord);
|
||||
}
|
||||
#endif // _TEXTURE_BLEND
|
||||
|
||||
inline fixed4 calculateTexturePixel(float2 texcoord)
|
||||
{
|
||||
fixed4 pixel;
|
||||
|
||||
#if _TEXTURE_BLEND
|
||||
pixel = calculateBlendedTexturePixel(texcoord);
|
||||
#else
|
||||
pixel = tex2D(_MainTex, texcoord);
|
||||
#endif // !_TEXTURE_BLEND
|
||||
|
||||
#if defined(_COLOR_ADJUST)
|
||||
pixel = adjustColor(pixel);
|
||||
#endif // _COLOR_ADJUST
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
uniform fixed4 _MainTex_ST;
|
||||
|
||||
inline float2 calculateTextureCoord(float4 texcoord)
|
||||
{
|
||||
return TRANSFORM_TEX(texcoord, _MainTex);
|
||||
}
|
||||
|
||||
#endif // SHADER_SHARED_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce9f78731d2f39c49a8688633f53a524
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,446 @@
|
||||
Shader "Hidden/Internal-SpriteDepthNormalsTexture" {
|
||||
|
||||
// Use this shader to render a DepthNormals texture for a camera with correct sprite normals (using camera.RenderWithShader)
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
uniform float4 _FixedNormal;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.nz.xyz = _FixedNormal.xyz;
|
||||
#if UNITY_REVERSED_Z
|
||||
o.nz.z = -o.nz.z;
|
||||
#endif
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = -COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.nz.xyz = float3(0,0,1);
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abbda12fddbb0b048a842a3835470d30
|
||||
timeCreated: 1480325971
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,162 @@
|
||||
#ifndef SPRITE_LIGHTING_INCLUDED
|
||||
#define SPRITE_LIGHTING_INCLUDED
|
||||
|
||||
//Check for using mesh normals
|
||||
#if !defined(_FIXED_NORMALS) && !defined(_FIXED_NORMALS_BACK_RENDERING)
|
||||
#define MESH_NORMALS
|
||||
#endif // _FIXED_NORMALS || _FIXED_NORMALS_BACK_RENDERING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex structs
|
||||
//
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
float4 color : COLOR;
|
||||
#if defined(MESH_NORMALS)
|
||||
float3 normal : NORMAL;
|
||||
#endif // MESH_NORMALS
|
||||
#if defined(_NORMALMAP)
|
||||
float4 tangent : TANGENT;
|
||||
#endif // _NORMALMAP
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Normal functions
|
||||
//
|
||||
|
||||
//Fixed Normal defined in view space
|
||||
uniform float4 _FixedNormal = float4(0, 0, -1, 1);
|
||||
|
||||
inline half3 calculateSpriteWorldNormal(VertexInput vertex)
|
||||
{
|
||||
#if defined(MESH_NORMALS)
|
||||
return calculateWorldNormal(vertex.normal);
|
||||
#else //MESH_NORMALS
|
||||
//Rotate fixed normal by inverse camera matrix to convert the fixed normal into world space
|
||||
float3x3 invView = transpose((float3x3)UNITY_MATRIX_VP);
|
||||
float3 normal = _FixedNormal.xyz;
|
||||
#if UNITY_REVERSED_Z
|
||||
normal.z = -normal.z;
|
||||
#endif
|
||||
return normalize(mul(invView, normal));
|
||||
#endif // !MESH_NORMALS
|
||||
}
|
||||
|
||||
inline half3 calculateSpriteViewNormal(VertexInput vertex)
|
||||
{
|
||||
#if defined(MESH_NORMALS)
|
||||
return normalize(mul((float3x3)UNITY_MATRIX_IT_MV, vertex.normal));
|
||||
#else // !MESH_NORMALS
|
||||
float3 normal = _FixedNormal.xyz;
|
||||
#if UNITY_REVERSED_Z
|
||||
normal.z = -normal.z;
|
||||
#endif
|
||||
return normal;
|
||||
#endif // !MESH_NORMALS
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Normal map functions
|
||||
//
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
|
||||
inline half3 calculateSpriteWorldBinormal(half3 normalWorld, half3 tangentWorld, float tangentW)
|
||||
{
|
||||
#if defined(_FIXED_NORMALS_BACK_RENDERING)
|
||||
//If we're using fixed normals and sprite is facing away from camera, flip tangentW
|
||||
float3 zAxis = float3(0.0, 0.0, 1.0);
|
||||
float3 modelForward = mul((float3x3)unity_ObjectToWorld, zAxis);
|
||||
float3 cameraForward = mul((float3x3)UNITY_MATRIX_VP, zAxis);
|
||||
float directionDot = dot(modelForward, cameraForward);
|
||||
//Don't worry if directionDot is zero, sprite will be side on to camera so invisible meaning it doesnt matter that tangentW will be zero too
|
||||
tangentW *= sign(directionDot);
|
||||
#endif // _FIXED_NORMALS_BACK_RENDERING
|
||||
|
||||
return calculateWorldBinormal(normalWorld, tangentWorld, tangentW);
|
||||
}
|
||||
|
||||
#endif // _NORMALMAP
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Diffuse ramp functions
|
||||
//
|
||||
|
||||
//Disable for softer, more traditional diffuse ramping
|
||||
#define HARD_DIFFUSE_RAMP
|
||||
|
||||
uniform sampler2D _DiffuseRamp;
|
||||
|
||||
inline fixed3 calculateDiffuseRamp(float ramp)
|
||||
{
|
||||
return tex2D(_DiffuseRamp, float2(ramp, ramp)).rgb;
|
||||
}
|
||||
|
||||
inline fixed3 calculateRampedDiffuse(fixed3 lightColor, float attenuation, float angleDot)
|
||||
{
|
||||
float d = angleDot * 0.5 + 0.5;
|
||||
#if defined(HARD_DIFFUSE_RAMP)
|
||||
half3 ramp = calculateDiffuseRamp(d * attenuation * 2);
|
||||
return lightColor * ramp;
|
||||
#else
|
||||
half3 ramp = calculateDiffuseRamp(d);
|
||||
return lightColor * ramp * (attenuation * 2);
|
||||
#endif
|
||||
}
|
||||
#endif // _DIFFUSE_RAMP
|
||||
|
||||
////////////////////////////////////////
|
||||
// Rim Lighting functions
|
||||
//
|
||||
|
||||
#ifdef _RIM_LIGHTING
|
||||
|
||||
uniform float _RimPower;
|
||||
uniform fixed4 _RimColor;
|
||||
|
||||
inline fixed3 applyRimLighting(fixed3 posWorld, fixed3 normalWorld, fixed4 pixel) : SV_Target
|
||||
{
|
||||
fixed3 viewDir = normalize(_WorldSpaceCameraPos - posWorld);
|
||||
float invDot = 1.0 - saturate(dot(normalWorld, viewDir));
|
||||
float rimPower = pow(invDot, _RimPower);
|
||||
float rim = saturate(rimPower * _RimColor.a);
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
rim = calculateDiffuseRamp(rim).r;
|
||||
#endif
|
||||
|
||||
return lerp(pixel.rgb, _RimColor.xyz * pixel.a, rim);
|
||||
}
|
||||
|
||||
#endif //_RIM_LIGHTING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Emission functions
|
||||
//
|
||||
|
||||
#ifdef _EMISSION
|
||||
|
||||
uniform sampler2D _EmissionMap;
|
||||
uniform fixed4 _EmissionColor;
|
||||
uniform float _EmissionPower;
|
||||
|
||||
|
||||
#define APPLY_EMISSION(diffuse, uv) \
|
||||
{ \
|
||||
diffuse += tex2D(_EmissionMap, uv).rgb * _EmissionColor.rgb * _EmissionPower; \
|
||||
}
|
||||
|
||||
#else //!_EMISSION
|
||||
|
||||
#define APPLY_EMISSION(diffuse, uv)
|
||||
|
||||
#endif //!_EMISSION
|
||||
|
||||
#endif // SPRITE_LIGHTING_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 252dba02e84702448a0838ced241467d
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,198 @@
|
||||
#ifndef SPRITE_PIXEL_LIGHTING_INCLUDED
|
||||
#define SPRITE_PIXEL_LIGHTING_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
#include "SpriteLighting.cginc"
|
||||
#include "AutoLight.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Defines
|
||||
//
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex output struct
|
||||
//
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
#define _VERTEX_LIGHTING_INDEX TEXCOORD5
|
||||
#define _LIGHT_COORD_INDEX_0 6
|
||||
#define _LIGHT_COORD_INDEX_1 7
|
||||
#define _FOG_COORD_INDEX 8
|
||||
#else
|
||||
#define _VERTEX_LIGHTING_INDEX TEXCOORD3
|
||||
#define _LIGHT_COORD_INDEX_0 4
|
||||
#define _LIGHT_COORD_INDEX_1 5
|
||||
#define _FOG_COORD_INDEX 6
|
||||
#endif // _NORMALMAP
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 posWorld : TEXCOORD1;
|
||||
half3 normalWorld : TEXCOORD2;
|
||||
#if defined(_NORMALMAP)
|
||||
half3 tangentWorld : TEXCOORD3;
|
||||
half3 binormalWorld : TEXCOORD4;
|
||||
#endif // _NORMALMAP
|
||||
fixed3 vertexLighting : _VERTEX_LIGHTING_INDEX;
|
||||
LIGHTING_COORDS(_LIGHT_COORD_INDEX_0, _LIGHT_COORD_INDEX_1)
|
||||
#if defined(_FOG)
|
||||
UNITY_FOG_COORDS(_FOG_COORD_INDEX)
|
||||
#endif // _FOG
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Light calculations
|
||||
//
|
||||
|
||||
uniform fixed4 _LightColor0;
|
||||
|
||||
inline fixed3 calculateLightDiffuse(VertexOutput input, float3 normalWorld)
|
||||
{
|
||||
//For directional lights _WorldSpaceLightPos0.w is set to zero
|
||||
float3 lightWorldDirection = normalize(_WorldSpaceLightPos0.xyz - input.posWorld.xyz * _WorldSpaceLightPos0.w);
|
||||
|
||||
float attenuation = LIGHT_ATTENUATION(input);
|
||||
float angleDot = max(0, dot(normalWorld, lightWorldDirection));
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
fixed3 lightDiffuse = calculateRampedDiffuse(_LightColor0.rgb, attenuation, angleDot);
|
||||
#else
|
||||
fixed3 lightDiffuse = _LightColor0.rgb * (attenuation * angleDot);
|
||||
#endif // _DIFFUSE_RAMP
|
||||
|
||||
return lightDiffuse;
|
||||
}
|
||||
|
||||
inline float3 calculateNormalWorld(VertexOutput input)
|
||||
{
|
||||
#if defined(_NORMALMAP)
|
||||
return calculateNormalFromBumpMap(input.texcoord, input.tangentWorld, input.binormalWorld, input.normalWorld);
|
||||
#else
|
||||
return input.normalWorld;
|
||||
#endif
|
||||
}
|
||||
|
||||
fixed3 calculateVertexLighting(float3 posWorld, float3 normalWorld)
|
||||
{
|
||||
fixed3 vertexLighting = fixed3(0,0,0);
|
||||
|
||||
#ifdef VERTEXLIGHT_ON
|
||||
//Get approximated illumination from non-important point lights
|
||||
vertexLighting = Shade4PointLights ( unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
|
||||
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
|
||||
unity_4LightAtten0, posWorld, normalWorld) * 0.5;
|
||||
#endif
|
||||
|
||||
return vertexLighting;
|
||||
}
|
||||
|
||||
fixed3 calculateAmbientLight(half3 normalWorld)
|
||||
{
|
||||
#if defined(_SPHERICAL_HARMONICS)
|
||||
fixed3 ambient = ShadeSH9(half4(normalWorld, 1.0)) * 0.75f;
|
||||
#else
|
||||
fixed3 ambient = unity_AmbientSky.rgb * 0.75;
|
||||
#endif
|
||||
return ambient;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
VertexOutput vert(VertexInput v)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
output.pos = calculateLocalPos(v.vertex);
|
||||
output.color = calculateVertexColor(v.color);
|
||||
output.texcoord = calculateTextureCoord(v.texcoord);
|
||||
output.posWorld = calculateWorldPos(v.vertex);
|
||||
output.normalWorld = calculateSpriteWorldNormal(v);
|
||||
output.vertexLighting = calculateVertexLighting(output.posWorld, output.normalWorld);
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
output.tangentWorld = calculateWorldTangent(v.tangent);
|
||||
output.binormalWorld = calculateSpriteWorldBinormal(output.normalWorld, output.tangentWorld, v.tangent.w);
|
||||
#endif
|
||||
|
||||
TRANSFER_VERTEX_TO_FRAGMENT(output)
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_TRANSFER_FOG(output,output.pos);
|
||||
#endif // _FOG
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment programs
|
||||
//
|
||||
|
||||
fixed4 fragBase(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord);
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
//Get normal direction
|
||||
fixed3 normalWorld = calculateNormalWorld(input);
|
||||
|
||||
//Get Ambient diffuse
|
||||
fixed3 ambient = calculateAmbientLight(normalWorld);
|
||||
|
||||
//Get primary pixel light diffuse
|
||||
fixed3 diffuse = calculateLightDiffuse(input, normalWorld);
|
||||
|
||||
//Combine along with vertex lighting for the base lighting pass
|
||||
fixed3 lighting = ambient + diffuse + input.vertexLighting;
|
||||
|
||||
APPLY_EMISSION(lighting, input.texcoord)
|
||||
|
||||
fixed4 pixel = calculateLitPixel(texureColor, input.color, lighting);
|
||||
|
||||
#if defined(_RIM_LIGHTING)
|
||||
pixel.rgb = applyRimLighting(input.posWorld, normalWorld, pixel);
|
||||
#endif
|
||||
|
||||
COLORISE(pixel)
|
||||
|
||||
#if defined(_FOG)
|
||||
fixed4 fogColor = lerp(fixed4(0,0,0,0), unity_FogColor, pixel.a);
|
||||
UNITY_APPLY_FOG_COLOR(input.fogCoord, pixel, fogColor);
|
||||
#endif // _FOG
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
fixed4 fragAdd(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord);
|
||||
|
||||
#if defined(_COLOR_ADJUST)
|
||||
texureColor = adjustColor(texureColor);
|
||||
#endif // _COLOR_ADJUST
|
||||
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
//Get normal direction
|
||||
fixed3 normalWorld = calculateNormalWorld(input);
|
||||
|
||||
//Get light diffuse
|
||||
fixed3 lighting = calculateLightDiffuse(input, normalWorld);
|
||||
|
||||
fixed4 pixel = calculateAdditiveLitPixel(texureColor, input.color, lighting);
|
||||
|
||||
COLORISE_ADDITIVE(pixel)
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_APPLY_FOG_COLOR(input.fogCoord, pixel.rgb, fixed4(0,0,0,0)); // fog towards black in additive pass
|
||||
#endif // _FOG
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
|
||||
#endif // SPRITE_PIXEL_LIGHTING_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38bcbfc10385d424c9cbac5b5b9ec1af
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef SPRITE_SHADOWS_INCLUDED
|
||||
#define SPRITE_SHADOWS_INCLUDED
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex structs
|
||||
//
|
||||
|
||||
struct vertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct vertexOutput
|
||||
{
|
||||
V2F_SHADOW_CASTER;
|
||||
float4 texcoord : TEXCOORD1;
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed4 _MainTex_ST;
|
||||
|
||||
vertexOutput vert(vertexInput v)
|
||||
{
|
||||
vertexOutput o;
|
||||
TRANSFER_SHADOW_CASTER(o)
|
||||
o.texcoord = float4(TRANSFORM_TEX(v.texcoord, _MainTex), 0, 0);
|
||||
return o;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment program
|
||||
//
|
||||
|
||||
|
||||
uniform fixed _ShadowAlphaCutoff;
|
||||
|
||||
fixed4 frag(vertexOutput IN) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = tex2D(_MainTex, IN.texcoord.xy);
|
||||
clip(texureColor.a - _ShadowAlphaCutoff);
|
||||
|
||||
SHADOW_CASTER_FRAGMENT(IN)
|
||||
}
|
||||
|
||||
#endif // SPRITE_SHADOWS_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f58b811a44f1b44cb9aac3ddfe24f37
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef SPRITE_UNLIT_INCLUDED
|
||||
#define SPRITE_UNLIT_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex structs
|
||||
//
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
};
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
fixed4 color : COLOR;
|
||||
#if defined(_FOG)
|
||||
UNITY_FOG_COORDS(1)
|
||||
#endif // _FOG
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
VertexOutput vert(VertexInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
output.pos = calculateLocalPos(input.vertex);
|
||||
output.texcoord = calculateTextureCoord(input.texcoord);
|
||||
output.color = calculateVertexColor(input.color);
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_TRANSFER_FOG(output,output.pos);
|
||||
#endif // _FOG
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment program
|
||||
//
|
||||
|
||||
fixed4 frag(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
fixed4 pixel = calculatePixel(texureColor, input.color);
|
||||
|
||||
COLORISE(pixel)
|
||||
|
||||
#if defined(_FOG)
|
||||
fixed4 fogColor = lerp(fixed4(0,0,0,0), unity_FogColor, pixel.a);
|
||||
UNITY_APPLY_FOG_COLOR(input.fogCoord, pixel, fogColor);
|
||||
#endif // _FOG
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
#endif // SPRITE_UNLIT_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e67832d6dd9dd914ca946fa7fcaa4a9e
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,430 @@
|
||||
#ifndef SPRITE_VERTEX_LIGHTING_INCLUDED
|
||||
#define SPRITE_VERTEX_LIGHTING_INCLUDED
|
||||
|
||||
#include "ShaderShared.cginc"
|
||||
#include "SpriteLighting.cginc"
|
||||
#include "UnityStandardUtils.cginc"
|
||||
|
||||
////////////////////////////////////////
|
||||
// Defines
|
||||
//
|
||||
|
||||
//Define to use spot lights (more expensive)
|
||||
#define SPOT_LIGHTS
|
||||
|
||||
//Have to process lighting per pixel if using normal maps or a diffuse ramp or rim lighting
|
||||
#if defined(_NORMALMAP) || defined(_DIFFUSE_RAMP) || defined(_RIM_LIGHTING)
|
||||
#define PER_PIXEL_LIGHTING
|
||||
#endif
|
||||
|
||||
//Turn off bump mapping and diffuse ramping on older shader models as they dont support needed number of outputs
|
||||
#if defined(PER_PIXEL_LIGHTING) && (SHADER_TARGET < 30)
|
||||
#undef PER_PIXEL_LIGHTING
|
||||
#undef _NORMALMAP
|
||||
#undef _DIFFUSE_RAMP
|
||||
#undef _RIM_LIGHTING
|
||||
#endif
|
||||
|
||||
//In D3D9 only have a max of 9 TEXCOORD so can't have diffuse ramping or fog or rim lighting if processing lights per pixel
|
||||
#if defined(SHADER_API_D3D9) && defined(PER_PIXEL_LIGHTING)
|
||||
#if defined(_NORMALMAP)
|
||||
#undef _DIFFUSE_RAMP
|
||||
#undef _FOG
|
||||
#undef _RIM_LIGHTING
|
||||
#elif defined(_DIFFUSE_RAMP)
|
||||
#undef _FOG
|
||||
#undef _RIM_LIGHTING
|
||||
#elif defined(_RIM_LIGHTING)
|
||||
#undef _FOG
|
||||
#undef _DIFFUSE_RAMP
|
||||
#else
|
||||
#undef _DIFFUSE_RAMP
|
||||
#undef _RIM_LIGHTING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
#if defined(_NORMALMAP) && defined(_DIFFUSE_RAMP)
|
||||
#define ATTENUATIONS TEXCOORD9
|
||||
#if defined(_RIM_LIGHTING)
|
||||
#define _POS_WORLD_INDEX TEXCOORD10
|
||||
#define _FOG_COORD_INDEX 11
|
||||
#else
|
||||
#define _FOG_COORD_INDEX 10
|
||||
#endif
|
||||
#elif defined(_NORMALMAP) != defined(_DIFFUSE_RAMP)
|
||||
#define ATTENUATIONS TEXCOORD8
|
||||
#if defined(_RIM_LIGHTING)
|
||||
#define _POS_WORLD_INDEX TEXCOORD9
|
||||
#define _FOG_COORD_INDEX 10
|
||||
#else
|
||||
#define _FOG_COORD_INDEX 9
|
||||
#endif
|
||||
#else //!_DIFFUSE_RAMP && !_NORMALMAP
|
||||
#if defined(_RIM_LIGHTING)
|
||||
#define _POS_WORLD_INDEX TEXCOORD8
|
||||
#define _FOG_COORD_INDEX 9
|
||||
#else
|
||||
#define _FOG_COORD_INDEX 8
|
||||
#endif
|
||||
#endif
|
||||
#else //!PER_PIXEL_LIGHTING
|
||||
#define _FOG_COORD_INDEX 2
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex output struct
|
||||
//
|
||||
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float3 texcoord : TEXCOORD0;
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
half4 VertexLightInfo0 : TEXCOORD1;
|
||||
half4 VertexLightInfo1 : TEXCOORD2;
|
||||
half4 VertexLightInfo2 : TEXCOORD3;
|
||||
half4 VertexLightInfo3 : TEXCOORD4;
|
||||
half4 VertexLightInfo4 : TEXCOORD5;
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
half4 normalWorld : TEXCOORD6;
|
||||
half4 tangentWorld : TEXCOORD7;
|
||||
half4 binormalWorld : TEXCOORD8;
|
||||
#else
|
||||
half3 normalWorld : TEXCOORD6;
|
||||
half3 VertexLightInfo5 : TEXCOORD7;
|
||||
#endif
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
half4 LightAttenuations : ATTENUATIONS;
|
||||
#endif
|
||||
#if defined(_RIM_LIGHTING)
|
||||
float4 posWorld : _POS_WORLD_INDEX;
|
||||
#endif
|
||||
|
||||
#else //!PER_PIXEL_LIGHTING
|
||||
|
||||
half3 FullLighting : TEXCOORD1;
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_FOG_COORDS(_FOG_COORD_INDEX)
|
||||
#endif // _FOG
|
||||
};
|
||||
|
||||
////////////////////////////////////////
|
||||
// Light calculations
|
||||
//
|
||||
|
||||
struct VertexLightInfo
|
||||
{
|
||||
half3 lightDirection;
|
||||
fixed3 lightColor;
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
float attenuation;
|
||||
#endif // _DIFFUSE_RAMP
|
||||
};
|
||||
|
||||
inline VertexLightInfo getVertexLightAttenuatedInfo(int index, float3 viewPos)
|
||||
{
|
||||
VertexLightInfo lightInfo;
|
||||
|
||||
//For directional lights unity_LightPosition.w is set to zero
|
||||
lightInfo.lightDirection = unity_LightPosition[index].xyz - viewPos.xyz * unity_LightPosition[index].w;
|
||||
float lengthSq = dot(lightInfo.lightDirection, lightInfo.lightDirection);
|
||||
|
||||
// don't produce NaNs if some vertex position overlaps with the light
|
||||
lengthSq = max(lengthSq, 0.000001);
|
||||
|
||||
lightInfo.lightDirection *= rsqrt(lengthSq);
|
||||
|
||||
float attenuation = 1.0 / (1.0 + lengthSq * unity_LightAtten[index].z);
|
||||
|
||||
#if defined(SPOT_LIGHTS)
|
||||
//Spot light attenuation - for non-spot lights unity_LightAtten.x is set to -1 and y is set to 1
|
||||
{
|
||||
float rho = max (0, dot(lightInfo.lightDirection, unity_SpotDirection[index].xyz));
|
||||
float spotAtt = (rho - unity_LightAtten[index].x) * unity_LightAtten[index].y;
|
||||
attenuation *= saturate(spotAtt);
|
||||
}
|
||||
#endif // SPOT_LIGHTS
|
||||
|
||||
//If using a diffuse ramp texture then need to pass through the lights attenuation, otherwise premultiply the light color with it
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
lightInfo.lightColor = unity_LightColor[index].rgb;
|
||||
lightInfo.attenuation = attenuation;
|
||||
#else
|
||||
lightInfo.lightColor = unity_LightColor[index].rgb * attenuation;
|
||||
#endif // _DIFFUSE_RAMP
|
||||
|
||||
return lightInfo;
|
||||
}
|
||||
|
||||
fixed3 calculateAmbientLight(half3 normalWorld)
|
||||
{
|
||||
#if defined(_SPHERICAL_HARMONICS)
|
||||
|
||||
//Magic constants used to tweak ambient to approximate pixel shader spherical harmonics
|
||||
static const fixed3 worldUp = fixed3(0,1,0);
|
||||
static const float skyGroundDotMul = 2.5;
|
||||
static const float minEquatorMix = 0.5;
|
||||
static const float equatorColorBlur = 0.33;
|
||||
|
||||
float upDot = dot(normalWorld, worldUp);
|
||||
|
||||
//Fade between a flat lerp from sky to ground and a 3 way lerp based on how bright the equator light is.
|
||||
//This simulates how directional lights get blurred using spherical harmonics
|
||||
|
||||
//Work out color from ground and sky, ignoring equator
|
||||
float adjustedDot = upDot * skyGroundDotMul;
|
||||
fixed3 skyGroundColor = lerp(unity_AmbientGround, unity_AmbientSky, saturate((adjustedDot + 1.0) * 0.5));
|
||||
|
||||
//Work out equator lights brightness
|
||||
float equatorBright = saturate(dot(unity_AmbientEquator.rgb, unity_AmbientEquator.rgb));
|
||||
|
||||
//Blur equator color with sky and ground colors based on how bright it is.
|
||||
fixed3 equatorBlurredColor = lerp(unity_AmbientEquator, saturate(unity_AmbientEquator + unity_AmbientGround + unity_AmbientSky), equatorBright * equatorColorBlur);
|
||||
|
||||
//Work out 3 way lerp inc equator light
|
||||
fixed3 equatorColor = lerp(equatorBlurredColor, unity_AmbientGround, -upDot) * step(upDot, 0) + lerp(equatorBlurredColor, unity_AmbientSky, upDot) * step(0, upDot);
|
||||
|
||||
//Mix the two colors together based on how bright the equator light is
|
||||
return lerp(skyGroundColor, equatorColor, saturate(equatorBright + minEquatorMix)) * 0.75;
|
||||
|
||||
#else // !_SPHERICAL_HARMONICS
|
||||
|
||||
//Flat ambient is just the sky color
|
||||
return unity_AmbientSky.rgb * 0.75;
|
||||
|
||||
#endif // !_SPHERICAL_HARMONICS
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Light Packing Functions
|
||||
//
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
|
||||
inline fixed3 calculateLightDiffuse(fixed3 lightColor, half3 viewNormal, half3 lightViewDir, float attenuation)
|
||||
{
|
||||
float angleDot = max(0, dot(viewNormal, lightViewDir));
|
||||
return calculateRampedDiffuse(lightColor, attenuation, angleDot);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline fixed3 calculateLightDiffuse(fixed3 attenuatedLightColor, half3 viewNormal, half3 lightViewDir)
|
||||
{
|
||||
float angleDot = max(0, dot(viewNormal, lightViewDir));
|
||||
return attenuatedLightColor * angleDot;
|
||||
}
|
||||
|
||||
#endif // _NORMALMAP
|
||||
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
#define VERTEX_LIGHT_0_DIR VertexLightInfo0.xyz
|
||||
#define VERTEX_LIGHT_0_R VertexLightInfo4.x
|
||||
#define VERTEX_LIGHT_0_G VertexLightInfo4.y
|
||||
#define VERTEX_LIGHT_0_B VertexLightInfo4.z
|
||||
|
||||
#define VERTEX_LIGHT_1_DIR VertexLightInfo1.xyz
|
||||
#define VERTEX_LIGHT_1_R VertexLightInfo0.w
|
||||
#define VERTEX_LIGHT_1_G VertexLightInfo1.w
|
||||
#define VERTEX_LIGHT_1_B VertexLightInfo2.w
|
||||
|
||||
#define VERTEX_LIGHT_2_DIR VertexLightInfo2.xyz
|
||||
#define VERTEX_LIGHT_2_R VertexLightInfo3.w
|
||||
#define VERTEX_LIGHT_2_G VertexLightInfo4.w
|
||||
#define VERTEX_LIGHT_2_B texcoord.z
|
||||
|
||||
#define VERTEX_LIGHT_3_DIR VertexLightInfo3.xyz
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
#define VERTEX_LIGHT_3_R normalWorld.w
|
||||
#define VERTEX_LIGHT_3_G tangentWorld.w
|
||||
#define VERTEX_LIGHT_3_B binormalWorld.w
|
||||
#else
|
||||
#define VERTEX_LIGHT_3_R VertexLightInfo5.x
|
||||
#define VERTEX_LIGHT_3_G VertexLightInfo5.y
|
||||
#define VERTEX_LIGHT_3_B VertexLightInfo5.z
|
||||
#endif
|
||||
|
||||
#if defined(_DIFFUSE_RAMP)
|
||||
|
||||
#define LIGHT_DIFFUSE_ATTEN_0 LightAttenuations.x
|
||||
#define LIGHT_DIFFUSE_ATTEN_1 LightAttenuations.y
|
||||
#define LIGHT_DIFFUSE_ATTEN_2 LightAttenuations.z
|
||||
#define LIGHT_DIFFUSE_ATTEN_3 LightAttenuations.w
|
||||
|
||||
#define PACK_VERTEX_LIGHT_DIFFUSE(index, output, lightInfo) \
|
||||
{ \
|
||||
output.LIGHT_DIFFUSE_ATTEN_##index = lightInfo.attenuation; \
|
||||
}
|
||||
|
||||
#define ADD_VERTEX_LIGHT_DIFFUSE(index, diffuse, input, lightColor, viewNormal, lightViewDir) \
|
||||
{ \
|
||||
diffuse += calculateLightDiffuse(lightColor, viewNormal, lightViewDir, input.LIGHT_DIFFUSE_ATTEN_##index); \
|
||||
}
|
||||
#else
|
||||
#define PACK_VERTEX_LIGHT_DIFFUSE(index, output, lightInfo)
|
||||
#define ADD_VERTEX_LIGHT_DIFFUSE(index, diffuse, input, lightColor, viewNormal, lightViewDir) \
|
||||
{ \
|
||||
diffuse += calculateLightDiffuse(lightColor, viewNormal, lightViewDir); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define PACK_VERTEX_LIGHT(index, output, viewPos) \
|
||||
{ \
|
||||
VertexLightInfo lightInfo = getVertexLightAttenuatedInfo(index, viewPos); \
|
||||
output.VERTEX_LIGHT_##index##_DIR = lightInfo.lightDirection; \
|
||||
output.VERTEX_LIGHT_##index##_R = lightInfo.lightColor.r; \
|
||||
output.VERTEX_LIGHT_##index##_G = lightInfo.lightColor.g; \
|
||||
output.VERTEX_LIGHT_##index##_B = lightInfo.lightColor.b; \
|
||||
PACK_VERTEX_LIGHT_DIFFUSE(index, output, lightInfo); \
|
||||
}
|
||||
|
||||
#define ADD_VERTEX_LIGHT(index, input, viewNormal, diffuse) \
|
||||
{ \
|
||||
half3 lightViewDir = input.VERTEX_LIGHT_##index##_DIR; \
|
||||
fixed3 lightColor = fixed3(input.VERTEX_LIGHT_##index##_R, input.VERTEX_LIGHT_##index##_G, input.VERTEX_LIGHT_##index##_B); \
|
||||
ADD_VERTEX_LIGHT_DIFFUSE(index, diffuse, input, lightColor, viewNormal, lightViewDir) \
|
||||
}
|
||||
|
||||
#else //!PER_PIXEL_LIGHTING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex Only Functions
|
||||
//
|
||||
|
||||
inline fixed3 calculateLightDiffuse(int index, float3 viewPos, half3 viewNormal)
|
||||
{
|
||||
VertexLightInfo lightInfo = getVertexLightAttenuatedInfo(index, viewPos);
|
||||
float angleDot = max(0, dot(viewNormal, lightInfo.lightDirection));
|
||||
return lightInfo.lightColor * angleDot;
|
||||
}
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
////////////////////////////////////////
|
||||
// Vertex program
|
||||
//
|
||||
|
||||
VertexOutput vert(VertexInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
|
||||
output.pos = calculateLocalPos(input.vertex);
|
||||
output.color = calculateVertexColor(input.color);
|
||||
output.texcoord = float3(calculateTextureCoord(input.texcoord), 0);
|
||||
|
||||
float3 viewPos = UnityObjectToViewPos(input.vertex);
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
#if defined(_RIM_LIGHTING)
|
||||
output.posWorld = calculateWorldPos(input.vertex);
|
||||
#endif
|
||||
|
||||
PACK_VERTEX_LIGHT(0, output, viewPos)
|
||||
PACK_VERTEX_LIGHT(1, output, viewPos)
|
||||
PACK_VERTEX_LIGHT(2, output, viewPos)
|
||||
PACK_VERTEX_LIGHT(3, output, viewPos)
|
||||
|
||||
output.normalWorld.xyz = calculateSpriteWorldNormal(input);
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
output.tangentWorld.xyz = calculateWorldTangent(input.tangent);
|
||||
output.binormalWorld.xyz = calculateSpriteWorldBinormal(output.normalWorld, output.tangentWorld, input.tangent.w);
|
||||
#endif
|
||||
|
||||
#else // !PER_PIXEL_LIGHTING
|
||||
|
||||
//Just pack full lighting
|
||||
float3 viewNormal = calculateSpriteViewNormal(input);
|
||||
|
||||
//Get Ambient diffuse
|
||||
float3 normalWorld = calculateSpriteWorldNormal(input);
|
||||
fixed3 ambient = calculateAmbientLight(normalWorld);
|
||||
|
||||
fixed3 diffuse = calculateLightDiffuse(0, viewPos, viewNormal);
|
||||
diffuse += calculateLightDiffuse(1, viewPos, viewNormal);
|
||||
diffuse += calculateLightDiffuse(2, viewPos, viewNormal);
|
||||
diffuse += calculateLightDiffuse(3, viewPos, viewNormal);
|
||||
|
||||
output.FullLighting = ambient + diffuse;
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
#if defined(_FOG)
|
||||
UNITY_TRANSFER_FOG(output, output.pos);
|
||||
#endif // _FOG
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Fragment program
|
||||
//
|
||||
|
||||
fixed4 frag(VertexOutput input) : SV_Target
|
||||
{
|
||||
fixed4 texureColor = calculateTexturePixel(input.texcoord.xy);
|
||||
ALPHA_CLIP(texureColor, input.color)
|
||||
|
||||
#if defined(PER_PIXEL_LIGHTING)
|
||||
|
||||
#if defined(_NORMALMAP)
|
||||
half3 normalWorld = calculateNormalFromBumpMap(input.texcoord.xy, input.tangentWorld.xyz, input.binormalWorld.xyz, input.normalWorld.xyz);
|
||||
#else
|
||||
half3 normalWorld = input.normalWorld.xyz;
|
||||
#endif
|
||||
|
||||
//Get Ambient diffuse
|
||||
fixed3 ambient = calculateAmbientLight(normalWorld);
|
||||
|
||||
//Find vertex light diffuse
|
||||
fixed3 diffuse = fixed3(0,0,0);
|
||||
|
||||
//Add each vertex light to diffuse
|
||||
half3 normalView = normalize(mul((float3x3)UNITY_MATRIX_V, normalWorld));
|
||||
ADD_VERTEX_LIGHT(0, input, normalView, diffuse)
|
||||
ADD_VERTEX_LIGHT(1, input, normalView, diffuse)
|
||||
ADD_VERTEX_LIGHT(2, input, normalView, diffuse)
|
||||
ADD_VERTEX_LIGHT(3, input, normalView, diffuse)
|
||||
|
||||
fixed3 lighting = ambient + diffuse;
|
||||
|
||||
APPLY_EMISSION(lighting, input.texcoord.xy)
|
||||
|
||||
fixed4 pixel = calculateLitPixel(texureColor, input.color, lighting);
|
||||
|
||||
#if defined(_RIM_LIGHTING)
|
||||
pixel.rgb = applyRimLighting(input.posWorld, normalWorld, pixel);
|
||||
#endif
|
||||
|
||||
#else // !PER_PIXEL_LIGHTING
|
||||
|
||||
APPLY_EMISSION(input.FullLighting, input.texcoord.xy)
|
||||
|
||||
fixed4 pixel = calculateLitPixel(texureColor, input.color, input.FullLighting);
|
||||
|
||||
#endif // !PER_PIXEL_LIGHTING
|
||||
|
||||
COLORISE(pixel)
|
||||
|
||||
#if defined(_FOG)
|
||||
fixed4 fogColor = lerp(fixed4(0,0,0,0), unity_FogColor, pixel.a);
|
||||
UNITY_APPLY_FOG_COLOR(input.fogCoord, pixel, fogColor);
|
||||
#endif // _FOG
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
#endif // SPRITE_VERTEX_LIGHTING_INCLUDED
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b256f9f092407414392d98f339173a2d
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,161 @@
|
||||
Shader "Spine/Sprite/Pixel Lit"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Main Texture", 2D) = "white" {}
|
||||
_Color ("Color", Color) = (1,1,1,1)
|
||||
|
||||
_BumpScale("Scale", Float) = 1.0
|
||||
_BumpMap ("Normal Map", 2D) = "bump" {}
|
||||
|
||||
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
|
||||
[PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
|
||||
[PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
|
||||
|
||||
_EmissionColor("Color", Color) = (0,0,0,0)
|
||||
_EmissionMap("Emission", 2D) = "white" {}
|
||||
_EmissionPower("Emission Power", Float) = 2.0
|
||||
|
||||
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
|
||||
_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
|
||||
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
|
||||
_MetallicGlossMap("Metallic", 2D) = "white" {}
|
||||
|
||||
_DiffuseRamp ("Diffuse Ramp Texture", 2D) = "gray" {}
|
||||
|
||||
_FixedNormal ("Fixed Normal", Vector) = (0,0,1,1)
|
||||
_ZWrite ("Depth Write", Float) = 1.0
|
||||
_Cutoff ("Depth alpha cutoff", Range(0,1)) = 0.5
|
||||
_ShadowAlphaCutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
_CustomRenderQueue ("Custom Render Queue", Float) = 0.0
|
||||
|
||||
_OverlayColor ("Overlay Color", Color) = (0,0,0,0)
|
||||
_Hue("Hue", Range(-0.5,0.5)) = 0.0
|
||||
_Saturation("Saturation", Range(0,2)) = 1.0
|
||||
_Brightness("Brightness", Range(0,2)) = 1.0
|
||||
|
||||
_RimPower("Rim Power", Float) = 2.0
|
||||
_RimColor ("Rim Color", Color) = (1,1,1,1)
|
||||
|
||||
_BlendTex ("Blend Texture", 2D) = "white" {}
|
||||
_BlendAmount ("Blend", Range(0,1)) = 0.0
|
||||
|
||||
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
|
||||
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
|
||||
[HideInInspector] _RenderQueue ("__queue", Float) = 0.0
|
||||
[HideInInspector] _Cull ("__cull", Float) = 0.0
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue"="Transparent" "RenderType"="Sprite" "AlphaDepth"="False" "CanUseSpriteAtlas"="True" "IgnoreProjector"="True" }
|
||||
LOD 200
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "FORWARD"
|
||||
Tags { "LightMode" = "ForwardBase" }
|
||||
Blend [_SrcBlend] [_DstBlend]
|
||||
ZWrite [_ZWrite]
|
||||
ZTest LEqual
|
||||
Cull [_Cull]
|
||||
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
|
||||
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
|
||||
#pragma shader_feature _ _FIXED_NORMALS_VIEWSPACE _FIXED_NORMALS_VIEWSPACE_BACKFACE _FIXED_NORMALS_MODELSPACE _FIXED_NORMALS_MODELSPACE_BACKFACE
|
||||
#pragma shader_feature _ _SPECULAR _SPECULAR_GLOSSMAP
|
||||
#pragma shader_feature _NORMALMAP
|
||||
#pragma shader_feature _ALPHA_CLIP
|
||||
#pragma shader_feature _EMISSION
|
||||
#pragma shader_feature _RIM_LIGHTING
|
||||
#pragma shader_feature _DIFFUSE_RAMP
|
||||
#pragma shader_feature _COLOR_ADJUST
|
||||
#pragma shader_feature _TEXTURE_BLEND
|
||||
#pragma shader_feature _SPHERICAL_HARMONICS
|
||||
#pragma shader_feature _FOG
|
||||
|
||||
#pragma multi_compile_fwdbase
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_fog
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment fragBase
|
||||
|
||||
#include "CGIncludes/SpritePixelLighting.cginc"
|
||||
ENDCG
|
||||
}
|
||||
Pass
|
||||
{
|
||||
Name "FORWARD_DELTA"
|
||||
Tags { "LightMode" = "ForwardAdd" }
|
||||
Blend [_SrcBlend] One
|
||||
ZWrite Off
|
||||
ZTest LEqual
|
||||
Cull [_Cull]
|
||||
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
|
||||
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
|
||||
#pragma shader_feature _ _FIXED_NORMALS_VIEWSPACE _FIXED_NORMALS_VIEWSPACE_BACKFACE _FIXED_NORMALS_MODELSPACE _FIXED_NORMALS_MODELSPACE_BACKFACE
|
||||
#pragma shader_feature _ _SPECULAR _SPECULAR_GLOSSMAP
|
||||
#pragma shader_feature _NORMALMAP
|
||||
#pragma shader_feature _ALPHA_CLIP
|
||||
#pragma shader_feature _DIFFUSE_RAMP
|
||||
#pragma shader_feature _COLOR_ADJUST
|
||||
#pragma shader_feature _TEXTURE_BLEND
|
||||
#pragma shader_feature _FOG
|
||||
|
||||
#pragma multi_compile_fwdadd_fullshadows
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_fog
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment fragAdd
|
||||
|
||||
#include "CGIncludes/SpritePixelLighting.cginc"
|
||||
ENDCG
|
||||
}
|
||||
Pass
|
||||
{
|
||||
Name "ShadowCaster"
|
||||
Tags { "LightMode"="ShadowCaster" }
|
||||
Offset 1, 1
|
||||
|
||||
Fog { Mode Off }
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "CGIncludes/SpriteShadows.cginc"
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
FallBack "Spine/Sprite/Unlit"
|
||||
CustomEditor "SpineSpriteShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f7a5a97a82637f478494bc40ea8c8a2
|
||||
timeCreated: 1479457857
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
Shader "Spine/Sprite/Unlit"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Main Texture", 2D) = "white" {}
|
||||
_Color ("Color", Color) = (1,1,1,1)
|
||||
|
||||
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
|
||||
[PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
|
||||
[PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
|
||||
|
||||
_ZWrite ("Depth Write", Float) = 0.0
|
||||
_Cutoff ("Depth alpha cutoff", Range(0,1)) = 0.0
|
||||
_ShadowAlphaCutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
_CustomRenderQueue ("Custom Render Queue", Float) = 0.0
|
||||
|
||||
_OverlayColor ("Overlay Color", Color) = (0,0,0,0)
|
||||
_Hue("Hue", Range(-0.5,0.5)) = 0.0
|
||||
_Saturation("Saturation", Range(0,2)) = 1.0
|
||||
_Brightness("Brightness", Range(0,2)) = 1.0
|
||||
|
||||
_BlendTex ("Blend Texture", 2D) = "white" {}
|
||||
_BlendAmount ("Blend", Range(0,1)) = 0.0
|
||||
|
||||
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
|
||||
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
|
||||
[HideInInspector] _RenderQueue ("__queue", Float) = 0.0
|
||||
[HideInInspector] _Cull ("__cull", Float) = 0.0
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue"="Transparent" "RenderType"="Sprite" "AlphaDepth"="False" "CanUseSpriteAtlas"="True" "IgnoreProjector"="True" }
|
||||
LOD 100
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Blend [_SrcBlend] [_DstBlend]
|
||||
Lighting Off
|
||||
ZWrite [_ZWrite]
|
||||
ZTest LEqual
|
||||
Cull [_Cull]
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
|
||||
#pragma shader_feature _ALPHA_CLIP
|
||||
#pragma shader_feature _TEXTURE_BLEND
|
||||
#pragma shader_feature _COLOR_ADJUST
|
||||
#pragma shader_feature _FOG
|
||||
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_fog
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "CGIncludes/SpriteUnlit.cginc"
|
||||
ENDCG
|
||||
}
|
||||
Pass
|
||||
{
|
||||
Name "ShadowCaster"
|
||||
Tags { "LightMode"="ShadowCaster" }
|
||||
Offset 1, 1
|
||||
|
||||
Fog { Mode Off }
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "CGIncludes/SpriteShadows.cginc"
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
CustomEditor "SpineSpriteShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64005298b9a80bb4899eabd5140dc4a8
|
||||
timeCreated: 1479457857
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,128 @@
|
||||
Shader "Spine/Sprite/Vertex Lit"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Main Texture", 2D) = "white" {}
|
||||
_Color ("Color", Color) = (1,1,1,1)
|
||||
|
||||
_BumpScale("Scale", Float) = 1.0
|
||||
_BumpMap ("Normal Map", 2D) = "bump" {}
|
||||
|
||||
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
|
||||
[PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
|
||||
[PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
|
||||
|
||||
_EmissionColor("Color", Color) = (0,0,0,0)
|
||||
_EmissionMap("Emission", 2D) = "white" {}
|
||||
_EmissionPower("Emission Power", Float) = 2.0
|
||||
|
||||
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
|
||||
_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
|
||||
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
|
||||
_MetallicGlossMap("Metallic", 2D) = "white" {}
|
||||
|
||||
_DiffuseRamp ("Diffuse Ramp Texture", 2D) = "gray" {}
|
||||
|
||||
_FixedNormal ("Fixed Normal", Vector) = (0,0,1,1)
|
||||
_ZWrite ("Depth Write", Float) = 0.0
|
||||
_Cutoff ("Depth alpha cutoff", Range(0,1)) = 0.0
|
||||
_ShadowAlphaCutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
_CustomRenderQueue ("Custom Render Queue", Float) = 0.0
|
||||
|
||||
_OverlayColor ("Overlay Color", Color) = (0,0,0,0)
|
||||
_Hue("Hue", Range(-0.5,0.5)) = 0.0
|
||||
_Saturation("Saturation", Range(0,2)) = 1.0
|
||||
_Brightness("Brightness", Range(0,2)) = 1.0
|
||||
|
||||
_RimPower("Rim Power", Float) = 2.0
|
||||
_RimColor ("Rim Color", Color) = (1,1,1,1)
|
||||
|
||||
_BlendTex ("Blend Texture", 2D) = "white" {}
|
||||
_BlendAmount ("Blend", Range(0,1)) = 0.0
|
||||
|
||||
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
|
||||
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
|
||||
[HideInInspector] _RenderQueue ("__queue", Float) = 0.0
|
||||
[HideInInspector] _Cull ("__cull", Float) = 0.0
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue"="Transparent" "RenderType"="Sprite" "AlphaDepth"="False" "CanUseSpriteAtlas"="True" "IgnoreProjector"="True" }
|
||||
LOD 150
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Vertex"
|
||||
Tags { "LightMode" = "Vertex" }
|
||||
Blend [_SrcBlend] [_DstBlend]
|
||||
ZWrite [_ZWrite]
|
||||
ZTest LEqual
|
||||
Cull [_Cull]
|
||||
Lighting On
|
||||
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
|
||||
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
|
||||
#pragma shader_feature _ _FIXED_NORMALS_VIEWSPACE _FIXED_NORMALS_VIEWSPACE_BACKFACE _FIXED_NORMALS_MODELSPACE _FIXED_NORMALS_MODELSPACE_BACKFACE
|
||||
#pragma shader_feature _ _SPECULAR _SPECULAR_GLOSSMAP
|
||||
#pragma shader_feature _NORMALMAP
|
||||
#pragma shader_feature _ALPHA_CLIP
|
||||
#pragma shader_feature _EMISSION
|
||||
#pragma shader_feature _DIFFUSE_RAMP
|
||||
#pragma shader_feature _COLOR_ADJUST
|
||||
#pragma shader_feature _RIM_LIGHTING
|
||||
#pragma shader_feature _TEXTURE_BLEND
|
||||
#pragma shader_feature _SPHERICAL_HARMONICS
|
||||
#pragma shader_feature _FOG
|
||||
|
||||
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_fog
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "CGIncludes/SpriteVertexLighting.cginc"
|
||||
ENDCG
|
||||
}
|
||||
Pass
|
||||
{
|
||||
Name "ShadowCaster"
|
||||
Tags { "LightMode"="ShadowCaster" }
|
||||
Offset 1, 1
|
||||
|
||||
Fog { Mode Off }
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma multi_compile _ PIXELSNAP_ON
|
||||
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "CGIncludes/SpriteShadows.cginc"
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
FallBack "Spine/Sprite/Unlit"
|
||||
CustomEditor "SpineSpriteShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ce511398fb980f41b7d316c51534590
|
||||
timeCreated: 1479457856
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6338355ec521d6848bb8ef1e10272b3e
|
||||
folderAsset: yes
|
||||
timeCreated: 1455493504
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,167 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Spine/UI/BoneFollowerGraphic")]
|
||||
public class BoneFollowerGraphic : MonoBehaviour {
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public SkeletonGraphic SkeletonGraphic {
|
||||
get { return skeletonGraphic; }
|
||||
set {
|
||||
skeletonGraphic = value;
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public bool initializeOnAwake = true;
|
||||
|
||||
/// <summary>If a bone isn't set in code, boneName is used to find the bone at the beginning. For runtime switching by name, use SetBoneByName. You can also set the BoneFollower.bone field directly.</summary>
|
||||
[SpineBone(dataField: "skeletonGraphic")]
|
||||
[SerializeField] public string boneName;
|
||||
|
||||
public bool followBoneRotation = true;
|
||||
[Tooltip("Follows the skeleton's flip state by controlling this Transform's local scale.")]
|
||||
public bool followSkeletonFlip = true;
|
||||
[Tooltip("Follows the target bone's local scale. BoneFollower cannot inherit world/skewed scale because of UnityEngine.Transform property limitations.")]
|
||||
public bool followLocalScale = false;
|
||||
public bool followZPosition = true;
|
||||
|
||||
[System.NonSerialized] public Bone bone;
|
||||
|
||||
Transform skeletonTransform;
|
||||
bool skeletonTransformIsParent;
|
||||
|
||||
[System.NonSerialized] public bool valid;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the target bone by its bone name. Returns false if no bone was found.</summary>
|
||||
public bool SetBone (string name) {
|
||||
bone = skeletonGraphic.Skeleton.FindBone(name);
|
||||
if (bone == null) {
|
||||
Debug.LogError("Bone not found: " + name, this);
|
||||
return false;
|
||||
}
|
||||
boneName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Awake () {
|
||||
if (initializeOnAwake) Initialize();
|
||||
}
|
||||
|
||||
public void Initialize () {
|
||||
bone = null;
|
||||
valid = skeletonGraphic != null && skeletonGraphic.IsValid;
|
||||
if (!valid) return;
|
||||
|
||||
skeletonTransform = skeletonGraphic.transform;
|
||||
// skeletonGraphic.OnRebuild -= HandleRebuildRenderer;
|
||||
// skeletonGraphic.OnRebuild += HandleRebuildRenderer;
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
|
||||
if (!string.IsNullOrEmpty(boneName))
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor) {
|
||||
LateUpdate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void LateUpdate () {
|
||||
if (!valid) {
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
#endif
|
||||
|
||||
if (bone == null) {
|
||||
if (string.IsNullOrEmpty(boneName)) return;
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
if (!SetBone(boneName)) return;
|
||||
}
|
||||
|
||||
var thisTransform = this.transform as RectTransform;
|
||||
if (thisTransform == null) return;
|
||||
|
||||
var canvas = skeletonGraphic.canvas;
|
||||
if (canvas == null) canvas = skeletonGraphic.GetComponentInParent<Canvas>();
|
||||
float scale = canvas.referencePixelsPerUnit;
|
||||
|
||||
if (skeletonTransformIsParent) {
|
||||
// Recommended setup: Use local transform properties if Spine GameObject is the immediate parent
|
||||
thisTransform.localPosition = new Vector3(bone.worldX * scale, bone.worldY * scale, followZPosition ? 0f : thisTransform.localPosition.z);
|
||||
if (followBoneRotation) thisTransform.localRotation = bone.GetQuaternion();
|
||||
} else {
|
||||
// For special cases: Use transform world properties if transform relationship is complicated
|
||||
Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX * scale, bone.worldY * scale, 0f));
|
||||
if (!followZPosition) targetWorldPosition.z = thisTransform.position.z;
|
||||
|
||||
float boneWorldRotation = bone.WorldRotationX;
|
||||
|
||||
Transform transformParent = thisTransform.parent;
|
||||
if (transformParent != null) {
|
||||
Matrix4x4 m = transformParent.localToWorldMatrix;
|
||||
if (m.m00 * m.m11 - m.m01 * m.m10 < 0) // Determinant2D is negative
|
||||
boneWorldRotation = -boneWorldRotation;
|
||||
}
|
||||
|
||||
if (followBoneRotation) {
|
||||
Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
|
||||
thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + boneWorldRotation));
|
||||
} else {
|
||||
thisTransform.position = targetWorldPosition;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 localScale = followLocalScale ? new Vector3(bone.scaleX, bone.scaleY, 1f) : new Vector3(1f, 1f, 1f);
|
||||
if (followSkeletonFlip) localScale.y *= Mathf.Sign(bone.skeleton.scaleX * bone.skeleton.scaleY);
|
||||
thisTransform.localScale = localScale;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b42a195b47491d34b9bcbc40898bcb29
|
||||
timeCreated: 1499211965
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43897010c7e77c54897cb98c1ddf84f1
|
||||
folderAsset: yes
|
||||
timeCreated: 1455128695
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,87 @@
|
||||
%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: SkeletonGraphicDefault
|
||||
m_Shader: {fileID: 4800000, guid: fa95b0fb6983c0f40a152e6f9aa82bfb, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _AlphaTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- PixelSnap: 0
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnableExternalAlpha: 0
|
||||
- _Glossiness: 0.5
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _Flip: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _RendererColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b66cf7a186d13054989b33a5c90044e4
|
||||
timeCreated: 1455140322
|
||||
licenseType: Free
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,79 @@
|
||||
%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: SkeletonGraphicTintBlack
|
||||
m_Shader: {fileID: 4800000, guid: f64c7bc238bb2c246b8ca1912b2b6b9c, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 5
|
||||
m_EnableInstancingVariants: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _Glossiness: 0.5
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Black: {r: 0, g: 0, b: 0, a: 0}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfcea0e11aa80bb4b8d05790b905fc31
|
||||
timeCreated: 1455140322
|
||||
licenseType: Free
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,125 @@
|
||||
// This is a premultiply-alpha adaptation of the built-in Unity shader "UI/Default" to allow Unity UI stencil masking.
|
||||
|
||||
Shader "Spine/SkeletonGraphic Tint Black"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||
[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
|
||||
|
||||
_Color ("Tint", Color) = (1,1,1,1)
|
||||
_Black ("Black Point", Color) = (0,0,0,0)
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
|
||||
_ColorMask ("Color Mask", Float) = 15
|
||||
|
||||
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue"="Transparent"
|
||||
"IgnoreProjector"="True"
|
||||
"RenderType"="Transparent"
|
||||
"PreviewType"="Plane"
|
||||
"CanUseSpriteAtlas"="True"
|
||||
}
|
||||
|
||||
Stencil
|
||||
{
|
||||
Ref [_Stencil]
|
||||
Comp [_StencilComp]
|
||||
Pass [_StencilOp]
|
||||
ReadMask [_StencilReadMask]
|
||||
WriteMask [_StencilWriteMask]
|
||||
}
|
||||
|
||||
Cull Off
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
ZTest [unity_GUIZTestMode]
|
||||
Fog { Mode Off }
|
||||
Blend One OneMinusSrcAlpha
|
||||
ColorMask [_ColorMask]
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityUI.cginc"
|
||||
|
||||
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||
|
||||
struct VertexInput {
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float2 uv1 : TEXCOORD1;
|
||||
float2 uv2 : TEXCOORD2;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
half2 texcoord : TEXCOORD0;
|
||||
float2 uv1 : TEXCOORD1;
|
||||
float2 uv2 : TEXCOORD2;
|
||||
float4 worldPosition : TEXCOORD3;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
fixed4 _Color;
|
||||
fixed4 _Black;
|
||||
fixed4 _TextureSampleAdd;
|
||||
float4 _ClipRect;
|
||||
|
||||
VertexOutput vert (VertexInput IN) {
|
||||
VertexOutput OUT;
|
||||
|
||||
UNITY_SETUP_INSTANCE_ID(IN);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
||||
|
||||
OUT.worldPosition = IN.vertex;
|
||||
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
||||
OUT.texcoord = IN.texcoord;
|
||||
|
||||
OUT.color = IN.color * float4(_Color.rgb * _Color.a, _Color.a); // Combine a PMA version of _Color with vertexColor.
|
||||
OUT.uv1 = IN.uv1;
|
||||
OUT.uv2 = IN.uv2;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
sampler2D _MainTex;
|
||||
|
||||
fixed4 frag (VertexOutput IN) : SV_Target
|
||||
{
|
||||
half4 texColor = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd);
|
||||
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
texColor.rgb *= texColor.a;
|
||||
#endif
|
||||
|
||||
texColor *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
||||
|
||||
#ifdef UNITY_UI_ALPHACLIP
|
||||
clip (texColor.a - 0.001);
|
||||
#endif
|
||||
|
||||
return (texColor * IN.color) + float4(((1-texColor.rgb) * (_Black.rgb + float3(IN.uv1.r, IN.uv1.g, IN.uv2.r)) * texColor.a * _Color.a * IN.color.a), 0);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f64c7bc238bb2c246b8ca1912b2b6b9c
|
||||
timeCreated: 1455080068
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,123 @@
|
||||
// This is a premultiply-alpha adaptation of the built-in Unity shader "UI/Default" in Unity 5.6.2 to allow Unity UI stencil masking.
|
||||
|
||||
Shader "Spine/SkeletonGraphic"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
|
||||
[Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
|
||||
_Color ("Tint", Color) = (1,1,1,1)
|
||||
|
||||
_StencilComp ("Stencil Comparison", Float) = 8
|
||||
_Stencil ("Stencil ID", Float) = 0
|
||||
_StencilOp ("Stencil Operation", Float) = 0
|
||||
_StencilWriteMask ("Stencil Write Mask", Float) = 255
|
||||
_StencilReadMask ("Stencil Read Mask", Float) = 255
|
||||
|
||||
_ColorMask ("Color Mask", Float) = 15
|
||||
|
||||
[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"Queue"="Transparent"
|
||||
"IgnoreProjector"="True"
|
||||
"RenderType"="Transparent"
|
||||
"PreviewType"="Plane"
|
||||
"CanUseSpriteAtlas"="True"
|
||||
}
|
||||
|
||||
Stencil
|
||||
{
|
||||
Ref [_Stencil]
|
||||
Comp [_StencilComp]
|
||||
Pass [_StencilOp]
|
||||
ReadMask [_StencilReadMask]
|
||||
WriteMask [_StencilWriteMask]
|
||||
}
|
||||
|
||||
Cull Off
|
||||
Lighting Off
|
||||
ZWrite Off
|
||||
ZTest [unity_GUIZTestMode]
|
||||
Fog { Mode Off }
|
||||
Blend One OneMinusSrcAlpha
|
||||
ColorMask [_ColorMask]
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma target 2.0
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityUI.cginc"
|
||||
|
||||
#pragma multi_compile __ UNITY_UI_ALPHACLIP
|
||||
|
||||
struct VertexInput {
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
half2 texcoord : TEXCOORD0;
|
||||
float4 worldPosition : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
fixed4 _Color;
|
||||
fixed4 _TextureSampleAdd;
|
||||
float4 _ClipRect;
|
||||
|
||||
VertexOutput vert (VertexInput IN) {
|
||||
VertexOutput OUT;
|
||||
|
||||
UNITY_SETUP_INSTANCE_ID(IN);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
|
||||
|
||||
OUT.worldPosition = IN.vertex;
|
||||
OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);
|
||||
OUT.texcoord = IN.texcoord;
|
||||
|
||||
#ifdef UNITY_HALF_TEXEL_OFFSET
|
||||
OUT.vertex.xy += (_ScreenParams.zw-1.0) * float2(-1,1);
|
||||
#endif
|
||||
|
||||
OUT.color = IN.color * float4(_Color.rgb * _Color.a, _Color.a); // Combine a PMA version of _Color with vertexColor.
|
||||
return OUT;
|
||||
}
|
||||
|
||||
sampler2D _MainTex;
|
||||
|
||||
fixed4 frag (VertexOutput IN) : SV_Target
|
||||
{
|
||||
half4 texColor = tex2D(_MainTex, IN.texcoord);
|
||||
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
texColor.rgb *= texColor.a;
|
||||
#endif
|
||||
|
||||
half4 color = (texColor + _TextureSampleAdd) * IN.color;
|
||||
|
||||
color *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
|
||||
|
||||
#ifdef UNITY_UI_ALPHACLIP
|
||||
clip (color.a - 0.001);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa95b0fb6983c0f40a152e6f9aa82bfb
|
||||
timeCreated: 1455080068
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,327 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Spine.Unity {
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[RequireComponent(typeof(CanvasRenderer), typeof(RectTransform)), DisallowMultipleComponent]
|
||||
[AddComponentMenu("Spine/SkeletonGraphic (Unity UI Canvas)")]
|
||||
public class SkeletonGraphic : MaskableGraphic, ISkeletonComponent, IAnimationStateComponent, ISkeletonAnimation, IHasSkeletonDataAsset {
|
||||
|
||||
#region Inspector
|
||||
public SkeletonDataAsset skeletonDataAsset;
|
||||
public SkeletonDataAsset SkeletonDataAsset { get { return skeletonDataAsset; } }
|
||||
|
||||
[SpineSkin(dataField:"skeletonDataAsset", defaultAsEmptyString:true)]
|
||||
public string initialSkinName;
|
||||
public bool initialFlipX, initialFlipY;
|
||||
|
||||
[SpineAnimation(dataField:"skeletonDataAsset")]
|
||||
public string startingAnimation;
|
||||
public bool startingLoop;
|
||||
public float timeScale = 1f;
|
||||
public bool freeze;
|
||||
public bool unscaledTime;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate () {
|
||||
// This handles Scene View preview.
|
||||
base.OnValidate ();
|
||||
if (this.IsValid) {
|
||||
if (skeletonDataAsset == null) {
|
||||
Clear();
|
||||
} else if (skeletonDataAsset.skeletonJSON == null) {
|
||||
Clear();
|
||||
} else if (skeletonDataAsset.GetSkeletonData(true) != skeleton.data) {
|
||||
Clear();
|
||||
Initialize(true);
|
||||
if (skeletonDataAsset.atlasAssets.Length > 1 || skeletonDataAsset.atlasAssets[0].MaterialCount > 1)
|
||||
Debug.LogError("Unity UI does not support multiple textures per Renderer. Your skeleton will not be rendered correctly. Recommend using SkeletonAnimation instead. This requires the use of a Screen space camera canvas.");
|
||||
} else {
|
||||
if (freeze) return;
|
||||
|
||||
if (!string.IsNullOrEmpty(initialSkinName)) {
|
||||
var skin = skeleton.data.FindSkin(initialSkinName);
|
||||
if (skin != null) {
|
||||
if (skin == skeleton.data.defaultSkin)
|
||||
skeleton.SetSkin((Skin)null);
|
||||
else
|
||||
skeleton.SetSkin(skin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Only provide visual feedback to inspector changes in Unity Editor Edit mode.
|
||||
if (!Application.isPlaying) {
|
||||
skeleton.scaleX = this.initialFlipX ? -1 : 1;
|
||||
skeleton.scaleY = this.initialFlipY ? -1 : 1;
|
||||
|
||||
skeleton.SetToSetupPose();
|
||||
if (!string.IsNullOrEmpty(startingAnimation))
|
||||
skeleton.PoseWithAnimation(startingAnimation, 0f, false);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// Under some circumstances (e.g. sometimes on the first import) OnValidate is called
|
||||
// before SpineEditorUtilities.ImportSpineContent, causing an unnecessary exception.
|
||||
// The (skeletonDataAsset.skeletonJSON != null) condition serves to prevent this exception.
|
||||
if (skeletonDataAsset != null && skeletonDataAsset.skeletonJSON != null)
|
||||
Initialize(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Reset () {
|
||||
|
||||
base.Reset();
|
||||
if (material == null || material.shader != Shader.Find("Spine/SkeletonGraphic"))
|
||||
Debug.LogWarning("SkeletonGraphic works best with the SkeletonGraphic material.");
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region Runtime Instantiation
|
||||
/// <summary>Create a new GameObject with a SkeletonGraphic component.</summary>
|
||||
/// <param name="material">Material for the canvas renderer to use. Usually, the default SkeletonGraphic material will work.</param>
|
||||
public static SkeletonGraphic NewSkeletonGraphicGameObject (SkeletonDataAsset skeletonDataAsset, Transform parent, Material material) {
|
||||
var sg = SkeletonGraphic.AddSkeletonGraphicComponent(new GameObject("New Spine GameObject"), skeletonDataAsset, material);
|
||||
if (parent != null) sg.transform.SetParent(parent, false);
|
||||
return sg;
|
||||
}
|
||||
|
||||
/// <summary>Add a SkeletonGraphic component to a GameObject.</summary>
|
||||
/// <param name="material">Material for the canvas renderer to use. Usually, the default SkeletonGraphic material will work.</param>
|
||||
public static SkeletonGraphic AddSkeletonGraphicComponent (GameObject gameObject, SkeletonDataAsset skeletonDataAsset, Material material) {
|
||||
var c = gameObject.AddComponent<SkeletonGraphic>();
|
||||
if (skeletonDataAsset != null) {
|
||||
c.material = material;
|
||||
c.skeletonDataAsset = skeletonDataAsset;
|
||||
c.Initialize(false);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Internals
|
||||
// This is used by the UI system to determine what to put in the MaterialPropertyBlock.
|
||||
Texture overrideTexture;
|
||||
public Texture OverrideTexture {
|
||||
get { return overrideTexture; }
|
||||
set {
|
||||
overrideTexture = value;
|
||||
canvasRenderer.SetTexture(this.mainTexture); // Refresh canvasRenderer's texture. Make sure it handles null.
|
||||
}
|
||||
}
|
||||
public override Texture mainTexture {
|
||||
get {
|
||||
// Fail loudly when incorrectly set up.
|
||||
if (overrideTexture != null) return overrideTexture;
|
||||
return skeletonDataAsset == null ? null : skeletonDataAsset.atlasAssets[0].PrimaryMaterial.mainTexture;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake () {
|
||||
|
||||
base.Awake ();
|
||||
if (!this.IsValid) {
|
||||
#if UNITY_EDITOR
|
||||
// workaround for special import case of open scene where OnValidate and Awake are
|
||||
// called in wrong order, before setup of Spine assets.
|
||||
if (!Application.isPlaying) {
|
||||
if (this.skeletonDataAsset != null && this.skeletonDataAsset.skeletonJSON == null)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Initialize(false);
|
||||
Rebuild(CanvasUpdate.PreRender);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Rebuild (CanvasUpdate update) {
|
||||
base.Rebuild(update);
|
||||
if (canvasRenderer.cull) return;
|
||||
if (update == CanvasUpdate.PreRender) UpdateMesh();
|
||||
}
|
||||
|
||||
public virtual void Update () {
|
||||
if (freeze) return;
|
||||
Update(unscaledTime ? Time.unscaledDeltaTime : Time.deltaTime);
|
||||
}
|
||||
|
||||
public virtual void Update (float deltaTime) {
|
||||
if (!this.IsValid) return;
|
||||
|
||||
deltaTime *= timeScale;
|
||||
skeleton.Update(deltaTime);
|
||||
state.Update(deltaTime);
|
||||
state.Apply(skeleton);
|
||||
|
||||
if (UpdateLocal != null) UpdateLocal(this);
|
||||
|
||||
skeleton.UpdateWorldTransform();
|
||||
|
||||
if (UpdateWorld != null) {
|
||||
UpdateWorld(this);
|
||||
skeleton.UpdateWorldTransform();
|
||||
}
|
||||
|
||||
if (UpdateComplete != null) UpdateComplete(this);
|
||||
}
|
||||
|
||||
public void LateUpdate () {
|
||||
if (freeze) return;
|
||||
//this.SetVerticesDirty(); // Which is better?
|
||||
UpdateMesh();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region API
|
||||
protected Skeleton skeleton;
|
||||
public Skeleton Skeleton { get { return skeleton; } internal set { skeleton = value; } }
|
||||
public SkeletonData SkeletonData { get { return skeleton == null ? null : skeleton.data; } }
|
||||
public bool IsValid { get { return skeleton != null; } }
|
||||
|
||||
protected Spine.AnimationState state;
|
||||
public Spine.AnimationState AnimationState { get { return state; } }
|
||||
|
||||
[SerializeField] protected Spine.Unity.MeshGenerator meshGenerator = new MeshGenerator();
|
||||
public Spine.Unity.MeshGenerator MeshGenerator { get { return this.meshGenerator; } }
|
||||
DoubleBuffered<Spine.Unity.MeshRendererBuffers.SmartMesh> meshBuffers;
|
||||
SkeletonRendererInstruction currentInstructions = new SkeletonRendererInstruction();
|
||||
|
||||
public Mesh GetLastMesh () {
|
||||
return meshBuffers.GetCurrent().mesh;
|
||||
}
|
||||
|
||||
public event UpdateBonesDelegate UpdateLocal;
|
||||
public event UpdateBonesDelegate UpdateWorld;
|
||||
public event UpdateBonesDelegate UpdateComplete;
|
||||
|
||||
/// <summary> Occurs after the vertex data populated every frame, before the vertices are pushed into the mesh.</summary>
|
||||
public event Spine.Unity.MeshGeneratorDelegate OnPostProcessVertices;
|
||||
|
||||
public void Clear () {
|
||||
skeleton = null;
|
||||
canvasRenderer.Clear();
|
||||
}
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (this.IsValid && !overwrite) return;
|
||||
|
||||
// Make sure none of the stuff is null
|
||||
if (this.skeletonDataAsset == null) return;
|
||||
var skeletonData = this.skeletonDataAsset.GetSkeletonData(false);
|
||||
if (skeletonData == null) return;
|
||||
|
||||
if (skeletonDataAsset.atlasAssets.Length <= 0 || skeletonDataAsset.atlasAssets[0].MaterialCount <= 0) return;
|
||||
|
||||
this.state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
|
||||
if (state == null) {
|
||||
Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
this.skeleton = new Skeleton(skeletonData) {
|
||||
scaleX = this.initialFlipX ? -1 : 1,
|
||||
scaleY = this.initialFlipY ? -1 : 1
|
||||
};
|
||||
|
||||
meshBuffers = new DoubleBuffered<MeshRendererBuffers.SmartMesh>();
|
||||
canvasRenderer.SetTexture(this.mainTexture); // Needed for overwriting initializations.
|
||||
|
||||
// Set the initial Skin and Animation
|
||||
if (!string.IsNullOrEmpty(initialSkinName))
|
||||
skeleton.SetSkin(initialSkinName);
|
||||
|
||||
if (!string.IsNullOrEmpty(startingAnimation)) {
|
||||
var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(startingAnimation);
|
||||
if (animationObject != null) {
|
||||
animationObject.PoseSkeleton(skeleton, 0f);
|
||||
skeleton.UpdateWorldTransform();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying) {
|
||||
#endif
|
||||
|
||||
// Make this block not run in Unity Editor edit mode.
|
||||
state.SetAnimation(0, animationObject, startingLoop);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
startingAnimation = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateMesh () {
|
||||
if (!this.IsValid) return;
|
||||
|
||||
skeleton.SetColor(this.color);
|
||||
var smartMesh = meshBuffers.GetNext();
|
||||
var currentInstructions = this.currentInstructions;
|
||||
|
||||
MeshGenerator.GenerateSingleSubmeshInstruction(currentInstructions, skeleton, this.material);
|
||||
bool updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, smartMesh.instructionUsed);
|
||||
|
||||
meshGenerator.Begin();
|
||||
if (currentInstructions.hasActiveClipping) {
|
||||
meshGenerator.AddSubmesh(currentInstructions.submeshInstructions.Items[0], updateTriangles);
|
||||
} else {
|
||||
meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
|
||||
}
|
||||
|
||||
if (canvas != null) meshGenerator.ScaleVertexData(canvas.referencePixelsPerUnit);
|
||||
if (OnPostProcessVertices != null) OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
|
||||
|
||||
var mesh = smartMesh.mesh;
|
||||
meshGenerator.FillVertexData(mesh);
|
||||
if (updateTriangles) meshGenerator.FillTrianglesSingle(mesh);
|
||||
meshGenerator.FillLateVertexData(mesh);
|
||||
|
||||
canvasRenderer.SetMesh(mesh);
|
||||
smartMesh.instructionUsed.Set(currentInstructions);
|
||||
|
||||
//this.UpdateMaterial(); // TODO: This allocates memory.
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d85b887af7e6c3f45a2e2d2920d641bc
|
||||
timeCreated: 1455576193
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
|
||||
- skeletonDataAsset: {instanceID: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,104 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated May 1, 2019. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2019, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE LLC "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 LLC 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;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Modules {
|
||||
public class SkeletonGraphicMirror : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderer source;
|
||||
public bool mirrorOnStart = true;
|
||||
public bool restoreOnDisable = true;
|
||||
SkeletonGraphic skeletonGraphic;
|
||||
|
||||
Skeleton originalSkeleton;
|
||||
bool originalFreeze;
|
||||
Texture2D overrideTexture;
|
||||
|
||||
private void Awake () {
|
||||
skeletonGraphic = GetComponent<SkeletonGraphic>();
|
||||
}
|
||||
|
||||
void Start () {
|
||||
if (mirrorOnStart)
|
||||
StartMirroring();
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
skeletonGraphic.UpdateMesh();
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (restoreOnDisable)
|
||||
RestoreIndependentSkeleton();
|
||||
}
|
||||
|
||||
/// <summary>Freeze the SkeletonGraphic on this GameObject, and use the source as the Skeleton to be rendered by the SkeletonGraphic.</summary>
|
||||
public void StartMirroring () {
|
||||
if (source == null)
|
||||
return;
|
||||
if (skeletonGraphic == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.startingAnimation = string.Empty;
|
||||
|
||||
if (originalSkeleton == null) {
|
||||
originalSkeleton = skeletonGraphic.Skeleton;
|
||||
originalFreeze = skeletonGraphic.freeze;
|
||||
}
|
||||
|
||||
skeletonGraphic.Skeleton = source.skeleton;
|
||||
skeletonGraphic.freeze = true;
|
||||
if (overrideTexture != null)
|
||||
skeletonGraphic.OverrideTexture = overrideTexture;
|
||||
}
|
||||
|
||||
/// <summary>Use a new texture for the SkeletonGraphic. Use this if your source skeleton uses a repacked atlas. </summary>
|
||||
public void UpdateTexture (Texture2D newOverrideTexture) {
|
||||
overrideTexture = newOverrideTexture;
|
||||
if (newOverrideTexture != null)
|
||||
skeletonGraphic.OverrideTexture = overrideTexture;
|
||||
}
|
||||
|
||||
/// <summary>Stops mirroring the source SkeletonRenderer and allows the SkeletonGraphic to become an independent Skeleton component again.</summary>
|
||||
public void RestoreIndependentSkeleton () {
|
||||
if (originalSkeleton == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.Skeleton = originalSkeleton;
|
||||
skeletonGraphic.freeze = originalFreeze;
|
||||
skeletonGraphic.OverrideTexture = null;
|
||||
|
||||
originalSkeleton = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbeb0b9949e46754eb0e0b61021b4f1c
|
||||
timeCreated: 1532024358
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user