mirror of
https://github.com/DeMuenu/MoonlightVRC.git
synced 2025-12-13 11:33:54 +00:00
Refactor shadowcaster to use explicit plane basis
Replaces the use of world-to-local matrices for shadowcaster planes with explicit plane origin, basis, and normal vectors in both C# and shader code. Updates property setting in ShadowcasterUpdater and its editor preview, and rewrites the shadow sampling function in the shader include to use the new basis. Adjusts all affected shaders to use the new properties and sampling function for improved clarity and flexibility.
This commit is contained in:
@@ -86,13 +86,22 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
||||
|
||||
MoonlightGlobalVariables
|
||||
|
||||
float4x4 _Udon_WorldToLocal_1;
|
||||
|
||||
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;
|
||||
|
||||
float4x4 _Udon_WorldToLocal_2;
|
||||
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;
|
||||
@@ -152,20 +161,26 @@ Shader "DeMuenu/World/Hoppou/RevealStandart"
|
||||
Lambert(_Udon_LightPositions[LightCounter].xyz ,i, N); //defines NdotL
|
||||
|
||||
LightTypeCalculations(_Udon_LightColors, LightCounter, i, NdotL, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
||||
|
||||
float4 ShadowCasterMult_1 = 1;
|
||||
float4 ShadowCasterMult_2 = 1;
|
||||
|
||||
float4 ShadowCasterMult_1 = float4(1,1,1,1);
|
||||
float4 ShadowCasterMult_2 = float4(1,1,1,1);
|
||||
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5)) {
|
||||
ShadowCasterMult_1 = SampleShadowcasterPlane(_Udon_WorldToLocal_1, _Udon_shadowCasterTex_1, _Udon_LightPositions[LightCounter].xyz, i.worldPos, _Udon_OutSideColor_1);
|
||||
ShadowCasterMult_1 *= _Udon_shadowCasterColor_1;
|
||||
ShadowCasterMult_1 = float4(ShadowCasterMult_1.rgb * (1-ShadowCasterMult_1.a), 1);
|
||||
ShadowCasterMult_1 = max(ShadowCasterMult_1, _Udon_MinBrightnessShadow_1)
|
||||
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5))
|
||||
{
|
||||
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);
|
||||
ShadowCasterMult_1 = max(sc1, _Udon_MinBrightnessShadow_1);
|
||||
}
|
||||
if (_Udon_ShadowMapIndex[LightCounter] > 1.5) {
|
||||
ShadowCasterMult_2 = SampleShadowcasterPlane(_Udon_WorldToLocal_2, _Udon_shadowCasterTex_2, _Udon_LightPositions[LightCounter].xyz, i.worldPos, _Udon_OutSideColor_2);
|
||||
ShadowCasterMult_2 *= _Udon_shadowCasterColor_2;
|
||||
ShadowCasterMult_2 = float4(ShadowCasterMult_2.rgb * (1-ShadowCasterMult_2.a), 1);
|
||||
ShadowCasterMult_2 = max(ShadowCasterMult_2, _Udon_MinBrightnessShadow_2)
|
||||
|
||||
if (_Udon_ShadowMapIndex[LightCounter] > 1.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);
|
||||
ShadowCasterMult_2 = max(sc2, _Udon_MinBrightnessShadow_2);
|
||||
}
|
||||
|
||||
dmax = dmax + contrib * float4(LightColor, 1) * ShadowCasterMult_1 * ShadowCasterMult_2;
|
||||
|
||||
@@ -3,54 +3,30 @@
|
||||
|
||||
#include "UnityCG.cginc" // for tex2Dlod, etc.
|
||||
|
||||
static const float EPS = 1e-5;
|
||||
static const float WS_EPS = 1e-5;
|
||||
|
||||
// Returns whether segment hits the unit plane quad in plane-local z=0.
|
||||
// Outputs uv in [0,1] and t in [0,1] along A->B.
|
||||
inline bool RaySegmentHitsPlaneQuad(float4x4 worldToLocal, float3 rayOrigin, float3 rayEnd, out float2 uv, out float t)
|
||||
inline float4 SampleShadowcasterPlaneWS_Basis(
|
||||
float3 A, float3 B,
|
||||
float3 P0, float3 Uinv, float3 Vinv, float3 N,
|
||||
sampler2D tex, float4 OutsideColor, float4 ShadowColor)
|
||||
{
|
||||
float3 aP = mul(worldToLocal, float4(rayOrigin, 1)).xyz;
|
||||
float3 bP = mul(worldToLocal, float4(rayEnd, 1)).xyz;
|
||||
float3 d = B - A;
|
||||
float dn = dot(N, d);
|
||||
if (abs(dn) < WS_EPS) return OutsideColor;
|
||||
|
||||
float3 d = bP - aP;
|
||||
float dz = d.z;
|
||||
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;
|
||||
|
||||
// Parallel-ish to plane?
|
||||
if (abs(dz) < EPS) return false;
|
||||
// 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;
|
||||
|
||||
// Intersect z=0
|
||||
t = -aP.z / dz;
|
||||
|
||||
// Segment only
|
||||
if (t < 0.0 || t > 1.0) return false;
|
||||
|
||||
float3 hit = aP + d * t;
|
||||
|
||||
// Inside 1x1 centered quad?
|
||||
if (abs(hit.x) > 0.5 || abs(hit.y) > 0.5) return false;
|
||||
|
||||
uv = hit.xy + 0.5; // [-0.5,0.5] -> [0,1]
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fragment-shader version: uses proper filtering/mips via tex2D
|
||||
inline float4 SampleShadowcasterPlane(float4x4 worldToLocal, sampler2D tex, float3 rayOrigin, float3 rayEnd, float4 OutsideColor)
|
||||
{
|
||||
float2 uv; float t;
|
||||
if (RaySegmentHitsPlaneQuad(worldToLocal, rayOrigin, rayEnd, uv, t))
|
||||
return tex2D(tex, uv); // full color
|
||||
|
||||
return OutsideColor;
|
||||
}
|
||||
|
||||
// Anywhere (vertex/geom/compute/custom code) version: forces LOD 0
|
||||
inline float4 SampleShadowcasterPlaneLOD0(float4x4 worldToLocal, sampler2D tex, float3 rayOrigin, float3 rayEnd, float4 OutsideColor)
|
||||
{
|
||||
float2 uv; float t;
|
||||
if (RaySegmentHitsPlaneQuad(worldToLocal, rayOrigin, rayEnd, uv, t))
|
||||
return tex2Dlod(tex, float4(uv, 0, 0)); // full color at mip 0
|
||||
|
||||
return OutsideColor;
|
||||
float4 returnColor = tex2D(tex, float2(u + 0.5, v + 0.5)) * ShadowColor;
|
||||
returnColor = float4(returnColor.rgb * (1 - returnColor.a), 1);
|
||||
return returnColor;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,18 +79,25 @@ Shader "DeMuenu/World/Hoppou/Particles/LitParticles"
|
||||
|
||||
MoonlightGlobalVariables
|
||||
|
||||
float4x4 _Udon_WorldToLocal_1;
|
||||
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;
|
||||
|
||||
float4x4 _Udon_WorldToLocal_2;
|
||||
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;
|
||||
|
||||
v2f vert (appdata v)
|
||||
{
|
||||
v2f o;
|
||||
@@ -129,22 +136,28 @@ Shader "DeMuenu/World/Hoppou/Particles/LitParticles"
|
||||
|
||||
LightTypeCalculations(_Udon_LightColors, LightCounter, i, 1, dIntensity, _Udon_LightPositions[LightCounter].a, _Udon_LightPositions[LightCounter].xyz);
|
||||
|
||||
float4 ShadowCasterMult_1 = float4(1,1,1,1);
|
||||
float4 ShadowCasterMult_2 = float4(1,1,1,1);
|
||||
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5)) {
|
||||
ShadowCasterMult_1 = SampleShadowcasterPlane(_Udon_WorldToLocal_1, _Udon_shadowCasterTex_1, _Udon_LightPositions[LightCounter].xyz, i.worldPos, _Udon_OutSideColor_1);
|
||||
ShadowCasterMult_1 *= _Udon_shadowCasterColor_1;
|
||||
ShadowCasterMult_1 = float4(ShadowCasterMult_1.rgb * (1-ShadowCasterMult_1.a), 1);
|
||||
ShadowCasterMult_1 = max(ShadowCasterMult_1, _Udon_MinBrightnessShadow_1)
|
||||
}
|
||||
if (_Udon_ShadowMapIndex[LightCounter] > 1.5) {
|
||||
ShadowCasterMult_2 = SampleShadowcasterPlane(_Udon_WorldToLocal_2, _Udon_shadowCasterTex_2, _Udon_LightPositions[LightCounter].xyz, i.worldPos, _Udon_OutSideColor_2);
|
||||
ShadowCasterMult_2 *= _Udon_shadowCasterColor_2;
|
||||
ShadowCasterMult_2 = float4(ShadowCasterMult_2.rgb * (1-ShadowCasterMult_2.a), 1);
|
||||
ShadowCasterMult_2 = max(ShadowCasterMult_2, _Udon_MinBrightnessShadow_2)
|
||||
float4 ShadowCasterMult_1 = 1;
|
||||
float4 ShadowCasterMult_2 = 1;
|
||||
|
||||
if (((_Udon_ShadowMapIndex[LightCounter] > 0.5) && (_Udon_ShadowMapIndex[LightCounter] < 1.5)) || (_Udon_ShadowMapIndex[LightCounter] > 2.5))
|
||||
{
|
||||
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);
|
||||
ShadowCasterMult_1 = max(sc1, _Udon_MinBrightnessShadow_1);
|
||||
}
|
||||
|
||||
dmax = dmax + contrib * float4(LightColor, 1) * ShadowCasterMult1 * ShadowCasterMult_2;
|
||||
if (_Udon_ShadowMapIndex[LightCounter] > 1.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);
|
||||
ShadowCasterMult_2 = max(sc2, _Udon_MinBrightnessShadow_2);
|
||||
}
|
||||
|
||||
dmax = dmax + contrib * float4(LightColor, 1) * ShadowCasterMult_1 * ShadowCasterMult_2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user