This commit is contained in:
SoulliesOfficial
2026-03-18 13:42:23 -04:00
parent 7580c4d87c
commit 56cee0cf01
38 changed files with 1156 additions and 3392 deletions

View File

@@ -29,7 +29,7 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1000, y: 1000, z: 1000}
m_LocalScale: {x: 100, y: 1, z: 100}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
@@ -59,10 +59,15 @@ MeshRenderer:
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: d9d66429d76d45e4588709a0f48707ed, type: 2}
- {fileID: 2100000, guid: 2cb2bfcfeddfbbe4b9148fa39d4fca23, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -80,9 +85,11 @@ MeshRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &8823166546278708317
MonoBehaviour:

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap
{
[System.Serializable]
public class DTMFramesFloor_BM : EnvironmentObject_BM
{
public float patternSizeX = 100.0f;
public float patternSizeY = 100.0f;
public float gridDensity = 1.0f;
public float timeAngle = 0.1f;
public float stepA = 0.25f;
public float stepB = 0.24f;
public bool enableOuterBorder = true;
public float outerBorderColorR = 1f;
public float outerBorderColorG = 1f;
public float outerBorderColorB = 1f;
public float outerBorderColorA = 1f;
public float outerBorderWidth = 0.02f;
public DTMFramesFloor_BM()
{
}
public override void ExecuteBM()
{
Color outerColor = new Color(outerBorderColorR, outerBorderColorG, outerBorderColorB, outerBorderColorA);
matchedElement = DTMFramesFloor.GenerateElement(elementName, elementGuid, tags, false,
themeBundleName, objectName, GetElement(attachedElementGuid), isStatic,
patternSizeX, patternSizeY, gridDensity,
timeAngle, stepA, stepB,
enableOuterBorder, outerColor, outerBorderWidth);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d6073730876ef064e86673c02d0c6e36

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap
{
[System.Serializable]
public class DTMGlobalFog_BM : EnvironmentObject_BM
{
public FlexibleFloat_BM fogColorStartR = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorStartG = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorStartB = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorStartA = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorEndR = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorEndG = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorEndB = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorEndA = new FlexibleFloat_BM();
public FlexibleFloat_BM fogColorDuo = new FlexibleFloat_BM();
public FlexibleFloat_BM skyboxFogIntensity = new FlexibleFloat_BM();
public FlexibleFloat_BM skyboxFogHeight = new FlexibleFloat_BM();
public FlexibleFloat_BM skyboxFogFalloff = new FlexibleFloat_BM();
public FlexibleFloat_BM skyboxFogOffset = new FlexibleFloat_BM();
public DTMGlobalFog_BM()
{
}
public override void ExecuteBM()
{
matchedElement = DTMGlobalFog.GenerateElement(elementName, elementGuid, tags, false,
themeBundleName, objectName, GetElement(attachedElementGuid), isStatic,
fogColorStartR?.ConvertToGameType(), fogColorStartG?.ConvertToGameType(), fogColorStartB?.ConvertToGameType(), fogColorStartA?.ConvertToGameType(),
fogColorEndR?.ConvertToGameType(), fogColorEndG?.ConvertToGameType(), fogColorEndB?.ConvertToGameType(), fogColorEndA?.ConvertToGameType(),
fogColorDuo?.ConvertToGameType(),
skyboxFogIntensity?.ConvertToGameType(), skyboxFogHeight?.ConvertToGameType(),
skyboxFogFalloff?.ConvertToGameType(), skyboxFogOffset?.ConvertToGameType());
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 68f4e10e5b6171549a44658b6b917a2a

View File

@@ -7,7 +7,7 @@ using UnityEngine;
namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
{
public class DTM_Ripple : MonoBehaviour, IPoolable
public class DTMRipple : MonoBehaviour, IPoolable
{
#region [] Exposed Fields & References
public ParticleSystem mainRipple;

View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
{
public class DTMFramesFloor : EnvironmentObject
{
#region [] Exposed Fields
public float patternSizeX;
public float patternSizeY;
public float gridDensity;
public float timeAngle;
public float stepA;
public float stepB;
public bool enableOuterBorder;
public Color outerBorderColor;
public float outerBorderWidth;
public Renderer meshRenderer;
#endregion
#region [] Lifecycle & Factory
public static DTMFramesFloor GenerateElement(string elementName, Guid id, List<string> tags,
bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement,
bool isStatic,
float patternSizeX, float patternSizeY, float gridDensity,
float timeAngle, float stepA, float stepB,
bool enableOuterBorder,
Color outerBorderColor,
float outerBorderWidth)
{
DTMFramesFloor framesFloor = EnvironmentObject.GenerateElement(elementName, id, tags,
isFirstGenerated, themeBundleName, objectName, parentElement, isStatic).GetComponent<DTMFramesFloor>();
framesFloor.patternSizeX = patternSizeX;
framesFloor.patternSizeY = patternSizeY;
framesFloor.gridDensity = gridDensity;
framesFloor.timeAngle = timeAngle;
framesFloor.stepA = stepA;
framesFloor.stepB = stepB;
framesFloor.enableOuterBorder = enableOuterBorder;
framesFloor.outerBorderColor = outerBorderColor;
framesFloor.outerBorderWidth = outerBorderWidth;
return framesFloor;
}
public override void FirstSetUpObject(bool isFirstGenerated)
{
if (meshRenderer == null)
meshRenderer = GetComponentInChildren<Renderer>();
meshRenderer.InitializeShader(); // 实例化材质 / Instantiate material
UpdateMaterialProperties();
}
#endregion
#region [] Core Effect Logic
public void UpdateMaterialProperties()
{
if (meshRenderer != null && meshRenderer.material != null)
{
Material mat = meshRenderer.material;
mat.SetVector("_PatternSize", new Vector4(patternSizeX, patternSizeY, 0, 0));
mat.SetFloat("_GridDensity", gridDensity);
mat.SetFloat("_TimeAngle", timeAngle);
mat.SetFloat("_StepA", stepA);
mat.SetFloat("_StepB", stepB);
float borderOn = enableOuterBorder ? 1f : 0f;
mat.SetFloat("_EnableOuterBorder", borderOn);
if (enableOuterBorder)
{
mat.EnableKeyword("_OUTER_BORDER_ON");
}
else
{
mat.DisableKeyword("_OUTER_BORDER_ON");
}
mat.SetColor("_OuterBorderColor", outerBorderColor);
mat.SetFloat("_OuterBorderWidth", outerBorderWidth);
// Base Color and Alpha Sync (Unity Color -> HDR)
mat.SetColor("_Color0", colorSubmodule.currentBaseColor);
}
}
public override void Refresh()
{
base.Refresh();
// Sync environment color changes
if (meshRenderer != null)
{
meshRenderer.material.SetColor("_Color0", colorSubmodule.currentBaseColor);
}
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 677671f1d5140b2489dc52c18792b8f5

View File

@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UnityEngine;
using AtmosphericHeightFog;
using FogMode = AtmosphericHeightFog.FogMode;
namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
{
public class DTMGlobalFog : EnvironmentObject
{
#region [] Exposed Fields
public HeightFogGlobal heightFogGlobal;
public FlexibleFloat fogColorStartR, fogColorStartG, fogColorStartB, fogColorStartA;
public FlexibleFloat fogColorEndR, fogColorEndG, fogColorEndB, fogColorEndA;
public FlexibleFloat fogColorDuo;
public FlexibleFloat skyboxFogIntensity;
public FlexibleFloat skyboxFogHeight;
public FlexibleFloat skyboxFogFalloff;
public FlexibleFloat skyboxFogOffset;
#endregion
#region [] Lifecycle & Factory
public static DTMGlobalFog GenerateElement(string elementName, Guid id, List<string> tags,
bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement,
bool isStatic,
FlexibleFloat fogColorStartR, FlexibleFloat fogColorStartG, FlexibleFloat fogColorStartB, FlexibleFloat fogColorStartA,
FlexibleFloat fogColorEndR, FlexibleFloat fogColorEndG, FlexibleFloat fogColorEndB, FlexibleFloat fogColorEndA,
FlexibleFloat fogColorDuo,
FlexibleFloat skyboxFogIntensity, FlexibleFloat skyboxFogHeight,
FlexibleFloat skyboxFogFalloff, FlexibleFloat skyboxFogOffset)
{
DTMGlobalFog globalFog = EnvironmentObject.GenerateElement(elementName, id, tags,
isFirstGenerated, themeBundleName, objectName, parentElement, isStatic).GetComponent<DTMGlobalFog>();
globalFog.fogColorStartR = fogColorStartR;
globalFog.fogColorStartG = fogColorStartG;
globalFog.fogColorStartB = fogColorStartB;
globalFog.fogColorStartA = fogColorStartA;
globalFog.fogColorEndR = fogColorEndR;
globalFog.fogColorEndG = fogColorEndG;
globalFog.fogColorEndB = fogColorEndB;
globalFog.fogColorEndA = fogColorEndA;
globalFog.fogColorDuo = fogColorDuo;
globalFog.skyboxFogIntensity = skyboxFogIntensity;
globalFog.skyboxFogHeight = skyboxFogHeight;
globalFog.skyboxFogFalloff = skyboxFogFalloff;
globalFog.skyboxFogOffset = skyboxFogOffset;
return globalFog;
}
public override void FirstSetUpObject(bool isFirstGenerated)
{
if (heightFogGlobal == null)
{
heightFogGlobal = GetComponentInChildren<HeightFogGlobal>();
}
// Ensure fog mode is set to script settings so it accepts our overrides
if (heightFogGlobal != null)
{
heightFogGlobal.fogMode = FogMode.UseScriptSettings;
}
}
#endregion
#region [] Event Animation Logic
private void Update()
{
if (heightFogGlobal == null) return;
float songTime = CoreServices.TimeProvider.SongTime;
fogColorStartR?.UpdateFlexibleFloat(songTime);
fogColorStartG?.UpdateFlexibleFloat(songTime);
fogColorStartB?.UpdateFlexibleFloat(songTime);
fogColorStartA?.UpdateFlexibleFloat(songTime);
fogColorEndR?.UpdateFlexibleFloat(songTime);
fogColorEndG?.UpdateFlexibleFloat(songTime);
fogColorEndB?.UpdateFlexibleFloat(songTime);
fogColorEndA?.UpdateFlexibleFloat(songTime);
fogColorDuo?.UpdateFlexibleFloat(songTime);
skyboxFogIntensity?.UpdateFlexibleFloat(songTime);
skyboxFogHeight?.UpdateFlexibleFloat(songTime);
skyboxFogFalloff?.UpdateFlexibleFloat(songTime);
skyboxFogOffset?.UpdateFlexibleFloat(songTime);
if (fogColorStartR != null && fogColorStartG != null && fogColorStartB != null && fogColorStartA != null)
{
heightFogGlobal.fogColorStart = new Color(fogColorStartR.value, fogColorStartG.value, fogColorStartB.value, fogColorStartA.value);
}
if (fogColorEndR != null && fogColorEndG != null && fogColorEndB != null && fogColorEndA != null)
{
heightFogGlobal.fogColorEnd = new Color(fogColorEndR.value, fogColorEndG.value, fogColorEndB.value, fogColorEndA.value);
}
if (fogColorDuo != null) heightFogGlobal.fogColorDuo = fogColorDuo.value;
if (skyboxFogIntensity != null) heightFogGlobal.skyboxFogIntensity = skyboxFogIntensity.value;
if (skyboxFogHeight != null) heightFogGlobal.skyboxFogHeight = skyboxFogHeight.value;
if (skyboxFogFalloff != null) heightFogGlobal.skyboxFogFalloff = skyboxFogFalloff.value;
if (skyboxFogOffset != null) heightFogGlobal.skyboxFogOffset = skyboxFogOffset.value;
}
#endregion
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e8bab02f6d349f6418ccfe0674b93013

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
{
public class DTMStarrySkybox : GameElement
{
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 638fbd0e919667f47a93485dd230c71f

View File

@@ -6,7 +6,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
public class DTMRippleEffect : EffectBase
{
#region [] Effect Fields & States
private DTM_Ripple ripple;
private DTMRipple ripple;
public float rippleTime;
public Vector3 positionOffset;
public Vector3 eulerAnglesOffset;
@@ -33,7 +33,7 @@ namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse
public override void Adjust()
{
GameObject prefab = GameManager.Instance.customPrefabs["departure_to_multiverse"].GetPrefab("DTM_Ripple");
ripple = LeanPool.Spawn(prefab, attachedGameElement.transform).GetComponent<DTM_Ripple>();
ripple = LeanPool.Spawn(prefab, attachedGameElement.transform).GetComponent<DTMRipple>();
ripple.transform.localPosition = positionOffset;
ripple.transform.localEulerAngles = eulerAnglesOffset;
ripple.transform.localScale = scale;

View File

@@ -1,107 +0,0 @@
import os
import re
game_dir = r"d:\Projects\ichni Official\Assets\ThemeBundles\DepartureToMultiverse\Scripts\Game"
datacore_dir = r"d:\Projects\ichni Official\Assets\ThemeBundles\DepartureToMultiverse\Scripts\DataCore"
def extract_beatmap_namespace(filepath):
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
except Exception as e:
print("Error reading", filepath, e)
return
# Find the start of namespace Beatmap
match = re.search(r'^\s*namespace\s+Beatmap\s*\{', content, re.MULTILINE)
if not match:
print("No Beatmap namespace in", filepath)
return
start_idx = match.start()
# We need to find the matching closing brace
brace_depth = 0
end_idx = -1
for i in range(start_idx, len(content)):
if content[i] == '{':
brace_depth += 1
elif content[i] == '}':
brace_depth -= 1
if brace_depth == 0:
end_idx = i + 1
break
if end_idx == -1:
print("Mismatched braces in", filepath)
return
bm_namespace_content = content[start_idx:end_idx]
# Find the name of the _BM class to name the new file
class_match = re.search(r'public\s+(?:partial\s+)?class\s+(\w+_BM)', bm_namespace_content)
if not class_match:
print("No _BM class found in namespace Beatmap for", filepath)
return
bm_class_name = class_match.group(1)
# Make the original file clean
new_game_content = content[:start_idx] + content[end_idx:]
new_game_content = new_game_content.rstrip()
# close the namespace of the original file if needed, actually it's usually inside the original namespace!
# Let's check if "namespace Beatmap" is inside another namespace.
# Yes, typically "namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse" wraps everything.
# The new_game_content currently might have a trailing `}` because the outer namespace is closed at the end.
# E.g.
# namespace Outer {
# class OuterClass { }
# namespace Beatmap { ... }
# }
# If we remove "namespace Beatmap { ... }", we still need the trailing "}".
new_game_content = re.sub(r'[\r\n\s]*namespace\s+Beatmap[\s\S]*\}\s*\}\s*$', '\n}', content) # A quick hacky way but relies on structure.
# Better way: just remove the exact substring, then it leaves the outer closing brace intact.
# wait, if namespace Beatmap { ... } is inside namespace Outer { ... }
# start_idx to end_idx is exactly "namespace Beatmap { ... }"
# So content[:start_idx] + content[end_idx:] will leave the outer } perfectly.
new_content = content[:start_idx] + content[end_idx:]
# Clean up excess newlines
new_content = re.sub(r'\n\s*\n\s*\n', '\n\n', new_content)
# Ensure it ends with a newline
new_content = new_content.strip() + '\n'
with open(filepath, 'w', encoding='utf-8') as f:
f.write(new_content)
# Now create the DataCore file
rel_path = os.path.relpath(filepath, game_dir)
datacore_file_dir = os.path.dirname(os.path.join(datacore_dir, rel_path))
os.makedirs(datacore_file_dir, exist_ok=True)
datacore_filepath = os.path.join(datacore_file_dir, bm_class_name + ".cs")
# We need usings. Extract original usings
usings = "".join(re.findall(r'^(?:using\s+[\w\.]+;\s*)+', content, re.MULTILINE))
# Format the new DataCore file
datacore_content = usings + "\n"
# Wrap in outer namespace
datacore_content += "namespace Ichni.RhythmGame.ThemeBundles.DepartureToMultiverse.Beatmap\n{\n"
# Extract the classes inside "namespace Beatmap"
inner_classes = re.search(r'namespace\s+Beatmap\s*\{([\s\S]*)\}', bm_namespace_content).group(1)
datacore_content += inner_classes + "}\n"
with open(datacore_filepath, 'w', encoding='utf-8') as f:
f.write(datacore_content)
print(f"Split {os.path.basename(filepath)} -> {bm_class_name}.cs")
for root, dirs, files in os.walk(game_dir):
for file in files:
if file.endswith('.cs'):
filepath = os.path.join(root, file)
extract_beatmap_namespace(filepath)

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 93391ba5485d4154293a4540acd4e942
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,213 @@
Shader "Soullies/DTM_FramesFloor"
{
Properties
{
[HDR]_Color0("Color0", Color) = (1, 1, 1, 0)
[Header(Pattern Settings)]
_PatternSize("Pattern Size (X, Y)", Vector) = (2.0, 2.0, 0, 0)
_GridDensity("Grid Density (Quantity Multiplier)", Float) = 1.0
_TimeAngle("Time Angle (Speed)", Float) = 1.0
[Header(Edge Settings)]
_StepA("Step A", Range(0, 1)) = 0.293
_StepB("Step B", Range(0, 1)) = 0.345
[Header(Outer Enclosing Border)]
[Toggle(_OUTER_BORDER_ON)] _EnableOuterBorder("Enable Outer Border", Float) = 0
[HDR] _OuterBorderColor("Outer Border Color", Color) = (1, 1, 1, 1)
_OuterBorderWidth("Outer Border Width", Range(0.0, 0.5)) = 0.02
[Header(Render State)]
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", Float) = 5 // SrcAlpha
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend", Float) = 10 // OneMinusSrcAlpha
[Enum(Off, 0, On, 1)] _ZWrite("Z Write", Float) = 0
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType" = "Transparent"
"Queue" = "Transparent-300"
"UniversalMaterialType" = "Unlit"
"IgnoreProjector" = "True"
}
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
Cull Back
Pass
{
Name "ForwardOnly"
Tags { "LightMode" = "UniversalForwardOnly" }
HLSLPROGRAM
// -------------------------------------
// Target Config
#pragma target 4.5
#pragma prefer_hlslcc gles
// DOTS and Instancing
#pragma multi_compile_instancing
#pragma multi_compile_fog
// Feature Flags
#pragma shader_feature_local _OUTER_BORDER_ON
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float2 uv : TEXCOORD1;
half fogFactor : TEXCOORD2;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
CBUFFER_START(UnityPerMaterial)
half4 _Color0;
float4 _PatternSize;
float _GridDensity;
float _TimeAngle;
float _StepA;
float _StepB;
half4 _OuterBorderColor;
float _OuterBorderWidth;
CBUFFER_END
// -------------------------------------
// Custom Helper Functions
float2 VoronoiHash(float2 p)
{
p = float2(dot(p, float2(127.1, 311.7)), dot(p, float2(269.5, 183.3)));
return frac(sin(p) * 43758.5453);
}
// Manhattan-based Voronoi optimized for Mobile URP
float VoronoiDistance(float2 v, float t)
{
float2 n = floor(v);
float2 f = frac(v);
float minDist = 8.0;
UNITY_UNROLL
for (int j = -1; j <= 1; j++)
{
UNITY_UNROLL
for (int i = -1; i <= 1; i++)
{
float2 g = float2((float)i, (float)j);
float2 o = VoronoiHash(n + g);
// Oscillating movement
o = sin(t + o * 6.2831853) * 0.5 + 0.5;
float2 r = f - g - o;
// Manhattan distance for rectangular frames
float d = 0.5 * (abs(r.x) + abs(r.y));
minDist = min(minDist, d);
}
}
return minDist;
}
// -------------------------------------
// Vertex Shader
Varyings vert(Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.positionWS = vertexInput.positionWS;
output.uv = input.uv;
output.fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
return output;
}
// -------------------------------------
// Fragment Shader
half4 frag(Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
// ==========================================
// 1. inner Grid Pattern Calculation
// ==========================================
float2 worldUV = input.positionWS.xz;
// Density Multiplier: Higher density = smaller frames = more quantity
float density = max(_GridDensity, 0.0001);
float2 sizeDivisor = max(_PatternSize.xy, float2(0.0001, 0.0001)) / density;
float2 scaledUV = worldUV / sizeDivisor;
// Rotate 45 degrees
float c = 0.707106;
float s = 0.707106;
float2 rotatedUV = mul(scaledUV, float2x2(c, -s, s, c));
// Time driven animation
float t = _TimeAngle * _TimeParameters.x;
// Voronoi mathematical noise
float v = VoronoiDistance(rotatedUV, t);
// Anti-aliased border mask computation
float fw = fwidth(v);
float edge1 = smoothstep(_StepA - fw, _StepA + fw, v);
float edge2 = smoothstep(_StepB - fw, _StepB + fw, v);
float gridAlphaMask = edge2 - edge1;
half3 gridColor = _Color0.rgb;
half gridAlpha = gridAlphaMask * _Color0.a;
// ==========================================
// 2. Outer Enclosing Border
// ==========================================
half3 finalColor = gridColor;
half finalAlpha = gridAlpha;
#if defined(_OUTER_BORDER_ON)
// Calculate distance to nearest UV edge
float2 edgeDist = min(input.uv, 1.0 - input.uv);
float closestEdge = min(edgeDist.x, edgeDist.y);
// Uses fwidth for clean smoothstep transition at the edge
float borderfw = fwidth(closestEdge);
// Creates a solid border with a smooth antialiased inner falloff
float borderMask = 1.0 - smoothstep(_OuterBorderWidth - borderfw, _OuterBorderWidth + borderfw, closestEdge);
// Lerp grid to border
finalColor = lerp(gridColor, _OuterBorderColor.rgb, borderMask);
finalAlpha = lerp(gridAlpha, _OuterBorderColor.a, borderMask);
#endif
// Apply URP Fog
finalColor = MixFog(finalColor, input.fogFactor);
return half4(finalColor, finalAlpha);
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}

View File

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