mirror of
https://github.com/DeMuenu/MoonlightVRC.git
synced 2025-12-13 11:33:54 +00:00
@@ -17,7 +17,8 @@ public static class PlayerPositionsToShaderPreview
|
|||||||
public Vector4[] colors;
|
public Vector4[] colors;
|
||||||
public Vector4[] directions;
|
public Vector4[] directions;
|
||||||
public float[] types;
|
public float[] types;
|
||||||
public int size;
|
public float[] shadowMapIndices;
|
||||||
|
public int size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PlayerPositionsToShaderPreview()
|
static PlayerPositionsToShaderPreview()
|
||||||
@@ -66,16 +67,17 @@ public static class PlayerPositionsToShaderPreview
|
|||||||
static void EnsureArrays(PlayerPositionsToShader src, int required)
|
static void EnsureArrays(PlayerPositionsToShader src, int required)
|
||||||
{
|
{
|
||||||
if (!_cache.TryGetValue(src, out var c) ||
|
if (!_cache.TryGetValue(src, out var c) ||
|
||||||
c.positions == null || c.colors == null || c.directions == null || c.types == null ||
|
c.positions == null || c.colors == null || c.directions == null || c.types == null || c.shadowMapIndices == null ||
|
||||||
c.size != required)
|
c.size != required)
|
||||||
{
|
{
|
||||||
c = new Cache
|
c = new Cache
|
||||||
{
|
{
|
||||||
positions = new Vector4[required],
|
positions = new Vector4[required],
|
||||||
colors = new Vector4[required],
|
colors = new Vector4[required],
|
||||||
directions = new Vector4[required],
|
directions = new Vector4[required],
|
||||||
types = new float[required],
|
types = new float[required],
|
||||||
size = required
|
shadowMapIndices = new float[required],
|
||||||
|
size = required
|
||||||
};
|
};
|
||||||
_cache[src] = c;
|
_cache[src] = c;
|
||||||
}
|
}
|
||||||
@@ -87,25 +89,27 @@ public static class PlayerPositionsToShaderPreview
|
|||||||
EnsureArrays(src, max);
|
EnsureArrays(src, max);
|
||||||
|
|
||||||
var c = _cache[src];
|
var c = _cache[src];
|
||||||
var positions = c.positions;
|
var positions = c.positions;
|
||||||
var colors = c.colors;
|
var colors = c.colors;
|
||||||
var directions = c.directions;
|
var directions = c.directions;
|
||||||
var types = c.types;
|
var types = c.types;
|
||||||
|
var shadowMapIndices = c.shadowMapIndices;
|
||||||
|
|
||||||
// Clear arrays to safe defaults
|
// Clear arrays to safe defaults
|
||||||
for (int i = 0; i < max; i++)
|
for (int i = 0; i < max; i++)
|
||||||
{
|
{
|
||||||
positions[i] = Vector4.zero;
|
positions[i] = Vector4.zero;
|
||||||
colors[i] = Vector4.zero;
|
colors[i] = Vector4.zero;
|
||||||
directions[i] = Vector4.zero;
|
directions[i] = Vector4.zero;
|
||||||
types[i] = 0f;
|
types[i] = 0f;
|
||||||
|
shadowMapIndices[i] = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the Editor-side function defined on the partial class
|
// Use the Editor-side function defined on the partial class
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
src.Editor_BuildPreview(out positions, out colors, out directions, out types, out count);
|
src.Editor_BuildPreview(out positions, out colors, out directions, out types, out shadowMapIndices, out count);
|
||||||
|
|
||||||
// replace cache arrays if sizes changed
|
// replace cache arrays if sizes changed
|
||||||
if (positions.Length != c.size)
|
if (positions.Length != c.size)
|
||||||
@@ -113,11 +117,12 @@ public static class PlayerPositionsToShaderPreview
|
|||||||
|
|
||||||
_cache[src] = new Cache
|
_cache[src] = new Cache
|
||||||
{
|
{
|
||||||
positions = positions,
|
positions = positions,
|
||||||
colors = colors,
|
colors = colors,
|
||||||
directions = directions,
|
directions = directions,
|
||||||
types = types,
|
types = types,
|
||||||
size = positions.Length
|
shadowMapIndices = shadowMapIndices,
|
||||||
|
size = positions.Length
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -152,6 +157,12 @@ public static class PlayerPositionsToShaderPreview
|
|||||||
Shader.SetGlobalFloatArray(id, types);
|
Shader.SetGlobalFloatArray(id, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(src.shadowMapIndexProperty))
|
||||||
|
{
|
||||||
|
int id = Shader.PropertyToID(src.shadowMapIndexProperty);
|
||||||
|
Shader.SetGlobalFloatArray(id, shadowMapIndices);
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(src.countProperty))
|
if (!string.IsNullOrEmpty(src.countProperty))
|
||||||
{
|
{
|
||||||
int id = Shader.PropertyToID(src.countProperty);
|
int id = Shader.PropertyToID(src.countProperty);
|
||||||
|
|||||||
152
EditorPreview/Editor/ShadowcasterUpdaterPreview.cs
Normal file
152
EditorPreview/Editor/ShadowcasterUpdaterPreview.cs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public static class ShadowcasterUpdaterEditorLoop
|
||||||
|
{
|
||||||
|
private const double Interval = 0.1;
|
||||||
|
private const float Eps = 1e-6f;
|
||||||
|
|
||||||
|
private static double _lastUpdateTime;
|
||||||
|
private static ShadowcasterUpdater[] _cached;
|
||||||
|
private static readonly MaterialPropertyBlock _mpb = new MaterialPropertyBlock();
|
||||||
|
|
||||||
|
static ShadowcasterUpdaterEditorLoop()
|
||||||
|
{
|
||||||
|
_lastUpdateTime = EditorApplication.timeSinceStartup;
|
||||||
|
|
||||||
|
EditorApplication.update += Update;
|
||||||
|
EditorApplication.hierarchyChanged += RefreshCache;
|
||||||
|
AssemblyReloadEvents.afterAssemblyReload += RefreshCache;
|
||||||
|
|
||||||
|
RefreshCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RefreshCache()
|
||||||
|
{
|
||||||
|
_cached = FindSceneUpdaters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ShadowcasterUpdater[] FindSceneUpdaters()
|
||||||
|
{
|
||||||
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
return Object.FindObjectsOfType<ShadowcasterUpdater>(true);
|
||||||
|
#else
|
||||||
|
// Unity 2019-compatible path: include inactive, filter out assets/prefabs not in a scene
|
||||||
|
var all = Resources.FindObjectsOfTypeAll(typeof(ShadowcasterUpdater));
|
||||||
|
var list = new List<ShadowcasterUpdater>(all.Length);
|
||||||
|
foreach (var o in all)
|
||||||
|
{
|
||||||
|
var c = o as ShadowcasterUpdater;
|
||||||
|
if (c == null) continue;
|
||||||
|
if (EditorUtility.IsPersistent(c)) continue; // skip assets
|
||||||
|
if (!c.gameObject.scene.IsValid()) continue;
|
||||||
|
list.Add(c);
|
||||||
|
}
|
||||||
|
return list.ToArray();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Update()
|
||||||
|
{
|
||||||
|
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
|
||||||
|
if (EditorApplication.isCompiling) return;
|
||||||
|
|
||||||
|
var now = EditorApplication.timeSinceStartup;
|
||||||
|
if (now - _lastUpdateTime < Interval) return;
|
||||||
|
_lastUpdateTime = now;
|
||||||
|
|
||||||
|
var arr = _cached;
|
||||||
|
if (arr == null || arr.Length == 0) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < arr.Length; i++)
|
||||||
|
{
|
||||||
|
var u = arr[i];
|
||||||
|
if (u == null) continue;
|
||||||
|
TryUpdate(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make changes visible in Scene/Game view without wiggling the mouse
|
||||||
|
SceneView.RepaintAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryUpdate(ShadowcasterUpdater u)
|
||||||
|
{
|
||||||
|
// If inspector values changed, make sure textures/colors/min brightness are pushed
|
||||||
|
try
|
||||||
|
{
|
||||||
|
u.ApplyTextureData();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// UdonSharp can be touchy during certain editor states. Ignore and continue.
|
||||||
|
}
|
||||||
|
|
||||||
|
var targets = u.rendererTargets;
|
||||||
|
if (targets == null || targets.Length == 0) return;
|
||||||
|
|
||||||
|
// Match the runtime script's plane definition (0.5 half-size before scaling)
|
||||||
|
const float quadHalfWidth = 0.5f;
|
||||||
|
const float quadHalfHeight = 0.5f;
|
||||||
|
|
||||||
|
Transform t = u.transform;
|
||||||
|
|
||||||
|
// World-space basis from transform
|
||||||
|
Vector3 Udir = t.rotation * Vector3.right; // local +X
|
||||||
|
Vector3 Vdir = t.rotation * Vector3.up; // local +Y
|
||||||
|
|
||||||
|
// Half extents after non-uniform scaling
|
||||||
|
float halfW = Mathf.Max(quadHalfWidth * t.lossyScale.x, Eps);
|
||||||
|
float halfH = Mathf.Max(quadHalfHeight * t.lossyScale.y, Eps);
|
||||||
|
|
||||||
|
// Reciprocal axes so dot(r, Uinv/Vinv) -> [-0.5, 0.5]
|
||||||
|
Vector3 Uinv = Udir / (2.0f * halfW);
|
||||||
|
Vector3 Vinv = Vdir / (2.0f * halfH);
|
||||||
|
|
||||||
|
// Unit normal
|
||||||
|
Vector3 N = Vector3.Normalize(Vector3.Cross(Udir, Vdir));
|
||||||
|
|
||||||
|
int idx = Mathf.Max(0, u.shadowcasterIndex);
|
||||||
|
string suf = "_" + idx.ToString();
|
||||||
|
|
||||||
|
int idShadowTex = Shader.PropertyToID("_Udon_shadowCasterTex" + suf);
|
||||||
|
int idShadowColor = Shader.PropertyToID("_Udon_shadowCasterColor" + suf);
|
||||||
|
int idOutsideColor = Shader.PropertyToID("_Udon_OutSideColor" + suf);
|
||||||
|
int idMinBrightness = Shader.PropertyToID("_Udon_MinBrightnessShadow" + suf);
|
||||||
|
|
||||||
|
int idPlaneOrigin = Shader.PropertyToID("_Udon_Plane_Origin_" + idx.ToString());
|
||||||
|
int idPlaneUinv = Shader.PropertyToID("_Udon_Plane_Uinv_" + idx.ToString());
|
||||||
|
int idPlaneVinv = Shader.PropertyToID("_Udon_Plane_Vinv_" + idx.ToString());
|
||||||
|
int idPlaneNormal = Shader.PropertyToID("_Udon_Plane_Normal_" + idx.ToString());
|
||||||
|
|
||||||
|
Vector4 origin = new Vector4(t.position.x, t.position.y, t.position.z, 0);
|
||||||
|
Vector4 uinv4 = new Vector4(Uinv.x, Uinv.y, Uinv.z, 0);
|
||||||
|
Vector4 vinv4 = new Vector4(Vinv.x, Vinv.y, Vinv.z, 0);
|
||||||
|
Vector4 n4 = new Vector4(N.x, N.y, N.z, 0);
|
||||||
|
|
||||||
|
for (int r = 0; r < targets.Length; r++)
|
||||||
|
{
|
||||||
|
var ren = targets[r];
|
||||||
|
if (ren == null) continue;
|
||||||
|
|
||||||
|
ren.GetPropertyBlock(_mpb);
|
||||||
|
|
||||||
|
// Also mirror texture/color in case ApplyTextureData couldn't run
|
||||||
|
if (u.ShadowcasterTexture != null) _mpb.SetTexture(idShadowTex, u.ShadowcasterTexture);
|
||||||
|
_mpb.SetColor(idShadowColor, u.TextureColor);
|
||||||
|
_mpb.SetColor(idOutsideColor, u.OutsideColor);
|
||||||
|
_mpb.SetFloat(idMinBrightness, u.MinBrightness);
|
||||||
|
|
||||||
|
// Plane data
|
||||||
|
_mpb.SetVector(idPlaneOrigin, origin);
|
||||||
|
_mpb.SetVector(idPlaneUinv, uinv4);
|
||||||
|
_mpb.SetVector(idPlaneVinv, vinv4);
|
||||||
|
_mpb.SetVector(idPlaneNormal, n4);
|
||||||
|
|
||||||
|
ren.SetPropertyBlock(_mpb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
EditorPreview/Editor/ShadowcasterUpdaterPreview.cs.meta
Normal file
11
EditorPreview/Editor/ShadowcasterUpdaterPreview.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0491ab6ce27c5ba449e98288f0e3d8ed
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -9,44 +9,52 @@ public partial class PlayerPositionsToShader
|
|||||||
out Vector4[] colors,
|
out Vector4[] colors,
|
||||||
out Vector4[] directions,
|
out Vector4[] directions,
|
||||||
out float[] types,
|
out float[] types,
|
||||||
|
out float[] shadowMapIndices,
|
||||||
out int count)
|
out int count)
|
||||||
{
|
{
|
||||||
int max = Mathf.Max(1, maxLights);
|
int max = Mathf.Max(1, maxLights);
|
||||||
|
|
||||||
positions = new Vector4[max];
|
positions = new Vector4[max];
|
||||||
colors = new Vector4[max];
|
colors = new Vector4[max];
|
||||||
directions = new Vector4[max];
|
directions = new Vector4[max];
|
||||||
types = new float[max];
|
types = new float[max];
|
||||||
count = 0;
|
shadowMapIndices = new float[max];
|
||||||
|
count = 0;
|
||||||
|
|
||||||
// ✅ Avoid Array.Empty<T>(); just guard the loop
|
if (otherLightSources == null) return;
|
||||||
if (otherLightSources != null)
|
|
||||||
|
for (int i = 0; i < otherLightSources.Length && count < max; i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < otherLightSources.Length && count < max; i++)
|
Transform t = otherLightSources[i];
|
||||||
{
|
if (t == null || !t.gameObject.activeInHierarchy) continue;
|
||||||
Transform t = otherLightSources[i];
|
|
||||||
if (t == null || !t.gameObject.activeInHierarchy) continue;
|
|
||||||
|
|
||||||
LightdataStorage data = t.GetComponent<LightdataStorage>();
|
LightdataStorage data = t.GetComponent<LightdataStorage>();
|
||||||
|
|
||||||
Vector3 pos = t.position;
|
Vector3 pos = t.position;
|
||||||
float range = (data != null) ? data.range * t.localScale.x : t.localScale.x;
|
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;
|
|
||||||
|
|
||||||
|
// rgb = color, a = intensity (packed to match runtime/shader)
|
||||||
|
Vector4 col = (data != null) ? data.GetFinalColor() : new Vector4(1f, 1f, 1f, 1f);
|
||||||
|
float intensity = (data != null) ? data.intensity * t.localScale.x : 1f;
|
||||||
|
|
||||||
Quaternion rot = t.rotation;
|
// w = cosHalfAngle (0 for omni)
|
||||||
Vector3 fwd = rot * Vector3.down;
|
float cosHalf = (data != null) ? data.GetCosHalfAngle() : 0f;
|
||||||
|
|
||||||
positions[count] = new Vector4(pos.x, pos.y, pos.z, range);
|
// 0=Omni, 1=Spot, 2=Directional (your custom enum)
|
||||||
colors[count] = new Vector4(col.x, col.y, col.z, intens);
|
int typeId = (data != null) ? data.GetTypeId() : 0;
|
||||||
directions[count] = new Vector4(fwd.x, fwd.y, fwd.z, data.spotAngleDeg);
|
|
||||||
types[count] = (float)typeId;
|
|
||||||
|
|
||||||
count++;
|
float shIndex = (data != null) ? data.shadowMapIndex : 0f;
|
||||||
}
|
|
||||||
|
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, intensity);
|
||||||
|
directions[count] = new Vector4(fwd.x, fwd.y, fwd.z, cosHalf);
|
||||||
|
types[count] = (float)typeId;
|
||||||
|
shadowMapIndices[count] = shIndex;
|
||||||
|
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
Mesh.meta
Normal file
8
Mesh.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2d573c2258a40a04f9932e8910763931
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Mesh/Plane.fbx
Normal file
BIN
Mesh/Plane.fbx
Normal file
Binary file not shown.
109
Mesh/Plane.fbx.meta
Normal file
109
Mesh/Plane.fbx.meta
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 26a14a3ac3d4388458abdbca51f4efc8
|
||||||
|
ModelImporter:
|
||||||
|
serializedVersion: 22200
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
materials:
|
||||||
|
materialImportMode: 2
|
||||||
|
materialName: 0
|
||||||
|
materialSearch: 1
|
||||||
|
materialLocation: 1
|
||||||
|
animations:
|
||||||
|
legacyGenerateAnimations: 4
|
||||||
|
bakeSimulation: 0
|
||||||
|
resampleCurves: 1
|
||||||
|
optimizeGameObjects: 0
|
||||||
|
removeConstantScaleCurves: 0
|
||||||
|
motionNodeName:
|
||||||
|
rigImportErrors:
|
||||||
|
rigImportWarnings:
|
||||||
|
animationImportErrors:
|
||||||
|
animationImportWarnings:
|
||||||
|
animationRetargetingWarnings:
|
||||||
|
animationDoRetargetingWarnings: 0
|
||||||
|
importAnimatedCustomProperties: 0
|
||||||
|
importConstraints: 0
|
||||||
|
animationCompression: 1
|
||||||
|
animationRotationError: 0.5
|
||||||
|
animationPositionError: 0.5
|
||||||
|
animationScaleError: 0.5
|
||||||
|
animationWrapMode: 0
|
||||||
|
extraExposedTransformPaths: []
|
||||||
|
extraUserProperties: []
|
||||||
|
clipAnimations: []
|
||||||
|
isReadable: 0
|
||||||
|
meshes:
|
||||||
|
lODScreenPercentages: []
|
||||||
|
globalScale: 1
|
||||||
|
meshCompression: 0
|
||||||
|
addColliders: 0
|
||||||
|
useSRGBMaterialColor: 1
|
||||||
|
sortHierarchyByName: 1
|
||||||
|
importPhysicalCameras: 1
|
||||||
|
importVisibility: 1
|
||||||
|
importBlendShapes: 1
|
||||||
|
importCameras: 1
|
||||||
|
importLights: 1
|
||||||
|
nodeNameCollisionStrategy: 1
|
||||||
|
fileIdsGeneration: 2
|
||||||
|
swapUVChannels: 0
|
||||||
|
generateSecondaryUV: 0
|
||||||
|
useFileUnits: 1
|
||||||
|
keepQuads: 0
|
||||||
|
weldVertices: 1
|
||||||
|
bakeAxisConversion: 0
|
||||||
|
preserveHierarchy: 0
|
||||||
|
skinWeightsMode: 0
|
||||||
|
maxBonesPerVertex: 4
|
||||||
|
minBoneWeight: 0.001
|
||||||
|
optimizeBones: 1
|
||||||
|
meshOptimizationFlags: -1
|
||||||
|
indexFormat: 0
|
||||||
|
secondaryUVAngleDistortion: 8
|
||||||
|
secondaryUVAreaDistortion: 15.000001
|
||||||
|
secondaryUVHardAngle: 88
|
||||||
|
secondaryUVMarginMethod: 1
|
||||||
|
secondaryUVMinLightmapResolution: 40
|
||||||
|
secondaryUVMinObjectScale: 1
|
||||||
|
secondaryUVPackMargin: 4
|
||||||
|
useFileScale: 1
|
||||||
|
strictVertexDataChecks: 0
|
||||||
|
tangentSpace:
|
||||||
|
normalSmoothAngle: 60
|
||||||
|
normalImportMode: 0
|
||||||
|
tangentImportMode: 3
|
||||||
|
normalCalculationMode: 4
|
||||||
|
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
|
||||||
|
blendShapeNormalImportMode: 1
|
||||||
|
normalSmoothingSource: 0
|
||||||
|
referencedClips: []
|
||||||
|
importAnimation: 1
|
||||||
|
humanDescription:
|
||||||
|
serializedVersion: 3
|
||||||
|
human: []
|
||||||
|
skeleton: []
|
||||||
|
armTwist: 0.5
|
||||||
|
foreArmTwist: 0.5
|
||||||
|
upperLegTwist: 0.5
|
||||||
|
legTwist: 0.5
|
||||||
|
armStretch: 0.05
|
||||||
|
legStretch: 0.05
|
||||||
|
feetSpacing: 0
|
||||||
|
globalScale: 1
|
||||||
|
rootMotionBoneName:
|
||||||
|
hasTranslationDoF: 0
|
||||||
|
hasExtraRoot: 0
|
||||||
|
skeletonHasParents: 1
|
||||||
|
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||||
|
autoGenerateAvatarMappingIfUnspecified: 1
|
||||||
|
animationType: 2
|
||||||
|
humanoidOversampling: 1
|
||||||
|
avatarSetup: 0
|
||||||
|
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
|
||||||
|
importBlendShapeDeformPercent: 1
|
||||||
|
remapMaterialsIfMaterialImportModeIsNone: 0
|
||||||
|
additionalBone: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -32,6 +32,10 @@ public class LightdataStorage : UdonSharpBehaviour
|
|||||||
[Tooltip("0 = omni (no cone)")]
|
[Tooltip("0 = omni (no cone)")]
|
||||||
public float spotAngleDeg = 0f;
|
public float spotAngleDeg = 0f;
|
||||||
|
|
||||||
|
[Header("Shadow Settings")]
|
||||||
|
[Tooltip("0 = no shadows, 1-4 = shadow map index")]
|
||||||
|
public float shadowMapIndex = 0f; // 0 = no shadows, 1-4 = shadow map index
|
||||||
|
|
||||||
// Convert to a Vector4 for your shader upload
|
// Convert to a Vector4 for your shader upload
|
||||||
public Vector4 GetFinalColor()
|
public Vector4 GetFinalColor()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
public float playerLightIntensity = 5f;
|
public float playerLightIntensity = 5f;
|
||||||
public float remoteLightIntensity = 2f;
|
public float remoteLightIntensity = 2f;
|
||||||
|
|
||||||
|
[Tooltip("0 = no shadows, 1-4 = shadow map index")]
|
||||||
|
public float PlayerShadowMapIndex = 0f; // 0 = no shadows, 1-4 = shadow map index
|
||||||
|
|
||||||
|
|
||||||
[Header("Shader property names (advanced users)")]
|
[Header("Shader property names (advanced users)")]
|
||||||
[Tooltip("Vector4 array: xyz = position, w = range")]
|
[Tooltip("Vector4 array: xyz = position, w = range")]
|
||||||
@@ -41,6 +44,9 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
[Tooltip("float array: light type (1=area, 2=cone, etc)")]
|
[Tooltip("float array: light type (1=area, 2=cone, etc)")]
|
||||||
public string typeProperty = "_Udon_LightType";
|
public string typeProperty = "_Udon_LightType";
|
||||||
|
|
||||||
|
[Tooltip("float array: shadow map index (0=none, 1-4=shadow map index)")]
|
||||||
|
public string shadowMapIndexProperty = "_Udon_ShadowMapIndex";
|
||||||
|
|
||||||
[Header("Max Lights (advanced users)")]
|
[Header("Max Lights (advanced users)")]
|
||||||
[Tooltip("Hard cap / array size. 80 = default cap")]
|
[Tooltip("Hard cap / array size. 80 = default cap")]
|
||||||
public int maxLights = 80;
|
public int maxLights = 80;
|
||||||
@@ -57,9 +63,11 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
|
|
||||||
private float[] _TypeArray;
|
private float[] _TypeArray;
|
||||||
private bool _TypeArray_isDirty = false;
|
private bool _TypeArray_isDirty = false;
|
||||||
|
private float[] _ShadowMapArray;
|
||||||
|
private bool _ShadowMap_isDirty = false;
|
||||||
|
|
||||||
private VRCPlayerApi[] _players;
|
private VRCPlayerApi[] _players;
|
||||||
private MaterialPropertyBlock _mpb;
|
|
||||||
|
|
||||||
public int currentCount { get; private set; }
|
public int currentCount { get; private set; }
|
||||||
|
|
||||||
@@ -70,6 +78,7 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
private int UdonID_LightColors;
|
private int UdonID_LightColors;
|
||||||
private int UdonID_LightDirections;
|
private int UdonID_LightDirections;
|
||||||
private int UdonID_LightType;
|
private int UdonID_LightType;
|
||||||
|
private int UdonID_ShadowMapIndex;
|
||||||
|
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
@@ -79,15 +88,16 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
_lightColors = new Vector4[maxLights];
|
_lightColors = new Vector4[maxLights];
|
||||||
_directions = new Vector4[maxLights];
|
_directions = new Vector4[maxLights];
|
||||||
_TypeArray = new float[maxLights];
|
_TypeArray = new float[maxLights];
|
||||||
|
_ShadowMapArray = new float[maxLights];
|
||||||
|
|
||||||
_players = new VRCPlayerApi[maxLights];
|
_players = new VRCPlayerApi[maxLights];
|
||||||
_mpb = new MaterialPropertyBlock();
|
|
||||||
|
|
||||||
UdonID_PlayerPositions = VRCShader.PropertyToID(positionsProperty);
|
UdonID_PlayerPositions = VRCShader.PropertyToID(positionsProperty);
|
||||||
UdonID_LightCount = VRCShader.PropertyToID(countProperty);
|
UdonID_LightCount = VRCShader.PropertyToID(countProperty);
|
||||||
UdonID_LightColors = VRCShader.PropertyToID(colorProperty);
|
UdonID_LightColors = VRCShader.PropertyToID(colorProperty);
|
||||||
UdonID_LightDirections = VRCShader.PropertyToID(directionsProperty);
|
UdonID_LightDirections = VRCShader.PropertyToID(directionsProperty);
|
||||||
UdonID_LightType = VRCShader.PropertyToID(typeProperty);
|
UdonID_LightType = VRCShader.PropertyToID(typeProperty);
|
||||||
|
UdonID_ShadowMapIndex = VRCShader.PropertyToID(shadowMapIndexProperty);
|
||||||
|
|
||||||
|
|
||||||
UpdateData();
|
UpdateData();
|
||||||
@@ -150,6 +160,11 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
_TypeArray[i] = 0f;
|
_TypeArray[i] = 0f;
|
||||||
_TypeArray_isDirty = true;
|
_TypeArray_isDirty = true;
|
||||||
}
|
}
|
||||||
|
if (_ShadowMapArray[i] != PlayerShadowMapIndex)
|
||||||
|
{
|
||||||
|
_ShadowMapArray[i] = PlayerShadowMapIndex;
|
||||||
|
_ShadowMap_isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -175,6 +190,11 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
_TypeArray[i] = 0f;
|
_TypeArray[i] = 0f;
|
||||||
_TypeArray_isDirty = true;
|
_TypeArray_isDirty = true;
|
||||||
}
|
}
|
||||||
|
if (_ShadowMapArray[i] != 0f)
|
||||||
|
{
|
||||||
|
_ShadowMapArray[i] = 0f;
|
||||||
|
_ShadowMap_isDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +250,13 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
_TypeArray_isDirty = true;
|
_TypeArray_isDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float shadowMapIndex = (data != null) ? data.shadowMapIndex : 0f;
|
||||||
|
if (_ShadowMapArray[currentCount] != shadowMapIndex)
|
||||||
|
{
|
||||||
|
_ShadowMapArray[currentCount] = shadowMapIndex;
|
||||||
|
_ShadowMap_isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
currentCount++;
|
currentCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,6 +286,12 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
_TypeArray[i] = 0f;
|
_TypeArray[i] = 0f;
|
||||||
_TypeArray_isDirty = true;
|
_TypeArray_isDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_ShadowMapArray[i] != 0f)
|
||||||
|
{
|
||||||
|
_ShadowMapArray[i] = 0f;
|
||||||
|
_ShadowMap_isDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,23 +300,26 @@ public partial class PlayerPositionsToShader : UdonSharpBehaviour
|
|||||||
|
|
||||||
// Snapshot which things are dirty this frame
|
// Snapshot which things are dirty this frame
|
||||||
bool pushPositions = _positons_isDirty;
|
bool pushPositions = _positons_isDirty;
|
||||||
bool pushColors = _lightColors_isDirty;
|
bool pushColors = _lightColors_isDirty;
|
||||||
bool pushDirs = _directions_isDirty;
|
bool pushDirs = _directions_isDirty;
|
||||||
bool pushTypes = _TypeArray_isDirty && !string.IsNullOrEmpty(typeProperty);
|
bool pushTypes = _TypeArray_isDirty && !string.IsNullOrEmpty(typeProperty);
|
||||||
|
bool pushShadowMap = _ShadowMap_isDirty;
|
||||||
|
|
||||||
|
|
||||||
if (pushPositions) VRCShader.SetGlobalVectorArray(UdonID_PlayerPositions, _positions);
|
if (pushPositions) VRCShader.SetGlobalVectorArray(UdonID_PlayerPositions, _positions);
|
||||||
if (pushColors) VRCShader.SetGlobalVectorArray(UdonID_LightColors, _lightColors);
|
if (pushColors) VRCShader.SetGlobalVectorArray(UdonID_LightColors, _lightColors);
|
||||||
if (pushDirs) VRCShader.SetGlobalVectorArray(UdonID_LightDirections, _directions);
|
if (pushDirs) VRCShader.SetGlobalVectorArray(UdonID_LightDirections, _directions);
|
||||||
if (pushTypes) _mpb.SetFloatArray(UdonID_LightType, _TypeArray);
|
if (pushTypes) VRCShader.SetGlobalFloatArray(UdonID_LightType, _TypeArray);
|
||||||
|
if (pushShadowMap) VRCShader.SetGlobalFloatArray(UdonID_ShadowMapIndex, _ShadowMapArray);
|
||||||
|
|
||||||
VRCShader.SetGlobalFloat(UdonID_LightCount, currentCount);
|
VRCShader.SetGlobalFloat(UdonID_LightCount, currentCount);
|
||||||
|
Debug.Log($"[MoonlightVRC] Pushed {currentCount} lights to shader.");
|
||||||
|
|
||||||
// Only now mark them clean
|
// Only now mark them clean
|
||||||
if (pushPositions) { _positons_isDirty = false;}
|
if (pushPositions) { _positons_isDirty = false; }
|
||||||
if (pushColors) { _lightColors_isDirty = false;}
|
if (pushColors) { _lightColors_isDirty = false; }
|
||||||
if (pushDirs) { _directions_isDirty = false;}
|
if (pushDirs) { _directions_isDirty = false; }
|
||||||
if (pushTypes) { _TypeArray_isDirty = false;}
|
if (pushTypes) { _TypeArray_isDirty = false; }
|
||||||
|
if (pushShadowMap) { _ShadowMap_isDirty = false; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
76
Scripts/ShadowcasterUpdater.cs
Normal file
76
Scripts/ShadowcasterUpdater.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
using System.Security.Permissions;
|
||||||
|
using UdonSharp;
|
||||||
|
using UnityEngine;
|
||||||
|
using VRC.SDKBase;
|
||||||
|
using VRC.Udon;
|
||||||
|
|
||||||
|
public class ShadowcasterUpdater : UdonSharpBehaviour
|
||||||
|
{
|
||||||
|
|
||||||
|
public Renderer[] rendererTargets;
|
||||||
|
public Texture2D ShadowcasterTexture;
|
||||||
|
public Color OutsideColor = Color.white;
|
||||||
|
public Color TextureColor = Color.white;
|
||||||
|
public float MinBrightness = 0.0f;
|
||||||
|
|
||||||
|
public int shadowcasterIndex = 1;
|
||||||
|
|
||||||
|
private MaterialPropertyBlock _mpb;
|
||||||
|
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
_mpb = new MaterialPropertyBlock();
|
||||||
|
ApplyTextureData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyTextureData()
|
||||||
|
{
|
||||||
|
foreach (Renderer mat in rendererTargets)
|
||||||
|
{
|
||||||
|
if (mat == null) continue;
|
||||||
|
mat.GetPropertyBlock(_mpb);
|
||||||
|
_mpb.SetTexture("_Udon_shadowCasterTex" + "_" + shadowcasterIndex.ToString(), ShadowcasterTexture);
|
||||||
|
_mpb.SetColor("_Udon_shadowCasterColor" + "_" + shadowcasterIndex.ToString(), TextureColor);
|
||||||
|
_mpb.SetColor("_Udon_OutSideColor" + "_" + shadowcasterIndex.ToString(), OutsideColor);
|
||||||
|
_mpb.SetFloat("_Udon_MinBrightnessShadow" + "_" + shadowcasterIndex.ToString(), MinBrightness);
|
||||||
|
mat.SetPropertyBlock(_mpb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void LateUpdate()
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (Renderer mat in rendererTargets)
|
||||||
|
{
|
||||||
|
if (mat == null) continue;
|
||||||
|
mat.GetPropertyBlock(_mpb);
|
||||||
|
|
||||||
|
float quadHalfWidth = 0.5f;
|
||||||
|
float quadHalfHeight = 0.5f;
|
||||||
|
|
||||||
|
// World-space basis directions from transform
|
||||||
|
Vector3 Udir = transform.rotation * Vector3.right; // plane local +X
|
||||||
|
Vector3 Vdir = transform.rotation * Vector3.up; // plane local +Y
|
||||||
|
|
||||||
|
// World-space half extents after non-uniform scaling
|
||||||
|
float halfW = quadHalfWidth * transform.lossyScale.x;
|
||||||
|
float halfH = quadHalfHeight * transform.lossyScale.y;
|
||||||
|
|
||||||
|
// Reciprocal axes so dot(r, Uinv/Vinv) -> [-0.5, 0.5]
|
||||||
|
Vector3 Uinv = Udir / (2.0f * Mathf.Max(halfW, 1e-6f));
|
||||||
|
Vector3 Vinv = Vdir / (2.0f * Mathf.Max(halfH, 1e-6f));
|
||||||
|
|
||||||
|
// Unit normal
|
||||||
|
Vector3 N = Vector3.Normalize(Vector3.Cross(Udir, Vdir));
|
||||||
|
|
||||||
|
_mpb.SetVector("_Udon_Plane_Origin_" + shadowcasterIndex.ToString(), new Vector4(transform.position.x, transform.position.y, transform.position.z, 0));
|
||||||
|
_mpb.SetVector("_Udon_Plane_Uinv_" + shadowcasterIndex.ToString(), new Vector4(Uinv.x, Uinv.y, Uinv.z, 0));
|
||||||
|
_mpb.SetVector("_Udon_Plane_Vinv_" + shadowcasterIndex.ToString(), new Vector4(Vinv.x, Vinv.y, Vinv.z, 0));
|
||||||
|
_mpb.SetVector("_Udon_Plane_Normal_" + shadowcasterIndex.ToString(), new Vector4(N.x, N.y, N.z, 0));
|
||||||
|
|
||||||
|
mat.SetPropertyBlock(_mpb);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Scripts/ShadowcasterUpdater.cs.meta
Normal file
11
Scripts/ShadowcasterUpdater.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 36c63f8382c2aad48b73fe4628db0f38
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -15,8 +15,13 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
|||||||
//Moonlight
|
//Moonlight
|
||||||
_InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1
|
_InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1
|
||||||
_LightCutoffDistance ("Light Cutoff Distance", Float) = 100
|
_LightCutoffDistance ("Light Cutoff Distance", Float) = 100
|
||||||
|
|
||||||
|
_EnableShadowCasting ("Enable Shadowcasting", Float) = 0
|
||||||
|
_BlurPixels ("Shadowcaster Blur Pixels", Float) = 0
|
||||||
//Moonlight END
|
//Moonlight END
|
||||||
|
|
||||||
|
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull Mode", Float) = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,6 +29,7 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
|||||||
{
|
{
|
||||||
Tags { "RenderType"="Opaque" }
|
Tags { "RenderType"="Opaque" }
|
||||||
LOD 100
|
LOD 100
|
||||||
|
Cull[_Cull]
|
||||||
|
|
||||||
Pass
|
Pass
|
||||||
{
|
{
|
||||||
@@ -36,6 +42,7 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
|||||||
#include "Includes/Lambert.hlsl"
|
#include "Includes/Lambert.hlsl"
|
||||||
#include "Includes/DefaultSetup.hlsl"
|
#include "Includes/DefaultSetup.hlsl"
|
||||||
#include "Includes/Variables.hlsl"
|
#include "Includes/Variables.hlsl"
|
||||||
|
#include "Includes/Shadowcaster.cginc"
|
||||||
|
|
||||||
//Moonlight Defines
|
//Moonlight Defines
|
||||||
#define MAX_LIGHTS 80 // >= maxPlayers in script
|
#define MAX_LIGHTS 80 // >= maxPlayers in script
|
||||||
@@ -85,6 +92,32 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
|||||||
MoonlightGlobalVariables
|
MoonlightGlobalVariables
|
||||||
|
|
||||||
|
|
||||||
|
float4 _Udon_Plane_Origin_1; // xyz = origin (world), w unused
|
||||||
|
float4 _Udon_Plane_Uinv_1; // xyz = Udir / (2*halfWidth)
|
||||||
|
float4 _Udon_Plane_Vinv_1; // xyz = Vdir / (2*halfHeight)
|
||||||
|
float4 _Udon_Plane_Normal_1; // xyz = unit normal
|
||||||
|
|
||||||
|
sampler2D _Udon_shadowCasterTex_1;
|
||||||
|
float4 _Udon_shadowCasterColor_1;
|
||||||
|
float4 _Udon_OutSideColor_1;
|
||||||
|
float _Udon_MinBrightnessShadow_1;
|
||||||
|
|
||||||
|
float4 _Udon_Plane_Origin_2;
|
||||||
|
float4 _Udon_Plane_Uinv_2;
|
||||||
|
float4 _Udon_Plane_Vinv_2;
|
||||||
|
float4 _Udon_Plane_Normal_2;
|
||||||
|
|
||||||
|
sampler2D _Udon_shadowCasterTex_2;
|
||||||
|
float4 _Udon_shadowCasterColor_2;
|
||||||
|
float4 _Udon_OutSideColor_2;
|
||||||
|
float _Udon_MinBrightnessShadow_2;
|
||||||
|
|
||||||
|
float _BlurPixels;
|
||||||
|
float4 _Udon_shadowCasterTex_1_TexelSize; // xy = 1/width, 1/height
|
||||||
|
float4 _Udon_shadowCasterTex_2_TexelSize;
|
||||||
|
|
||||||
|
bool _EnableShadowCasting;
|
||||||
|
|
||||||
v2f vert (appdata v)
|
v2f vert (appdata v)
|
||||||
{
|
{
|
||||||
v2f o;
|
v2f o;
|
||||||
@@ -140,7 +173,27 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
|||||||
|
|
||||||
LightTypeCalculations(_Udon_LightColors, LightCounter, i, NdotL, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
LightTypeCalculations(_Udon_LightColors, LightCounter, i, NdotL, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
||||||
|
|
||||||
dmax = dmax + contrib * float4(LightColor, 1) * NdotL; // accumulate light contributions
|
float4 ShadowCasterMult_1 = 1;
|
||||||
|
float4 ShadowCasterMult_2 = 1;
|
||||||
|
|
||||||
|
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5) && (_EnableShadowCasting > 0.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5 && _EnableShadowCasting))
|
||||||
|
{
|
||||||
|
float4 sc1 = SampleShadowcasterPlaneWS_Basis(
|
||||||
|
_Udon_LightPositions[LightCounter].xyz, i.worldPos,
|
||||||
|
_Udon_Plane_Origin_1.xyz, _Udon_Plane_Uinv_1.xyz, _Udon_Plane_Vinv_1.xyz, _Udon_Plane_Normal_1.xyz,
|
||||||
|
_Udon_shadowCasterTex_1, _Udon_OutSideColor_1, _Udon_shadowCasterColor_1, _BlurPixels, _Udon_shadowCasterTex_1_TexelSize.xy);
|
||||||
|
ShadowCasterMult_1 = max(sc1, _Udon_MinBrightnessShadow_1);
|
||||||
|
}
|
||||||
|
if (_Udon_ShadowMapIndex[LightCounter] > 1.5 && (_EnableShadowCasting > 0.5))
|
||||||
|
{
|
||||||
|
float4 sc2 = SampleShadowcasterPlaneWS_Basis(
|
||||||
|
_Udon_LightPositions[LightCounter].xyz, i.worldPos,
|
||||||
|
_Udon_Plane_Origin_2.xyz, _Udon_Plane_Uinv_2.xyz, _Udon_Plane_Vinv_2.xyz, _Udon_Plane_Normal_2.xyz,
|
||||||
|
_Udon_shadowCasterTex_2, _Udon_OutSideColor_2, _Udon_shadowCasterColor_2, _BlurPixels, _Udon_shadowCasterTex_2_TexelSize.xy);
|
||||||
|
ShadowCasterMult_2 = max(sc2, _Udon_MinBrightnessShadow_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
dmax = dmax + contrib * float4(LightColor, 1) * NdotL * ShadowCasterMult_1 * ShadowCasterMult_2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
{ \
|
{ \
|
||||||
contrib = _Udon_LightColors[LightCounter].a / max(1e-4, max(0, max(1, distanceFromLight - radius) * invSqMul) * max(0, max(1, distanceFromLight - radius) * invSqMul)); \
|
contrib = _Udon_LightColors[LightCounter].a / max(1e-4, max(0, max(1, distanceFromLight - radius) * invSqMul) * max(0, max(1, distanceFromLight - radius) * invSqMul)); \
|
||||||
\
|
\
|
||||||
dIntensity += contrib * NdotL; \
|
dIntensity += contrib; \
|
||||||
} \
|
} \
|
||||||
else if (_Udon_LightType[LightCounter] == 1) \
|
else if (_Udon_LightType[LightCounter] == 1) \
|
||||||
{ \
|
{ \
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
contrib= 1 - step(threshold, contrib); \
|
contrib= 1 - step(threshold, contrib); \
|
||||||
\
|
\
|
||||||
contrib = contrib * invSq; \
|
contrib = contrib * invSq; \
|
||||||
dIntensity += contrib * NdotL; \
|
dIntensity += contrib; \
|
||||||
} \
|
} \
|
||||||
float3 LightColor = _Udon_LightColors[LightCounter].xyz; \
|
float3 LightColor = _Udon_LightColors[LightCounter].xyz; \
|
||||||
|
|
||||||
|
|||||||
46
Shader/Includes/Shadowcaster.cginc
Normal file
46
Shader/Includes/Shadowcaster.cginc
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef SHADOWCASTER_PLANE
|
||||||
|
#define SHADOWCASTER_PLANE
|
||||||
|
|
||||||
|
#include "UnityCG.cginc" // tex2D, tex2Dgrad
|
||||||
|
|
||||||
|
static const float WS_EPS = 1e-5;
|
||||||
|
|
||||||
|
inline float4 SampleShadowcasterPlaneWS_Basis(
|
||||||
|
float3 A, float3 B,
|
||||||
|
float3 P0, float3 Uinv, float3 Vinv, float3 N,
|
||||||
|
sampler2D tex, float4 OutsideColor, float4 ShadowColor,
|
||||||
|
float blurPixels, float2 texelSize)
|
||||||
|
{
|
||||||
|
float3 d = B - A;
|
||||||
|
float dn = dot(N, d);
|
||||||
|
if (abs(dn) < WS_EPS) return OutsideColor;
|
||||||
|
|
||||||
|
float t = dot(N, P0 - A) / dn;
|
||||||
|
if (t < 0.0 || t > 1.0) return OutsideColor;
|
||||||
|
|
||||||
|
float3 hit = A + d * t;
|
||||||
|
float3 r = hit - P0;
|
||||||
|
|
||||||
|
// u,v in [-0.5, 0.5] if inside quad
|
||||||
|
float u = dot(r, Uinv);
|
||||||
|
float v = dot(r, Vinv);
|
||||||
|
if (abs(u) > 0.5 || abs(v) > 0.5) return OutsideColor;
|
||||||
|
|
||||||
|
float2 uv = float2(u + 0.5, v + 0.5);
|
||||||
|
|
||||||
|
// If blur is tiny, do the normal one-tap
|
||||||
|
if (blurPixels <= 0.001)
|
||||||
|
{
|
||||||
|
float4 col = tex2D(tex, uv) * ShadowColor;
|
||||||
|
return float4(col.rgb * (1 - col.a), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inflate gradients so the sampler picks a higher mip (cheap blur).
|
||||||
|
float2 g = texelSize * blurPixels;
|
||||||
|
float4 blurred = tex2Dgrad(tex, uv, float2(g.x, 0), float2(0, g.y));
|
||||||
|
|
||||||
|
float4 outCol = blurred * ShadowColor;
|
||||||
|
return float4(outCol.rgb * (1 - outCol.a), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
7
Shader/Includes/Shadowcaster.cginc.meta
Normal file
7
Shader/Includes/Shadowcaster.cginc.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 407fd8c92bce1a84ab69e3abad2320b0
|
||||||
|
ShaderIncludeImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
float4 _Udon_LightColors[MAX_LIGHTS]; /* xyz = position */ \
|
float4 _Udon_LightColors[MAX_LIGHTS]; /* xyz = position */ \
|
||||||
float4 _Udon_LightDirections[MAX_LIGHTS]; /* xyz = direction, w = cos(halfAngle) */ \
|
float4 _Udon_LightDirections[MAX_LIGHTS]; /* xyz = direction, w = cos(halfAngle) */ \
|
||||||
float _Udon_LightType[MAX_LIGHTS]; /* 0 = sphere, 1 = cone */ \
|
float _Udon_LightType[MAX_LIGHTS]; /* 0 = sphere, 1 = cone */ \
|
||||||
|
float _Udon_ShadowMapIndex[MAX_LIGHTS];\
|
||||||
float _Udon_PlayerCount; /* set via SetFloat */ \
|
float _Udon_PlayerCount; /* set via SetFloat */ \
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -9,6 +9,9 @@ Shader "DeMuenu/World/Hoppou/Particles/LitParticles"
|
|||||||
//Moonlight
|
//Moonlight
|
||||||
_InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1
|
_InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1
|
||||||
_LightCutoffDistance ("Light Cutoff Distance", Float) = 100
|
_LightCutoffDistance ("Light Cutoff Distance", Float) = 100
|
||||||
|
|
||||||
|
_EnableShadowCasting ("Enable Shadowcasting", Float) = 0
|
||||||
|
_BlurPixels ("Shadowcaster Blur Pixels", Float) = 0
|
||||||
//Moonlight END
|
//Moonlight END
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +39,7 @@ Shader "DeMuenu/World/Hoppou/Particles/LitParticles"
|
|||||||
#include "Includes/Lambert.hlsl"
|
#include "Includes/Lambert.hlsl"
|
||||||
#include "Includes/DefaultSetup.hlsl"
|
#include "Includes/DefaultSetup.hlsl"
|
||||||
#include "Includes/Variables.hlsl"
|
#include "Includes/Variables.hlsl"
|
||||||
|
#include "Includes/Shadowcaster.cginc"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -78,6 +82,31 @@ Shader "DeMuenu/World/Hoppou/Particles/LitParticles"
|
|||||||
|
|
||||||
MoonlightGlobalVariables
|
MoonlightGlobalVariables
|
||||||
|
|
||||||
|
float4 _Udon_Plane_Origin_1; // xyz = origin (world), w unused
|
||||||
|
float4 _Udon_Plane_Uinv_1; // xyz = Udir / (2*halfWidth)
|
||||||
|
float4 _Udon_Plane_Vinv_1; // xyz = Vdir / (2*halfHeight)
|
||||||
|
float4 _Udon_Plane_Normal_1; // xyz = unit normal
|
||||||
|
|
||||||
|
sampler2D _Udon_shadowCasterTex_1;
|
||||||
|
float4 _Udon_shadowCasterColor_1;
|
||||||
|
float4 _Udon_OutSideColor_1;
|
||||||
|
float _Udon_MinBrightnessShadow_1;
|
||||||
|
|
||||||
|
float4 _Udon_Plane_Origin_2;
|
||||||
|
float4 _Udon_Plane_Uinv_2;
|
||||||
|
float4 _Udon_Plane_Vinv_2;
|
||||||
|
float4 _Udon_Plane_Normal_2;
|
||||||
|
|
||||||
|
sampler2D _Udon_shadowCasterTex_2;
|
||||||
|
float4 _Udon_shadowCasterColor_2;
|
||||||
|
float4 _Udon_OutSideColor_2;
|
||||||
|
float _Udon_MinBrightnessShadow_2;
|
||||||
|
|
||||||
|
float _BlurPixels;
|
||||||
|
float4 _Udon_shadowCasterTex_1_TexelSize; // xy = 1/width, 1/height
|
||||||
|
float4 _Udon_shadowCasterTex_2_TexelSize;
|
||||||
|
|
||||||
|
bool _EnableShadowCasting;
|
||||||
|
|
||||||
v2f vert (appdata v)
|
v2f vert (appdata v)
|
||||||
{
|
{
|
||||||
@@ -114,11 +143,29 @@ Shader "DeMuenu/World/Hoppou/Particles/LitParticles"
|
|||||||
|
|
||||||
InLoopSetup(_Udon_LightPositions, LightCounter, count, i); //defines distanceFromLight, contrib
|
InLoopSetup(_Udon_LightPositions, LightCounter, count, i); //defines distanceFromLight, contrib
|
||||||
|
|
||||||
Lambert(_Udon_LightPositions[LightCounter].xyz ,i, N); //defines NdotL
|
|
||||||
|
|
||||||
LightTypeCalculations(_Udon_LightColors, LightCounter, i, NdotL, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
LightTypeCalculations(_Udon_LightColors, LightCounter, i, 1, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
||||||
|
|
||||||
dmax = dmax + contrib * float4(LightColor, 1) * NdotL; // accumulate light contributions
|
float4 ShadowCasterMult_1 = 1;
|
||||||
|
float4 ShadowCasterMult_2 = 1;
|
||||||
|
|
||||||
|
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5) && (_EnableShadowCasting > 0.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5 && _EnableShadowCasting))
|
||||||
|
{
|
||||||
|
float4 sc1 = SampleShadowcasterPlaneWS_Basis(
|
||||||
|
_Udon_LightPositions[LightCounter].xyz, i.worldPos,
|
||||||
|
_Udon_Plane_Origin_1.xyz, _Udon_Plane_Uinv_1.xyz, _Udon_Plane_Vinv_1.xyz, _Udon_Plane_Normal_1.xyz,
|
||||||
|
_Udon_shadowCasterTex_1, _Udon_OutSideColor_1, _Udon_shadowCasterColor_1, _BlurPixels, _Udon_shadowCasterTex_1_TexelSize.xy);
|
||||||
|
ShadowCasterMult_1 = max(sc1, _Udon_MinBrightnessShadow_1);
|
||||||
|
}
|
||||||
|
if (_Udon_ShadowMapIndex[LightCounter] > 1.5 && (_EnableShadowCasting > 0.5)) {
|
||||||
|
float4 sc2 = SampleShadowcasterPlaneWS_Basis(
|
||||||
|
_Udon_LightPositions[LightCounter].xyz, i.worldPos,
|
||||||
|
_Udon_Plane_Origin_2.xyz, _Udon_Plane_Uinv_2.xyz, _Udon_Plane_Vinv_2.xyz, _Udon_Plane_Normal_2.xyz,
|
||||||
|
_Udon_shadowCasterTex_2, _Udon_OutSideColor_2, _Udon_shadowCasterColor_2, _BlurPixels, _Udon_shadowCasterTex_2_TexelSize.xy);
|
||||||
|
ShadowCasterMult_2 = max(sc2, _Udon_MinBrightnessShadow_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
dmax = dmax + contrib * float4(LightColor, 1) * ShadowCasterMult_1 * ShadowCasterMult_2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ Shader "DeMuenu/World/Hoppou/Water"
|
|||||||
_InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1
|
_InverseSqareMultiplier ("Inverse Square Multiplier", Float) = 1
|
||||||
_LightCutoffDistance ("Light Cutoff Distance", Float) = 100
|
_LightCutoffDistance ("Light Cutoff Distance", Float) = 100
|
||||||
|
|
||||||
|
_EnableShadowCasting ("Enable Shadowcasting", Float) = 0
|
||||||
|
_BlurPixels ("Shadowcaster Blur Pixels", Float) = 0
|
||||||
|
//Moonlight END
|
||||||
|
|
||||||
_SpecPower ("Spec Power", Range(4,256)) = 64
|
_SpecPower ("Spec Power", Range(4,256)) = 64
|
||||||
_SpecIntensity ("Spec Intensity", Range(0,10)) = 1
|
_SpecIntensity ("Spec Intensity", Range(0,10)) = 1
|
||||||
_AmbientFloor ("Ambient Floor", Range(0,1)) = 0.08
|
_AmbientFloor ("Ambient Floor", Range(0,1)) = 0.08
|
||||||
@@ -24,7 +28,6 @@ Shader "DeMuenu/World/Hoppou/Water"
|
|||||||
_F0 ("F0", Range(0,1)) = 0.02
|
_F0 ("F0", Range(0,1)) = 0.02
|
||||||
_FresnelPower ("Fresnel Power", Range(1,8)) = 5
|
_FresnelPower ("Fresnel Power", Range(1,8)) = 5
|
||||||
_ReflectionStrength ("Reflection Strength", Range(0,1)) = 0.7
|
_ReflectionStrength ("Reflection Strength", Range(0,1)) = 0.7
|
||||||
//Moonlight END
|
|
||||||
|
|
||||||
_WaveInput ("Wave Input", 2D) = "black" {}
|
_WaveInput ("Wave Input", 2D) = "black" {}
|
||||||
_CameraScale ("Camera Scale", Float) = 15
|
_CameraScale ("Camera Scale", Float) = 15
|
||||||
@@ -51,6 +54,7 @@ Shader "DeMuenu/World/Hoppou/Water"
|
|||||||
#include "Includes/Lambert.hlsl"
|
#include "Includes/Lambert.hlsl"
|
||||||
#include "Includes/DefaultSetup.hlsl"
|
#include "Includes/DefaultSetup.hlsl"
|
||||||
#include "Includes/Variables.hlsl"
|
#include "Includes/Variables.hlsl"
|
||||||
|
#include "Includes/Shadowcaster.cginc"
|
||||||
|
|
||||||
//Moonlight Defines
|
//Moonlight Defines
|
||||||
#define MAX_LIGHTS 80 // >= maxPlayers in script
|
#define MAX_LIGHTS 80 // >= maxPlayers in script
|
||||||
@@ -94,6 +98,33 @@ Shader "DeMuenu/World/Hoppou/Water"
|
|||||||
|
|
||||||
MoonlightGlobalVariables
|
MoonlightGlobalVariables
|
||||||
|
|
||||||
|
float4 _Udon_Plane_Origin_1; // xyz = origin (world), w unused
|
||||||
|
float4 _Udon_Plane_Uinv_1; // xyz = Udir / (2*halfWidth)
|
||||||
|
float4 _Udon_Plane_Vinv_1; // xyz = Vdir / (2*halfHeight)
|
||||||
|
float4 _Udon_Plane_Normal_1; // xyz = unit normal
|
||||||
|
|
||||||
|
sampler2D _Udon_shadowCasterTex_1;
|
||||||
|
float4 _Udon_shadowCasterColor_1;
|
||||||
|
float4 _Udon_OutSideColor_1;
|
||||||
|
float _Udon_MinBrightnessShadow_1;
|
||||||
|
|
||||||
|
float4 _Udon_Plane_Origin_2;
|
||||||
|
float4 _Udon_Plane_Uinv_2;
|
||||||
|
float4 _Udon_Plane_Vinv_2;
|
||||||
|
float4 _Udon_Plane_Normal_2;
|
||||||
|
|
||||||
|
sampler2D _Udon_shadowCasterTex_2;
|
||||||
|
float4 _Udon_shadowCasterColor_2;
|
||||||
|
float4 _Udon_OutSideColor_2;
|
||||||
|
float _Udon_MinBrightnessShadow_2;
|
||||||
|
|
||||||
|
float _BlurPixels;
|
||||||
|
float4 _Udon_shadowCasterTex_1_TexelSize; // xy = 1/width, 1/height
|
||||||
|
float4 _Udon_shadowCasterTex_2_TexelSize;
|
||||||
|
|
||||||
|
bool _EnableShadowCasting;
|
||||||
|
|
||||||
|
|
||||||
//Watershader specific
|
//Watershader specific
|
||||||
float _SpecPower, _SpecIntensity;
|
float _SpecPower, _SpecIntensity;
|
||||||
float3 _AmbientFloor;
|
float3 _AmbientFloor;
|
||||||
@@ -185,13 +216,30 @@ Shader "DeMuenu/World/Hoppou/Water"
|
|||||||
|
|
||||||
LightTypeCalculations(_Udon_LightColors, LightCounter, i, 1, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
LightTypeCalculations(_Udon_LightColors, LightCounter, i, 1, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
||||||
|
|
||||||
|
float4 ShadowCasterMult_1 = 1;
|
||||||
|
float4 ShadowCasterMult_2 = 1;
|
||||||
|
|
||||||
|
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5) && (_EnableShadowCasting > 0.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5 && _EnableShadowCasting))
|
||||||
|
{
|
||||||
|
float4 sc1 = SampleShadowcasterPlaneWS_Basis(
|
||||||
|
_Udon_LightPositions[LightCounter].xyz, i.worldPos,
|
||||||
|
_Udon_Plane_Origin_1.xyz, _Udon_Plane_Uinv_1.xyz, _Udon_Plane_Vinv_1.xyz, _Udon_Plane_Normal_1.xyz,
|
||||||
|
_Udon_shadowCasterTex_1, _Udon_OutSideColor_1, _Udon_shadowCasterColor_1, _BlurPixels, _Udon_shadowCasterTex_1_TexelSize.xy);
|
||||||
|
ShadowCasterMult_1 = max(sc1, _Udon_MinBrightnessShadow_1);
|
||||||
|
}
|
||||||
|
if (_Udon_ShadowMapIndex[LightCounter] > 1.5 && (_EnableShadowCasting > 0.5)) {
|
||||||
|
float4 sc2 = SampleShadowcasterPlaneWS_Basis(
|
||||||
|
_Udon_LightPositions[LightCounter].xyz, i.worldPos,
|
||||||
|
_Udon_Plane_Origin_2.xyz, _Udon_Plane_Uinv_2.xyz, _Udon_Plane_Vinv_2.xyz, _Udon_Plane_Normal_2.xyz,
|
||||||
|
_Udon_shadowCasterTex_2, _Udon_OutSideColor_2, _Udon_shadowCasterColor_2, _BlurPixels, _Udon_shadowCasterTex_2_TexelSize.xy);
|
||||||
|
ShadowCasterMult_2 = max(sc2, _Udon_MinBrightnessShadow_2);
|
||||||
|
}
|
||||||
|
|
||||||
//Watershader specific
|
//Watershader specific
|
||||||
//float fres = Schlick(saturate(dot(N, V)), _F0, _FresnelPower);
|
//float fres = Schlick(saturate(dot(N, V)), _F0, _FresnelPower);
|
||||||
float spec = pow(saturate(dot(R, L)), _SpecPower);
|
float spec = pow(saturate(dot(R, L)), _SpecPower);
|
||||||
//return float4(spec, spec, spec,1);
|
//return float4(spec, spec, spec,1);
|
||||||
dmax.rgb += _Udon_LightColors[LightCounter].rgb * contrib + _Udon_LightColors[LightCounter].rgb * _SpecIntensity * spec * contrib;
|
dmax.rgb += _Udon_LightColors[LightCounter].rgb * contrib * ShadowCasterMult_1 * ShadowCasterMult_2 + _Udon_LightColors[LightCounter].rgb * _SpecIntensity * spec * contrib * ShadowCasterMult_1 * ShadowCasterMult_2;
|
||||||
dmax.a -= _SpecIntensity * spec;
|
dmax.a -= _SpecIntensity * spec;
|
||||||
//dmax = dmax + contrib * float4(LightColor, 1); // accumulate light contributions
|
//dmax = dmax + contrib * float4(LightColor, 1); // accumulate light contributions
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user