diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer.meta b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer.meta new file mode 100644 index 00000000..539ce0b0 --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 219c802523cf3724cb4a3378dc5891f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.cs b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.cs new file mode 100644 index 00000000..30f0431c --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.cs @@ -0,0 +1,146 @@ +using UnityEngine; + +namespace TEngine +{ + public class UIGaussianBlurLayer : MonoBehaviour + { + public UnityEngine.UI.RawImage rawImage; + public Shader shader; + + [Range(0, 6), Tooltip("[降采样次数]向下采样的次数。此值越大,则采样间隔越大,需要处理的像素点越少,运行速度越快。")] + public int DownSampleNum = 2; + + [Range(0.0f, 20.0f), Tooltip("[模糊扩散度]进行高斯模糊时,相邻像素点的间隔。此值越大相邻像素间隔越远,图像越模糊。但过大的值会导致失真。")] + public float BlurSpreadSize = 3.0f; + + [Range(0, 8), Tooltip("[迭代次数]此值越大,则模糊操作的迭代次数越多,模糊效果越好,但消耗越大。")] + public int BlurIterations = 3; + + private Camera m_camera; + private RenderTexture m_renderTexture; + private Material m_material; + private string m_shaderName = "UI/UIGaussianBlurLayer"; + private Color m_color; + public float targetAlpha = 1f; + private static readonly int DownSampleValue = Shader.PropertyToID("_DownSampleValue"); + + #region MaterialGetAndSet + + Material material + { + get + { + if (m_material == null) + { + m_material = new Material(shader); + m_material.hideFlags = HideFlags.HideAndDontSave; + } + + return m_material; + } + } + + #endregion + + void Start() + { + m_camera = GetComponent(); + if (shader == null) + { + shader = Shader.Find(m_shaderName); + if (shader == null) + { + var dodShader = new TShader(m_shaderName); + if (dodShader.Shader != null) + { + shader = dodShader.Shader; + } + } + } + + m_color = rawImage.color; + m_color.a = 1f; + } + + private void Cleanup() + { + if (m_material) + { + Object.DestroyImmediate(m_material); + } + + if (rawImage.texture) + { + RenderTexture.ReleaseTemporary(m_renderTexture); + } + } + + private void OnEnable() + { + Cleanup(); + } + + private void OnDestroy() + { + Cleanup(); + } + + void OnRenderImage(RenderTexture src, RenderTexture dest) + { + Graphics.Blit(src, dest); + + if (!gameObject.activeInHierarchy && enabled) + { + return; + } + + if (!m_camera || !shader || m_renderTexture != null) + { + return; + } + + float widthMod = 1.0f / (1.0f * (1 << DownSampleNum)); + material.SetFloat(DownSampleValue, BlurSpreadSize * widthMod); + + int renderWidth = src.width >> DownSampleNum; + int renderHeight = src.height >> DownSampleNum; + m_renderTexture = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.RGB111110Float); + m_renderTexture.filterMode = FilterMode.Bilinear; + + Graphics.Blit(src, m_renderTexture, material, 0); + for (int i = 0; i < BlurIterations; i++) + { + //【2.1】Shader参数赋值 + //迭代偏移量参数 + float iterationOffs = (i * 1.0f); + //Shader的降采样参数赋值 + material.SetFloat(DownSampleValue, BlurSpreadSize * widthMod + iterationOffs); + // 【2.2】处理Shader的通道1,垂直方向模糊处理 || Pass1,for vertical blur + // 定义一个临时渲染的缓存tempBuffer + RenderTexture tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.RGB111110Float); + // 拷贝rawTexture中的渲染数据到tempBuffer,并仅绘制指定的pass1的纹理数据 + Graphics.Blit(m_renderTexture, tempBuffer, material, 1); + // 清空rawTexture + RenderTexture.ReleaseTemporary(m_renderTexture); + // 将tempBuffer赋给rawTexture,此时rawTexture里面pass0和pass1的数据已经准备好 + m_renderTexture = tempBuffer; + // 【2.3】处理Shader的通道2,竖直方向模糊处理 || Pass2,for horizontal blur + // 获取临时渲染纹理 + tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, RenderTextureFormat.RGB111110Float); + // 拷贝rawTexture中的渲染数据到tempBuffer,并仅绘制指定的pass2的纹理数据 + Graphics.Blit(m_renderTexture, tempBuffer, m_material, 2); + //【2.4】得到pass0、pass1和pass2的数据都已经准备好的rawTexture + // 再次清空rawTexture + RenderTexture.ReleaseTemporary(m_renderTexture); + // 再次将tempBuffer赋给rawTexture,此时rawTexture里面pass0、pass1和pass2的数据都已经准备好 + m_renderTexture = tempBuffer; + } + + rawImage.texture = m_renderTexture; + m_color.a = targetAlpha; + rawImage.color = m_color; + m_camera.enabled = false; + enabled = false; + } + } +} \ No newline at end of file diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.cs.meta b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.cs.meta new file mode 100644 index 00000000..8eeed68f --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f73c619aa2af18b43979f277d4a5f3e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.meta b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.meta new file mode 100644 index 00000000..2caded69 --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: edca5284c2a8d944d98cf1d46fe081ec +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.prefab b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.prefab new file mode 100644 index 00000000..811de18a --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.prefab @@ -0,0 +1,184 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1562184453692040 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224238891325741678} + - component: {fileID: 20169205874799070} + - component: {fileID: 124765018147328134} + - component: {fileID: 626956972312568253} + m_Layer: 5 + m_Name: UIGaussianBlurLayer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224238891325741678 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562184453692040} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 224810591013113534} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!20 &20169205874799070 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562184453692040} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 3 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1 + field of view: 60 + orthographic: 1 + orthographic size: 1 + m_Depth: 20 + m_CullingMask: + serializedVersion: 2 + m_Bits: 0 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 0 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 0 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!124 &124765018147328134 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562184453692040} + m_Enabled: 0 +--- !u!114 &626956972312568253 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1562184453692040} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f73c619aa2af18b43979f277d4a5f3e6, type: 3} + m_Name: + m_EditorClassIdentifier: + rawImage: {fileID: 114153017290501506} + shader: {fileID: 0} + DownSampleNum: 2 + BlurSpreadSize: 3 + BlurIterations: 3 + targetAlpha: 1 +--- !u!1 &1918405838007012 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224810591013113534} + - component: {fileID: 222383555938289358} + - component: {fileID: 114153017290501506} + m_Layer: 5 + m_Name: RawImage + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224810591013113534 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918405838007012} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 224238891325741678} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &222383555938289358 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918405838007012} + m_CullTransparentMesh: 1 +--- !u!114 &114153017290501506 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1918405838007012} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Texture: {fileID: 0} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.prefab.meta b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.prefab.meta new file mode 100644 index 00000000..2bd04dc1 --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 092bddb143051974e8d8ffcc72f3f36a +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer/UIGaussianBlurLayer.shader b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer/UIGaussianBlurLayer.shader new file mode 100644 index 00000000..1ffa4449 --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer/UIGaussianBlurLayer.shader @@ -0,0 +1,232 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "UI/UIGaussianBlurLayer" +{ + //-----------------------------------【属性 || Properties】------------------------------------------ + Properties + { + //主纹理 + _MainTex("Base (RGB)", 2D) = "white" {} + } + + //----------------------------------【子着色器 || SubShader】--------------------------------------- + SubShader + { + ZWrite Off + Blend Off + + //---------------------------------------【通道0 || Pass 0】------------------------------------ + //通道0:降采样通道 ||Pass 0: Down Sample Pass + Pass + { + ZTest Off + Cull Off + + CGPROGRAM + + //指定此通道的顶点着色器为vert_DownSmpl + #pragma vertex vert_DownSmpl + //指定此通道的像素着色器为frag_DownSmpl + #pragma fragment frag_DownSmpl + + ENDCG + } + + //---------------------------------------【通道1 || Pass 1】------------------------------------ + //通道1:垂直方向模糊处理通道 ||Pass 1: Vertical Pass + Pass + { + ZTest Always + Cull Off + + CGPROGRAM + + //指定此通道的顶点着色器为vert_BlurVertical + #pragma vertex vert_BlurVertical + //指定此通道的像素着色器为frag_Blur + #pragma fragment frag_Blur + + ENDCG + } + + //---------------------------------------【通道2 || Pass 2】------------------------------------ + //通道2:水平方向模糊处理通道 ||Pass 2: Horizontal Pass + Pass + { + ZTest Always + Cull Off + + CGPROGRAM + + //指定此通道的顶点着色器为vert_BlurHorizontal + #pragma vertex vert_BlurHorizontal + //指定此通道的像素着色器为frag_Blur + #pragma fragment frag_Blur + + ENDCG + } + } + + //-------------------------CG着色语言声明部分 || Begin CG Include Part---------------------- + CGINCLUDE + + //【1】头文件包含 || include + #include "UnityCG.cginc" + + //【2】变量声明 || Variable Declaration + sampler2D _MainTex; + //UnityCG.cginc中内置的变量,纹理中的单像素尺寸|| it is the size of a texel of the texture + uniform half4 _MainTex_TexelSize; + //C#脚本控制的变量 || Parameter + uniform half _DownSampleValue; + + //【3】顶点输入结构体 || Vertex Input Struct + struct VertexInput + { + //顶点位置坐标 + float4 vertex : POSITION; + //一级纹理坐标 + half2 texcoord : TEXCOORD0; + }; + + //【4】降采样输出结构体 || Vertex Input Struct + struct VertexOutput_DownSmpl + { + //像素位置坐标 + float4 pos : SV_POSITION; + //一级纹理坐标(右上) + half2 uv20 : TEXCOORD0; + //二级纹理坐标(左下) + half2 uv21 : TEXCOORD1; + //三级纹理坐标(右下) + half2 uv22 : TEXCOORD2; + //四级纹理坐标(左上) + half2 uv23 : TEXCOORD3; + }; + + //【5】准备高斯模糊权重矩阵参数7x4的矩阵 || Gauss Weight + static const half4 GaussWeight[7] = + { + half4(0.0205,0.0205,0.0205,0), + half4(0.0855,0.0855,0.0855,0), + half4(0.232,0.232,0.232,0), + half4(0.324,0.324,0.324,1), + half4(0.232,0.232,0.232,0), + half4(0.0855,0.0855,0.0855,0), + half4(0.0205,0.0205,0.0205,0) + }; + + //【6】顶点着色函数 || Vertex Shader Function + VertexOutput_DownSmpl vert_DownSmpl(VertexInput v) + { + //【6.1】实例化一个降采样输出结构 + VertexOutput_DownSmpl o; + + //【6.2】填充输出结构 + //将三维空间中的坐标投影到二维窗口 + o.pos = UnityObjectToClipPos(v.vertex); + //对图像的降采样:取像素上下左右周围的点,分别存于四级纹理坐标中 + o.uv20 = v.texcoord + _MainTex_TexelSize.xy* half2(0.5h, 0.5h);; + o.uv21 = v.texcoord + _MainTex_TexelSize.xy * half2(-0.5h, -0.5h); + o.uv22 = v.texcoord + _MainTex_TexelSize.xy * half2(0.5h, -0.5h); + o.uv23 = v.texcoord + _MainTex_TexelSize.xy * half2(-0.5h, 0.5h); + + //【6.3】返回最终的输出结果 + return o; + } + + //【7】片段着色函数 || Fragment Shader Function + fixed4 frag_DownSmpl(VertexOutput_DownSmpl i) : SV_Target + { + //【7.1】定义一个临时的颜色值 + fixed4 color = (0,0,0,0); + + //【7.2】四个相邻像素点处的纹理值相加 + color += tex2D(_MainTex, i.uv20); + color += tex2D(_MainTex, i.uv21); + color += tex2D(_MainTex, i.uv22); + color += tex2D(_MainTex, i.uv23); + + //【7.3】返回最终的平均值 + return color / 4; + } + + //【8】顶点输入结构体 || Vertex Input Struct + struct VertexOutput_Blur + { + //像素坐标 + float4 pos : SV_POSITION; + //一级纹理(纹理坐标) + half4 uv : TEXCOORD0; + //二级纹理(偏移量) + half2 offset : TEXCOORD1; + }; + + //【9】顶点着色函数 || Vertex Shader Function + VertexOutput_Blur vert_BlurHorizontal(VertexInput v) + { + //【9.1】实例化一个输出结构 + VertexOutput_Blur o; + + //【9.2】填充输出结构 + //将三维空间中的坐标投影到二维窗口 + o.pos = UnityObjectToClipPos(v.vertex); + //纹理坐标 + o.uv = half4(v.texcoord.xy, 1, 1); + //计算X方向的偏移量 + o.offset = _MainTex_TexelSize.xy * half2(1.0, 0.0) * _DownSampleValue; + + //【9.3】返回最终的输出结果 + return o; + } + + //【10】顶点着色函数 || Vertex Shader Function + VertexOutput_Blur vert_BlurVertical(VertexInput v) + { + //【10.1】实例化一个输出结构 + VertexOutput_Blur o; + + //【10.2】填充输出结构 + //将三维空间中的坐标投影到二维窗口 + o.pos = UnityObjectToClipPos(v.vertex); + //纹理坐标 + o.uv = half4(v.texcoord.xy, 1, 1); + //计算Y方向的偏移量 + o.offset = _MainTex_TexelSize.xy * half2(0.0, 1.0) * _DownSampleValue; + + //【10.3】返回最终的输出结果 + return o; + } + + //【11】片段着色函数 || Fragment Shader Function + half4 frag_Blur(VertexOutput_Blur i) : SV_Target + { + //【11.1】获取原始的uv坐标 + half2 uv = i.uv.xy; + + //【11.2】获取偏移量 + half2 OffsetWidth = i.offset; + //从中心点偏移3个间隔,从最左或最上开始加权累加 + half2 uv_withOffset = uv - OffsetWidth * 3.0; + + //【11.3】循环获取加权后的颜色值 + half4 color = 0; + for (int j = 0; j< 7; j++) + { + //偏移后的像素纹理值 + half4 texCol = tex2D(_MainTex, uv_withOffset); + //待输出颜色值+=偏移后的像素纹理值 x 高斯权重 + color += texCol * GaussWeight[j]; + //移到下一个像素处,准备下一次循环加权 + uv_withOffset += OffsetWidth; + } + + //【11.4】返回最终的颜色值 + return color; + } + + //-------------------结束CG着色语言声明部分 || End CG Programming Part------------------ + ENDCG + + FallBack Off +} diff --git a/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer/UIGaussianBlurLayer.shader.meta b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer/UIGaussianBlurLayer.shader.meta new file mode 100644 index 00000000..faa7c662 --- /dev/null +++ b/Assets/TEngine/Runtime/Extension/UGUIExtension/UIGaussianBlurLayer/UIGaussianBlurLayer/UIGaussianBlurLayer.shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f0aa76bc245d2f941ba90eadd9bc02c2 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: