initial commit
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
// OutlineFx © NullTale - https://x.com/NullTale/
|
||||
namespace OutlineFx
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class Optional<T>
|
||||
{
|
||||
[SerializeField]
|
||||
internal bool enabled;
|
||||
|
||||
[SerializeField]
|
||||
internal T value = default!;
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => enabled;
|
||||
set => enabled = value;
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
get => value;
|
||||
set => this.value = value;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
public Optional(bool enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Optional(T value, bool enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T GetValue(T disabledValue)
|
||||
{
|
||||
return enabled ? value : disabledValue;
|
||||
}
|
||||
|
||||
public T GetValueOrDefault()
|
||||
{
|
||||
return enabled ? value : default;
|
||||
}
|
||||
|
||||
public static implicit operator bool(Optional<T> opt)
|
||||
{
|
||||
return opt.enabled;
|
||||
}
|
||||
|
||||
public static implicit operator T(Optional<T> opt)
|
||||
{
|
||||
return opt.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 718243a646830064cb47da777eb68934
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/Optional.cs
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
|
||||
// OutlineFx © NullTale - https://x.com/NullTale/
|
||||
namespace OutlineFx
|
||||
{
|
||||
[ExecuteAlways] [DisallowMultipleComponent]
|
||||
public abstract class Outline : MonoBehaviour
|
||||
{
|
||||
internal Renderer _renderer;
|
||||
|
||||
public abstract Color Color {get; set; }
|
||||
|
||||
// =======================================================================
|
||||
private void OnEnable()
|
||||
{
|
||||
_renderer = GetComponent<Renderer>();
|
||||
}
|
||||
|
||||
private void OnWillRenderObject()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor && Equals(_renderer, null) == false)
|
||||
{
|
||||
if (TryGetComponent<Renderer>(out _renderer) == false)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OutlineFxFeature.Render(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46ca052234754909a86ce4897938622b
|
||||
timeCreated: 1721240301
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/Outline.cs
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
// OutlineFx © NullTale - https://x.com/NullTale/
|
||||
namespace OutlineFx
|
||||
{
|
||||
[DefaultExecutionOrder(10000)]
|
||||
public class OutlineBlocker : Outline
|
||||
{
|
||||
private static Color s_color = new Color(0, 0, 0, 7f / 255f);
|
||||
|
||||
public override Color Color
|
||||
{
|
||||
get => new Color(0, 0, 0, 14f / 255f);
|
||||
set
|
||||
{
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe0edcb63acb478aadea1918b40e26b3
|
||||
timeCreated: 1721238836
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/OutlineBlocker.cs
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,138 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
// OutlineFx © NullTale - https://x.com/NullTale/
|
||||
namespace OutlineFx
|
||||
{
|
||||
public partial class OutlineFxFeature
|
||||
{
|
||||
private static readonly int s_Alpha = Shader.PropertyToID("_Alpha");
|
||||
private static readonly int s_MainTex = Shader.PropertyToID("_MainTex");
|
||||
private static readonly int s_Step = Shader.PropertyToID("_Step");
|
||||
private static readonly int s_Color = Shader.PropertyToID("_Color");
|
||||
private static readonly int s_Solid = Shader.PropertyToID("_Solid");
|
||||
|
||||
private static readonly int s_AlphaTex = Shader.PropertyToID("_AlphaTex");
|
||||
private static readonly int s_AlphaTO = Shader.PropertyToID("_AlphaTO");
|
||||
|
||||
private class Pass : ScriptableRenderPass
|
||||
{
|
||||
public OutlineFxFeature _owner;
|
||||
|
||||
private FilteringSettings _filtering;
|
||||
private RenderStateBlock _override;
|
||||
private RenderTarget _buffer;
|
||||
private RTHandle _output;
|
||||
|
||||
// =======================================================================
|
||||
public void Init()
|
||||
{
|
||||
renderPassEvent = _owner._event;
|
||||
_buffer = new RenderTarget().Allocate(nameof(_buffer));
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
// allocate resources
|
||||
var cmd = CommandBufferPool.Get(nameof(OutlineFxFeature));
|
||||
var desc = renderingData.cameraData.cameraTargetDescriptor;
|
||||
desc.colorFormat = RenderTextureFormat.ARGB32;
|
||||
_buffer.Get(cmd, desc);
|
||||
|
||||
if (_owner._outlineMat == null)
|
||||
return;
|
||||
|
||||
_owner._outlineMat.SetFloat(s_Alpha, _owner._alphaCutout);
|
||||
_owner._outlineMat.SetFloat(s_Solid, _owner._solid);
|
||||
|
||||
if (_owner._solidMask._enabled)
|
||||
{
|
||||
var sm = _owner._solidMask;
|
||||
_owner._outlineMat.SetTexture(s_AlphaTex, sm._pattern);
|
||||
var xPeriod = 1f / (sm._velocity.x / 1000f);
|
||||
var yPeriod = 1f / (sm._velocity.y / 1000f);
|
||||
var xOffset = sm._velocity.x == 0 ? 0 : (Time.unscaledTime % xPeriod) / xPeriod * sm._scale;
|
||||
var yOffset = sm._velocity.y == 0 ? 0 : (Time.unscaledTime % yPeriod) / yPeriod * sm._scale;
|
||||
|
||||
var aspectTex = sm._pattern.width / (float)sm._pattern.height;
|
||||
|
||||
_owner._outlineMat.SetVector(s_AlphaTO, new Vector4(sm._scale * (Screen.width / (float)Screen.height) / aspectTex, sm._scale, xOffset, yOffset));
|
||||
}
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
if (_owner._output.Enabled == false)
|
||||
_output = RTHandles.Alloc(renderingData.cameraData.renderer.cameraColorTarget);
|
||||
#else
|
||||
_output = renderingData.cameraData.renderer.cameraColorTargetHandle;
|
||||
#endif
|
||||
if (_owner._output.Enabled)
|
||||
_output = _alloc(_owner._output.Value);
|
||||
|
||||
// render with layer mask
|
||||
cmd.SetRenderTarget(_buffer.Handle.nameID);
|
||||
cmd.ClearRenderTarget(false, true, Color.clear, 1f);
|
||||
|
||||
if (_owner._attachDepth)
|
||||
{
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
var depth = renderingData.cameraData.renderer.cameraDepthTarget == BuiltinRenderTextureType.CameraTarget
|
||||
? renderingData.cameraData.renderer.cameraColorTarget
|
||||
: renderingData.cameraData.renderer.cameraDepthTarget;
|
||||
#else
|
||||
var depth = renderingData.cameraData.renderer.cameraDepthTargetHandle;
|
||||
#endif
|
||||
cmd.SetRenderTarget(_buffer.Handle, depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.SetRenderTarget(_buffer.Handle);
|
||||
}
|
||||
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
cmd.Clear();
|
||||
|
||||
foreach (var inst in _renderers)
|
||||
{
|
||||
if (inst == null)
|
||||
continue;
|
||||
|
||||
cmd.SetGlobalTexture(s_MainTex, inst._renderer.sharedMaterial.mainTexture);
|
||||
cmd.SetGlobalColor(s_Color, inst.Color);
|
||||
cmd.DrawRenderer(inst._renderer, _owner._outlineMat, 0, 0);
|
||||
|
||||
}
|
||||
_renderers.Clear();
|
||||
|
||||
cmd.SetGlobalVector(s_Step, _owner._step);
|
||||
_blit(_buffer.Handle, _output, _owner._outlineMat, 1);
|
||||
|
||||
_execute();
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void _blit(RTHandle from, RTHandle to, Material mat, int pass = 0)
|
||||
{
|
||||
OutlineFxFeature._blit(cmd, from, to, mat, pass);
|
||||
}
|
||||
|
||||
void _execute()
|
||||
{
|
||||
context.ExecuteCommandBuffer(cmd);
|
||||
CommandBufferPool.Release(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public override void FrameCleanup(CommandBuffer cmd)
|
||||
{
|
||||
_buffer.Release(cmd);
|
||||
|
||||
#if !UNITY_2022_1_OR_NEWER
|
||||
RTHandles.Release(_output);
|
||||
#else
|
||||
if (_owner._output.Enabled)
|
||||
RTHandles.Release(_output);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7dd2cd9763dd1a1419cec5a4d92317ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/OutlineFx.Pass.cs
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnityEngine;
|
||||
|
||||
// OutlineFx © NullTale - https://x.com/NullTale/
|
||||
namespace OutlineFx
|
||||
{
|
||||
[ExecuteAlways]
|
||||
public class OutlineFx : Outline
|
||||
{
|
||||
public Color _color = Color.white;
|
||||
|
||||
public override Color Color
|
||||
{
|
||||
get => _color;
|
||||
set => _color = value;
|
||||
}
|
||||
|
||||
public float Alpha
|
||||
{
|
||||
get => _color.a;
|
||||
set => _color.a = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4218d78ef2d54d0898b7514e121a781f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/OutlineFx.cs
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
// OutlineFx © NullTale - https://x.com/NullTale/
|
||||
namespace OutlineFx
|
||||
{
|
||||
public partial class OutlineFxFeature : ScriptableRendererFeature
|
||||
{
|
||||
private const string k_OutlineShader = "Hidden/OutlineFx/Main";
|
||||
|
||||
private static readonly int s_MainTexId = Shader.PropertyToID("_MainTex");
|
||||
private static readonly int s_ColorId = Shader.PropertyToID("_Color");
|
||||
|
||||
private static List<ShaderTagId> k_ShaderTags;
|
||||
private static Mesh k_ScreenMesh;
|
||||
|
||||
public static Mesh ScreenMesh => k_ScreenMesh;
|
||||
|
||||
public float Solid
|
||||
{
|
||||
get => _solid;
|
||||
set => _solid = Mathf.Clamp01(value);
|
||||
}
|
||||
|
||||
public float Thickness
|
||||
{
|
||||
get => _thickness;
|
||||
set => _thickness = Mathf.Clamp01(value);
|
||||
}
|
||||
|
||||
public bool Mask
|
||||
{
|
||||
get => _solidMask._enabled;
|
||||
set
|
||||
{
|
||||
if (_solidMask._enabled == value)
|
||||
return;
|
||||
|
||||
_solidMask._enabled = value;
|
||||
|
||||
if (_solidMask._enabled)
|
||||
_outlineMat.EnableKeyword("ALPHA_MASK");
|
||||
else
|
||||
_outlineMat.DisableKeyword("ALPHA_MASK");
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("When draw outline")]
|
||||
private RenderPassEvent _event = RenderPassEvent.AfterRenderingPostProcessing;
|
||||
[Range(0, 1)]
|
||||
[SerializeField]
|
||||
[Tooltip("Solid fill of outline")]
|
||||
private float _solid;
|
||||
|
||||
[Range(0, 1f)]
|
||||
[Tooltip("Outline thickness")]
|
||||
public float _thickness = 0.001f;
|
||||
[Range(0, 1)]
|
||||
[SerializeField]
|
||||
[Tooltip("Alpha cutout threshold for transparent objects")]
|
||||
private float _alphaCutout = .5f;
|
||||
|
||||
[Tooltip("Edge filter")]
|
||||
public Mode _mode = Mode.Hard;
|
||||
[HideInInspector]
|
||||
public Filter _filter = Filter.Box;
|
||||
[HideInInspector]
|
||||
public bool _attachDepth = true;
|
||||
|
||||
public Optional<string> _output = new Optional<string>("_globalTex", false);
|
||||
|
||||
public SolidMask _solidMask = new SolidMask();
|
||||
|
||||
[SerializeField] [HideInInspector]
|
||||
public Shader _shader;
|
||||
|
||||
private Material _outlineMat;
|
||||
private Vector4 _step;
|
||||
private Pass _pass;
|
||||
|
||||
private static List<Outline> _renderers = new List<Outline>();
|
||||
|
||||
// =======================================================================
|
||||
public class RenderTarget
|
||||
{
|
||||
public RTHandle Handle;
|
||||
public int Id;
|
||||
|
||||
private bool _allocated;
|
||||
|
||||
// =======================================================================
|
||||
public RenderTarget Allocate(RenderTexture rt, string name)
|
||||
{
|
||||
Handle = RTHandles.Alloc(rt, name);
|
||||
Id = Shader.PropertyToID(name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public RenderTarget Allocate(string name)
|
||||
{
|
||||
Handle = _alloc(name);
|
||||
Id = Shader.PropertyToID(name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Get(CommandBuffer cmd, in RenderTextureDescriptor desc)
|
||||
{
|
||||
_allocated = true;
|
||||
cmd.GetTemporaryRT(Id, desc);
|
||||
}
|
||||
|
||||
public void Release(CommandBuffer cmd)
|
||||
{
|
||||
if (_allocated == false)
|
||||
return;
|
||||
|
||||
_allocated = false;
|
||||
cmd.ReleaseTemporaryRT(Id);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SolidMask
|
||||
{
|
||||
public bool _enabled;
|
||||
public Texture2D _pattern;
|
||||
public float _scale = 50f;
|
||||
public Vector2 _velocity = new Vector2(0, 0);
|
||||
}
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
Hard,
|
||||
Soft
|
||||
}
|
||||
|
||||
public enum Filter
|
||||
{
|
||||
Cross,
|
||||
Box
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
public override void Create()
|
||||
{
|
||||
|
||||
_pass = new Pass() { _owner = this };
|
||||
_pass.Init();
|
||||
_renderers.Clear();
|
||||
|
||||
_validateContent();
|
||||
_validateMaterial();
|
||||
|
||||
if (k_ScreenMesh == null)
|
||||
{
|
||||
// init triangle
|
||||
k_ScreenMesh = new Mesh();
|
||||
_initScreenMesh(k_ScreenMesh, Matrix4x4.identity);
|
||||
}
|
||||
|
||||
if (k_ShaderTags == null)
|
||||
{
|
||||
k_ShaderTags = new List<ShaderTagId>(new[]
|
||||
{
|
||||
new ShaderTagId("SRPDefaultUnlit"),
|
||||
new ShaderTagId("UniversalForward"),
|
||||
new ShaderTagId("UniversalForwardOnly")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
// in game or scene view only
|
||||
if (renderingData.cameraData.cameraType != CameraType.Game && renderingData.cameraData.cameraType != CameraType.SceneView)
|
||||
return;
|
||||
|
||||
if (_renderers.Count == 0)
|
||||
return;
|
||||
|
||||
var aspect = Screen.width / (float)Screen.height;
|
||||
_step.x = _thickness / aspect;
|
||||
_step.y = _thickness;
|
||||
_step *= 0.007f;
|
||||
if (_mode == Mode.Soft)
|
||||
_step *= 2f;
|
||||
|
||||
renderer.EnqueuePass(_pass);
|
||||
}
|
||||
|
||||
public static void Render(Outline inst)
|
||||
{
|
||||
_renderers.Add(inst);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
private void _validateMaterial()
|
||||
{
|
||||
_outlineMat = new Material(_shader);
|
||||
switch (_mode)
|
||||
{
|
||||
case Mode.Soft:
|
||||
_outlineMat.EnableKeyword("SOFT");
|
||||
break;
|
||||
case Mode.Hard:
|
||||
_outlineMat.EnableKeyword("HARD");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
switch (_filter)
|
||||
{
|
||||
case Filter.Cross:
|
||||
_outlineMat.EnableKeyword("CROSS");
|
||||
break;
|
||||
case Filter.Box:
|
||||
_outlineMat.EnableKeyword("BOX");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
if (_solidMask._enabled)
|
||||
{
|
||||
_outlineMat.EnableKeyword("ALPHA_MASK");
|
||||
}
|
||||
}
|
||||
|
||||
private void _validateContent()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (_shader == null)
|
||||
_shader = Shader.Find(k_OutlineShader);
|
||||
|
||||
if (_solidMask._pattern == null)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(UnityEditor.AssetDatabase.GetAssetPath(_shader));
|
||||
_solidMask._pattern = UnityEditor.AssetDatabase.LoadAssetAtPath<Texture2D>($"{dir}\\checker.png");
|
||||
}
|
||||
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void _initScreenMesh(Mesh mesh, Matrix4x4 mat)
|
||||
{
|
||||
mesh.vertices = _verts(0f);
|
||||
mesh.uv = _texCoords();
|
||||
mesh.triangles = new int[3] { 0, 1, 2 };
|
||||
|
||||
mesh.UploadMeshData(true);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
Vector3[] _verts(float z)
|
||||
{
|
||||
var r = new Vector3[3];
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var uv = new Vector2((i << 1) & 2, i & 2);
|
||||
r[i] = mat.MultiplyPoint(new Vector3(uv.x * 2f - 1f, uv.y * 2f - 1f, z));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector2[] _texCoords()
|
||||
{
|
||||
var r = new Vector2[3];
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
if (SystemInfo.graphicsUVStartsAtTop)
|
||||
r[i] = new Vector2((i << 1) & 2, 1.0f - (i & 2));
|
||||
else
|
||||
r[i] = new Vector2((i << 1) & 2, i & 2);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
private static void _blit(CommandBuffer cmd, RTHandle from, RTHandle to, Material mat, int pass = 0)
|
||||
{
|
||||
cmd.SetGlobalTexture(s_MainTexId, from.nameID);
|
||||
cmd.SetRenderTarget(to.nameID);
|
||||
cmd.DrawMesh(k_ScreenMesh, Matrix4x4.identity, mat, 0, pass);
|
||||
}
|
||||
|
||||
private static RTHandle _alloc(string id)
|
||||
{
|
||||
return RTHandles.Alloc(id, name: id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 177ddeadd26a80641ad757c51fb7f5d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/OutlineFxFeature.cs
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6be9b4f584271394cb2119f347ca20ce
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 92 B |
@@ -0,0 +1,196 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41acea03acbaebe4a9dc26dd8264449e
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 7482667652216324306
|
||||
second: Square
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 0
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 2
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 4
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: 0
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 0
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: Square
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 256
|
||||
height: 256
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: 0
|
||||
bones: []
|
||||
spriteID: 2d009a6b596c7d760800000000000000
|
||||
internalID: 7482667652216324306
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
physicsShape:
|
||||
- - {x: -128, y: 128}
|
||||
- {x: -128, y: -128}
|
||||
- {x: 128, y: -128}
|
||||
- {x: 128, y: 128}
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable:
|
||||
Square: 7482667652216324306
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/Shaders/Checker.png
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,184 @@
|
||||
Shader "Hidden/OutlineFx/Main"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Pass // 0
|
||||
{
|
||||
name "Transparent"
|
||||
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
ZTest LEqual
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
|
||||
#include "Utils.hlsl"
|
||||
|
||||
#pragma vertex vert_mesh
|
||||
#pragma fragment frag
|
||||
|
||||
sampler2D _MainTex;
|
||||
float4 _Color;
|
||||
float _Alpha;
|
||||
|
||||
// =======================================================================
|
||||
float4 frag(fragIn i) : SV_Target
|
||||
{
|
||||
if (tex2D(_MainTex, i.uv).a < _Alpha)
|
||||
discard;
|
||||
|
||||
return _Color;
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass // 1
|
||||
{
|
||||
name "Outline"
|
||||
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
ZTest Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
#include "Utils.hlsl"
|
||||
|
||||
#pragma vertex vert_screen
|
||||
#pragma fragment frag
|
||||
|
||||
#pragma multi_compile_local BOX CROSS
|
||||
#pragma multi_compile_local SOFT HARD
|
||||
#pragma multi_compile_local _ ALPHA_MASK
|
||||
|
||||
#define BLUR_LENGTH 9
|
||||
#define BLUR_LENGTH_HALF ((BLUR_LENGTH - 1) / 2)
|
||||
static const float k_BlurWeights[BLUR_LENGTH] =
|
||||
{
|
||||
0.046995 * 2,
|
||||
0.064759 * 2,
|
||||
0.120985 * 2,
|
||||
0.176033 * 2,
|
||||
0.199471 * 2,
|
||||
0.176033 * 2,
|
||||
0.120985 * 2,
|
||||
0.064759 * 2,
|
||||
0.046995 * 2,
|
||||
};
|
||||
|
||||
sampler2D _MainTex;
|
||||
sampler2D _AlphaTex;
|
||||
float4 _AlphaTO;
|
||||
float2 _Step;
|
||||
float _Solid;
|
||||
|
||||
// =======================================================================
|
||||
float4 _sample_soft(float2 uv, in const float2 step)
|
||||
{
|
||||
float4 result = 0;
|
||||
uv -= BLUR_LENGTH_HALF * step;
|
||||
|
||||
[unroll]
|
||||
for (int n = 0; n < BLUR_LENGTH; n ++)
|
||||
{
|
||||
result += tex2D(_MainTex, uv) * k_BlurWeights[n];
|
||||
uv += step;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 _sample_hard(float2 uv, in const float2 step)
|
||||
{
|
||||
float4 result = 0;
|
||||
|
||||
uv -= BLUR_LENGTH_HALF * step;
|
||||
|
||||
[unroll]
|
||||
for (int n = 0; n < BLUR_LENGTH; n ++)
|
||||
{
|
||||
float4 sample = tex2D(_MainTex, uv);
|
||||
result = max(sample, result);
|
||||
uv += step;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 _sample(const float2 uv, in const float2 step)
|
||||
{
|
||||
#ifdef SOFT
|
||||
return _sample_soft(uv, step);
|
||||
#endif
|
||||
#ifdef HARD
|
||||
return _sample_hard(uv, step);
|
||||
#endif
|
||||
}
|
||||
|
||||
float4 frag(fragIn i) : SV_Target
|
||||
{
|
||||
float4 color = tex2D(_MainTex, i.uv);
|
||||
if (color.a > .0)
|
||||
{
|
||||
#ifdef ALPHA_MASK
|
||||
return float4(color.xyz, color.a * _Solid * tex2D(_AlphaTex, mad(i.uv, _AlphaTO.xy, _AlphaTO.zw)).a);
|
||||
#endif
|
||||
return float4(color.xyz, color.a * _Solid);
|
||||
}
|
||||
|
||||
float4 result = 0;
|
||||
|
||||
#ifdef BOX
|
||||
const float2 stepX = float2(_Step.x, 0);
|
||||
const float2 stepY = float2(0, _Step.y);
|
||||
float2 uv = i.uv - BLUR_LENGTH_HALF * stepX;
|
||||
|
||||
[unroll]
|
||||
for (int n = 0; n < BLUR_LENGTH; n ++)
|
||||
{
|
||||
#ifdef SOFT
|
||||
result += _sample(uv, stepY) * k_BlurWeights[n];
|
||||
#endif
|
||||
#ifdef HARD
|
||||
result = max(result, _sample(uv, stepY));
|
||||
#endif
|
||||
|
||||
uv += stepX;
|
||||
}
|
||||
#endif
|
||||
#ifdef CROSS
|
||||
result = (_sample(i.uv, _Step) + _sample(i.uv, float2(_Step.x, -_Step.y))) * .5f;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass // 2
|
||||
{
|
||||
name "Overlay"
|
||||
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
ZTest Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
#include "Utils.hlsl"
|
||||
|
||||
#pragma vertex vert_screen
|
||||
#pragma fragment frag
|
||||
|
||||
sampler2D _MainTex;
|
||||
|
||||
// =======================================================================
|
||||
float4 frag(fragIn i) : SV_Target
|
||||
{
|
||||
return tex2D(_MainTex, i.uv);
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a902e6d68fe8344890c5926c684e820
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/Shaders/Main.shader
|
||||
uploadId: 678360
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef OUTLINE_UTILS_INCLUDED
|
||||
#define OUTLINE_UTILS_INCLUDED
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct vertIn
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct fragIn
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
fragIn vert_mesh(vertIn v)
|
||||
{
|
||||
fragIn o;
|
||||
o.vertex = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.uv;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
fragIn vert_screen(vertIn v)
|
||||
{
|
||||
fragIn o;
|
||||
o.vertex = v.vertex;
|
||||
o.uv = v.uv;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float random(in const float2 uv)
|
||||
{
|
||||
return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cda35a27fcc461bb5a4ed317f358de3
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 290431
|
||||
packageName: Outline 2D/3D
|
||||
packageVersion: 1.0
|
||||
assetPath: Assets/Outline/Runtime/Shaders/Utils.hlsl
|
||||
uploadId: 678360
|
||||
Reference in New Issue
Block a user