From 357c8a0172f31f75d1d228e042c890b457de1da2 Mon Sep 17 00:00:00 2001 From: Bronson Zgeb Date: Mon, 1 Mar 2021 21:51:28 -0500 Subject: [PATCH] Trying a screenspace metaball-like rendering technique --- .../Metaballs/Materials/RenderMetaballRT.mat | 2 +- .../RenderMetaballsScreenSpace.cs | 201 ++++++++++++++++++ .../RenderMetaballsScreenSpace.cs.meta | 11 + Assets/Metaballs/Shaders/KawaseBlur.shader | 29 ++- .../Settings/CustomForwardRendererData.asset | 85 ++++---- 5 files changed, 275 insertions(+), 53 deletions(-) create mode 100644 Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs create mode 100644 Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs.meta diff --git a/Assets/Metaballs/Materials/RenderMetaballRT.mat b/Assets/Metaballs/Materials/RenderMetaballRT.mat index ca310a7..c378428 100644 --- a/Assets/Metaballs/Materials/RenderMetaballRT.mat +++ b/Assets/Metaballs/Materials/RenderMetaballRT.mat @@ -96,7 +96,7 @@ Material: - _ClearCoatMask: 0 - _ClearCoatSmoothness: 0 - _Cull: 2 - - _Cutoff: 0.65 + - _Cutoff: 0.71 - _DetailAlbedoMapScale: 1 - _DetailNormalMapScale: 1 - _DstBlend: 10 diff --git a/Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs b/Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs new file mode 100644 index 0000000..7023435 --- /dev/null +++ b/Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs @@ -0,0 +1,201 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Experimental.Rendering.Universal; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +public class RenderMetaballsScreenSpace : ScriptableRendererFeature +{ + class RenderMetaballsScreenSpacePass : ScriptableRenderPass + { + const string MetaballRTId = "_MetaballRT"; + const string MetaballRT2Id = "_MetaballRT2"; + + int _metaballRTId; + int _metaballRT2Id; + + public Material BlitMaterial; + public Material BlurMaterial; + public Material BlitCopyDepthMaterial; + + RenderTargetIdentifier _metaballRT; + RenderTargetIdentifier _metaballRT2; + RenderTargetIdentifier _cameraTargetId; + RenderTargetIdentifier _cameraDepthTargetId; + + RenderQueueType renderQueueType; + FilteringSettings m_FilteringSettings; + RenderObjects.CustomCameraSettings m_CameraSettings; + ProfilingSampler m_ProfilingSampler; + + public Material overrideMaterial { get; set; } + public int overrideMaterialPassIndex { get; set; } + + List m_ShaderTagIdList = new List(); + + RenderStateBlock m_RenderStateBlock; + + public RenderMetaballsScreenSpacePass(string profilerTag, RenderPassEvent renderPassEvent, string[] shaderTags, + RenderQueueType renderQueueType, int layerMask, RenderObjects.CustomCameraSettings cameraSettings) + { + profilingSampler = new ProfilingSampler(nameof(RenderObjectsPass)); + + m_ProfilingSampler = new ProfilingSampler(profilerTag); + this.renderPassEvent = renderPassEvent; + this.renderQueueType = renderQueueType; + this.overrideMaterial = null; + this.overrideMaterialPassIndex = 0; + RenderQueueRange renderQueueRange = (renderQueueType == RenderQueueType.Transparent) + ? RenderQueueRange.transparent + : RenderQueueRange.opaque; + m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask); + + if (shaderTags != null && shaderTags.Length > 0) + { + foreach (var passName in shaderTags) + m_ShaderTagIdList.Add(new ShaderTagId(passName)); + } + else + { + m_ShaderTagIdList.Add(new ShaderTagId("SRPDefaultUnlit")); + m_ShaderTagIdList.Add(new ShaderTagId("UniversalForward")); + m_ShaderTagIdList.Add(new ShaderTagId("UniversalForwardOnly")); + m_ShaderTagIdList.Add(new ShaderTagId("LightweightForward")); + } + + m_RenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing); + m_CameraSettings = cameraSettings; + + BlitCopyDepthMaterial = new Material(Shader.Find("Hidden/BlitToDepth")); + BlurMaterial = new Material(Shader.Find("Hidden/KawaseBlur")); + } + + // This method is called before executing the render pass. + // It can be used to configure render targets and their clear state. Also to create temporary render target textures. + // When empty this render pass will render to the active camera render target. + // You should never call CommandBuffer.SetRenderTarget. Instead call ConfigureTarget and ConfigureClear. + // The render pipeline will ensure target setup and clearing happens in a performant manner. + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + RenderTextureDescriptor blitTargetDescriptor = renderingData.cameraData.cameraTargetDescriptor; + blitTargetDescriptor.colorFormat = RenderTextureFormat.ARGB32; + + var renderer = renderingData.cameraData.renderer; + + _metaballRTId = Shader.PropertyToID(MetaballRTId); + _metaballRT2Id = Shader.PropertyToID(MetaballRT2Id); + + cmd.GetTemporaryRT(_metaballRTId, blitTargetDescriptor, FilterMode.Bilinear); + cmd.GetTemporaryRT(_metaballRT2Id, blitTargetDescriptor, FilterMode.Bilinear); + + _metaballRT = new RenderTargetIdentifier(_metaballRTId); + _metaballRT2 = new RenderTargetIdentifier(_metaballRT2Id); + + ConfigureTarget(_metaballRT); + + _cameraTargetId = renderer.cameraColorTarget; + _cameraDepthTargetId = new RenderTargetIdentifier("_CameraDepthTexture"); // renderer.cameraDepthTarget; + } + + // Here you can implement the rendering logic. + // Use ScriptableRenderContext to issue drawing commands or execute command buffers + // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html + // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline. + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + SortingCriteria sortingCriteria = (renderQueueType == RenderQueueType.Transparent) + ? SortingCriteria.CommonTransparent + : renderingData.cameraData.defaultOpaqueSortFlags; + + DrawingSettings drawingSettings = + CreateDrawingSettings(m_ShaderTagIdList, ref renderingData, sortingCriteria); + drawingSettings.overrideMaterial = overrideMaterial; + drawingSettings.overrideMaterialPassIndex = overrideMaterialPassIndex; + + ref CameraData cameraData = ref renderingData.cameraData; + + // NOTE: Do NOT mix ProfilingScope with named CommandBuffers i.e. CommandBufferPool.Get("name"). + // Currently there's an issue which results in mismatched markers. + CommandBuffer cmd = CommandBufferPool.Get(); + using (new ProfilingScope(cmd, m_ProfilingSampler)) + { + //Clear small RT + cmd.ClearRenderTarget(true, true, new Color(0, 0, 0, 0)); + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + //Blit Camera Depth Texture + Blit(cmd, _cameraDepthTargetId, _metaballRT, BlitCopyDepthMaterial); + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + //Draw to RT + context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref m_FilteringSettings, + ref m_RenderStateBlock); + + if (m_CameraSettings.overrideCamera && m_CameraSettings.restoreCamera) + { + RenderingUtils.SetViewAndProjectionMatrices(cmd, cameraData.GetViewMatrix(), + cameraData.GetGPUProjectionMatrix(), false); + } + + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + //Blur + cmd.SetGlobalVector("_Offsets", new Vector4(1.5f, 2.0f, 2.5f, 3.0f)); + Blit(cmd, _metaballRT, _metaballRT2, BlurMaterial); + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + Blit(cmd, _metaballRT2, _metaballRT, BlurMaterial); + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + Blit(cmd, _metaballRT, _metaballRT2, BlurMaterial); + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + Blit(cmd, _metaballRT2, _metaballRT, BlurMaterial); + context.ExecuteCommandBuffer(cmd); + cmd.Clear(); + + //Draw to Camera Target + Blit(cmd, _metaballRT, _cameraTargetId, BlitMaterial); + } + + context.ExecuteCommandBuffer(cmd); + CommandBufferPool.Release(cmd); + } + + // Cleanup any allocated resources that were created during the execution of this render pass. + public override void OnCameraCleanup(CommandBuffer cmd) + { + cmd.ReleaseTemporaryRT(_metaballRTId); + cmd.ReleaseTemporaryRT(_metaballRT2Id); + } + } + + public Material blitMaterial; + RenderMetaballsScreenSpacePass _scriptableMetaballsScreenSpacePass; + public RenderObjects.RenderObjectsSettings renderObjectsSettings = new RenderObjects.RenderObjectsSettings(); + + /// + public override void Create() + { + RenderObjects.FilterSettings filter = renderObjectsSettings.filterSettings; + _scriptableMetaballsScreenSpacePass = new RenderMetaballsScreenSpacePass(renderObjectsSettings.passTag, + renderObjectsSettings.Event, + filter.PassNames, filter.RenderQueueType, filter.LayerMask, renderObjectsSettings.cameraSettings) + { + BlitMaterial = blitMaterial + }; + } + + // Here you can inject one or multiple render passes in the renderer. + // This method is called when setting up the renderer once per-camera. + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + renderer.EnqueuePass(_scriptableMetaballsScreenSpacePass); + } +} \ No newline at end of file diff --git a/Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs.meta b/Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs.meta new file mode 100644 index 0000000..aceb6c4 --- /dev/null +++ b/Assets/Metaballs/RendererFeatures/RenderMetaballsScreenSpace.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 99924fc21a1264e4898a2a384f5b1183 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Metaballs/Shaders/KawaseBlur.shader b/Assets/Metaballs/Shaders/KawaseBlur.shader index 166cd25..4b061ba 100644 --- a/Assets/Metaballs/Shaders/KawaseBlur.shader +++ b/Assets/Metaballs/Shaders/KawaseBlur.shader @@ -48,10 +48,10 @@ Shader "Hidden/KawaseBlur" { fixed4 result = color; - result += tex2D(_MainTex, uv + half2( offset, offset) * texelResolution); - result += tex2D(_MainTex, uv + half2( offset, -offset) * texelResolution); - result += tex2D(_MainTex, uv + half2(-offset, offset) * texelResolution); - result += tex2D(_MainTex, uv + half2(-offset, -offset) * texelResolution); + result += tex2D(_MainTex, uv + half2( offset + 0.5, offset + 0.5) * texelResolution); + result += tex2D(_MainTex, uv + half2(-offset - 0.5, offset + 0.5) * texelResolution); + result += tex2D(_MainTex, uv + half2(-offset - 0.5, -offset - 0.5) * texelResolution); + result += tex2D(_MainTex, uv + half2( offset + 0.5, -offset - 0.5) * texelResolution); result /= 5.0h; return result; @@ -76,11 +76,22 @@ Shader "Hidden/KawaseBlur" const half2 uv = input.uv; fixed4 color = tex2D(_MainTex, uv); - color = applyBlur(color, uv, texelResolution, _Offsets.x); - color = applyBlur(color, uv, texelResolution, _Offsets.y); - color.a = applyAlphaBlur(color, uv, texelResolution, _Offsets.z); - //color.a = applyAlphaBlur(color, uv, texelResolution, _Offsets.w); - + color = applyBlur(color, uv, texelResolution, 1); + color = applyBlur(color, uv, texelResolution, 2); + //color = applyBlur(color, uv, texelResolution, 2); + //color = applyBlur(color, uv, texelResolution, 2); + //color = applyBlur(color, uv, texelResolution, 3); + //color = applyBlur(color, uv, texelResolution, 2); + //color = applyBlur(color, uv, texelResolution, 3); + + /* + color = applyBlur(color, uv, texelResolution, _Offsets.x + _Offsets.w); + color = applyBlur(color, uv, texelResolution, _Offsets.y + _Offsets.w); + color = applyBlur(color, uv, texelResolution, _Offsets.z + _Offsets.w); + color = applyBlur(color, uv, texelResolution, _Offsets.w + _Offsets.w); + */ + + //color = saturate(smoothstep(0, 0.4, color)); return color; } ENDCG diff --git a/Assets/Settings/CustomForwardRendererData.asset b/Assets/Settings/CustomForwardRendererData.asset index 497e076..cd0ebba 100644 --- a/Assets/Settings/CustomForwardRendererData.asset +++ b/Assets/Settings/CustomForwardRendererData.asset @@ -39,47 +39,6 @@ MonoBehaviour: restoreCamera: 1 offset: {x: 0, y: 0, z: 0, w: 0} cameraFieldOfView: 60 ---- !u!114 &-1912216177461967393 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: df2b5599ec606184aa283db49989a228, type: 3} - m_Name: RenderMetaballs - m_EditorClassIdentifier: - m_Active: 1 - blitMaterial: {fileID: 2100000, guid: ba62d2f9845041e498edc0cfd32a8813, type: 2} - renderObjectsSettings: - passTag: RenderMetaballs - Event: 400 - filterSettings: - RenderQueueType: 1 - LayerMask: - serializedVersion: 2 - m_Bits: 80 - PassNames: [] - overrideMaterial: {fileID: 0} - overrideMaterialPassIndex: 0 - overrideDepthState: 0 - depthCompareFunction: 4 - enableWrite: 1 - stencilSettings: - overrideStencilState: 0 - stencilReference: 0 - stencilCompareFunction: 8 - passOperation: 0 - failOperation: 0 - zFailOperation: 0 - cameraSettings: - overrideCamera: 0 - restoreCamera: 1 - offset: {x: 0, y: 0, z: 0, w: 0} - cameraFieldOfView: 60 - downsamplingAmount: 1 --- !u!114 &11400000 MonoBehaviour: m_ObjectHideFlags: 0 @@ -94,8 +53,8 @@ MonoBehaviour: m_EditorClassIdentifier: m_RendererFeatures: - {fileID: -6361803208588800877} - - {fileID: -1912216177461967393} - m_RendererFeatureMap: 93cc1f25b055b6a7dfc59f98847176e5 + - {fileID: 7112055495327021477} + m_RendererFeatureMap: 93cc1f25b055b6a7a5f9d4adca18b362 postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} xrSystemData: {fileID: 11400000, guid: 60e1133243b97e347b653163a8c01b64, type: 2} shaders: @@ -124,3 +83,43 @@ MonoBehaviour: m_ShadowTransparentReceive: 1 m_RenderingMode: 0 m_AccurateGbufferNormals: 0 +--- !u!114 &7112055495327021477 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 99924fc21a1264e4898a2a384f5b1183, type: 3} + m_Name: RenderMetaballsScreenSpace + m_EditorClassIdentifier: + m_Active: 1 + blitMaterial: {fileID: 2100000, guid: ba62d2f9845041e498edc0cfd32a8813, type: 2} + renderObjectsSettings: + passTag: RenderMetaballsScreenSpace + Event: 400 + filterSettings: + RenderQueueType: 0 + LayerMask: + serializedVersion: 2 + m_Bits: 16 + PassNames: [] + overrideMaterial: {fileID: 0} + overrideMaterialPassIndex: 0 + overrideDepthState: 0 + depthCompareFunction: 4 + enableWrite: 1 + stencilSettings: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 0 + failOperation: 0 + zFailOperation: 0 + cameraSettings: + overrideCamera: 0 + restoreCamera: 1 + offset: {x: 0, y: 0, z: 0, w: 0} + cameraFieldOfView: 60