From c5adc24bb055ef4605b3c5d317fad136874df44c Mon Sep 17 00:00:00 2001 From: DeMuenu <96650288+DeMuenu@users.noreply.github.com> Date: Wed, 24 Sep 2025 09:41:56 +0200 Subject: [PATCH] Initial commit --- .gitattributes | 2 + EditorPreview.meta | 8 + EditorPreview/Editor.meta | 8 + .../Editor/PlayerPositionsToShaderPreview.cs | 159 ++++++++++ .../PlayerPositionsToShaderPreview.cs.meta | 11 + .../PlayerPositionsToShader.Editor.cs | 53 ++++ .../PlayerPositionsToShader.Editor.cs.meta | 11 + Scripts.meta | 8 + Scripts/LightdataStorage.cs | 48 +++ Scripts/LightdataStorage.cs.meta | 11 + Scripts/PlayerPositionsToShader.cs | 280 ++++++++++++++++++ Scripts/PlayerPositionsToShader.cs.meta | 11 + Shader.meta | 8 + Shader/BlendinShader.shader | 190 ++++++++++++ Shader/BlendinShader.shader.meta | 9 + Shader/GhostWhiteShader.shader | 83 ++++++ Shader/GhostWhiteShader.shader.meta | 9 + Shader/LitParticles.shader | 186 ++++++++++++ Shader/LitParticles.shader.meta | 9 + Shader/MoonsLight.cingc | 90 ++++++ Shader/MoonsLight.cingc.meta | 7 + Shader/Water.shader | 216 ++++++++++++++ Shader/Water.shader.meta | 9 + 23 files changed, 1426 insertions(+) create mode 100644 .gitattributes create mode 100644 EditorPreview.meta create mode 100644 EditorPreview/Editor.meta create mode 100644 EditorPreview/Editor/PlayerPositionsToShaderPreview.cs create mode 100644 EditorPreview/Editor/PlayerPositionsToShaderPreview.cs.meta create mode 100644 EditorPreview/PlayerPositionsToShader.Editor.cs create mode 100644 EditorPreview/PlayerPositionsToShader.Editor.cs.meta create mode 100644 Scripts.meta create mode 100644 Scripts/LightdataStorage.cs create mode 100644 Scripts/LightdataStorage.cs.meta create mode 100644 Scripts/PlayerPositionsToShader.cs create mode 100644 Scripts/PlayerPositionsToShader.cs.meta create mode 100644 Shader.meta create mode 100644 Shader/BlendinShader.shader create mode 100644 Shader/BlendinShader.shader.meta create mode 100644 Shader/GhostWhiteShader.shader create mode 100644 Shader/GhostWhiteShader.shader.meta create mode 100644 Shader/LitParticles.shader create mode 100644 Shader/LitParticles.shader.meta create mode 100644 Shader/MoonsLight.cingc create mode 100644 Shader/MoonsLight.cingc.meta create mode 100644 Shader/Water.shader create mode 100644 Shader/Water.shader.meta diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/EditorPreview.meta b/EditorPreview.meta new file mode 100644 index 0000000..54164f3 --- /dev/null +++ b/EditorPreview.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a124e3c4f76d5c4694c91508af58fba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/EditorPreview/Editor.meta b/EditorPreview/Editor.meta new file mode 100644 index 0000000..9e2d9fb --- /dev/null +++ b/EditorPreview/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ee398d1bd8711f4e9424187553d2877 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/EditorPreview/Editor/PlayerPositionsToShaderPreview.cs b/EditorPreview/Editor/PlayerPositionsToShaderPreview.cs new file mode 100644 index 0000000..dc7d5b3 --- /dev/null +++ b/EditorPreview/Editor/PlayerPositionsToShaderPreview.cs @@ -0,0 +1,159 @@ +// Assets/Editor/PlayerPositionsToShaderPreview.cs +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +[InitializeOnLoad] +public static class PlayerPositionsToShaderPreview +{ + const double kTickInterval = 0.1; // seconds + static double _nextTick; + static readonly MaterialPropertyBlock _mpb = new MaterialPropertyBlock(); + static readonly Dictionary _cache = new Dictionary(); + + struct Cache + { + public Vector4[] positions; + public Vector4[] colors; + public Vector4[] directions; + public float[] types; + public int size; + } + + static PlayerPositionsToShaderPreview() + { + EditorApplication.update += Update; + EditorApplication.hierarchyChanged += ForceTick; + Undo.undoRedoPerformed += ForceTick; + Selection.selectionChanged += ForceTick; + } + + public static void ForceTick() => _nextTick = 0; + + static void Update() + { +#if UNITY_2019_1_OR_NEWER + if (EditorApplication.isPlayingOrWillChangePlaymode) return; +#else + if (EditorApplication.isPlaying) return; +#endif + double now = EditorApplication.timeSinceStartup; + if (now < _nextTick) return; + _nextTick = now + kTickInterval; + + var behaviours = FindAllInScene(); + foreach (var b in behaviours) + { + if (b == null || !b.isActiveAndEnabled) continue; + if (EditorUtility.IsPersistent(b)) continue; // skip assets + PushFromUdonBehaviour(b); + } + + SceneView.RepaintAll(); + } + + static PlayerPositionsToShader[] FindAllInScene() + { +#if UNITY_2023_1_OR_NEWER + return Object.FindObjectsByType(FindObjectsInactive.Exclude, FindObjectsSortMode.None); +#elif UNITY_2020_1_OR_NEWER + return Object.FindObjectsOfType(true); +#else + return Resources.FindObjectsOfTypeAll(); +#endif + } + + static void EnsureArrays(PlayerPositionsToShader src, int required) + { + if (!_cache.TryGetValue(src, out var c) || + c.positions == null || c.colors == null || c.directions == null || c.types == null || + c.size != required) + { + c = new Cache + { + positions = new Vector4[required], + colors = new Vector4[required], + directions = new Vector4[required], + types = new float[required], + size = required + }; + _cache[src] = c; + } + } + + static void PushFromUdonBehaviour(PlayerPositionsToShader src) + { + int max = Mathf.Max(1, src.maxLights); + EnsureArrays(src, max); + + var c = _cache[src]; + var positions = c.positions; + var colors = c.colors; + var directions = c.directions; + var types = c.types; + + for (int i = 0; i < max; i++) + { + positions[i] = Vector4.zero; + colors[i] = Vector4.zero; + directions[i] = Vector4.zero; + types[i] = 0f; + } + + // 🔗 Use the Editor-side function defined on the partial class + int count = 0; + try + { + src.Editor_BuildPreview(out positions, out colors, out directions, out types, out count); + // replace cache arrays if sizes changed + if (positions.Length != c.size) EnsureArrays(src, positions.Length); + _cache[src] = new Cache { positions = positions, colors = colors, directions = directions, types = types, size = positions.Length }; + } + catch + { + // Ultra-safe fallback: nothing to push if the method signature changes unexpectedly + count = 0; + } + + var rds = src.targets ?? System.Array.Empty(); + for (int r = 0; r < rds.Length; r++) + { + var rd = rds[r]; + if (rd == null) continue; + + rd.GetPropertyBlock(_mpb); + + if (!string.IsNullOrEmpty(src.positionsProperty)) _mpb.SetVectorArray(src.positionsProperty, positions); + if (!string.IsNullOrEmpty(src.colorProperty)) _mpb.SetVectorArray(src.colorProperty, colors); + if (!string.IsNullOrEmpty(src.directionsProperty)) _mpb.SetVectorArray(src.directionsProperty, directions); + if (!string.IsNullOrEmpty(src.typeProperty)) _mpb.SetFloatArray (src.typeProperty, types); + if (!string.IsNullOrEmpty(src.countProperty)) _mpb.SetFloat (src.countProperty, count); + + rd.SetPropertyBlock(_mpb); + } + } +} + +[CustomEditor(typeof(PlayerPositionsToShader))] +public class PlayerPositionsToShaderInspector : Editor +{ + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + GUILayout.Space(6); + using (new EditorGUI.DisabledScope(true)) + { + EditorGUILayout.LabelField("Edit-Mode Preview", EditorStyles.boldLabel); + EditorGUILayout.LabelField("Updates ~10×/s using \"Other Transforms\" as emitters."); + } + + if (GUILayout.Button("Refresh Now")) + { + PlayerPositionsToShaderPreview.ForceTick(); + EditorApplication.QueuePlayerLoopUpdate(); + SceneView.RepaintAll(); + } + } +} +#endif diff --git a/EditorPreview/Editor/PlayerPositionsToShaderPreview.cs.meta b/EditorPreview/Editor/PlayerPositionsToShaderPreview.cs.meta new file mode 100644 index 0000000..50ed4f6 --- /dev/null +++ b/EditorPreview/Editor/PlayerPositionsToShaderPreview.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2eac5e5df0d18524e84022a091ada4f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/EditorPreview/PlayerPositionsToShader.Editor.cs b/EditorPreview/PlayerPositionsToShader.Editor.cs new file mode 100644 index 0000000..9d5e592 --- /dev/null +++ b/EditorPreview/PlayerPositionsToShader.Editor.cs @@ -0,0 +1,53 @@ +// Assets/Lighting/Scripts/PlayerPositionsToShader.Editor.cs +#if UNITY_EDITOR +using UnityEngine; + +public partial class PlayerPositionsToShader +{ + public void Editor_BuildPreview( + out Vector4[] positions, + out Vector4[] colors, + out Vector4[] directions, + out float[] types, + out int count) + { + int max = Mathf.Max(1, maxLights); + + positions = new Vector4[max]; + colors = new Vector4[max]; + directions = new Vector4[max]; + types = new float[max]; + count = 0; + + // ✅ Avoid Array.Empty(); just guard the loop + if (otherLightSources != null) + { + for (int i = 0; i < otherLightSources.Length && count < max; i++) + { + Transform t = otherLightSources[i]; + if (t == null || !t.gameObject.activeInHierarchy) continue; + + LightdataStorage data = t.GetComponent(); + + Vector3 pos = t.position; + float range = (data != null) ? data.range * t.localScale.x : t.localScale.x; + Vector4 col = (data != null) ? data.GetFinalColor() : new Vector4(1f, 1f, 1f, 1f); + float intens = (data != null) ? data.intensity * t.localScale.x : 1f; + float cosHalf = (data != null) ? data.GetCosHalfAngle() : 1f; + int typeId = (data != null) ? data.GetTypeId() : 0; + + + Quaternion rot = t.rotation; + Vector3 fwd = rot * Vector3.down; + + positions[count] = new Vector4(pos.x, pos.y, pos.z, range); + colors[count] = new Vector4(col.x, col.y, col.z, intens); + directions[count] = new Vector4(fwd.x, fwd.y, fwd.z, data.spotAngleDeg); + types[count] = (float)typeId; + + count++; + } + } + } +} +#endif diff --git a/EditorPreview/PlayerPositionsToShader.Editor.cs.meta b/EditorPreview/PlayerPositionsToShader.Editor.cs.meta new file mode 100644 index 0000000..55a9ffe --- /dev/null +++ b/EditorPreview/PlayerPositionsToShader.Editor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93398d31d2739524dad37ec5e916b222 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts.meta b/Scripts.meta new file mode 100644 index 0000000..6a5bb7c --- /dev/null +++ b/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 23121b67c238da34e9055714600bb22a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LightdataStorage.cs b/Scripts/LightdataStorage.cs new file mode 100644 index 0000000..503f501 --- /dev/null +++ b/Scripts/LightdataStorage.cs @@ -0,0 +1,48 @@ +using UdonSharp; +using UnityEngine; +using VRC.SDKBase; +using VRC.Udon; + + + +public enum LightType { Sphere, Spot } + +[UdonBehaviourSyncMode(BehaviourSyncMode.None)] +public class LightdataStorage : UdonSharpBehaviour +{ + + [Header("Type")] + [Tooltip("Select the logical light type for this source.")] + public LightType lightType = LightType.Sphere; + + + [Header("Light Settings")] + + public float range = 5f; + + + + [ColorUsage(true, true)] // (showAlpha: true, HDR: true) + public Color color = Color.white; + + [Tooltip("Intensity multiplier applied to the color (kept separate so you can tweak brightness without changing hue).")] + public float intensity = 1f; + + [Header("Spotlight Shape")] + [Tooltip("0 = omni (no cone)")] + public float spotAngleDeg = 0f; + + // Convert to a Vector4 for your shader upload + public Vector4 GetFinalColor() + { + return new Vector4(color.r * intensity, color.g * intensity, color.b * intensity, color.a); + } + + public float GetCosHalfAngle() + { + if (spotAngleDeg <= 0f) return 0f; + return Mathf.Cos(Mathf.Deg2Rad * (spotAngleDeg * 0.5f)); + } + + public int GetTypeId() => (int)lightType; // Omni=0, Spot=1, Directional=2 +} diff --git a/Scripts/LightdataStorage.cs.meta b/Scripts/LightdataStorage.cs.meta new file mode 100644 index 0000000..ec36c04 --- /dev/null +++ b/Scripts/LightdataStorage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d87e774841a8cbf4fa961c9076c880bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/PlayerPositionsToShader.cs b/Scripts/PlayerPositionsToShader.cs new file mode 100644 index 0000000..db1000f --- /dev/null +++ b/Scripts/PlayerPositionsToShader.cs @@ -0,0 +1,280 @@ +using System; +using UdonSharp; +using Unity.Mathematics; +using UnityEngine; +using VRC.SDKBase; +using VRC.Udon; + +public partial class PlayerPositionsToShader : UdonSharpBehaviour +{ + [Header("Lightsources")] + [Tooltip("Place Transforms here which should also emit Light (attach LightdataStorage to them).")] + public Transform[] otherLightSources; + + [Header("Renderers that use a supported shader")] + public Renderer[] targets; + + [Header("Strength")] + [Tooltip("Local player light range")] + public float lightStrengthLocal = 10f; + + [Tooltip("Remote players light range")] + public float lightStrengthRemote = 5f; + + [Tooltip("Players light intensity")] + public float playerLightIntensity = 5f; + public float remoteLightIntensity = 2f; + + + [Header("Shader property names (advanced users)")] + [Tooltip("Vector4 array: xyz = position, w = range")] + public string positionsProperty = "_PlayerPositions"; + + [Tooltip("Actual array count")] + public string countProperty = "_PlayerCount"; + + [Tooltip("RGBA array: rgb = color, a = intensity")] + public string colorProperty = "_LightColors"; + + [Tooltip("Vector4 array: xyz = direction, w = spot in degrees")] + public string directionsProperty = "_LightDirections"; + + [Tooltip("float array: light type (1=area, 2=cone, etc)")] + public string typeProperty = "_LightType"; + + [Header("Max Lights (advanced users)")] + [Tooltip("Hard cap / array size. 80 = default cap")] + public int maxLights = 80; + + + + // Internals + private Vector4[] _positions; + private bool _positons_isDirty = false; + private Vector4[] _lightColors; + private bool _lightColors_isDirty = false; + private Vector4[] _directions; + private bool _directions_isDirty = false; + + private float[] _TypeArray; + private bool _TypeArray_isDirty = false; + + private VRCPlayerApi[] _players; + private MaterialPropertyBlock _mpb; + + public int currentCount { get; private set; } + + void Start() + { + if (maxLights < 1) maxLights = 1; + + _positions = new Vector4[maxLights]; + _lightColors = new Vector4[maxLights]; + _directions = new Vector4[maxLights]; + _TypeArray = new float[maxLights]; + + _players = new VRCPlayerApi[maxLights]; + _mpb = new MaterialPropertyBlock(); + + UpdateData(); + PushToRenderers(); + } + + void LateUpdate() + { + UpdateData(); + PushToRenderers(); + } + + private void UpdateData() + { + currentCount = VRCPlayerApi.GetPlayerCount(); + + + VRCPlayerApi.GetPlayers(_players); + + // --- Players as light sources --- + for (int i = 0; i < currentCount && currentCount < maxLights; i++) + { + VRCPlayerApi p = _players[i]; + if (Utilities.IsValid(p)) + { + Vector3 pos = p.GetPosition(); + float lightRange = p.isLocal ? lightStrengthLocal : lightStrengthRemote; + float intensity = p.isLocal ? playerLightIntensity : remoteLightIntensity; + + + Vector4 posTemp = new Vector4(pos.x, pos.y + 1f, pos.z, lightRange); + if (_positions[i] != posTemp) + { + _positions[i] = posTemp; + _positons_isDirty = true; + } + + Vector4 colorTemp = new Vector4(1f, 1f, 1f, intensity); + if (_lightColors[i] != colorTemp) + { + _lightColors[i] = colorTemp; + _lightColors_isDirty = true; + } + + + //Quaternion rot = p.GetRotation(); //We skip this for players, as they have round lights + Vector3 fwd = Vector3.up; + Vector4 TempDir = new Vector4(fwd.x, fwd.y, fwd.z, 10f); + if (_directions[i] != TempDir) + { + _directions[i] = new Vector4(TempDir.x, TempDir.y, TempDir.z, 10f); + _directions_isDirty = true; + } + + if (_TypeArray[i] != 0f) + { + _TypeArray[i] = 0f; + _TypeArray_isDirty = true; + } + + + } + else + { + if (_positions[i] != Vector4.zero) + { + _positions[i] = Vector4.zero; + _positons_isDirty = true; + } + if (_lightColors[i] != Vector4.zero) + { + _lightColors[i] = Vector4.zero; + _lightColors_isDirty = true; + } + if (_directions[i] != Vector4.zero) + { + _directions[i] = Vector4.zero; + _directions_isDirty = true; + } + if (_TypeArray[i] != 0f) + { + _TypeArray[i] = 0f; + _TypeArray_isDirty = true; + } + } + } + + // --- Scene light sources --- + if (otherLightSources != null) + { + for (int j = 0; j < otherLightSources.Length && currentCount < maxLights; j++) + { + Transform t = otherLightSources[j]; + if (t == null || !t.gameObject.activeInHierarchy) continue; + + LightdataStorage data = t.GetComponent(); + + Vector3 pos = t.position; + float range = (data != null) ? data.range * t.localScale.x: t.localScale.x; + + // NOTE: we pack intensity into color.w (to match your current shader usage) + Vector4 col = (data != null) ? data.GetFinalColor() : new Vector4(1f, 1f, 1f, 1f); + float intensity = (data != null) ? data.intensity * t.localScale.x : 1f; + + //Vector3 fwd = new Vector3(t.localRotation.x, t.localRotation.y, t.localRotation.z); + + Quaternion rot = t.rotation; + Vector3 fwd = rot * Vector3.down; + + + float cosHalf = (data != null) ? data.GetCosHalfAngle() : 0f; + + Vector4 posTemp = new Vector4(pos.x, pos.y, pos.z, range); + if (_positions[currentCount] != posTemp) + { + _positions[currentCount] = posTemp; + _positons_isDirty = true; + } + Vector4 colorTemp = new Vector4(col.x, col.y, col.z, intensity); + if (_lightColors[currentCount] != colorTemp) + { + _lightColors[currentCount] = colorTemp; + _lightColors_isDirty = true; + } + Vector4 dirTemp = new Vector4(fwd.x, fwd.y, fwd.z, cosHalf); + if (_directions[currentCount] != dirTemp) + { + _directions[currentCount] = dirTemp; + _directions_isDirty = true; + } + + // ✅ Use your custom enum id (Omni=0, Spot=1, Directional=2) + int typeId = (data != null) ? data.GetTypeId() : 0; + if (_TypeArray[currentCount] != (float)typeId) + { + _TypeArray[currentCount] = (float)typeId; + _TypeArray_isDirty = true; + } + + currentCount++; + } + } + + for (int i = currentCount; i < maxLights; i++) + { + if (_positions[i] != Vector4.zero) + { + _positions[i] = Vector4.zero; + _positons_isDirty = true; + } + + if (_lightColors[i] != Vector4.zero) + { + _lightColors[i] = Vector4.zero; + _lightColors_isDirty = true; + } + + if (_directions[i] != Vector4.zero) + { + _directions[i] = Vector4.zero; + _directions_isDirty = true; + } + + if (_TypeArray[i] != 0f) + { + _TypeArray[i] = 0f; + _TypeArray_isDirty = true; + } + } + } + + private void PushToRenderers() + { + if (targets == null || targets.Length == 0) return; + + // Snapshot which things are dirty this frame + bool pushPositions = _positons_isDirty; + bool pushColors = _lightColors_isDirty; + bool pushDirs = _directions_isDirty; + bool pushTypes = _TypeArray_isDirty && !string.IsNullOrEmpty(typeProperty); + + for (int r = 0; r < targets.Length; r++) + { + Renderer rd = targets[r]; + if (!Utilities.IsValid(rd)) continue; + + rd.GetPropertyBlock(_mpb); + + if (pushPositions) _mpb.SetVectorArray(positionsProperty, _positions); + if (pushColors) _mpb.SetVectorArray(colorProperty, _lightColors); + if (pushDirs) _mpb.SetVectorArray(directionsProperty, _directions); + if (pushTypes) _mpb.SetFloatArray(typeProperty, _TypeArray); + + _mpb.SetFloat(countProperty, currentCount); + rd.SetPropertyBlock(_mpb); + } + + // Only now mark them clean + if (pushPositions) { _positons_isDirty = false; Debug.Log("Updated Positions"); } + if (pushColors) { _lightColors_isDirty = false; Debug.Log("Updated LightColors"); } + if (pushDirs) { _directions_isDirty = false; Debug.Log("Updated Directions"); } + if (pushTypes) { _TypeArray_isDirty = false; Debug.Log("Updated TypeArray"); } + } +} diff --git a/Scripts/PlayerPositionsToShader.cs.meta b/Scripts/PlayerPositionsToShader.cs.meta new file mode 100644 index 0000000..1d470d3 --- /dev/null +++ b/Scripts/PlayerPositionsToShader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae77287fea761ef4d9c2f38c0d71d901 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Shader.meta b/Shader.meta new file mode 100644 index 0000000..f739019 --- /dev/null +++ b/Shader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b1f08ce8e71a3342a43990e3fb8a9dc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Shader/BlendinShader.shader b/Shader/BlendinShader.shader new file mode 100644 index 0000000..a744825 --- /dev/null +++ b/Shader/BlendinShader.shader @@ -0,0 +1,190 @@ +Shader "DeMuenu/World/Hoppou/RevealStandart" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _MultTex ("Multiply Texture", 2D) = "white" {} + _MultiplicatorTex ("Multiply Texture Strength", Range(0,3)) = 0 + _Color ("Color", Color) = (1,1,1,1) + + _EmmisiveText ("Emmissive Texture", 2D) = "white" {} + _EmmissiveColor ("Emmissive Color", Color) = (1,1,1,1) + _EmmissiveStrength ("Emmissive Strength", Range(0,10)) = 0 + + + //MoonsLight + _InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1 + _LightCutoffDistance ("Light Cutoff Distance", Float) = 100 + //MoonsLight END + + + + } + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + //MoonsLight Defines + #define MAX_LIGHTS 80 // >= maxPlayers in script + //MoonsLight Defines END + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + float3 normal : NORMAL; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float2 uv2 : TEXCOORD1; + float2 uvEmmis : TEXCOORD4; + //UNITY_FOG_COORDS(1) + float4 vertex : SV_POSITION; + + //MoonsLight + float3 worldPos : TEXCOORD2; + float3 worldNormal: TEXCOORD3; + + //MoonsLight END + + + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + sampler2D _MultTex; + float4 _MultTex_ST; + float _MultiplicatorTex; + float4 _Color; + + + sampler2D _EmmisiveText; + float4 _EmmisiveText_ST; + float4 _EmmissiveColor; + float _EmmissiveStrength; + + + //MoonsLight variables + float _InverseSqareMultiplier; + float _LightCutoffDistance; + + float4 _LightPositions[MAX_LIGHTS]; // xyz = position + float4 _LightColors[MAX_LIGHTS]; // xyz = position + float4 _LightDirections[MAX_LIGHTS]; // xyz = direction, w = cos(halfAngle) + float _LightType[MAX_LIGHTS]; // 0 = sphere, 1 = cone + float _PlayerCount; // set via SetFloat + //MoonsLight variables END + + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + o.uv2 = TRANSFORM_TEX(v.uv, _MultTex); + o.uvEmmis = TRANSFORM_TEX(v.uv, _EmmisiveText); + + + //MoonsLight Vertex + float4 wp = mul(unity_ObjectToWorld, v.vertex); + o.worldPos = wp.xyz; + o.worldNormal = UnityObjectToWorldNormal(v.normal); + //MoonsLight Vertex END + + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + // sample the texture + fixed4 col = tex2D(_MainTex, i.uv); + fixed4 mult = tex2D(_MultTex, i.uv2); + col = lerp(col, mult, _MultiplicatorTex); + fixed4 emmis = tex2D(_EmmisiveText, i.uvEmmis); + + + //MoonsLight + int count = (int)_PlayerCount; + + float3 N = normalize(i.worldNormal); //for lambertian diffuse + // Example: compute distance to nearest player + float4 dmax = float4(0,0,0,1); + float dIntensity = 0; + [loop] + for (int idx = 0; idx < MAX_LIGHTS; idx++) + { + if (idx >= count) break; + float radius = _LightPositions[idx].a; + float3 q = _LightPositions[idx].xyz; + + float distanceFromLight = length(i.worldPos - q); + if (distanceFromLight > _LightCutoffDistance) continue; + + float sd = 0.0; + float contrib = 0.0; + + + float invSqMul = max(1e-4, _InverseSqareMultiplier); + + + //Lambertian diffuse + float3 L = normalize(q - i.worldPos); // q = light position + float NdotL = saturate(dot(N, L) * 0.5 + 0.5); // one-sided Lambert + if (NdotL <= 0) continue; + + if(_LightType[idx] == 0) + { + float invSq = _LightColors[idx].a / max(1e-4, max(0, max(1, distanceFromLight - radius) * invSqMul) * max(0, max(1, distanceFromLight - radius) * invSqMul)); + contrib = invSq; + //contrib = contrib * step(-distance(i.worldPos, q), -1 + radius * 1); // 0 if outside sphere + dIntensity += contrib * NdotL; + } + else if (_LightType[idx] == 1) + { + float invSq = _LightColors[idx].a / max(1e-4, (distanceFromLight * invSqMul) * (distanceFromLight * invSqMul)); + float threshold = (-1 + _LightDirections[idx].w / 180); + + contrib = min(dot(normalize(i.worldPos - q), -normalize(_LightDirections[idx].xyz)), 0); + contrib= 1 - step(threshold, contrib); + + contrib = contrib * invSq; + dIntensity += contrib * NdotL; + } + float3 LightColor = _LightColors[idx].xyz; // * NormalDirMult; + + + + dmax = dmax + contrib * float4(LightColor, 1) * NdotL; // accumulate light contributions + + + + + } + + //dmax.xyz = min(dmax * dIntensity, 1.0); + dmax.w = 1.0; + dmax = dmax; + + + //MoonsLight END + + + return col * _Color * dmax + emmis * _EmmissiveStrength * _EmmissiveColor; + } + ENDCG + } + } + + FallBack "Diffuse" +} \ No newline at end of file diff --git a/Shader/BlendinShader.shader.meta b/Shader/BlendinShader.shader.meta new file mode 100644 index 0000000..84ebee5 --- /dev/null +++ b/Shader/BlendinShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 10b36b8f1c13f5947ba9527616152cdb +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Shader/GhostWhiteShader.shader b/Shader/GhostWhiteShader.shader new file mode 100644 index 0000000..a9b005d --- /dev/null +++ b/Shader/GhostWhiteShader.shader @@ -0,0 +1,83 @@ +Shader "DeMuenu/World/Hoppou/GhostWhite" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _Color ("Color", Color) = (1,1,1,1) + _EmmissiveColor ("Emmissive Color", Color) = (1,1,1,1) + _EmmissiveStrength ("Emmissive Strength", Range(0,10)) = 0 + + _BaseColor ("Base Color", Color) = (0.06,0.08,0.1,1) + _FresnelColor ("Fresnel Color", Color) = (0.3,0.7,1,1) + _Power ("Fresnel Power", Range(0.1, 8)) = 3 + _Intensity ("Fresnel Intensity", Range(0, 4)) = 1 + } + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + // make fog work + #pragma multi_compile_fog + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float3 normal : NORMAL; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + float3 worldNormal : TEXCOORD2; + float3 worldViewDir : TEXCOORD1; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + fixed4 _Color; + fixed4 _EmmissiveColor; + float _EmmissiveStrength; + fixed4 _BaseColor, _FresnelColor; + float _Power, _Intensity; + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + o.worldNormal = UnityObjectToWorldNormal(v.normal); + float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; + o.worldViewDir = _WorldSpaceCameraPos - worldPos; + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + float3 N = normalize(i.worldNormal); + float3 V = normalize(i.worldViewDir); + // Schlick-style rim: (1 - N·V)^power + float fresnel = pow(1.0 - saturate(dot(N, V)), _Power); + + // sample the texture + fixed4 col = tex2D(_MainTex, i.uv) * _Color ; + + + col = float4(col.rgb + _FresnelColor.rgb * (fresnel * _Intensity), 1); + + // apply fog + return col + (_EmmissiveColor * _EmmissiveStrength); + } + ENDCG + } + } +} diff --git a/Shader/GhostWhiteShader.shader.meta b/Shader/GhostWhiteShader.shader.meta new file mode 100644 index 0000000..cf68595 --- /dev/null +++ b/Shader/GhostWhiteShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0914d1e38b9fb9748b943666168cb363 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Shader/LitParticles.shader b/Shader/LitParticles.shader new file mode 100644 index 0000000..4ebc479 --- /dev/null +++ b/Shader/LitParticles.shader @@ -0,0 +1,186 @@ +Shader "DeMuenu/World/Hoppou/Particles/LitParticles" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _Color ("Color", Color) = (1,1,1,1) + + + //MoonsLight + _InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1 + _LightCutoffDistance ("Light Cutoff Distance", Float) = 100 + //MoonsLight END + + + + } + SubShader + { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } + Blend SrcAlpha One + Cull Off + Lighting Off + ZWrite Off + LOD 100 + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #define MAX_LIGHTS 80 // >= maxPlayers in script + + #include "UnityCG.cginc" + + + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + + float4 color : COLOR; + + float3 normal : NORMAL; + + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float4 vertex : SV_POSITION; + //MoonsLight + float3 worldPos : TEXCOORD2; + + float4 color : COLOR; + + float3 worldNormal: TEXCOORD3; + //MoonsLight END + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + sampler2D _MultTex; + float4 _MultTex_ST; + float4 _Color; + + + sampler2D _EmmisiveText; + float4 _EmmisiveText_ST; + float4 _EmmissiveColor; + float _EmmissiveStrength; + + + //MoonsLight + float _InverseSqareMultiplier; + float _LightCutoffDistance; + + float4 _LightPositions[MAX_LIGHTS]; // xyz = position + float4 _LightColors[MAX_LIGHTS]; // xyz = position + float4 _LightDirections[MAX_LIGHTS]; // xyz = direction, w = cos(halfAngle) + float _LightType[MAX_LIGHTS]; // 0 = sphere, 1 = cone + float _PlayerCount; // set via SetFloat + //MoonsLight END + + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + + + //MoonsLight + float4 wp = mul(unity_ObjectToWorld, v.vertex); + o.worldPos = wp.xyz; + o.color = v.color; + o.worldNormal = UnityObjectToWorldNormal(v.normal); + //MoonsLight END + + + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + // sample the texture + fixed4 col = tex2D(_MainTex, i.uv); + + + //MoonsLight + int count = (int)_PlayerCount; + + float3 N = normalize(i.worldNormal); //for lambertian diffuse + // Example: compute distance to nearest player + float4 dmax = float4(0,0,0,1); + float dIntensity = 0; + [loop] + for (int idx = 0; idx < MAX_LIGHTS; idx++) + { + if (idx >= count) break; + float radius = _LightPositions[idx].a; + float3 q = _LightPositions[idx].xyz; + + float distanceFromLight = length(i.worldPos - q); + if (distanceFromLight > _LightCutoffDistance) continue; + + float sd = 0.0; + float contrib = 0.0; + + + float invSqMul = max(1e-4, _InverseSqareMultiplier); + + + //Lambertian diffuse + float3 L = normalize(q - i.worldPos); // q = light position + float NdotL = saturate(dot(N, L) * 0.5 + 0.5); // one-sided Lambert + if (NdotL <= 0) continue; + + if(_LightType[idx] == 0) + { + float invSq = _LightColors[idx].a / max(1e-4, max(0, max(1, distanceFromLight - radius) * invSqMul) * max(0, max(1, distanceFromLight - radius) * invSqMul)); + contrib = invSq; + //contrib = contrib * step(-distance(i.worldPos, q), -1 + radius * 1); // 0 if outside sphere + dIntensity += contrib * NdotL; + } + else if (_LightType[idx] == 1) + { + float invSq = _LightColors[idx].a / max(1e-4, (distanceFromLight * invSqMul) * (distanceFromLight * invSqMul)); + float threshold = (-1 + _LightDirections[idx].w / 180); + + contrib = min(dot(normalize(i.worldPos - q), -normalize(_LightDirections[idx].xyz)), 0); + contrib= 1 - step(threshold, contrib); + + contrib = contrib * invSq; + dIntensity += contrib * NdotL; + } + float3 LightColor = _LightColors[idx].xyz; // * NormalDirMult; + + + + dmax = dmax + contrib * float4(LightColor, 1) * NdotL; // accumulate light contributions + + + + + } + + //dmax.xyz = min(dmax * dIntensity, 1.0); + dmax.w = 1.0; + dmax = dmax; + + + //MoonsLight END + + + + return col * _Color * min(dmax, 1.0) * i.color; + + } + ENDCG + } + } + + FallBack "Diffuse" +} \ No newline at end of file diff --git a/Shader/LitParticles.shader.meta b/Shader/LitParticles.shader.meta new file mode 100644 index 0000000..7386fd8 --- /dev/null +++ b/Shader/LitParticles.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3ee874bc1f0a27c4caf078bd17d5c0c7 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Shader/MoonsLight.cingc b/Shader/MoonsLight.cingc new file mode 100644 index 0000000..3da0818 --- /dev/null +++ b/Shader/MoonsLight.cingc @@ -0,0 +1,90 @@ +#ifndef MOONSLIGHT_INCLUDED +#define MOONSLIGHT_INCLUDED + +// You can override this before including if TEXCOORD2 is taken: +// #define MOONSLIGHT_TEXCOORD TEXCOORD4 +#ifndef MOONSLIGHT_TEXCOORD +#define MOONSLIGHT_TEXCOORD TEXCOORD2 +#endif + +// Pick a safe max for your target hardware. +#ifndef MAX_LIGHTS +#define MAX_LIGHTS 80 +#endif + +#include "UnityCG.cginc" + +// ---------- Uniforms (set from script as Global/Material arrays) ---------- +uniform float4 _LightPositions[MAX_LIGHTS]; // xyz = pos, w = radius +uniform float4 _LightColors[MAX_LIGHTS]; // xyz = rgb (not normalized), w = intensity scalar +uniform float4 _LightDirections[MAX_LIGHTS]; // xyz = dir, w = half-angle in degrees (cone) +uniform float _LightType[MAX_LIGHTS]; // 0 = sphere, 1 = cone +uniform float _PlayerCount; + +// ---------- Helpers you can inject into your v2f / vertex ---------- +#define MOONSLIGHT_V2F_MEMBERS float3 worldPos : MOONSLIGHT_TEXCOORD; + +inline void MoonsLight_FillV2F(float4 vertexOS, out float3 worldPos) +{ + worldPos = mul(unity_ObjectToWorld, vertexOS).xyz; +} + +// ---------- Core lighting (return value is 0..1 rgba contribution) ---------- +inline float4 MoonsLight_Accumulate(float3 worldPos, float3 worldNormal) +{ + float3 N = normalize(worldNormal); + float4 accum = float4(0,0,0,1); + float dIntensity = 0.0; + + int count = (int)_PlayerCount; + + [loop] + for (int idx = 0; idx < MAX_LIGHTS; idx++) + { + if (idx >= count) break; + + float3 q = _LightPositions[idx].xyz; + float radius = _LightPositions[idx].w; + + float3 L = normalize(q - worldPos); + float NdotL = saturate(dot(N, L) * 0.5 + 0.5); // one-sided Lambert + float contrib = 0.0; + + if (_LightType[idx] == 0.0) + { + // Sphere (SDF-ish falloff reused from your code) + float sd = length(worldPos - q) - radius; + sd = lerp(1.0, -sd, step(0.0, sd)); + contrib = min(1.0, max(max(sd, max(0.01, _LightColors[idx].a) / (sd * sd)), 0.01)); + dIntensity += contrib * NdotL; + } + else + { + // Cone (directional spot) + float threshold = (-1 + _LightDirections[idx].w / 180.0); + contrib = min(dot(normalize(worldPos - q), -normalize(_LightDirections[idx].xyz)), 0.0); + contrib = 1.0 - step(threshold, contrib); + float distanceFromLight = length(worldPos - q); + contrib = min(1.0, contrib * (max(0.01, _LightColors[idx].a) / (distanceFromLight * distanceFromLight))); + dIntensity += contrib * NdotL; + } + + float3 lightRgb = normalize(_LightColors[idx].xyz); + accum += contrib * float4(lightRgb, 1.0); + } + + accum.xyz = normalize(accum.xyz); + accum.xyz = min(accum.xyz * dIntensity, 1.0); + accum.w = 1.0; + return min(accum, 1.0); +} + +// Optional: reuse your camera-distance fade +inline float4 MoonsLight_ApplyDistanceFade(float4 color, float3 worldPos, float distanceFadeMultiplier, float distanceMin) +{ + float dist = length(_WorldSpaceCameraPos.xyz - worldPos) / 100.0; + color.xyz *= min(1.0, max(distanceMin, max(0.0, 1.0 - abs(dist) * distanceFadeMultiplier))); + return color; +} + +#endif // MOONSLIGHT_INCLUDED diff --git a/Shader/MoonsLight.cingc.meta b/Shader/MoonsLight.cingc.meta new file mode 100644 index 0000000..f32c089 --- /dev/null +++ b/Shader/MoonsLight.cingc.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 76476ee372212af4e9094c2e42bc3cc5 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Shader/Water.shader b/Shader/Water.shader new file mode 100644 index 0000000..8dcaccf --- /dev/null +++ b/Shader/Water.shader @@ -0,0 +1,216 @@ +Shader "DeMuenu/World/Hoppou/Water" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _Color ("Color", Color) = (1,1,1,0.5) + _NormalMap ("Normal Map", 2D) = "bump" {} + _NormalMapStrength1 ("Normal Map Strength", Range(0,1)) = 1 + _NormalMapStrength2 ("Normal Map Strength 2", Range(0,1)) = 0.5 + _NormalMap2Tiling ("Normal Map 2 Tiling", Float) = 2 + _NormalMapScrollSpeed ("Normal Map Scroll Speed", Float) = 0.1 + _NormalMapScrollSpeed2 ("Normal Map 2 Scroll Speed", Float) = 0.05 + + //MoonsLight + _InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1 + _LightCutoffDistance ("Light Cutoff Distance", Float) = 100 + + _SpecPower ("Spec Power", Range(4,256)) = 64 + _SpecIntensity ("Spec Intensity", Range(0,10)) = 1 + _AmbientFloor ("Ambient Floor", Range(0,1)) = 0.08 + + _F0 ("F0", Range(0,1)) = 0.02 + _FresnelPower ("Fresnel Power", Range(1,8)) = 5 + _ReflectionStrength ("Reflection Strength", Range(0,1)) = 0.7 + //MoonsLight END + } + SubShader + { + Tags { "Queue"="Transparent" "RenderType"="Transparent" } + LOD 100 + Blend SrcAlpha OneMinusSrcAlpha + ZWrite Off + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + + //MoonsLight Defines + #define MAX_LIGHTS 80 // >= maxPlayers in script + //MoonsLight Defines END + + struct appdata + { + float4 vertex : POSITION; + float2 uv : TEXCOORD0; + float3 normal : NORMAL; + }; + + struct v2f + { + float2 uv : TEXCOORD0; + float2 uvnorm : TEXCOORD1; + float4 vertex : SV_POSITION; + + //MoonsLight + float3 worldPos : TEXCOORD2; + float3 worldNormal: TEXCOORD3; + //MoonsLight END + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + float4 _Color; + sampler2D _NormalMap; + float4 _NormalMap_ST; + float _NormalMapStrength1; + float _NormalMapStrength2; + float _NormalMap2Tiling; + float _NormalMapScrollSpeed; + float _NormalMapScrollSpeed2; + + + //MoonsLight variables + float _InverseSqareMultiplier; + float _LightCutoffDistance; + + float4 _LightPositions[MAX_LIGHTS]; // xyz = position + float4 _LightColors[MAX_LIGHTS]; // xyz = position + float4 _LightDirections[MAX_LIGHTS]; // xyz = direction, w = cos(halfAngle) + float _LightType[MAX_LIGHTS]; // 0 = sphere, 1 = cone + float _PlayerCount; // set via SetFloat + + //Watershader specific + float _SpecPower, _SpecIntensity; + float3 _AmbientFloor; + + + float _F0, _FresnelPower, _ReflectionStrength; + + inline float SchlickFresnel(float NoV, float F0, float power) + { + float f = pow(saturate(1.0 - NoV), power); + return saturate(F0 + (1.0 - F0) * f); + } + //MoonsLight variables END + + v2f vert (appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.uv, _MainTex); + o.uvnorm = TRANSFORM_TEX(v.uv, _NormalMap); + //MoonsLight Vertex + float4 wp = mul(unity_ObjectToWorld, v.vertex); + o.worldPos = wp.xyz; + o.worldNormal = UnityObjectToWorldNormal(v.normal); + //MoonsLight Vertex END + return o; + } + + fixed4 frag (v2f i) : SV_Target + { + // sample the texture + fixed4 col = tex2D(_MainTex, i.uv); + fixed4 norm = tex2D(_NormalMap, i.uvnorm + float2(0, _NormalMapScrollSpeed * sin(_Time.y))); + fixed4 norm2 = tex2D(_NormalMap, i.uvnorm * _NormalMap2Tiling + float2(_NormalMapScrollSpeed2 * sin(_Time.y), 0)); + float3 NormalOffset1 = UnpackNormal(norm).xyz; + float3 NormalOffset2 = UnpackNormal(norm2).xyz; + + //MoonsLight + int count = (int)_PlayerCount; + + float3 N = normalize(i.worldNormal + NormalOffset1 * _NormalMapStrength1 + NormalOffset2 * _NormalMapStrength2); //for lambertian diffuse + + + //Waterspecific + float3 V = normalize(_WorldSpaceCameraPos - i.worldPos); + float3 R = reflect(-V, N); //for reflection vector + //Waterspecific END + //return float4(R,1); + + + + + // Example: compute distance to nearest player + float4 dmax = float4(0,0,0,1); + float dIntensity = 0; + [loop] + for (int idx = 0; idx < MAX_LIGHTS; idx++) + { + if (idx >= count) break; + float radius = _LightPositions[idx].a; + float3 q = _LightPositions[idx].xyz; + + float distanceFromLight = length(i.worldPos - q); + if (distanceFromLight > _LightCutoffDistance) continue; + + float sd = 0.0; + float contrib = 0.0; + + + float invSqMul = max(1e-4, _InverseSqareMultiplier); + + + //Lambertian diffuse + float3 L = normalize(q - i.worldPos); // q = light position + float NdotL = saturate(dot(N, L) * 0.5 + 0.5); // one-sided Lambert + if (NdotL <= 0) continue; + + if(_LightType[idx] == 0) + { + float invSq = _LightColors[idx].a / max(1e-4, max(0, max(1, distanceFromLight - radius) * invSqMul) * max(0, max(1, distanceFromLight - radius) * invSqMul)); + contrib = invSq; + //contrib = contrib * step(-distance(i.worldPos, q), -1 + radius * 1); // 0 if outside sphere + dIntensity += contrib * NdotL; + } + else if (_LightType[idx] == 1) + { + float invSq = _LightColors[idx].a / max(1e-4, (distanceFromLight * invSqMul) * (distanceFromLight * invSqMul)); + float threshold = (-1 + _LightDirections[idx].w / 180); + + contrib = min(dot(normalize(i.worldPos - q), -normalize(_LightDirections[idx].xyz)), 0); + contrib= 1 - step(threshold, contrib); + + contrib = contrib * invSq; + dIntensity += contrib * NdotL; + } + float3 LightColor = _LightColors[idx].xyz; // * NormalDirMult; + + //Watershader specific + //float fres = Schlick(saturate(dot(N, V)), _F0, _FresnelPower); + float3 R = reflect(-V, N); + float spec = pow(saturate(dot(R, L)), _SpecPower); + //return float4(spec, spec, spec,1); + dmax.rgb += _LightColors[idx].rgb * contrib + _LightColors[idx].rgb * _SpecIntensity * spec * contrib; + dmax.a -= _SpecIntensity * spec; + //dmax = dmax + contrib * float4(LightColor, 1); // accumulate light contributions + + + + } + + //dmax.xyz = min(dmax * dIntensity, 1.0); + + float NoV = saturate(dot(N, V)); + float fres = SchlickFresnel(NoV, _F0, _FresnelPower); + + dmax.w = 1.0; + dmax.a = dmax.a * _ReflectionStrength * fres; + + + //MoonsLight END + + + + // Final color + return col * _Color * dmax ; + } + ENDCG + } + } +} diff --git a/Shader/Water.shader.meta b/Shader/Water.shader.meta new file mode 100644 index 0000000..641231a --- /dev/null +++ b/Shader/Water.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b99615b9af356d248a6940b9961c417a +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: