initial commit

This commit is contained in:
cblech
2025-01-04 13:29:07 +01:00
commit 22f67f4347
124 changed files with 12157 additions and 0 deletions
+60
View File
@@ -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;
}
}
}
+18
View File
@@ -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
+32
View File
@@ -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);
}
}
}
+10
View File
@@ -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
+20
View File
@@ -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
+138
View File
@@ -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
+23
View File
@@ -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;
}
}
}
+18
View File
@@ -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
+301
View File
@@ -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
+8
View File
@@ -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
+184
View File
@@ -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
+41
View File
@@ -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