mirror of
https://github.com/DeMuenu/MoonlightVRC.git
synced 2025-12-12 19:13:56 +00:00
91 lines
3.2 KiB
Plaintext
91 lines
3.2 KiB
Plaintext
#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
|