Files
Ipseity-Demo/Assets/_Content/Shaders/Include/CurvedWorld.hlsl
T
2026-09-28 14:58:25 +02:00

66 lines
2.7 KiB
HLSL

#ifndef CURVED_WORLD_INCLUDED
#define CURVED_WORLD_INCLUDED
// Bend frame: the camera view by default. PortalMeadow can pin it to a fixed world-space frame
// (e.g. a portal) so the bend stays still while the world is only seen through that portal.
float4x4 _CurvedWorldFrame, _CurvedWorldFrameInv;
float _CurvedWorldFrameFixed;
float3 CurvedWorldToFrame(float3 positionWS)
{
return _CurvedWorldFrameFixed > 0.5 ? mul(_CurvedWorldFrame, float4(positionWS, 1)).xyz : TransformWorldToView(positionWS);
}
float3 CurvedFrameToWorld(float3 positionFS)
{
return mul(_CurvedWorldFrameFixed > 0.5 ? _CurvedWorldFrameInv : UNITY_MATRIX_I_V, float4(positionFS, 1)).xyz;
}
float3 CurvedWorldDirToFrame(float3 directionWS)
{
return mul((float3x3)(_CurvedWorldFrameFixed > 0.5 ? _CurvedWorldFrame : UNITY_MATRIX_V), directionWS);
}
float3 CurvedFrameDirToWorld(float3 directionFS)
{
return mul((float3x3)(_CurvedWorldFrameFixed > 0.5 ? _CurvedWorldFrameInv : UNITY_MATRIX_I_V), directionFS);
}
// Shared by the ground and the grass; also usable as a Shader Graph custom function.
void CurvedWorld_float(float3 PositionOS, float Curvature, float StartDistance,
float HorizontalInfluence, float BendAngle, out float3 Out)
{
#ifdef SHADERGRAPH_PREVIEW
Out = PositionOS;
#else
float3 positionVS = CurvedWorldToFrame(TransformObjectToWorld(PositionOS));
// Rotate the bend frame around the camera's forward axis (degrees).
// 0 = down, 90 = right, 180 = up, 270 = left.
float s, c;
sincos(radians(BendAngle), s, c);
float lateral = dot(positionVS.xy, float2(c, s));
float distanceFromCamera = max(0.0, -positionVS.z - StartDistance);
float bend = (distanceFromCamera * distanceFromCamera
+ lateral * lateral * HorizontalInfluence) * Curvature;
positionVS.xy += float2(s, -c) * bend;
Out = TransformWorldToObject(CurvedFrameToWorld(positionVS));
#endif
}
// Preserve existing Shader Graph custom functions using the original signature.
void CurvedWorld_float(float3 PositionOS, float Curvature, float StartDistance,
float HorizontalInfluence, out float3 Out)
{
CurvedWorld_float(PositionOS, Curvature, StartDistance, HorizontalInfluence, 0, Out);
}
float3 CurvedWorldNormalVS(float3 positionVS, float3 normalVS, float Curvature,
float StartDistance, float HorizontalInfluence, float BendAngle)
{
float s, c;
sincos(radians(BendAngle), s, c);
float lateral = dot(positionVS.xy, float2(c, s));
float3 gradient = 2 * Curvature * float3(HorizontalInfluence * lateral * float2(c, s),
-max(0.0, -positionVS.z - StartDistance));
// Inverse transpose of the bend Jacobian; the gradient is perpendicular to its direction.
return normalVS - gradient * dot(float2(s, -c), normalVS.xy);
}
#endif