Flatkit 추가 및 설정

This commit is contained in:
2026-01-25 11:27:33 +09:00
parent 05233497e7
commit cf16910a32
1938 changed files with 408633 additions and 244 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 78d0c5250a38946caaafa2b13edcbb4f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,128 @@
#if !UNITY_2022_3_OR_NEWER
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace FlatKit {
internal class BlitTexturePass : ScriptableRenderPass {
public static readonly string CopyEffectShaderName = "Hidden/FlatKit/CopyTexture";
private readonly ProfilingSampler _profilingSampler;
private readonly Material _effectMaterial;
private readonly ScriptableRenderPassInput _passInput;
private readonly Material _copyMaterial;
#if UNITY_2022_1_OR_NEWER
private RTHandle _temporaryColorTexture;
#else
private RenderTargetHandle _temporaryColorTexture;
#endif
public BlitTexturePass(Material effectMaterial, bool useDepth, bool useNormals, bool useColor) {
_effectMaterial = effectMaterial;
var name = effectMaterial.name.Substring(effectMaterial.name.LastIndexOf('/') + 1);
_profilingSampler = new ProfilingSampler($"Blit {name}");
_passInput = (useColor ? ScriptableRenderPassInput.Color : ScriptableRenderPassInput.None) |
(useDepth ? ScriptableRenderPassInput.Depth : ScriptableRenderPassInput.None) |
(useNormals ? ScriptableRenderPassInput.Normal : ScriptableRenderPassInput.None);
#if !UNITY_2022_1_OR_NEWER
_copyMaterial = CoreUtils.CreateEngineMaterial(CopyEffectShaderName);
#endif
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) {
ConfigureInput(_passInput);
base.Configure(cmd, cameraTextureDescriptor);
}
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) {
#if !UNITY_2022_1_OR_NEWER
ConfigureTarget(new RenderTargetIdentifier(renderingData.cameraData.renderer.cameraColorTarget, 0,
CubemapFace.Unknown, -1));
_temporaryColorTexture.Init("_EffectTexture");
#endif
}
public void Setup(RenderingData renderingData) {
#if UNITY_2022_1_OR_NEWER
var descriptor = renderingData.cameraData.cameraTargetDescriptor;
descriptor.depthBufferBits = 0;
RenderingUtils.ReAllocateIfNeeded(ref _temporaryColorTexture, descriptor, wrapMode: TextureWrapMode.Clamp,
name: "_EffectTexture");
#endif
}
public void Dispose() {
#if UNITY_2022_1_OR_NEWER
_temporaryColorTexture?.Release();
#endif
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
if (_effectMaterial == null) return;
CommandBuffer cmd = CommandBufferPool.Get();
using (new ProfilingScope(cmd, _profilingSampler)) {
var descriptor = renderingData.cameraData.cameraTargetDescriptor;
descriptor.depthBufferBits = 0;
SetSourceSize(cmd, descriptor);
#if UNITY_2022_1_OR_NEWER
var cameraTargetHandle = renderingData.cameraData.renderer.cameraColorTargetHandle;
// cmd.GetTemporaryRT(Shader.PropertyToID(_temporaryColorTexture.name), descriptor);
#else
var cameraTargetHandle = renderingData.cameraData.renderer.cameraColorTarget;
cmd.GetTemporaryRT(_temporaryColorTexture.id, descriptor);
#endif
// Also seen as `renderingData.cameraData.xr.enabled` and `#if ENABLE_VR && ENABLE_XR_MODULE`.
if (renderingData.cameraData.xrRendering) {
_effectMaterial.EnableKeyword("_USE_DRAW_PROCEDURAL"); // `UniversalRenderPipelineCore.cs`.
#if UNITY_2022_1_OR_NEWER
#pragma warning disable CS0618
cmd.SetRenderTarget(_temporaryColorTexture);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _effectMaterial, 0, 0);
cmd.SetGlobalTexture("_EffectTexture", _temporaryColorTexture);
cmd.SetRenderTarget(new RenderTargetIdentifier(cameraTargetHandle, 0, CubemapFace.Unknown, -1));
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _copyMaterial, 0, 0);
#else
cmd.SetRenderTarget(_temporaryColorTexture.Identifier());
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _effectMaterial, 0, 0);
cmd.SetGlobalTexture("_EffectTexture", _temporaryColorTexture.Identifier());
cmd.SetRenderTarget(new RenderTargetIdentifier(cameraTargetHandle, 0, CubemapFace.Unknown, -1));
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, _copyMaterial, 0, 0);
#endif
} else {
_effectMaterial.DisableKeyword("_USE_DRAW_PROCEDURAL");
// Note: `FinalBlitPass` has `cmd.SetRenderTarget` at this point, but it's unclear what that does.
#if UNITY_2022_1_OR_NEWER
cmd.Blit(cameraTargetHandle, _temporaryColorTexture, _effectMaterial, 0);
cmd.Blit(_temporaryColorTexture, cameraTargetHandle);
#else
cmd.Blit(cameraTargetHandle, _temporaryColorTexture.Identifier(), _effectMaterial, 0);
cmd.Blit(_temporaryColorTexture.Identifier(), cameraTargetHandle);
#endif
}
}
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
CommandBufferPool.Release(cmd);
}
// Copied from `PostProcessUtils.cs`.
private static void SetSourceSize(CommandBuffer cmd, RenderTextureDescriptor desc) {
float width = desc.width;
float height = desc.height;
if (desc.useDynamicScale) {
width *= ScalableBufferManager.widthScaleFactor;
height *= ScalableBufferManager.heightScaleFactor;
}
cmd.SetGlobalVector("_SourceSize", new Vector4(width, height, 1.0f / width, 1.0f / height));
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5985b630931f0e846b661c4bbc4d0a25
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using UnityEngine;
using UnityEngine.Rendering;
namespace FlatKit {
public static class RendererFeatureUtils {
public static void SetKeyword(Material material, string keyword, bool enabled) {
if (material == null) {
return;
}
#if UNITY_2021_2_OR_NEWER
if (material.shader != null) {
// Unity 2021.2+ lets us query the shader's keyword space; only call SetKeyword when the symbol is actually declared
// to avoid "keyword doesn't exist" errors on Unity 6.3.
var keywordSpace = material.shader.keywordSpace;
LocalKeyword localKeyword = keywordSpace.FindKeyword(keyword);
if (localKeyword.isValid) {
material.SetKeyword(localKeyword, enabled);
return;
}
}
#endif
if (enabled) {
material.EnableKeyword(keyword);
} else {
material.DisableKeyword(keyword);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3a43bf53130f412f88de25122442bade
timeCreated: 1720407925

View File

@@ -0,0 +1,251 @@
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
#if UNITY_6000_0_OR_NEWER
using System;
using UnityEngine.Rendering.RenderGraphModule;
#endif
public class ScreenRenderPass : ScriptableRenderPass {
private Material _passMaterial;
private bool _requiresColor;
private bool _isBeforeTransparents;
private PassData _passData;
private ProfilingSampler _profilingSampler;
private RTHandle _copiedColor;
private static readonly Vector4 BlitScaleBias = new(1f, 1f, 0f, 0f);
private static readonly MaterialPropertyBlock SharedPropertyBlock = new();
private const string TexName = "_BlitTexture";
private static readonly int BlitTextureShaderID = Shader.PropertyToID(TexName);
private static readonly int BlitScaleBiasID = Shader.PropertyToID("_BlitScaleBias");
public void Setup(Material mat, bool requiresColor, bool isBeforeTransparents, string featureName,
in RenderingData renderingData) {
_passMaterial = mat;
_requiresColor = requiresColor;
_isBeforeTransparents = isBeforeTransparents;
_profilingSampler ??= new ProfilingSampler(featureName);
var colorCopyDescriptor = renderingData.cameraData.cameraTargetDescriptor;
colorCopyDescriptor.depthBufferBits = (int)DepthBits.None;
#if UNITY_6000_0_OR_NEWER
requiresIntermediateTexture = _requiresColor && !_isBeforeTransparents;
RenderingUtils.ReAllocateHandleIfNeeded(ref _copiedColor, colorCopyDescriptor, FilterMode.Point,
TextureWrapMode.Clamp, name: "_FullscreenPassColorCopy");
#elif UNITY_2022_3_OR_NEWER
RenderingUtils.ReAllocateIfNeeded(ref _copiedColor, colorCopyDescriptor, name: "_FullscreenPassColorCopy");
#endif
_passData ??= new PassData();
}
public void Dispose() {
_copiedColor?.Release();
}
#if UNITY_6000_0_OR_NEWER
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) {
var resourceData = frameData.Get<UniversalResourceData>();
var cameraData = frameData.Get<UniversalCameraData>();
if (_passMaterial == null) {
return;
}
if (!resourceData.activeColorTexture.IsValid()) {
return;
}
if (_requiresColor && resourceData.isActiveTargetBackBuffer) {
Debug.LogWarning("[Flat Kit] ScreenRenderPass requires sampling the active color buffer, but the renderer " +
"is currently writing directly to the backbuffer. Enable an intermediate color target " +
"(Renderer > Rendering > Intermediate Texture Mode = Always) or move the feature to an " +
"earlier render event.");
return;
}
TextureHandle copySource = TextureHandle.nullHandle;
if (_requiresColor) {
TextureDesc descriptor;
if (resourceData.cameraColor.IsValid()) {
descriptor = renderGraph.GetTextureDesc(resourceData.cameraColor);
} else {
descriptor = renderGraph.GetTextureDesc(resourceData.activeColorTexture);
}
descriptor.name = "_FlatKit_FullScreenCopy";
descriptor.clearBuffer = false;
TextureHandle copiedColor = renderGraph.CreateTexture(descriptor);
using (var builder = renderGraph.AddRasterRenderPass<CopyPassData>("FlatKit Copy Color", out var passData,
_profilingSampler)) {
passData.source = resourceData.activeColorTexture;
builder.UseTexture(passData.source, AccessFlags.Read);
builder.SetRenderAttachment(copiedColor, 0, AccessFlags.Write);
builder.SetRenderFunc((CopyPassData data, RasterGraphContext ctx) => {
Blitter.BlitTexture(ctx.cmd, data.source, BlitScaleBias, 0, false);
});
}
copySource = copiedColor;
}
using (var builder = renderGraph.AddRasterRenderPass<MainPassData>(_profilingSampler.name, out var passData,
_profilingSampler)) {
passData.material = _passMaterial;
passData.source = copySource;
if (passData.source.IsValid()) {
builder.UseTexture(passData.source, AccessFlags.Read);
}
var passInput = input;
bool needsColor = (passInput & ScriptableRenderPassInput.Color) != ScriptableRenderPassInput.None;
bool needsDepth = (passInput & ScriptableRenderPassInput.Depth) != ScriptableRenderPassInput.None;
bool needsNormals = (passInput & ScriptableRenderPassInput.Normal) != ScriptableRenderPassInput.None;
bool needsMotion = (passInput & ScriptableRenderPassInput.Motion) != ScriptableRenderPassInput.None;
if (needsColor && resourceData.cameraOpaqueTexture.IsValid()) {
builder.UseTexture(resourceData.cameraOpaqueTexture);
}
if (needsDepth && resourceData.cameraDepthTexture.IsValid()) {
builder.UseTexture(resourceData.cameraDepthTexture);
}
if (needsNormals && resourceData.cameraNormalsTexture.IsValid()) {
builder.UseTexture(resourceData.cameraNormalsTexture);
}
if (needsMotion && cameraData.renderer.SupportsMotionVectors()) {
if (resourceData.motionVectorColor.IsValid()) {
builder.UseTexture(resourceData.motionVectorColor);
}
if (resourceData.motionVectorDepth.IsValid()) {
builder.UseTexture(resourceData.motionVectorDepth);
}
}
builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write);
builder.SetRenderFunc((MainPassData data, RasterGraphContext ctx) => {
SharedPropertyBlock.Clear();
if (data.source.IsValid()) {
SharedPropertyBlock.SetTexture(BlitTextureShaderID, data.source);
}
SharedPropertyBlock.SetVector(BlitScaleBiasID, BlitScaleBias);
ctx.cmd.DrawProcedural(Matrix4x4.identity, data.material, 0, MeshTopology.Triangles, 3, 1,
SharedPropertyBlock);
});
}
}
[Obsolete("This rendering path is for compatibility mode only (when Render Graph is disabled).", false)]
#endif
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
_passData.effectMaterial = _passMaterial;
_passData.requiresColor = _requiresColor;
_passData.isBeforeTransparents = _isBeforeTransparents;
_passData.profilingSampler = _profilingSampler;
_passData.copiedColor = _copiedColor;
ExecutePass(_passData, ref renderingData, ref context);
}
#if UNITY_6000_0_OR_NEWER
[Obsolete("This rendering path is for compatibility mode only (when Render Graph is disabled).", false)]
#endif
private static void ExecutePass(PassData passData, ref RenderingData renderingData,
ref ScriptableRenderContext context) {
var passMaterial = passData.effectMaterial;
var requiresColor = passData.requiresColor;
var copiedColor = passData.copiedColor;
var profilingSampler = passData.profilingSampler;
if (passMaterial == null) {
return;
}
if (renderingData.cameraData.isPreviewCamera) {
return;
}
CommandBuffer cmd;
bool releaseCommandBuffer;
// Unity 6.3+ no longer exposes RenderingData.commandBuffer outside URP, so rely on pooled buffers there (and on pre-2022.3).
#if UNITY_6000_3_OR_NEWER
cmd = CommandBufferPool.Get();
releaseCommandBuffer = true;
#elif UNITY_2022_3_OR_NEWER && !UNITY_6000_3_OR_NEWER
cmd = renderingData.commandBuffer;
releaseCommandBuffer = false;
#else
cmd = CommandBufferPool.Get();
releaseCommandBuffer = true;
#endif
var cameraData = renderingData.cameraData;
using (new ProfilingScope(cmd, profilingSampler)) {
if (requiresColor) {
#if UNITY_6000_3_OR_NEWER
RTHandle source = cameraData.renderer.cameraColorTargetHandle;
Blitter.BlitCameraTexture(cmd, source, copiedColor);
#elif UNITY_2022_3_OR_NEWER && !UNITY_6000_3_OR_NEWER
RTHandle source = passData.isBeforeTransparents
? cameraData.renderer.GetCameraColorBackBuffer(cmd)
: cameraData.renderer.cameraColorTargetHandle;
Blitter.BlitCameraTexture(cmd, source, copiedColor);
#else
RenderTargetIdentifier source = cameraData.renderer.cameraColorTarget;
cmd.Blit(source, copiedColor);
#endif
passMaterial.SetTexture(BlitTextureShaderID, copiedColor);
}
#if UNITY_6000_3_OR_NEWER
CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle);
#elif UNITY_2022_3_OR_NEWER && !UNITY_6000_3_OR_NEWER
CoreUtils.SetRenderTarget(cmd, cameraData.renderer.GetCameraColorBackBuffer(cmd));
#else
CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTarget);
#endif
CoreUtils.DrawFullScreen(cmd, passMaterial);
context.ExecuteCommandBuffer(cmd);
if (releaseCommandBuffer) {
CommandBufferPool.Release(cmd);
} else {
cmd.Clear();
}
}
}
private class PassData {
internal Material effectMaterial;
internal bool requiresColor;
internal bool isBeforeTransparents;
public ProfilingSampler profilingSampler;
public RTHandle copiedColor;
}
#if UNITY_6000_0_OR_NEWER
private class CopyPassData {
internal TextureHandle source;
}
private class MainPassData {
internal TextureHandle source;
internal Material material;
}
#endif
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4352bba7c98b4f53bdc3856f0edf40f4
timeCreated: 1691382047

View File

@@ -0,0 +1,71 @@
#if UNITY_EDITOR
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace FlatKit {
public static class SubAssetMaterial {
public static Material GetOrCreate(Object settings, string shaderName) {
// Return if called from OnValidate.
{
var stackTrace = new System.Diagnostics.StackTrace();
var frames = stackTrace.GetFrames();
if (frames != null) {
if (frames.Select(frame => frame.GetMethod())
.Any(method => method != null && method.Name == "OnValidate")) {
return null;
}
}
}
var settingsPath = AssetDatabase.GetAssetPath(settings);
var subAssets = AssetDatabase.LoadAllAssetsAtPath(settingsPath);
const string subAssetName = "Effect Material";
var existingMaterial = subAssets.FirstOrDefault(o => o.name == subAssetName) as Material;
if (existingMaterial != null) return existingMaterial;
var shader = Shader.Find(shaderName);
if (shader == null) return null;
var newMaterial = new Material(shader) { name = subAssetName };
try {
AssetDatabase.AddObjectToAsset(newMaterial, settings);
AssetDatabase.ImportAsset(settingsPath);
}
catch {
// ignored
}
return newMaterial;
}
public static void AlwaysInclude(string shaderName) {
var shader = Shader.Find(shaderName);
if (shader == null) return;
var graphicsSettingsObj =
AssetDatabase.LoadAssetAtPath<GraphicsSettings>("ProjectSettings/GraphicsSettings.asset");
if (graphicsSettingsObj == null) return;
var serializedObject = new SerializedObject(graphicsSettingsObj);
var arrayProp = serializedObject.FindProperty("m_AlwaysIncludedShaders");
bool hasShader = false;
for (int i = 0; i < arrayProp.arraySize; ++i) {
var arrayElem = arrayProp.GetArrayElementAtIndex(i);
if (shader == arrayElem.objectReferenceValue) {
hasShader = true;
break;
}
}
if (!hasShader) {
int arrayIndex = arrayProp.arraySize;
arrayProp.InsertArrayElementAtIndex(arrayIndex);
var arrayElem = arrayProp.GetArrayElementAtIndex(arrayIndex);
arrayElem.objectReferenceValue = shader;
serializedObject.ApplyModifiedProperties();
AssetDatabase.SaveAssets();
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 57832b6c4cbc426896f2230d92a1f228
timeCreated: 1669323534

View File

@@ -0,0 +1,3 @@
{
"reference": "GUID:15fc0a57446b3144c949da3e2b9737a9"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5933a64b832764e4a81747888e4134ed
AssemblyDefinitionReferenceImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1f5760a2382d40169a691c961d4f9104
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,362 @@
using UnityEngine;
using UnityEngine.Rendering.Universal;
#if UNITY_2022_3_OR_NEWER
using ExternPropertyAttributes;
namespace FlatKit {
public class FlatKitFog : ScriptableRendererFeature {
[Tooltip("To create new settings use 'Create > FlatKit > Fog Settings'.")]
[Expandable]
public FogSettings settings;
private Material _effectMaterial;
private ScreenRenderPass _fullScreenPass;
private bool _requiresColor;
private bool _injectedBeforeTransparents;
private ScriptableRenderPassInput _requirements = ScriptableRenderPassInput.Color;
private Texture2D _lutDepth;
private Texture2D _lutHeight;
private const string ShaderName = "Hidden/FlatKit/FogWrap";
private const string CameraRelativePosition = "FOG_CAMERA_RELATIVE";
private const string UseDistanceFog = "USE_DISTANCE_FOG";
private const string UseHeightFog = "USE_HEIGHT_FOG";
private static int distanceLut => Shader.PropertyToID("_DistanceLUT");
private static int near => Shader.PropertyToID("_Near");
private static int far => Shader.PropertyToID("_Far");
private static int distanceFogIntensity => Shader.PropertyToID("_DistanceFogIntensity");
private static int heightLut => Shader.PropertyToID("_HeightLUT");
private static int lowWorldY => Shader.PropertyToID("_LowWorldY");
private static int highWorldY => Shader.PropertyToID("_HighWorldY");
private static int heightFogIntensity => Shader.PropertyToID("_HeightFogIntensity");
private static int distanceHeightBlend => Shader.PropertyToID("_DistanceHeightBlend");
/// <summary>
/// Access the runtime effect material to override fog parameters at runtime.
/// This enables minimal, code-driven tweaks without changing the Settings asset.
///
/// Shader (2022.3+ path): "Hidden/FlatKit/FogWrap"
///
/// Common shader properties you can set:
/// - Textures: _DistanceLUT (Texture2D), _HeightLUT (Texture2D)
/// - Floats: _Near, _Far, _LowWorldY, _HighWorldY,
/// _DistanceFogIntensity, _HeightFogIntensity, _DistanceHeightBlend
/// - Keywords: USE_DISTANCE_FOG, USE_HEIGHT_FOG, FOG_CAMERA_RELATIVE
///
/// Notes:
/// - If you supply your own LUTs, set _DistanceLUT/_HeightLUT directly.
/// - Settings asset changes (via its inspector) can overwrite your values when applied.
/// </summary>
public Material EffectMaterial => _effectMaterial;
public override void Create() {
// Settings.
{
if (settings == null) return;
settings.onSettingsChanged = null;
settings.onReset = null;
settings.onSettingsChanged += SetMaterialProperties;
settings.onReset += SetMaterialProperties;
}
// Material.
{
#if UNITY_EDITOR
settings.effectMaterial = SubAssetMaterial.GetOrCreate(settings, ShaderName);
if (settings.effectMaterial == null) return;
#endif
_effectMaterial = settings.effectMaterial;
SetMaterialProperties();
}
{
_fullScreenPass = new ScreenRenderPass {
renderPassEvent = settings.renderEvent,
};
_requirements = ScriptableRenderPassInput.Depth | ScriptableRenderPassInput.Color;
ScriptableRenderPassInput modifiedRequirements = _requirements;
_requiresColor = (_requirements & ScriptableRenderPassInput.Color) != 0;
_injectedBeforeTransparents = settings.renderEvent <= RenderPassEvent.BeforeRenderingTransparents;
if (_requiresColor && !_injectedBeforeTransparents) {
modifiedRequirements ^= ScriptableRenderPassInput.Color;
}
_fullScreenPass.ConfigureInput(modifiedRequirements);
}
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
if (settings == null || !settings.applyInSceneView && renderingData.cameraData.isSceneViewCamera) return;
if (renderingData.cameraData.isPreviewCamera) return;
if (_effectMaterial == null) return;
_fullScreenPass.Setup(_effectMaterial, _requiresColor, _injectedBeforeTransparents, "Flat Kit Fog",
renderingData);
renderer.EnqueuePass(_fullScreenPass);
}
// Re-generate LUT textures when unity disposes them on scene save.
#if UNITY_EDITOR
public override void OnCameraPreCull(ScriptableRenderer renderer, in CameraData cameraData) {
base.OnCameraPreCull(renderer, in cameraData);
if (settings == null || _effectMaterial == null) return;
if (settings.useDistance && !_effectMaterial.GetTexture(distanceLut)) UpdateDistanceLut();
if (settings.useHeight && !_effectMaterial.GetTexture(heightLut)) UpdateHeightLut();
}
#endif
protected override void Dispose(bool disposing) {
_fullScreenPass?.Dispose();
}
private void SetMaterialProperties() {
if (_effectMaterial == null) return;
RendererFeatureUtils.SetKeyword(_effectMaterial, UseDistanceFog, settings.useDistance);
if (settings.useDistance) {
UpdateDistanceLut();
_effectMaterial.SetFloat(near, settings.near);
_effectMaterial.SetFloat(far, settings.far);
_effectMaterial.SetFloat(distanceFogIntensity, settings.distanceFogIntensity);
}
RendererFeatureUtils.SetKeyword(_effectMaterial, UseHeightFog, settings.useHeight);
if (settings.useHeight) {
UpdateHeightLut();
_effectMaterial.SetFloat(lowWorldY, settings.low);
_effectMaterial.SetFloat(highWorldY, settings.high);
_effectMaterial.SetFloat(heightFogIntensity, settings.heightFogIntensity);
_effectMaterial.SetFloat(distanceHeightBlend, settings.distanceHeightBlend);
}
RendererFeatureUtils.SetKeyword(_effectMaterial, CameraRelativePosition, settings.cameraRelativePosition);
}
private void UpdateDistanceLut() {
if (settings.distanceGradient == null) return;
const int width = 256;
const int height = 1;
if (_lutDepth == null) {
_lutDepth = new Texture2D(width, height, TextureFormat.RGBA32, /*mipChain=*/false) {
wrapMode = TextureWrapMode.Clamp,
hideFlags = HideFlags.HideAndDontSave,
filterMode = FilterMode.Bilinear
};
}
for (float x = 0; x < width; x++) {
Color color = settings.distanceGradient.Evaluate(x / (width - 1));
for (float y = 0; y < height; y++) {
_lutDepth.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
}
}
_lutDepth.Apply();
_effectMaterial.SetTexture(distanceLut, _lutDepth);
}
private void UpdateHeightLut() {
if (settings.heightGradient == null) return;
const int width = 256;
const int height = 1;
if (_lutHeight == null) {
_lutHeight = new Texture2D(width, height, TextureFormat.RGBA32, /*mipChain=*/false) {
wrapMode = TextureWrapMode.Clamp,
hideFlags = HideFlags.HideAndDontSave,
filterMode = FilterMode.Bilinear
};
}
for (float x = 0; x < width; x++) {
Color color = settings.heightGradient.Evaluate(x / (width - 1));
for (float y = 0; y < height; y++) {
_lutHeight.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
}
}
_lutHeight.Apply();
_effectMaterial.SetTexture(heightLut, _lutHeight);
}
}
}
#else
namespace FlatKit {
public class FlatKitFog : ScriptableRendererFeature {
[Tooltip("To create new settings use 'Create > FlatKit > Fog Settings'.")]
public FogSettings settings;
[SerializeField, HideInInspector]
private Material _effectMaterial;
private BlitTexturePass _blitTexturePass;
private Texture2D _lutDepth;
private Texture2D _lutHeight;
private static readonly string FogShaderName = "Hidden/FlatKit/FogFilter";
private static readonly int DistanceLut = Shader.PropertyToID("_DistanceLUT");
private static readonly int Near = Shader.PropertyToID("_Near");
private static readonly int Far = Shader.PropertyToID("_Far");
private static readonly int UseDistanceFog = Shader.PropertyToID("_UseDistanceFog");
private static readonly int UseDistanceFogOnSky = Shader.PropertyToID("_UseDistanceFogOnSky");
private static readonly int DistanceFogIntensity = Shader.PropertyToID("_DistanceFogIntensity");
private static readonly int HeightLut = Shader.PropertyToID("_HeightLUT");
private static readonly int LowWorldY = Shader.PropertyToID("_LowWorldY");
private static readonly int HighWorldY = Shader.PropertyToID("_HighWorldY");
private static readonly int UseHeightFog = Shader.PropertyToID("_UseHeightFog");
private static readonly int UseHeightFogOnSky = Shader.PropertyToID("_UseHeightFogOnSky");
private static readonly int HeightFogIntensity = Shader.PropertyToID("_HeightFogIntensity");
private static readonly int DistanceHeightBlend = Shader.PropertyToID("_DistanceHeightBlend");
/// <summary>
/// Access the runtime effect material to override fog parameters at runtime.
/// This enables minimal, code-driven tweaks without changing the Settings asset.
///
/// Shader (legacy path): "Hidden/FlatKit/FogFilter"
///
/// Common shader properties you can set:
/// - Textures: _DistanceLUT (Texture2D), _HeightLUT (Texture2D)
/// - Floats: _Near, _Far, _LowWorldY, _HighWorldY,
/// _UseDistanceFog (0/1), _UseDistanceFogOnSky (0/1), _DistanceFogIntensity,
/// _UseHeightFog (0/1), _UseHeightFogOnSky (0/1), _HeightFogIntensity, _DistanceHeightBlend
///
/// Notes:
/// - If you supply your own LUTs, set _DistanceLUT/_HeightLUT directly.
/// - Settings asset changes (via its inspector) can overwrite your values when applied.
/// </summary>
public Material EffectMaterial => _effectMaterial;
public override void Create() {
#if UNITY_EDITOR
if (_effectMaterial == null) {
SubAssetMaterial.AlwaysInclude(BlitTexturePass.CopyEffectShaderName);
SubAssetMaterial.AlwaysInclude(FogShaderName);
}
#endif
if (settings == null) {
return;
}
if (!CreateMaterials()) {
return;
}
SetMaterialProperties();
_blitTexturePass = new BlitTexturePass(_effectMaterial, useDepth: true, useNormals: false, useColor: false);
}
protected override void Dispose(bool disposing) {
_blitTexturePass.Dispose();
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
#if UNITY_EDITOR
if (renderingData.cameraData.isPreviewCamera) return;
if (!settings.applyInSceneView && renderingData.cameraData.cameraType == CameraType.SceneView) return;
#endif
SetMaterialProperties();
_blitTexturePass.Setup(renderingData);
_blitTexturePass.renderPassEvent = settings.renderEvent;
renderer.EnqueuePass(_blitTexturePass);
}
private bool CreateMaterials() {
if (_effectMaterial == null) {
var effectShader = Shader.Find(FogShaderName);
var blitShader = Shader.Find(BlitTexturePass.CopyEffectShaderName);
if (effectShader == null || blitShader == null) return false;
_effectMaterial = UnityEngine.Rendering.CoreUtils.CreateEngineMaterial(effectShader);
}
return _effectMaterial != null;
}
private void SetMaterialProperties() {
if (_effectMaterial == null) {
return;
}
UpdateDistanceLut();
_effectMaterial.SetTexture(DistanceLut, _lutDepth);
_effectMaterial.SetFloat(Near, settings.near);
_effectMaterial.SetFloat(Far, settings.far);
_effectMaterial.SetFloat(UseDistanceFog, settings.useDistance ? 1f : 0f);
_effectMaterial.SetFloat(UseDistanceFogOnSky, settings.useDistanceFogOnSky ? 1f : 0f);
_effectMaterial.SetFloat(DistanceFogIntensity, settings.distanceFogIntensity);
UpdateHeightLut();
_effectMaterial.SetTexture(HeightLut, _lutHeight);
_effectMaterial.SetFloat(LowWorldY, settings.low);
_effectMaterial.SetFloat(HighWorldY, settings.high);
_effectMaterial.SetFloat(UseHeightFog, settings.useHeight ? 1f : 0f);
_effectMaterial.SetFloat(UseHeightFogOnSky, settings.useHeightFogOnSky ? 1f : 0f);
_effectMaterial.SetFloat(HeightFogIntensity, settings.heightFogIntensity);
_effectMaterial.SetFloat(DistanceHeightBlend, settings.distanceHeightBlend);
}
private void UpdateDistanceLut() {
if (settings.distanceGradient == null) return;
if (_lutDepth != null) {
DestroyImmediate(_lutDepth);
}
const int width = 256;
const int height = 1;
_lutDepth = new Texture2D(width, height, TextureFormat.RGBA32, /*mipChain=*/false) {
wrapMode = TextureWrapMode.Clamp,
hideFlags = HideFlags.HideAndDontSave,
filterMode = FilterMode.Bilinear
};
//22b5f7ed-989d-49d1-90d9-c62d76c3081a
for (float x = 0; x < width; x++) {
Color color = settings.distanceGradient.Evaluate(x / (width - 1));
for (float y = 0; y < height; y++) {
_lutDepth.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
}
}
_lutDepth.Apply();
}
private void UpdateHeightLut() {
if (settings.heightGradient == null) return;
if (_lutHeight != null) {
DestroyImmediate(_lutHeight);
}
const int width = 256;
const int height = 1;
_lutHeight = new Texture2D(width, height, TextureFormat.RGBA32, /*mipChain=*/false) {
wrapMode = TextureWrapMode.Clamp,
hideFlags = HideFlags.HideAndDontSave,
filterMode = FilterMode.Bilinear
};
for (float x = 0; x < width; x++) {
Color color = settings.heightGradient.Evaluate(x / (width - 1));
for (float y = 0; y < height; y++) {
_lutHeight.SetPixel(Mathf.CeilToInt(x), Mathf.CeilToInt(y), color);
}
}
_lutHeight.Apply();
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 770acbaed70db4ad696458511aa3f084
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
#ifndef FLAT_KIT_FOG_INCLUDED
#define FLAT_KIT_FOG_INCLUDED
TEXTURE2D_X (_BlitTexture);
SAMPLER (sampler_BlitTexture);
float Linear01Depth(float z)
{
const float isOrtho = unity_OrthoParams.w;
const float isPers = 1.0 - unity_OrthoParams.w;
z *= _ZBufferParams.x;
return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
}
float LinearEyeDepth(float z)
{
return rcp(_ZBufferParams.z * z + _ZBufferParams.w);
}
float4 SampleCameraColor(float2 uv)
{
return SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_BlitTexture, UnityStereoTransformScreenSpaceTex(uv));
}
void Fog_float(float2 UV, out float4 Out)
{
float4 original = SampleCameraColor(UV);
float fogBlend = _DistanceHeightBlend;
float depthPacked = SampleSceneDepth(UV);
#if defined(USE_DISTANCE_FOG)
const float depthCameraPlanes = Linear01Depth(depthPacked);
const float depthAbsolute = _ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) * depthCameraPlanes;
const float depthFogPlanes = saturate((depthAbsolute - _Near) / (_Far - _Near));
float4 distanceFog = SAMPLE_TEXTURE2D_X(_DistanceLUT, sampler_DistanceLUT, float2(depthFogPlanes, 0.5));
distanceFog.a *= _DistanceFogIntensity;
#else
float4 distanceFog = float4(0, 0, 0, 0);
fogBlend = 1.0;
#endif
#if defined(USE_HEIGHT_FOG)
#if defined(FOG_CAMERA_RELATIVE)
const float3 worldPos = float3(UV, depthPacked) * LinearEyeDepth(depthPacked) + _WorldSpaceCameraPos;
#else
#if !UNITY_REVERSED_Z
// Adjust z to match NDC for OpenGL
depthPacked = lerp(UNITY_NEAR_CLIP_VALUE, 1, depthPacked);
#endif
const float3 worldPos = ComputeWorldSpacePosition(UV, depthPacked, UNITY_MATRIX_I_VP);
#endif
const float heightUV = saturate((worldPos.y - _LowWorldY) / (_HighWorldY - _LowWorldY));
float4 heightFog = SAMPLE_TEXTURE2D_X(_HeightLUT, sampler_HeightLUT, float2(heightUV, 0.5));
heightFog.a *= _HeightFogIntensity;
#else
float4 heightFog = float4(0, 0, 0, 0);
fogBlend = 0.0;
#endif
const float4 fog = lerp(distanceFog, heightFog, fogBlend);
float4 final = lerp(original, fog, fog.a);
final.a = original.a;
Out = final;
}
#endif // FLAT_KIT_FOG_INCLUDED

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 44d13df04220413aa6b3f8ee1597a610
timeCreated: 1691556962

View File

@@ -0,0 +1,149 @@
using System;
using ExternPropertyAttributes;
using UnityEngine;
using UnityEngine.Rendering.Universal;
// ReSharper disable RedundantDefaultMemberInitializer
#if UNITY_2022_3_OR_NEWER
namespace FlatKit {
[CreateAssetMenu(fileName = "FogSettings", menuName = "FlatKit/Fog Settings")]
public class FogSettings : ScriptableObject {
[Space] // Expandable.
[Label("<b>Distance Fog</b>")]
[Tooltip("Whether to use distance fog. This is the fog that fades out the scene into the background.")]
public bool useDistance = true;
[Tooltip("The color changes from near (left) to far (right).")]
[Label(" Distance Gradient"), ShowIf(nameof(useDistance))]
public Gradient distanceGradient;
[Tooltip("The distance from the camera in world units at which the fog starts.")]
[Label(" Near"), ShowIf(nameof(useDistance))]
public float near = 0;
[Tooltip("The distance from the camera in world units at which the fog ends.")]
[Label(" Far"), ShowIf(nameof(useDistance))]
public float far = 100;
[Range(0, 1)]
[Tooltip("How much the fog should be applied. 0 means no fog, 1 means full fog.")]
[Label(" Intensity"), ShowIf(nameof(useDistance))]
public float distanceFogIntensity = 1.0f;
[Space(12)]
[HorizontalLine(1, EColor.Translucent)]
[Label("<b>Height Fog</b>")]
[Tooltip("Whether to use height fog. This is the fog that goes up from the ground.")]
public bool useHeight = false;
[Tooltip("The color changes from low (left) to high (right).")]
[Label(" Height Gradient"), ShowIf(nameof(useHeight))]
public Gradient heightGradient;
[Tooltip("The height in world units at which the fog starts.")]
[Label(" Low"), ShowIf(nameof(useHeight))]
public float low = 0;
[Tooltip("The height in world units at which the fog ends.")]
[Label(" High"), ShowIf(nameof(useHeight))]
public float high = 10;
[Range(0, 1)]
[Tooltip("How much the fog should be applied. 0 means no fog, 1 means full fog.")]
[Label(" Intensity"), ShowIf(nameof(useHeight))]
public float heightFogIntensity = 1.0f;
[Tooltip("Reverts fog behavior to pre-3.9.0. This is useful if you want to use the new fog settings, but want to " +
"keep the old look of your scene.")]
[Label(" Camera Relative Position"), ShowIf(nameof(useHeight))]
public bool cameraRelativePosition = false;
[Space(12)]
[HorizontalLine]
[Header("Blending")]
[Range(0, 1)]
[Tooltip("The ratio between distance and height fog. 0 means only distance fog, 1 means only height fog.")]
[Label(" Distance/Height Blend")]
public float distanceHeightBlend = 0.5f;
[Header("Advanced Settings")]
[Tooltip("The render stage at which the effect is applied. To exclude transparent objects, like water or " +
"UI elements, set this to \"Before Transparent\".")]
[Label(" Render Event")]
public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
[Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
"mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
[Label(" Apply In Scene View")]
public bool applyInSceneView = true;
[HideInInspector]
public Material effectMaterial;
internal Action onSettingsChanged;
internal Action onReset;
private void OnValidate() {
low = Mathf.Min(low, high);
high = Mathf.Max(low, high);
onSettingsChanged?.Invoke();
}
private void Reset() {
onReset?.Invoke();
}
private void OnDestroy() {
onSettingsChanged = null;
onReset = null;
}
}
}
#else
namespace FlatKit {
[CreateAssetMenu(fileName = "FogSettings", menuName = "FlatKit/Fog Settings")]
public class FogSettings : ScriptableObject {
[Header("Distance Fog")]
public bool useDistance = true;
public Gradient distanceGradient;
public float near = 0;
public float far = 100;
[Range(0, 1)]
public float distanceFogIntensity = 1.0f;
public bool useDistanceFogOnSky = false;
[Header("Height Fog")]
[Space]
public bool useHeight = false;
public Gradient heightGradient;
public float low = 0;
public float high = 10;
[Range(0, 1)]
public float heightFogIntensity = 1.0f;
public bool useHeightFogOnSky = false;
[Header("Blending")]
[Space]
[Range(0, 1)]
public float distanceHeightBlend = 0.5f;
[Header("Advanced settings")]
[Space, Tooltip("The render stage at which the effect is applied. To exclude transparent objects, like water or " +
"UI elements, set this to \"Before Transparent\".")]
public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
[Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
"mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
public bool applyInSceneView = true;
private void OnValidate() {
low = Mathf.Min(low, high);
high = Mathf.Max(low, high);
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8a6f656ab8114e939b71b289ffd9d7b2
timeCreated: 1585524905

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c77db07224d9f784d90d7eb0e84c57f7
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 684a64ee80b8473d90aefdbfeb94e75c
timeCreated: 1720713507

View File

@@ -0,0 +1,112 @@
using System.Collections.Generic;
using ExternPropertyAttributes;
using JetBrains.Annotations;
using UnityEditor;
using UnityEngine;
#if UNITY_2023_3_OR_NEWER
using UnityEngine.Rendering.Universal;
#else
using UnityEngine.Experimental.Rendering.Universal;
#endif
namespace FlatKit {
#if UNITY_EDITOR
[CustomEditor(typeof(ObjectOutlineRendererFeature))]
public class ObjectOutlineRendererFeatureEditor : Editor {
private bool _advancedSettingsFoldout;
public override void OnInspectorGUI() {
var feature = target as ObjectOutlineRendererFeature;
if (feature == null) return;
#if !UNITY_2022_3_OR_NEWER
EditorGUILayout.Space();
EditorGUILayout.HelpBox("This feature requires Unity 2022.3 or newer.", MessageType.Error);
EditorGUILayout.Space(-10);
#else
// Default properties.
_advancedSettingsFoldout = EditorGUILayout.Foldout(_advancedSettingsFoldout, "Advanced Settings");
if (_advancedSettingsFoldout) {
EditorGUI.indentLevel++;
// Style the background of the foldout.
EditorGUILayout.BeginVertical("HelpBox");
base.OnInspectorGUI();
EditorGUILayout.EndVertical();
EditorGUI.indentLevel--;
}
// Custom properties.
var autoReferenceMaterials =
serializedObject.FindProperty(nameof(ObjectOutlineRendererFeature.autoReferenceMaterials));
EditorGUI.indentLevel--;
autoReferenceMaterials.boolValue = EditorGUILayout.ToggleLeft(
new GUIContent(autoReferenceMaterials.displayName, autoReferenceMaterials.tooltip),
autoReferenceMaterials.boolValue);
EditorGUI.indentLevel++;
if (autoReferenceMaterials.boolValue) {
EditorGUI.indentLevel++;
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.BeginVertical("HelpBox");
var materials = serializedObject.FindProperty(nameof(ObjectOutlineRendererFeature.materials));
EditorGUILayout.PropertyField(materials, true);
EditorGUILayout.EndVertical();
EditorGUI.EndDisabledGroup();
EditorGUI.indentLevel--;
}
#endif
}
}
#endif
public class ObjectOutlineRendererFeature : RenderObjects {
[ReadOnly]
[Tooltip("Materials using this feature. The list is updated automatically based on the `Enable Outline` toggle " +
"on materials using the Stylized Surface shader.")]
[HideInInspector]
[SerializeField]
public List<Material> materials = new();
[Tooltip("Keep track of materials using outlines and automatically delete this feature if no materials use it." +
"If disabled, you must manually remove this feature when no materials use it.")]
[HideInInspector]
[SerializeField]
public bool autoReferenceMaterials = true;
public override void Create() {
#if UNITY_2022_3_OR_NEWER
settings.overrideMode = RenderObjectsSettings.OverrideMaterialMode.Shader;
settings.overrideShader = Shader.Find("FlatKit/Stylized Surface");
settings.overrideShaderPassIndex = 1;
#endif
settings.filterSettings.LayerMask = -1;
settings.filterSettings.PassNames = new[] { "Outline" };
if (autoReferenceMaterials) {
// Remove any invalid materials.
materials.RemoveAll(m => m == null);
} else {
materials.Clear();
}
base.Create();
}
// Returns true if there are any materials using this feature.
[MustUseReturnValue]
public bool RegisterMaterial(Material material, bool active) {
if (!autoReferenceMaterials) return true;
if (active) {
if (!materials.Contains(material)) {
materials.Add(material);
}
} else {
materials.Remove(material);
}
return materials.Count > 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 576f949be0794f548b825c9ce6f556db
timeCreated: 1720322907

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2c9bd0da26084915818a1687ef924322
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,284 @@
using UnityEngine;
using UnityEngine.Rendering.Universal;
#if UNITY_2022_3_OR_NEWER
using ExternPropertyAttributes;
namespace FlatKit {
public class FlatKitOutline : ScriptableRendererFeature {
[Tooltip("To create new settings use 'Create > FlatKit > Outline Settings'.")]
[Expandable]
public OutlineSettings settings;
private Material _effectMaterial;
private ScreenRenderPass _fullScreenPass;
private bool _requiresColor;
private bool _injectedBeforeTransparents;
private ScriptableRenderPassInput _requirements = ScriptableRenderPassInput.Color;
private const string ShaderName = "Hidden/FlatKit/OutlineWrap";
private static int edgeColor => Shader.PropertyToID("_EdgeColor");
private static int thickness => Shader.PropertyToID("_Thickness");
private static int depthThresholdMin => Shader.PropertyToID("_DepthThresholdMin");
private static int depthThresholdMax => Shader.PropertyToID("_DepthThresholdMax");
private static int normalThresholdMin => Shader.PropertyToID("_NormalThresholdMin");
private static int normalThresholdMax => Shader.PropertyToID("_NormalThresholdMax");
private static int colorThresholdMin => Shader.PropertyToID("_ColorThresholdMin");
private static int colorThresholdMax => Shader.PropertyToID("_ColorThresholdMax");
private static int fadeRangeStart => Shader.PropertyToID("_FadeRangeStart");
private static int fadeRangeEnd => Shader.PropertyToID("_FadeRangeEnd");
/// <summary>
/// Access the runtime effect material to override outline parameters at runtime
/// without mutating the Settings asset.
///
/// Shader (2022.3+ path): "Hidden/FlatKit/OutlineWrap"
///
/// Common shader properties/keywords:
/// - Floats: _Thickness, _DepthThresholdMin/_Max, _NormalThresholdMin/_Max, _ColorThresholdMin/_Max,
/// _FadeRangeStart, _FadeRangeEnd
/// - Colors: _EdgeColor
/// - Keywords: OUTLINE_USE_DEPTH, OUTLINE_USE_NORMALS, OUTLINE_USE_COLOR,
/// OUTLINE_ONLY, RESOLUTION_INVARIANT_THICKNESS, OUTLINE_FADE_OUT
///
/// Note: Inspector changes on the Settings asset may overwrite your values if applied later.
/// </summary>
public Material EffectMaterial => _effectMaterial;
public override void Create() {
// Settings.
{
if (settings == null) return;
settings.onSettingsChanged = null;
settings.onReset = null;
settings.onSettingsChanged += SetMaterialProperties;
settings.onReset += SetMaterialProperties;
}
// Material.
{
#if UNITY_EDITOR
settings.effectMaterial = SubAssetMaterial.GetOrCreate(settings, ShaderName);
if (settings.effectMaterial == null) return;
#endif
_effectMaterial = settings.effectMaterial;
SetMaterialProperties();
}
{
_fullScreenPass = new ScreenRenderPass {
renderPassEvent = settings.renderEvent,
};
_requirements = ScriptableRenderPassInput.Color; // Needed for the full-screen blit.
if (settings.useDepth) _requirements |= ScriptableRenderPassInput.Depth;
if (settings.useNormals) _requirements |= ScriptableRenderPassInput.Normal;
if (settings.fadeWithDistance) _requirements |= ScriptableRenderPassInput.Depth;
ScriptableRenderPassInput modifiedRequirements = _requirements;
_requiresColor = (_requirements & ScriptableRenderPassInput.Color) != 0;
_injectedBeforeTransparents = settings.renderEvent <= RenderPassEvent.BeforeRenderingTransparents;
if (_requiresColor && !_injectedBeforeTransparents) {
modifiedRequirements ^= ScriptableRenderPassInput.Color;
}
_fullScreenPass.ConfigureInput(modifiedRequirements);
}
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
if (settings == null || !settings.applyInSceneView && renderingData.cameraData.isSceneViewCamera) return;
if (renderingData.cameraData.isPreviewCamera) return;
if (_effectMaterial == null) return;
_fullScreenPass.Setup(_effectMaterial, _requiresColor, _injectedBeforeTransparents, "Flat Kit Outline",
renderingData);
renderer.EnqueuePass(_fullScreenPass);
}
protected override void Dispose(bool disposing) {
_fullScreenPass?.Dispose();
}
private void SetMaterialProperties() {
if (_effectMaterial == null) return;
const string depthKeyword = "OUTLINE_USE_DEPTH";
RendererFeatureUtils.SetKeyword(_effectMaterial, depthKeyword, settings.useDepth);
const string normalsKeyword = "OUTLINE_USE_NORMALS";
RendererFeatureUtils.SetKeyword(_effectMaterial, normalsKeyword, settings.useNormals);
const string colorKeyword = "OUTLINE_USE_COLOR";
RendererFeatureUtils.SetKeyword(_effectMaterial, colorKeyword, settings.useColor);
const string outlineOnlyKeyword = "OUTLINE_ONLY";
RendererFeatureUtils.SetKeyword(_effectMaterial, outlineOnlyKeyword, settings.outlineOnly);
const string resolutionInvariantKeyword = "RESOLUTION_INVARIANT_THICKNESS";
RendererFeatureUtils.SetKeyword(_effectMaterial, resolutionInvariantKeyword, settings.resolutionInvariant);
const string fadeWithDistanceKeyword = "OUTLINE_FADE_OUT";
RendererFeatureUtils.SetKeyword(_effectMaterial, fadeWithDistanceKeyword, settings.fadeWithDistance);
_effectMaterial.SetColor(edgeColor, settings.edgeColor);
_effectMaterial.SetFloat(thickness, settings.thickness);
_effectMaterial.SetFloat(depthThresholdMin, settings.minDepthThreshold);
_effectMaterial.SetFloat(depthThresholdMax, settings.maxDepthThreshold);
_effectMaterial.SetFloat(normalThresholdMin, settings.minNormalsThreshold);
_effectMaterial.SetFloat(normalThresholdMax, settings.maxNormalsThreshold);
_effectMaterial.SetFloat(colorThresholdMin, settings.minColorThreshold);
_effectMaterial.SetFloat(colorThresholdMax, settings.maxColorThreshold);
_effectMaterial.SetFloat(fadeRangeStart, settings.fadeRangeStart);
_effectMaterial.SetFloat(fadeRangeEnd, settings.fadeRangeEnd);
}
}
}
#else
namespace FlatKit {
public class FlatKitOutline : ScriptableRendererFeature {
[Tooltip("To create new settings use 'Create > FlatKit > Outline Settings'.")]
public OutlineSettings settings;
[SerializeField, HideInInspector]
private Material _effectMaterial;
private BlitTexturePass _blitTexturePass;
private static readonly string OutlineShaderName = "Hidden/FlatKit/OutlineFilter";
private static readonly int EdgeColor = Shader.PropertyToID("_EdgeColor");
private static readonly int Thickness = Shader.PropertyToID("_Thickness");
private static readonly int DepthThresholdMin = Shader.PropertyToID("_DepthThresholdMin");
private static readonly int DepthThresholdMax = Shader.PropertyToID("_DepthThresholdMax");
private static readonly int NormalThresholdMin = Shader.PropertyToID("_NormalThresholdMin");
private static readonly int NormalThresholdMax = Shader.PropertyToID("_NormalThresholdMax");
private static readonly int ColorThresholdMin = Shader.PropertyToID("_ColorThresholdMin");
private static readonly int ColorThresholdMax = Shader.PropertyToID("_ColorThresholdMax");
/// <summary>
/// Access the runtime effect material to override outline parameters at runtime
/// without mutating the Settings asset.
///
/// Shader (legacy path): "Hidden/FlatKit/OutlineFilter"
///
/// Common shader properties/keywords:
/// - Floats: _Thickness, _DepthThresholdMin/_Max, _NormalThresholdMin/_Max, _ColorThresholdMin/_Max
/// - Colors: _EdgeColor
/// - Keywords: OUTLINE_USE_DEPTH, OUTLINE_USE_NORMALS, OUTLINE_USE_COLOR,
/// OUTLINE_ONLY, RESOLUTION_INVARIANT_THICKNESS
///
/// Note: Inspector changes on the Settings asset may overwrite your values if applied later.
/// </summary>
public Material EffectMaterial => _effectMaterial;
public override void Create() {
#if UNITY_EDITOR
if (_effectMaterial == null) {
SubAssetMaterial.AlwaysInclude(BlitTexturePass.CopyEffectShaderName);
SubAssetMaterial.AlwaysInclude(OutlineShaderName);
}
#endif
if (settings == null) {
return;
}
if (!CreateMaterials()) {
return;
}
SetMaterialProperties();
_blitTexturePass ??=
new BlitTexturePass(_effectMaterial, settings.useDepth, settings.useNormals, useColor: true);
}
protected override void Dispose(bool disposing) {
_blitTexturePass.Dispose();
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
#if UNITY_EDITOR
if (renderingData.cameraData.isPreviewCamera) return;
if (!settings.applyInSceneView && renderingData.cameraData.cameraType == CameraType.SceneView) return;
#endif
SetMaterialProperties();
_blitTexturePass.Setup(renderingData);
_blitTexturePass.renderPassEvent = settings.renderEvent;
renderer.EnqueuePass(_blitTexturePass);
}
private bool CreateMaterials() {
if (_effectMaterial == null) {
var effectShader = Shader.Find(OutlineShaderName);
var blitShader = Shader.Find(BlitTexturePass.CopyEffectShaderName);
if (effectShader == null || blitShader == null) return false;
_effectMaterial = UnityEngine.Rendering.CoreUtils.CreateEngineMaterial(effectShader);
}
return _effectMaterial != null;
}
private void SetMaterialProperties() {
if (_effectMaterial == null) {
return;
}
const string depthKeyword = "OUTLINE_USE_DEPTH";
if (settings.useDepth) {
_effectMaterial.EnableKeyword(depthKeyword);
} else {
_effectMaterial.DisableKeyword(depthKeyword);
}
const string normalsKeyword = "OUTLINE_USE_NORMALS";
if (settings.useNormals) {
_effectMaterial.EnableKeyword(normalsKeyword);
} else {
_effectMaterial.DisableKeyword(normalsKeyword);
}
const string colorKeyword = "OUTLINE_USE_COLOR";
if (settings.useColor) {
_effectMaterial.EnableKeyword(colorKeyword);
} else {
_effectMaterial.DisableKeyword(colorKeyword);
}
const string outlineOnlyKeyword = "OUTLINE_ONLY";
if (settings.outlineOnly) {
_effectMaterial.EnableKeyword(outlineOnlyKeyword);
} else {
_effectMaterial.DisableKeyword(outlineOnlyKeyword);
}
const string resolutionInvariantKeyword = "RESOLUTION_INVARIANT_THICKNESS";
if (settings.resolutionInvariant) {
_effectMaterial.EnableKeyword(resolutionInvariantKeyword);
} else {
_effectMaterial.DisableKeyword(resolutionInvariantKeyword);
}
_effectMaterial.SetColor(EdgeColor, settings.edgeColor);
_effectMaterial.SetFloat(Thickness, settings.thickness);
_effectMaterial.SetFloat(DepthThresholdMin, settings.minDepthThreshold);
_effectMaterial.SetFloat(DepthThresholdMax, settings.maxDepthThreshold);
_effectMaterial.SetFloat(NormalThresholdMin, settings.minNormalsThreshold);
_effectMaterial.SetFloat(NormalThresholdMax, settings.maxNormalsThreshold);
_effectMaterial.SetFloat(ColorThresholdMin, settings.minColorThreshold);
_effectMaterial.SetFloat(ColorThresholdMax, settings.maxColorThreshold);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1cca7768aaaea4b0081f14e7f9d4b5ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,109 @@
#ifndef FLAT_KIT_OUTLINE_INCLUDED
#define FLAT_KIT_OUTLINE_INCLUDED
TEXTURE2D_X (_BlitTexture);
SAMPLER (sampler_BlitTexture);
float Linear01Depth(float z)
{
const float isOrtho = unity_OrthoParams.w;
const float isPers = 1.0 - unity_OrthoParams.w;
z *= _ZBufferParams.x;
return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
}
float SampleDepth(float2 uv)
{
const float d = SampleSceneDepth(uv);
return Linear01Depth(d);
}
float4 SampleCameraColor(float2 uv)
{
return SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_BlitTexture, UnityStereoTransformScreenSpaceTex(uv));
}
void Outline_float(float2 UV, out float4 Out)
{
float4 original = SampleCameraColor(UV);
const float offset_positive = +ceil(_Thickness * 0.5f);
const float offset_negative = -floor(_Thickness * 0.5f);
#if RESOLUTION_INVARIANT_THICKNESS
const float screen_ratio = _ScreenSize.x / _ScreenSize.y;
const float2 texel_size = 1.0 / 800.0 * float2(1.0, screen_ratio);
#else
const float2 texel_size = _ScreenSize.zw;
#endif
float left = texel_size.x * offset_negative;
float right = texel_size.x * offset_positive;
float top = texel_size.y * offset_negative;
float bottom = texel_size.y * offset_positive;
const float2 uv0 = UV + float2(left, top);
const float2 uv1 = UV + float2(right, bottom);
const float2 uv2 = UV + float2(right, top);
const float2 uv3 = UV + float2(left, bottom);
#ifdef OUTLINE_USE_DEPTH
const float d0 = SampleDepth(uv0);
const float d1 = SampleDepth(uv1);
const float d2 = SampleDepth(uv2);
const float d3 = SampleDepth(uv3);
const float depth_threshold_scale = 300.0f;
float d = length(float2(d1 - d0, d3 - d2)) * depth_threshold_scale;
d = smoothstep(_DepthThresholdMin, _DepthThresholdMax, d);
#else
float d = 0.0f;
#endif // OUTLINE_USE_DEPTH
#ifdef OUTLINE_USE_NORMALS
const float3 n0 = SampleSceneNormals(uv0);
const float3 n1 = SampleSceneNormals(uv1);
const float3 n2 = SampleSceneNormals(uv2);
const float3 n3 = SampleSceneNormals(uv3);
const float3 nd1 = n1 - n0;
const float3 nd2 = n3 - n2;
float n = sqrt(dot(nd1, nd1) + dot(nd2, nd2));
n = smoothstep(_NormalThresholdMin, _NormalThresholdMax, n);
#else
float n = 0.0f;
#endif // OUTLINE_USE_NORMALS
#ifdef OUTLINE_USE_COLOR
const float3 c0 = SampleCameraColor(uv0).rgb;
const float3 c1 = SampleCameraColor(uv1).rgb;
const float3 c2 = SampleCameraColor(uv2).rgb;
const float3 c3 = SampleCameraColor(uv3).rgb;
const float3 cd1 = c1 - c0;
const float3 cd2 = c3 - c2;
float c = sqrt(dot(cd1, cd1) + dot(cd2, cd2));
c = smoothstep(_ColorThresholdMin, _ColorThresholdMax, c);
#else
float c = 0;
#endif // OUTLINE_USE_COLOR
const float g = max(d, max(n, c));
#ifdef OUTLINE_FADE_OUT
const float linear_depth = LinearEyeDepth(SampleSceneDepth(UV), _ZBufferParams);
const float fade = smoothstep(_FadeRangeEnd, _FadeRangeStart, linear_depth);
_EdgeColor.a *= fade;
#endif // OUTLINE_FADE_OUT
#ifdef OUTLINE_ONLY
original.rgb = lerp(1.0 - _EdgeColor.rgb, _EdgeColor.rgb, g * _EdgeColor.a);
#endif // OUTLINE_ONLY
float4 output;
output.rgb = lerp(original.rgb, _EdgeColor.rgb, g * _EdgeColor.a);
output.a = original.a;
Out = output;
}
#endif // FLAT_KIT_OUTLINE_INCLUDED

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 55858e4cd94d48b0a267735f29dd1e5e
timeCreated: 1691384044

View File

@@ -0,0 +1,201 @@
using System;
using ExternPropertyAttributes;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using Debug = UnityEngine.Debug;
// ReSharper disable RedundantDefaultMemberInitializer
#if UNITY_2022_3_OR_NEWER
namespace FlatKit {
[CreateAssetMenu(fileName = "OutlineSettings", menuName = "FlatKit/Outline Settings")]
public class OutlineSettings : ScriptableObject {
[Space] // Expandable.
[Tooltip("The color of the lines. Alpha is used for transparency, " +
"0 means fully transparent and 1 means fully opaque lines.")]
public Color edgeColor = Color.white;
[Range(0, 5)]
[Tooltip("The width of the lines in screen space. If 'Resolution Invariant' is disabled, " +
"this is the width in pixels. Otherwise, it is a relative width.")]
public int thickness = 1;
[Tooltip("If enabled, the line width will stay constant regardless of the rendering resolution. " +
"However, some of the lines may appear blurry.")]
public bool resolutionInvariant = false;
[Tooltip("If enabled, the outline will become more transparent the further away it is from the camera.")]
public bool fadeWithDistance = false;
[ShowIf(nameof(fadeWithDistance))]
[Label(" Start")]
[Tooltip("The distance from the camera at which the outline starts to fade. The value is in world units.")]
public float fadeRangeStart = 10f;
[ShowIf(nameof(fadeWithDistance))]
[Label(" End")]
[Tooltip("The distance from the camera at which the outline is fully transparent. The value is in world units.")]
public float fadeRangeEnd = 50f;
[HorizontalLine]
[Tooltip("Whether to use depth information to draw outlines. This adds lines around objects that are in front of " +
"other objects.")]
public bool useDepth = true;
[ShowIf(nameof(useDepth))]
[Label(" Min Threshold")]
[Min(0)]
[Tooltip("Minimum distance between two pixels to be considered an edge. The outline is drawn almost transparent.")]
public float minDepthThreshold = 0.1f;
[ShowIf(nameof(useDepth))]
[Label(" Max Threshold")]
[Min(0)]
[Tooltip("Maximum distance between two pixels to be considered an edge. The outline is drawn fully opaque.")]
public float maxDepthThreshold = 0.25f;
[HorizontalLine(1, EColor.Translucent)]
[Tooltip("Whether to use world-space normals information to draw outlines. This adds lines " +
"on sharp edges of objects.")]
public bool useNormals = false;
[ShowIf(nameof(useNormals))]
[Label(" Min Threshold")]
[Min(0)]
[Tooltip("Minimum angle between two normals to be considered an edge. The outline is drawn almost transparent.")]
public float minNormalsThreshold = 0.1f;
[ShowIf(nameof(useNormals))]
[Label(" Max Threshold")]
[Min(0)]
[Tooltip("Maximum angle between two normals to be considered an edge. The outline is drawn fully opaque.")]
public float maxNormalsThreshold = 0.25f;
[HorizontalLine(1, EColor.Translucent)]
[Tooltip("Whether to use color information to draw outlines. This adds lines where the color of the object " +
"changes.")]
public bool useColor = false;
[ShowIf(nameof(useColor))]
[Label(" Min Threshold")]
[Min(0)]
[Tooltip("Minimum difference in color between two pixels to be considered an edge. The outline is drawn almost " +
"transparent.")]
public float minColorThreshold = 0.1f;
[ShowIf(nameof(useColor))]
[Label(" Max Threshold")]
[Min(0)]
[Tooltip("Maximum difference in color between two pixels to be considered an edge. The outline is drawn fully " +
"opaque.")]
public float maxColorThreshold = 0.25f;
[HorizontalLine]
[Tooltip("The render stage at which the effect is applied. To exclude transparent objects, like water or UI " +
"elements, set this to \"Before Transparent\".")]
public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
[Tooltip("Only draw the outline, replacing the original color with a complimentary color.")]
public bool outlineOnly = false;
[Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
"mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
public bool applyInSceneView = true;
[HideInInspector]
public Material effectMaterial;
internal Action onSettingsChanged;
internal Action onReset;
private void OnValidate() {
if (minDepthThreshold > maxDepthThreshold + float.Epsilon) {
Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: <b>'Min Depth Threshold'</b> must not " +
"be greater than <b>'Max Depth Threshold'</b>");
}
if (minNormalsThreshold > maxNormalsThreshold + float.Epsilon) {
Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: <b>'Min Normals Threshold'</b> must not " +
"be greater than <b>'Max Normals Threshold'</b>");
}
if (minColorThreshold > maxColorThreshold + float.Epsilon) {
Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: <b>'Min Color Threshold'</b> must not " +
"be greater than <b>'Max Color Threshold'</b>");
}
fadeRangeStart = Mathf.Max(0f, Mathf.Min(fadeRangeStart, fadeRangeEnd));
fadeRangeEnd = Mathf.Max(fadeRangeStart, Mathf.Min(fadeRangeEnd, 1000f));
onSettingsChanged?.Invoke();
}
private void Reset() {
onReset?.Invoke();
}
private void OnDestroy() {
onSettingsChanged = null;
onReset = null;
}
}
}
#else
namespace FlatKit {
[CreateAssetMenu(fileName = "OutlineSettings", menuName = "FlatKit/Outline Settings")]
public class OutlineSettings : ScriptableObject {
public Color edgeColor = Color.white;
[Range(0, 5)]
public int thickness = 1;
[Tooltip("If enabled, the line width will stay constant regardless of the rendering resolution. " +
"However, some of the lines may appear blurry.")]
public bool resolutionInvariant = false;
[Space]
public bool useDepth = true;
public bool useNormals = false;
public bool useColor = false;
[Header("Advanced settings")]
public float minDepthThreshold = 0f;
public float maxDepthThreshold = 0.25f;
[Space]
public float minNormalsThreshold = 0f;
public float maxNormalsThreshold = 0.25f;
[Space]
public float minColorThreshold = 0f;
public float maxColorThreshold = 0.25f;
[Space, Tooltip("The render stage at which the effect is applied. To exclude transparent objects, " +
"like water or UI elements, set this to \"Before Transparent\".")]
public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
public bool outlineOnly = false;
[Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
"mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
public bool applyInSceneView = true;
private void OnValidate() {
if (minDepthThreshold > maxDepthThreshold + float.Epsilon) {
Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: 'Min Depth Threshold' must not " +
"be greater than 'Max Depth Threshold'");
}
if (minNormalsThreshold > maxNormalsThreshold + float.Epsilon) {
Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: 'Min Normals Threshold' must not " +
"be greater than 'Max Normals Threshold'");
}
if (minColorThreshold > maxColorThreshold + float.Epsilon) {
Debug.LogWarning("<b>[Flat Kit]</b> Outline configuration error: 'Min Color Threshold' must not " +
"be greater than 'Max Color Threshold'");
}
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 130791d3e20646d2b6d81688877b0909
timeCreated: 1585531463

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f968e7540d632cc40b5ca8b340a3e718
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 86e5004805d440718ff05f937654caf4
timeCreated: 1697581791

View File

@@ -0,0 +1,92 @@
using ExternPropertyAttributes;
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace FlatKit {
public class FlatKitPixelation : ScriptableRendererFeature {
[Expandable]
[Tooltip("To create new settings use 'Create > FlatKit > Pixelation Settings'.")]
public PixelationSettings settings;
private Material _effectMaterial;
private ScreenRenderPass _fullScreenPass;
private bool _requiresColor;
private bool _injectedBeforeTransparents;
private ScriptableRenderPassInput _requirements = ScriptableRenderPassInput.Color;
private const string ShaderName = "Hidden/FlatKit/PixelationWrap";
private static int pixelSizeProperty => Shader.PropertyToID("_PixelSize");
/// <summary>
/// Access the runtime effect material to override pixelation parameters at runtime
/// without mutating the Settings asset.
///
/// Shader: "Hidden/FlatKit/PixelationWrap"
///
/// Common shader properties:
/// - Floats: _PixelSize (computed as 1 / resolution by default)
///
/// Note: Inspector changes on the Settings asset may overwrite your values if applied later.
/// </summary>
public Material EffectMaterial => _effectMaterial;
public override void Create() {
// Settings.
{
if (settings == null) return;
settings.onSettingsChanged = null;
settings.onReset = null;
settings.onSettingsChanged += SetMaterialProperties;
settings.onReset += SetMaterialProperties;
}
// Material.
{
#if UNITY_EDITOR
settings.effectMaterial = SubAssetMaterial.GetOrCreate(settings, ShaderName);
if (settings.effectMaterial == null) return;
#endif
_effectMaterial = settings.effectMaterial;
SetMaterialProperties();
}
{
_fullScreenPass = new ScreenRenderPass {
renderPassEvent = settings.renderEvent,
};
_requirements = ScriptableRenderPassInput.Color;
ScriptableRenderPassInput modifiedRequirements = _requirements;
_requiresColor = (_requirements & ScriptableRenderPassInput.Color) != 0;
_injectedBeforeTransparents = settings.renderEvent <= RenderPassEvent.BeforeRenderingTransparents;
if (_requiresColor && !_injectedBeforeTransparents) {
modifiedRequirements ^= ScriptableRenderPassInput.Color;
}
_fullScreenPass.ConfigureInput(modifiedRequirements);
}
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
if (settings == null || !settings.applyInSceneView && renderingData.cameraData.isSceneViewCamera) return;
if (renderingData.cameraData.isPreviewCamera) return;
if (_effectMaterial == null) return;
_fullScreenPass.Setup(_effectMaterial, _requiresColor, _injectedBeforeTransparents, "Flat Kit Pixelation",
renderingData);
renderer.EnqueuePass(_fullScreenPass);
}
protected override void Dispose(bool disposing) {
_fullScreenPass?.Dispose();
}
private void SetMaterialProperties() {
if (_effectMaterial == null) return;
var pixelSize = Mathf.Max(1f / settings.resolution, 0.0001f);
_effectMaterial.SetFloat(pixelSizeProperty, pixelSize);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: edb250ac097f481fa89c38a1e224b773
timeCreated: 1697581791

View File

@@ -0,0 +1,25 @@
#ifndef FLAT_KIT_PIXELATION_INCLUDED
#define FLAT_KIT_PIXELATION_INCLUDED
TEXTURE2D_X (_BlitTexture);
SAMPLER (sampler_BlitTexture);
float4 SampleCameraColor(float2 uv)
{
// Using sampler_PointClamp instead of sampler_BlitTexture to avoid bilinear filtering.
return SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_PointClamp, UnityStereoTransformScreenSpaceTex(uv));
}
void Pixelation_float(float2 UV, out float4 Out)
{
float longerScreenSizePixelSize = _PixelSize;
float aspectRatio = _ScreenParams.x / _ScreenParams.y;
float2 pixelSize = aspectRatio > 1
? float2(longerScreenSizePixelSize, longerScreenSizePixelSize * aspectRatio)
: float2(longerScreenSizePixelSize / aspectRatio, longerScreenSizePixelSize);
float2 uv = UV / pixelSize;
uv = floor(uv);
uv *= pixelSize;
Out = SampleCameraColor(uv);
}
#endif // FLAT_KIT_PIXELATION_INCLUDED

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d00436b1cf7a4c7c8cb42e8f0bc826c9
timeCreated: 1697581791

View File

@@ -0,0 +1,52 @@
using System;
using ExternPropertyAttributes;
using UnityEngine;
using UnityEngine.Rendering.Universal;
// ReSharper disable RedundantDefaultMemberInitializer
namespace FlatKit {
[CreateAssetMenu(fileName = "PixelationSettings", menuName = "FlatKit/Pixelation Settings")]
public class PixelationSettings : ScriptableObject {
[Space] // Expandable.
#if !UNITY_2022_3_OR_NEWER
[ExternPropertyAttributes.InfoBox(
"Pixelation Effect requires Unity 2022.3 or newer. Please upgrade your Unity version to use this feature.",
ExternPropertyAttributes.EInfoBoxType.Warning)]
[Space]
#endif
[Tooltip("The number of pixels on the longer side of the screen.\nLower values result in a more pixelated image.")]
[Min(0)]
public int resolution = 320;
[HorizontalLine(1, EColor.Translucent)]
[Tooltip("The render stage at which the effect is applied. To exclude transparent objects, like water or " +
"UI elements, set this to \"Before Transparent\".")]
public RenderPassEvent renderEvent = RenderPassEvent.BeforeRenderingPostProcessing;
[Tooltip("Whether the effect should be applied in the Scene view as well as in the Game view. Please keep in " +
"mind that Unity always renders the scene view with the default Renderer settings of the URP config.")]
public bool applyInSceneView = true;
[HideInInspector]
public Material effectMaterial;
internal Action onSettingsChanged;
internal Action onReset;
private void OnValidate() {
onSettingsChanged?.Invoke();
}
private void Reset() {
onReset?.Invoke();
}
private void OnDestroy() {
onSettingsChanged = null;
onReset = null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6bf7a6fd37ee46709aa013efc3270aba
timeCreated: 1697581791

View File

@@ -0,0 +1,625 @@
{
"m_SGVersion": 3,
"m_Type": "UnityEditor.ShaderGraph.GraphData",
"m_ObjectId": "1c91f7928335480e8da474fcedfb1646",
"m_Properties": [
{
"m_Id": "120c814773e946579675f32587651895"
}
],
"m_Keywords": [],
"m_Dropdowns": [],
"m_CategoryData": [
{
"m_Id": "9b7a3cf03dd848d99086a26aaeb3b30d"
}
],
"m_Nodes": [
{
"m_Id": "124549f5950643a09e2f87c4f74e9dd6"
},
{
"m_Id": "ca0fa6ce4dd049e6b3c0102f58e9831a"
},
{
"m_Id": "92980b70b95c486e84565917adbcdffd"
},
{
"m_Id": "1f9b5fa558dd414f8295a949f5f566b6"
},
{
"m_Id": "32f3a6d7f0d1419d9ad654a50f5ac295"
}
],
"m_GroupDatas": [],
"m_StickyNoteDatas": [],
"m_Edges": [
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "1f9b5fa558dd414f8295a949f5f566b6"
},
"m_SlotId": 0
},
"m_InputSlot": {
"m_Node": {
"m_Id": "92980b70b95c486e84565917adbcdffd"
},
"m_SlotId": 2
}
},
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "32f3a6d7f0d1419d9ad654a50f5ac295"
},
"m_SlotId": 4
},
"m_InputSlot": {
"m_Node": {
"m_Id": "ca0fa6ce4dd049e6b3c0102f58e9831a"
},
"m_SlotId": 0
}
},
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "92980b70b95c486e84565917adbcdffd"
},
"m_SlotId": 0
},
"m_InputSlot": {
"m_Node": {
"m_Id": "124549f5950643a09e2f87c4f74e9dd6"
},
"m_SlotId": 0
}
},
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "92980b70b95c486e84565917adbcdffd"
},
"m_SlotId": 0
},
"m_InputSlot": {
"m_Node": {
"m_Id": "32f3a6d7f0d1419d9ad654a50f5ac295"
},
"m_SlotId": 0
}
}
],
"m_VertexContext": {
"m_Position": {
"x": 16.999998092651368,
"y": 32.00004196166992
},
"m_Blocks": []
},
"m_FragmentContext": {
"m_Position": {
"x": 0.0,
"y": 200.0
},
"m_Blocks": [
{
"m_Id": "124549f5950643a09e2f87c4f74e9dd6"
},
{
"m_Id": "ca0fa6ce4dd049e6b3c0102f58e9831a"
}
]
},
"m_PreviewData": {
"serializedMesh": {
"m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}",
"m_Guid": ""
},
"preventRotation": false
},
"m_Path": "Hidden/FlatKit",
"m_GraphPrecision": 1,
"m_PreviewMode": 2,
"m_OutputNode": {
"m_Id": ""
},
"m_ActiveTargets": [
{
"m_Id": "6de9888e3b9844abb410aa7f1cbe319e"
}
]
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot",
"m_ObjectId": "000c5eeb790444bd82861eb7a9d73169",
"m_Id": 2,
"m_DisplayName": "UV",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "UV",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0
},
"m_Labels": []
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty",
"m_ObjectId": "120c814773e946579675f32587651895",
"m_Guid": {
"m_GuidSerialized": "a8445f83-acbd-4186-a4dd-9348b1dc70f6"
},
"m_Name": "Pixel Size",
"m_DefaultRefNameVersion": 1,
"m_RefNameGeneratedByDisplayName": "Pixel Size",
"m_DefaultReferenceName": "_Pixel_Size",
"m_OverrideReferenceName": "_PixelSize",
"m_GeneratePropertyBlock": true,
"m_UseCustomSlotLabel": false,
"m_CustomSlotLabel": "",
"m_DismissedVersion": 0,
"m_Precision": 0,
"overrideHLSLDeclaration": false,
"hlslDeclarationOverride": 0,
"m_Hidden": false,
"m_Value": 1.0,
"m_FloatType": 0,
"m_RangeValues": {
"x": 0.0,
"y": 5.0
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
"m_ObjectId": "124549f5950643a09e2f87c4f74e9dd6",
"m_Group": {
"m_Id": ""
},
"m_Name": "SurfaceDescription.BaseColor",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 0.0,
"height": 0.0
}
},
"m_Slots": [
{
"m_Id": "9a7200ad60604ef09f5d67209401bf75"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_SerializedDescriptor": "SurfaceDescription.BaseColor"
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.ScreenPositionNode",
"m_ObjectId": "1f9b5fa558dd414f8295a949f5f566b6",
"m_Group": {
"m_Id": ""
},
"m_Name": "Screen Position",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -563.3333129882813,
"y": 200.0,
"width": 147.3333740234375,
"height": 131.99996948242188
}
},
"m_Slots": [
{
"m_Id": "491fba181a5442c296dfffa19efd71f3"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": false,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_ScreenSpaceType": 0
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.SplitNode",
"m_ObjectId": "32f3a6d7f0d1419d9ad654a50f5ac295",
"m_Group": {
"m_Id": ""
},
"m_Name": "Split",
"m_DrawState": {
"m_Expanded": false,
"m_Position": {
"serializedVersion": "2",
"x": -145.00001525878907,
"y": 290.9999694824219,
"width": 119.00001525878906,
"height": 77.00006103515625
}
},
"m_Slots": [
{
"m_Id": "65fcd7b0d8cf498596e96f95ef3fb267"
},
{
"m_Id": "8f3a8134e0bc4a5fa20a53b54ec8382b"
},
{
"m_Id": "6c96fb89373a455dab6a5d7e074519c6"
},
{
"m_Id": "bb92d54e4f874bd3b1186db88e7338d6"
},
{
"m_Id": "8d59403795d343e5abafa7d95650a21b"
}
],
"synonyms": [
"separate"
],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot",
"m_ObjectId": "491fba181a5442c296dfffa19efd71f3",
"m_Id": 0,
"m_DisplayName": "Out",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "Out",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.DynamicVectorMaterialSlot",
"m_ObjectId": "65fcd7b0d8cf498596e96f95ef3fb267",
"m_Id": 0,
"m_DisplayName": "In",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "In",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "6c96fb89373a455dab6a5d7e074519c6",
"m_Id": 2,
"m_DisplayName": "G",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "G",
"m_StageCapability": 3,
"m_Value": 0.0,
"m_DefaultValue": 0.0,
"m_Labels": []
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget",
"m_ObjectId": "6de9888e3b9844abb410aa7f1cbe319e",
"m_Datas": [
{
"m_Id": "f96621e0417148329344ce08081a08aa"
}
],
"m_ActiveSubTarget": {
"m_Id": "aa590bf2e5f14b53893d161e232b1f36"
},
"m_AllowMaterialOverride": false,
"m_SurfaceType": 0,
"m_ZTestMode": 4,
"m_ZWriteControl": 0,
"m_AlphaMode": 0,
"m_RenderFace": 2,
"m_AlphaClip": false,
"m_CastShadows": true,
"m_ReceiveShadows": true,
"m_SupportsLODCrossFade": false,
"m_CustomEditorGUI": "",
"m_SupportVFX": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "82e211689f994de0a779d29c1ea3c1eb",
"m_Id": 0,
"m_DisplayName": "Alpha",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "Alpha",
"m_StageCapability": 2,
"m_Value": 1.0,
"m_DefaultValue": 1.0,
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "8d59403795d343e5abafa7d95650a21b",
"m_Id": 4,
"m_DisplayName": "A",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "A",
"m_StageCapability": 3,
"m_Value": 0.0,
"m_DefaultValue": 0.0,
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "8f3a8134e0bc4a5fa20a53b54ec8382b",
"m_Id": 1,
"m_DisplayName": "R",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "R",
"m_StageCapability": 3,
"m_Value": 0.0,
"m_DefaultValue": 0.0,
"m_Labels": []
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode",
"m_ObjectId": "92980b70b95c486e84565917adbcdffd",
"m_Group": {
"m_Id": ""
},
"m_Name": "Pixelation (Custom Function)",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -418.66668701171877,
"y": 200.0,
"width": 211.3333740234375,
"height": 95.99996948242188
}
},
"m_Slots": [
{
"m_Id": "ac3fddfa47924bab812f39451a6ecb79"
},
{
"m_Id": "000c5eeb790444bd82861eb7a9d73169"
}
],
"synonyms": [
"code",
"HLSL"
],
"m_Precision": 0,
"m_PreviewExpanded": false,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_SourceType": 0,
"m_FunctionName": "Pixelation",
"m_FunctionSource": "d00436b1cf7a4c7c8cb42e8f0bc826c9",
"m_FunctionBody": "Enter function body here..."
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot",
"m_ObjectId": "9a7200ad60604ef09f5d67209401bf75",
"m_Id": 0,
"m_DisplayName": "Base Color",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "BaseColor",
"m_StageCapability": 2,
"m_Value": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"m_Labels": [],
"m_ColorMode": 0,
"m_DefaultColor": {
"r": 0.5,
"g": 0.5,
"b": 0.5,
"a": 1.0
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.CategoryData",
"m_ObjectId": "9b7a3cf03dd848d99086a26aaeb3b30d",
"m_Name": "",
"m_ChildObjectList": [
{
"m_Id": "120c814773e946579675f32587651895"
}
]
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalFullscreenSubTarget",
"m_ObjectId": "aa590bf2e5f14b53893d161e232b1f36"
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot",
"m_ObjectId": "ac3fddfa47924bab812f39451a6ecb79",
"m_Id": 0,
"m_DisplayName": "Out",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "Out",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "bb92d54e4f874bd3b1186db88e7338d6",
"m_Id": 3,
"m_DisplayName": "B",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "B",
"m_StageCapability": 3,
"m_Value": 0.0,
"m_DefaultValue": 0.0,
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
"m_ObjectId": "ca0fa6ce4dd049e6b3c0102f58e9831a",
"m_Group": {
"m_Id": ""
},
"m_Name": "SurfaceDescription.Alpha",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 0.0,
"height": 0.0
}
},
"m_Slots": [
{
"m_Id": "82e211689f994de0a779d29c1ea3c1eb"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_SerializedDescriptor": "SurfaceDescription.Alpha"
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.Rendering.Fullscreen.ShaderGraph.FullscreenData",
"m_ObjectId": "f96621e0417148329344ce08081a08aa",
"m_Version": 0,
"m_fullscreenMode": 0,
"m_BlendMode": 0,
"m_SrcColorBlendMode": 0,
"m_DstColorBlendMode": 1,
"m_ColorBlendOperation": 0,
"m_SrcAlphaBlendMode": 0,
"m_DstAlphaBlendMode": 1,
"m_AlphaBlendOperation": 0,
"m_EnableStencil": false,
"m_StencilReference": 0,
"m_StencilReadMask": 255,
"m_StencilWriteMask": 255,
"m_StencilCompareFunction": 8,
"m_StencilPassOperation": 0,
"m_StencilFailOperation": 0,
"m_StencilDepthFailOperation": 0,
"m_DepthWrite": false,
"m_depthWriteMode": 0,
"m_AllowMaterialOverride": false,
"m_DepthTestMode": 0
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 6b2177cf82af36949b9a8d210c2b4962
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 533b7b273fd64cd88d55213ba3af51a3
timeCreated: 1668359087

View File

@@ -0,0 +1,74 @@
Shader "Hidden/FlatKit/CopyTexture"
{
SubShader
{
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
LOD 100
ZWrite Off Cull Off
Pass
{
Name "Custom Copy Texture"
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#pragma multi_compile _ _USE_DRAW_PROCEDURAL
float4 _SourceSize;
TEXTURE2D_X(_EffectTexture);
SAMPLER(sampler_EffectTexture);
float4 SampleEffectTexture(float2 uv)
{
return SAMPLE_TEXTURE2D_X(_EffectTexture, sampler_EffectTexture, UnityStereoTransformScreenSpaceTex(uv));
}
struct Attributes
{
float4 positionHCS : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
#if _USE_DRAW_PROCEDURAL
output.positionCS = float4(input.positionHCS.xyz, 1.0);
#if UNITY_UV_STARTS_AT_TOP
output.positionCS.y *= -1;
#endif
#else
output.positionCS = TransformObjectToHClip(input.positionHCS.xyz);
#endif
output.uv = input.uv;
return output;
}
half4 frag(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float4 c = SampleEffectTexture(input.uv);
return c;
}
#pragma vertex vert
#pragma fragment frag
ENDHLSL
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e05a9f4f2755f3941a86a256f16c0d82
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,179 @@
Shader "Hidden/FlatKit/FogFilter"
{
Properties
{
[Toggle(USE_DISTANCE_FOG)]_UseDistanceFog ("Use Distance", Float) = 0
[Toggle(USE_DISTANCE_FOG_ON_SKY)]_UseDistanceFogOnSky ("Use Distance Fog On Sky", Float) = 0
[Space]
_Near ("Near", Float) = 0
_Far ("Far", Float) = 100
[Space]
_DistanceFogIntensity ("Distance Fog Intensity", Range(0, 1)) = 1
[Space(25)]
[Toggle(USE_HEGHT_FOG)]_UseHeightFog ("Use Height", Float) = 0
[Toggle(USE_HEGHT_FOG_ON_SKY)]_UseHeightFogOnSky ("Use Height Fog On Sky", Float) = 0
[Space]
_LowWorldY ("Low", Float) = 0
_HighWorldY ("High", Float) = 10
[Space]
_HeightFogIntensity ("Height Fog Intensity", Range(0, 1)) = 1
[Space(25)]
_DistanceHeightBlend ("Distance / Height blend", Range(0, 1)) = 0.5
}
SubShader
{
Tags
{
"RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"
}
LOD 100
ZWrite Off Cull Off
Pass
{
Name "Fog"
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"
#pragma multi_compile _ _USE_DRAW_PROCEDURAL
sampler2D _DistanceLUT;
float _Near;
float _Far;
half _UseDistanceFog;
half _UseDistanceFogOnSky;
sampler2D _HeightLUT;
float _LowWorldY;
float _HighWorldY;
half _UseHeightFog;
half _UseHeightFogOnSky;
float _DistanceFogIntensity;
float _HeightFogIntensity;
float _DistanceHeightBlend;
#define ALMOST_ONE 0.999
// Using `_CameraColorTexture` instead of the opaque texture `SampleSceneColor` to handle transparency.
TEXTURE2D_X(_CameraColorTexture);
SAMPLER(sampler_CameraColorTexture);
float4 _CameraColorTexture_TexelSize;
// Z buffer depth to linear 0-1 depth
// Handles orthographic projection correctly
float Linear01Depth(float z)
{
float isOrtho = unity_OrthoParams.w;
float isPers = 1.0 - unity_OrthoParams.w;
z *= _ZBufferParams.x;
return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
}
float4 SampleCameraColor(float2 uv)
{
return SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, UnityStereoTransformScreenSpaceTex(uv));
}
float LinearEyeDepth(float z)
{
return rcp(_ZBufferParams.z * z + _ZBufferParams.w);
}
float4 Fog(float2 uv, float3 screen_pos)
{
float4 original = SampleCameraColor(uv);
const float depthPacked = SampleSceneDepth(uv);
const float depthEye = LinearEyeDepth(depthPacked);
const float depthCameraPlanes = Linear01Depth(depthPacked);
const float depthAbsolute = _ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) *
depthCameraPlanes;
const float depthFogPlanes = saturate((depthAbsolute - _Near) / (_Far - _Near));
const float isSky = step(ALMOST_ONE, depthCameraPlanes);
float4 distanceFog = tex2D(_DistanceLUT, float2(depthFogPlanes, 0.5));
distanceFog.a *= step(isSky, _UseDistanceFogOnSky);
distanceFog.a *= _UseDistanceFog * _DistanceFogIntensity;
const float3 worldPos = screen_pos * depthEye + _WorldSpaceCameraPos;
const float heightUV = saturate((worldPos.y - _LowWorldY) / (_HighWorldY - _LowWorldY));
float4 heightFog = tex2D(_HeightLUT, float2(heightUV, 0.5));
heightFog.a *= step(isSky, _UseHeightFogOnSky);
heightFog.a *= _UseHeightFog * _HeightFogIntensity;
float fogBlend = _DistanceHeightBlend;
if (!_UseDistanceFog) fogBlend = 1.0;
if (!_UseHeightFog) fogBlend = 0.0;
const float4 fog = lerp(distanceFog, heightFog, fogBlend);
float4 final = lerp(original, fog, fog.a);
final.a = original.a;
return final;
}
struct Attributes
{
float4 positionOS: POSITION;
float2 uv: TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float2 uv: TEXCOORD0;
float3 screen_pos: TEXCOORD1;
float4 vertex: SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert(Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
#if _USE_DRAW_PROCEDURAL
output.vertex = float4(input.positionOS.xyz, 1.0);
#if UNITY_UV_STARTS_AT_TOP
output.vertex.y *= -1;
#endif
#else
const VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.vertex = vertexInput.positionCS;
#endif
output.uv = input.uv;
output.screen_pos = ComputeScreenPos(output.vertex).xyz;
return output;
}
half4 frag(Varyings input): SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float4 c = Fog(input.uv, input.screen_pos);
return c;
}
#pragma vertex vert
#pragma fragment frag
ENDHLSL
}
}
FallBack "Diffuse"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6eb928abe872c4fd5a7acead14922715
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,218 @@
Shader "Hidden/FlatKit/OutlineFilter"
{
Properties
{
[HideInInspector]_BaseMap ("Base (RGB)", 2D) = "white" {}
_EdgeColor ("Outline Color", Color) = (1, 1, 1, 1)
_Thickness ("Thickness", Range(0, 5)) = 1
[Space(15)]
[Toggle(OUTLINE_USE_DEPTH)]_UseDepth ("Use Depth", Float) = 1
_DepthThresholdMin ("Min Depth Threshold", Range(0, 1)) = 0
_DepthThresholdMax ("Max Depth Threshold", Range(0, 1)) = 0.25
[Space(15)]
[Toggle(OUTLINE_USE_NORMALS)]_UseNormals ("Use Normals", Float) = 0
_NormalThresholdMin ("Min Normal Threshold", Range(0, 1)) = 0.5
_NormalThresholdMax ("Max Normal Threshold", Range(0, 1)) = 1.0
[Space(15)]
[Toggle(OUTLINE_USE_COLOR)]_UseColor ("Use Color", Float) = 0
_ColorThresholdMin ("Min Color Threshold", Range(0, 1)) = 0
_ColorThresholdMax ("Max Color Threshold", Range(0, 1)) = 0.25
[Space(15)]
[Toggle(OUTLINE_ONLY)]_OutlineOnly ("Outline Only", Float) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
LOD 100
ZWrite Off Cull Off
Pass
{
Name "Outline"
HLSLPROGRAM
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"
#pragma shader_feature OUTLINE_USE_DEPTH
#pragma shader_feature OUTLINE_USE_NORMALS
#pragma shader_feature OUTLINE_USE_COLOR
#pragma shader_feature OUTLINE_ONLY
#pragma shader_feature RESOLUTION_INVARIANT_THICKNESS
#pragma multi_compile _ _USE_DRAW_PROCEDURAL
uniform half _Thickness;
uniform half4 _EdgeColor;
uniform half _DepthThresholdMin, _DepthThresholdMax;
uniform half _NormalThresholdMin, _NormalThresholdMax;
uniform half _ColorThresholdMin, _ColorThresholdMax;
TEXTURE2D_X(_CameraColorTexture);
SAMPLER(sampler_CameraColorTexture);
// #define OUTLINE_USE_TRANSPARENT_DEPTH
#ifdef OUTLINE_USE_TRANSPARENT_DEPTH
TEXTURE2D_X(_CameraTransparentDepthTexture);
#endif
float4 _SourceSize;
// Z buffer depth to linear 0-1 depth
// Handles orthographic projection correctly
float Linear01Depth(float z)
{
const float isOrtho = unity_OrthoParams.w;
const float isPers = 1.0 - unity_OrthoParams.w;
z *= _ZBufferParams.x;
return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
}
float SampleDepth(float2 uv)
{
float d = SampleSceneDepth(uv);
#ifdef OUTLINE_USE_TRANSPARENT_DEPTH
d += SAMPLE_TEXTURE2D_X(_CameraTransparentDepthTexture, sampler_CameraColorTexture, UnityStereoTransformScreenSpaceTex(uv)).r;
#endif
return Linear01Depth(d);
}
float4 SampleCameraColor(float2 uv)
{
return SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, UnityStereoTransformScreenSpaceTex(uv));
}
float4 Outline(float2 uv)
{
float4 original = SampleCameraColor(uv);
const float offset_positive = +ceil(_Thickness * 0.5f);
const float offset_negative = -floor(_Thickness * 0.5f);
#if RESOLUTION_INVARIANT_THICKNESS
const float screen_ratio = _SourceSize.x / _SourceSize.y;
const float2 texel_size = 1.0 / 800.0 * float2(1.0, screen_ratio);
#else
const float2 texel_size = _SourceSize.zw;
#endif
float left = texel_size.x * offset_negative;
float right = texel_size.x * offset_positive;
float top = texel_size.y * offset_negative;
float bottom = texel_size.y * offset_positive;
const float2 uv0 = uv + float2(left, top);
const float2 uv1 = uv + float2(right, bottom);
const float2 uv2 = uv + float2(right, top);
const float2 uv3 = uv + float2(left, bottom);
#ifdef OUTLINE_USE_DEPTH
const float d0 = SampleDepth(uv0);
const float d1 = SampleDepth(uv1);
const float d2 = SampleDepth(uv2);
const float d3 = SampleDepth(uv3);
const float depth_threshold_scale = 300.0f;
float d = length(float2(d1 - d0, d3 - d2)) * depth_threshold_scale;
d = smoothstep(_DepthThresholdMin, _DepthThresholdMax, d);
#else
float d = 0.0f;
#endif // OUTLINE_USE_DEPTH
#ifdef OUTLINE_USE_NORMALS
const float3 n0 = SampleSceneNormals(uv0);
const float3 n1 = SampleSceneNormals(uv1);
const float3 n2 = SampleSceneNormals(uv2);
const float3 n3 = SampleSceneNormals(uv3);
const float3 nd1 = n1 - n0;
const float3 nd2 = n3 - n2;
float n = sqrt(dot(nd1, nd1) + dot(nd2, nd2));
n = smoothstep(_NormalThresholdMin, _NormalThresholdMax, n);
#else
float n = 0.0f;
#endif // OUTLINE_USE_NORMALS
#ifdef OUTLINE_USE_COLOR
const float3 c0 = SampleCameraColor(uv0).rgb;
const float3 c1 = SampleCameraColor(uv1).rgb;
const float3 c2 = SampleCameraColor(uv2).rgb;
const float3 c3 = SampleCameraColor(uv3).rgb;
const float3 cd1 = c1 - c0;
const float3 cd2 = c3 - c2;
float c = sqrt(dot(cd1, cd1) + dot(cd2, cd2));
c = smoothstep(_ColorThresholdMin, _ColorThresholdMax, c);
#else
float c = 0;
#endif // OUTLINE_USE_COLOR
const float g = max(d, max(n, c));
#ifdef OUTLINE_ONLY
original.rgb = lerp(1.0 - _EdgeColor.rgb, _EdgeColor.rgb, g * _EdgeColor.a);
#endif // OUTLINE_ONLY
float4 output;
output.rgb = lerp(original.rgb, _EdgeColor.rgb, g * _EdgeColor.a);
output.a = original.a;
return output;
}
struct Attributes
{
float4 positionHCS : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
#if _USE_DRAW_PROCEDURAL
output.positionCS = float4(input.positionHCS.xyz, 1.0);
#if UNITY_UV_STARTS_AT_TOP
output.positionCS.y *= -1;
#endif
#else
output.positionCS = TransformObjectToHClip(input.positionHCS.xyz);
#endif
output.uv = input.uv;
return output;
}
half4 frag(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float4 c = Outline(input.uv);
return c;
}
#pragma vertex vert
#pragma fragment frag
ENDHLSL
}
}
FallBack "Diffuse"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2e4419296dd04b32bcc48a56ac645aa9
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1 @@
This folder is used only in Unity 2021 or older.

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 657891af2ead49a2b9cbfd069f5cead2
timeCreated: 1701333515