Flatkit 추가 및 설정
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78d0c5250a38946caaafa2b13edcbb4f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5985b630931f0e846b661c4bbc4d0a25
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a43bf53130f412f88de25122442bade
|
||||
timeCreated: 1720407925
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4352bba7c98b4f53bdc3856f0edf40f4
|
||||
timeCreated: 1691382047
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57832b6c4cbc426896f2230d92a1f228
|
||||
timeCreated: 1669323534
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:15fc0a57446b3144c949da3e2b9737a9"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5933a64b832764e4a81747888e4134ed
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f5760a2382d40169a691c961d4f9104
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 770acbaed70db4ad696458511aa3f084
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44d13df04220413aa6b3f8ee1597a610
|
||||
timeCreated: 1691556962
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a6f656ab8114e939b71b289ffd9d7b2
|
||||
timeCreated: 1585524905
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c77db07224d9f784d90d7eb0e84c57f7
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 684a64ee80b8473d90aefdbfeb94e75c
|
||||
timeCreated: 1720713507
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 576f949be0794f548b825c9ce6f556db
|
||||
timeCreated: 1720322907
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c9bd0da26084915818a1687ef924322
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cca7768aaaea4b0081f14e7f9d4b5ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55858e4cd94d48b0a267735f29dd1e5e
|
||||
timeCreated: 1691384044
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 130791d3e20646d2b6d81688877b0909
|
||||
timeCreated: 1585531463
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f968e7540d632cc40b5ca8b340a3e718
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86e5004805d440718ff05f937654caf4
|
||||
timeCreated: 1697581791
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edb250ac097f481fa89c38a1e224b773
|
||||
timeCreated: 1697581791
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d00436b1cf7a4c7c8cb42e8f0bc826c9
|
||||
timeCreated: 1697581791
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bf7a6fd37ee46709aa013efc3270aba
|
||||
timeCreated: 1697581791
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b2177cf82af36949b9a8d210c2b4962
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 533b7b273fd64cd88d55213ba3af51a3
|
||||
timeCreated: 1668359087
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e05a9f4f2755f3941a86a256f16c0d82
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6eb928abe872c4fd5a7acead14922715
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e4419296dd04b32bcc48a56ac645aa9
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
This folder is used only in Unity 2021 or older.
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 657891af2ead49a2b9cbfd069f5cead2
|
||||
timeCreated: 1701333515
|
||||
Reference in New Issue
Block a user