Skip to content

Commit

Permalink
fix: ShaderGraph is not working correctly (#191)
Browse files Browse the repository at this point in the history
The renderer feature `SoftMaskable ShaderGraph Support (Editor)` is required in the editor.
![](https://github.com/user-attachments/assets/43dd860d-11dc-4fb5-9cf8-619019a378eb)

:warning: Currently, the soft-maskable ShaderGraph does not display correctly in the SceneView.
  • Loading branch information
mob-sakai committed Sep 12, 2024
1 parent c5062fa commit 82c38dd
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 25 deletions.
13 changes: 9 additions & 4 deletions Packages/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,17 +382,22 @@ Here, let's make [UI/Additive](https://raw.githubusercontent.com/mob-sakai/SoftM
### Usage with ShaderGraph
NOTE: Unity 2023.2/600.0+ is required.
NOTE: Unity 2023.2/6000.0+ is required.
1. Open the `Package Manager` window and select the `UI Soft Mask` package in the package list and click the `ShaderGraph Support > Import` button.
2. The sample includes `UIDefault (SoftMaskable).shadergraph` and `SoftMask.subshadergraph`.
You can use the sample as references to make your own shader graph compatible with SoftMask.
You can use the sample as references to make your own shader graph compatible with `SoftMask`.
1. Add `(SoftMaskable)` at the end of the shader name.
2. Add `SOFTMASK_EDITOR` as a `Boolean Keyword (Shader Feature)`.
3. Add the `Sub Graphs > SoftMask` node and connect it to the final alpha output.
3. Add the `Sub Graphs > SoftMask` node and connect it to the final alpha output.
![](https://github.com/user-attachments/assets/8da64af8-a4e2-4477-a253-c45fe11d3eec)
![](https://github.com/user-attachments/assets/8da64af8-a4e2-4477-a253-c45fe11d3eec)
3. To use the soft-maskable ShaderGraph in the editor, the `SoftMaskable ShaderGraph Support (Editor)` renderer feature is required.
This feature is specifically for previewing SoftMaskable ShaderGraph in the editor and will be automatically removed during the build process.
![SoftMaskable ShaderGraph Support](https://github.com/user-attachments/assets/43dd860d-11dc-4fb5-9cf8-619019a378eb)
⚠️ Currently, the soft-maskable ShaderGraph does not display correctly in the SceneView.
<br><br>
Expand Down
9 changes: 8 additions & 1 deletion Packages/src/Runtime/Coffee.SoftMaskForUGUI.asmdef
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"name": "Coffee.SoftMaskForUGUI",
"references": [
"Unity.TextMeshPro"
"Unity.TextMeshPro",
"Unity.RenderPipelines.Universal.Runtime",
"Unity.RenderPipelines.Core.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
Expand All @@ -20,6 +22,11 @@
"name": "com.unity.ugui",
"expression": "2.0.0",
"define": "TMP_ENABLE"
},
{
"name": "com.unity.render-pipelines.universal",
"expression": "16",
"define": "SHADERGRAPH_ENABLE"
}
]
}
9 changes: 5 additions & 4 deletions Packages/src/Runtime/SoftMask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.UI;
using Internal = Coffee.UISoftMaskInternal;

namespace Coffee.UISoftMask
{
Expand Down Expand Up @@ -106,7 +107,7 @@ public enum MaskingMode
internal RenderTexture _softMaskBuffer;
private UnityAction _updateParentSoftMask;
private CanvasViewChangeTrigger _viewChangeTrigger;
private List<SoftMask> children => _children != null ? _children : _children = ListPool<SoftMask>.Rent();
private List<SoftMask> children => _children != null ? _children : _children = Internal.ListPool<SoftMask>.Rent();

/// <summary>
/// Masking mode.<br />
Expand Down Expand Up @@ -357,7 +358,7 @@ protected override void OnDisable()

protected override void OnDestroy()
{
ListPool<SoftMask>.Return(ref _children);
Internal.ListPool<SoftMask>.Return(ref _children);
_onBeforeCanvasRebuild = null;
_renderSoftMaskBuffer = null;
_setSoftMaskDirty = null;
Expand Down Expand Up @@ -416,7 +417,7 @@ protected override void OnValidate()
graphic.SetVerticesDirty();
}

var list = ListPool<IMaskable>.Rent();
var list = Internal.ListPool<IMaskable>.Rent();
GetComponents(list);
for (var i = 0; i < list.Count; i++)
{
Expand All @@ -425,7 +426,7 @@ protected override void OnValidate()
list[i].RecalculateMasking();
}

ListPool<IMaskable>.Return(ref list);
Internal.ListPool<IMaskable>.Return(ref list);
}
#endif

Expand Down
88 changes: 88 additions & 0 deletions Packages/src/Runtime/SoftMaskableShaderGraphSupportFeature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#if SHADERGRAPH_ENABLE
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;

namespace Coffee.UISoftMask
{
[HelpURL("https://github.com/mob-sakai/SoftMaskForUGUI")]
[DisallowMultipleRendererFeature("SoftMaskable ShaderGraph Support (Editor)")]
[Tooltip("Enable SoftMaskable ShaderGraph support in the editor. This will not affect runtime behavior.")]
public class SoftMaskableShaderGraphSupportFeature : ScriptableRendererFeature
{
#if UNITY_EDITOR
private class Pass : ScriptableRenderPass
{
private static readonly int s_SoftMaskInGameView = Shader.PropertyToID("_SoftMaskInGameView");
private static readonly int s_SoftMaskInSceneView = Shader.PropertyToID("_SoftMaskInSceneView");

private class Data
{
public bool isGameView;
}

public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
using (var builder = renderGraph.AddRasterRenderPass<Data>("SoftMaskableShaderGraphSupport", out var d))
{
var cam = frameData.Get<UniversalCameraData>();
d.isGameView = cam.cameraType == CameraType.Game;
builder.AllowPassCulling(false);
builder.AllowGlobalStateModification(true);
builder.SetRenderFunc<Data>((x, context) =>
{
context.cmd.SetGlobalInt(s_SoftMaskInGameView, x.isGameView ? 1 : 0);
context.cmd.SetGlobalInt(s_SoftMaskInSceneView, !x.isGameView ? 1 : 0);
});
}
}

[Obsolete(
"This rendering path is for compatibility mode only (when Render Graph is disabled). Use Render Graph API instead.",
false)]
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
var isGameView = renderingData.cameraData.cameraType == CameraType.Game;
cmd.SetGlobalInt(s_SoftMaskInGameView, isGameView ? 1 : 0);
cmd.SetGlobalInt(s_SoftMaskInSceneView, !isGameView ? 1 : 0);
}

[Obsolete(
"This rendering path is for compatibility mode only (when Render Graph is disabled). Use Render Graph API instead.",
false)]
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
}

public override void OnCameraCleanup(CommandBuffer cmd)
{
cmd.SetGlobalInt(s_SoftMaskInGameView, 0);
cmd.SetGlobalInt(s_SoftMaskInSceneView, 0);
}
}

private Pass _pass;

public override void Create()
{
_pass = new Pass();
}

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(_pass);
}
#else
public override void Create()
{
}

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
}
#endif
}
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 7 additions & 6 deletions Packages/src/Runtime/Utilities/SoftMaskUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#if TMP_ENABLE
using TMPro;
#endif
using Internal = Coffee.UISoftMaskInternal;

namespace Coffee.UISoftMask
{
Expand All @@ -19,17 +20,17 @@ internal static class SoftMaskUtils
/// <summary>
/// Object pool for CommandBuffer instances.
/// </summary>
public static readonly ObjectPool<CommandBuffer> commandBufferPool =
new ObjectPool<CommandBuffer>(
public static readonly Internal.ObjectPool<CommandBuffer> commandBufferPool =
new Internal.ObjectPool<CommandBuffer>(
() => new CommandBuffer(),
x => x != null,
x => x.Clear());

/// <summary>
/// Object pool for MaterialPropertyBlock instances.
/// </summary>
public static readonly ObjectPool<MaterialPropertyBlock> materialPropertyBlockPool =
new ObjectPool<MaterialPropertyBlock>(
public static readonly Internal.ObjectPool<MaterialPropertyBlock> materialPropertyBlockPool =
new Internal.ObjectPool<MaterialPropertyBlock>(
() => new MaterialPropertyBlock(),
x => x != null,
x => x.Clear());
Expand Down Expand Up @@ -88,7 +89,7 @@ private static void InitializeOnLoadMethod()
#if TMP_ENABLE
private static void UpdateSubMeshUI(TextMeshProUGUI text, bool show, float aa, MinMax01 softness)
{
var subMeshes = ListPool<TMP_SubMeshUI>.Rent();
var subMeshes = Internal.ListPool<TMP_SubMeshUI>.Rent();
text.GetComponentsInChildren(subMeshes, 1);

for (var i = 0; i < subMeshes.Count; i++)
Expand All @@ -100,7 +101,7 @@ private static void UpdateSubMeshUI(TextMeshProUGUI text, bool show, float aa, M
maskingShape.showMaskGraphic = show;
}

ListPool<TMP_SubMeshUI>.Return(ref subMeshes);
Internal.ListPool<TMP_SubMeshUI>.Return(ref subMeshes);
}
#endif

Expand Down
41 changes: 31 additions & 10 deletions Packages/src/Shaders/SoftMask.cginc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ uniform float4x4 _GameVP;
uniform float4x4 _GameTVP;
uniform float4x4 _GameVP_2;
uniform float4x4 _GameTVP_2;
uniform int _SoftMaskInGameView;
uniform int _SoftMaskInSceneView;

float Approximately(float4x4 a, float4x4 b)
{
Expand Down Expand Up @@ -39,14 +41,9 @@ float2 WorldToUv(float4 worldPos, float offset)
isSceneView);
}

float2 ClipToUv(const float2 clipPos)
float2 ScreenToUv(const float2 screenPos)
{
half2 uv = clipPos.xy / _ScreenParams.xy;
#if UNITY_UV_STARTS_AT_TOP
if (0 <= _ProjectionParams.x)
uv.y = 1 - uv.y;
#endif

half2 uv = screenPos;
#if UNITY_PRETRANSFORM_TO_DISPLAY_ORIENTATION
float ratio = _ScreenParams.x / _ScreenParams.y;
switch (UNITY_DISPLAY_ORIENTATION_PRETRANSFORM)
Expand All @@ -63,6 +60,16 @@ float2 ClipToUv(const float2 clipPos)
return uv;
}

float2 ClipToUv(const float2 clipPos)
{
half2 screenPos = clipPos / _ScreenParams.xy;
#if UNITY_UV_STARTS_AT_TOP
if (0 <= _ProjectionParams.x)
screenPos.y = 1 - screenPos.y;
#endif
return ScreenToUv(screenPos);
}

float SoftMaskSample(float2 uv, float a)
{
if (_SoftMaskableEnable == 0)
Expand All @@ -82,7 +89,10 @@ float SoftMaskSample(float2 uv, float a)
#if SOFTMASK_EDITOR
int inScreen = step(0, uv.x) * step(uv.x, 1) * step(0, uv.y) * step(uv.y, 1);
alpha = lerp(_SoftMaskOutsideColor, alpha, inScreen);
clip (a * alpha.x * alpha.y * alpha.z * alpha.w - _AlphaClipThreshold - 0.001);
if (inScreen == 0)
{
clip (a * alpha.x * alpha.y * alpha.z * alpha.w - _AlphaClipThreshold - 0.001);
}
#endif

return alpha.x * alpha.y * alpha.z * alpha.w;
Expand All @@ -91,9 +101,20 @@ float SoftMaskSample(float2 uv, float a)
void SoftMaskForGraph_float(float4 ScreenPos, float4 WorldPos, float InAlpha, out float A)
{
#if SOFTMASK_EDITOR
A = SoftMaskSample(WorldToUv(WorldPos, 0), InAlpha) * InAlpha;
if (_SoftMaskInGameView == 1)
{
A = SoftMaskSample(ScreenToUv(ScreenPos.xy), 1) * InAlpha;
}
else if (_SoftMaskInSceneView == 1)
{
A = InAlpha;
}
else
{
A = SoftMaskSample(WorldToUv(WorldPos, 0.5), InAlpha) * InAlpha;
}
#else
A = SoftMaskSample(ScreenPos.xy, 1) * InAlpha;
A = SoftMaskSample(ScreenToUv(ScreenPos.xy), 1) * InAlpha;
#endif
}

Expand Down

0 comments on commit 82c38dd

Please sign in to comment.