Files
TheDeclineOfWarriors/Assets/Shaders/SpaceWarpUniversal.shader
T
2026-04-12 16:40:54 +07:00

294 lines
12 KiB
GLSL

Shader "The Decline Of Warriors/Space Warp Universal"
{
Properties
{
_BaseMap("Base Map", 2D) = "white" {}
_LightMap("Light Map", 2D) = "white" {}
_TextureArray("Texture Array", 2DArray) = "white" {}
_BaseColor("Base Color", Color) = (1, 1, 1, 1)
[ToggleUI] _UseBaseMap("Use Base Map", Float) = 1
[ToggleUI] _UseTextureArray("Use Texture Array", Float) = 0
[ToggleUI] _UseLightMap("Use Light Map", Float) = 0
[ToggleUI] _UseVertexColor("Use Vertex Color", Float) = 1
[ToggleUI] _UseFog("Use Fog", Float) = 1
[IntRange] _Mode("Warp Mode", Range(0, 9)) = 0
_J("Warp Scale", Float) = 16
_F5Distance("View Offset", Float) = 1
_AlphaClipThreshold("Alpha Clip Threshold", Range(0, 1)) = 0.001
[Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 2
[Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", Float) = 1
[Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend", Float) = 0
}
SubShader
{
Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Opaque" "Queue"="Geometry" }
LOD 100
Pass
{
Name "Forward"
Tags { "LightMode"="UniversalForward" }
Cull [_Cull]
ZWrite [_ZWrite]
Blend [_SrcBlend] [_DstBlend]
HLSLPROGRAM
#pragma target 3.5
#pragma require 2darray
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
TEXTURE2D(_BaseMap);
SAMPLER(sampler_BaseMap);
TEXTURE2D(_LightMap);
SAMPLER(sampler_LightMap);
TEXTURE2D_ARRAY(_TextureArray);
SAMPLER(sampler_TextureArray);
CBUFFER_START(UnityPerMaterial)
float4 _BaseMap_ST;
float4 _LightMap_ST;
half4 _BaseColor;
float _UseBaseMap;
float _UseTextureArray;
float _UseLightMap;
float _UseVertexColor;
float _UseFog;
float _Mode;
float _J;
float _F5Distance;
float _AlphaClipThreshold;
CBUFFER_END
float4 _SpaceWarpCameraPosition;
float4 _SpaceWarpPreviousCameraPosition;
float4 _SpaceWarpCameraForward;
float _SpaceWarpFrameTime;
float _SpaceWarpTime;
static const float kPi = 3.14159265359;
static const float kMinEpsilon = 1e-5;
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
half4 color : COLOR;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
float2 lightUv : TEXCOORD1;
float2 textureData : TEXCOORD2;
half4 color : COLOR;
float fogFactor : TEXCOORD3;
};
float Dot2(float3 value)
{
return dot(value, value);
}
float2 Rotate2D(float2 value, float angle)
{
float s = sin(angle);
float c = cos(angle);
return float2(c * value.x + s * value.y, -s * value.x + c * value.y);
}
float3 WarpSafeNormalize(float3 value)
{
float lengthSquared = max(dot(value, value), kMinEpsilon);
return value * rsqrt(lengthSquared);
}
float3 InvertSpace(float3 position, float3 offset)
{
float3 shifted = position + offset;
float shiftedLength = max(length(shifted), kMinEpsilon);
shifted = WarpSafeNormalize(shifted) * (Dot2(offset) / shiftedLength);
shifted = reflect(shifted, WarpSafeNormalize(offset));
return shifted + offset;
}
float3x3 Inverse3x3(float3x3 matrixValue)
{
float3 a = matrixValue[0];
float3 b = matrixValue[1];
float3 c = matrixValue[2];
float3 r0 = cross(b, c);
float3 r1 = cross(c, a);
float3 r2 = cross(a, b);
float determinant = dot(r2, c);
float safeDeterminant = sign(determinant) * max(abs(determinant), kMinEpsilon);
return transpose(float3x3(r0, r1, r2) / safeDeterminant);
}
float3 Torusify(float3 position, float3 cameraPosition, float warpScale)
{
float k = warpScale * 0.5;
float safeK = max(abs(k), kMinEpsilon);
position.y = tanh((position.y - cameraPosition.y) / safeK) * safeK;
position.y -= k;
position.xy = float2(-sin(position.x * kPi / warpScale) * position.y, cos(position.x * kPi / warpScale) * position.y) + float2(0.0, k);
position.y += k;
position.zy = float2(sin(position.z * kPi / warpScale) * position.y, cos(position.z * kPi / warpScale) * position.y) - float2(0.0, k);
return position;
}
float3 Cust1(float3 position, float distance)
{
float3 viewPosition = mul((float3x3)UNITY_MATRIX_V, position);
viewPosition.z -= distance / 1.1;
return mul((float3x3)UNITY_MATRIX_I_V, viewPosition);
}
float3 Cust2(float3 position, float3 cameraPosition, float warpScale)
{
float3 torusLocal = Torusify(position + cameraPosition, cameraPosition, warpScale) - Torusify(cameraPosition, cameraPosition, warpScale);
float3 vx = WarpSafeNormalize(Torusify(cameraPosition + float3(0.01, 0.0, 0.0), cameraPosition, warpScale) - Torusify(cameraPosition, cameraPosition, warpScale));
float3 vy = WarpSafeNormalize(Torusify(cameraPosition + float3(0.0, 0.01, 0.0), cameraPosition, warpScale) - Torusify(cameraPosition, cameraPosition, warpScale));
float3 vz = WarpSafeNormalize(Torusify(cameraPosition + float3(0.0, 0.0, 0.01), cameraPosition, warpScale) - Torusify(cameraPosition, cameraPosition, warpScale));
float3x3 directionMatrix = float3x3(vx, vy, vz);
return mul(Inverse3x3(directionMatrix), torusLocal);
}
float3 Cust3(float3 position, float distance, float warpScale, float timeValue)
{
float angle = (sin(timeValue / 6.0) * distance) / warpScale;
float s = sin(angle);
float c = cos(angle);
float3x3 rotation = float3x3(
c, 0.0, -s,
0.0, 1.0, 0.0,
s, 0.0, c
);
return mul(position, rotation);
}
float3 WarpPosition(float3 worldPosition)
{
float warpScale = max(_J, 1.0);
float3 cameraPosition = _SpaceWarpCameraPosition.w > 0.5 ? _SpaceWarpCameraPosition.xyz : GetCameraPositionWS();
float3 previousCameraPosition = _SpaceWarpPreviousCameraPosition.w > 0.5 ? _SpaceWarpPreviousCameraPosition.xyz : cameraPosition;
float frameTime = max(_SpaceWarpFrameTime, 0.0001);
float timeValue = _SpaceWarpTime > 0.0 ? _SpaceWarpTime : _Time.y;
float3 position = worldPosition - cameraPosition;
float3 cameraVelocity = (cameraPosition - previousCameraPosition) / frameTime;
float distance = length(position) / warpScale;
float x = position.x;
float y = position.y;
float z = position.z;
float2 orbit = Rotate2D(float2(warpScale, 0.0), timeValue);
float3x3 solv = float3x3(
pow(2.0, -y / warpScale), 0.0, 0.0,
x / warpScale, 1.0, -z / warpScale,
0.0, 0.0, pow(2.0, y / warpScale)
);
int mode = (int)round(_Mode);
if (mode == 0)
{
position = InvertSpace(position, float3(orbit.y, 0.0, orbit.x));
}
else if (mode == 1)
{
position = InvertSpace(position, float3(orbit.x, orbit.y, 0.0));
}
else if (mode == 2)
{
position = InvertSpace(position, float3(0.0, orbit.x, orbit.y));
}
else if (mode == 3)
{
position += cameraVelocity * distance / warpScale;
}
else if (mode == 4)
{
position = InvertSpace(position, float3(0.0, warpScale, 0.0));
}
else if (mode == 5)
{
position = InvertSpace(position, float3(0.0, -warpScale, 0.0));
}
else if (mode == 6)
{
position = mul(position, solv);
}
else if (mode == 7)
{
position = Cust1(position, length(position));
}
else if (mode == 8)
{
position = Cust2(position, cameraPosition, warpScale);
}
else if (mode == 9)
{
position = Cust3(position, length(position), warpScale, timeValue);
}
float3 cameraForward = _SpaceWarpCameraForward.w > 0.5 ? WarpSafeNormalize(_SpaceWarpCameraForward.xyz) : WarpSafeNormalize(GetWorldSpaceViewDir(worldPosition) * -1.0);
return cameraPosition + position - cameraForward * _F5Distance;
}
Varyings vert(Attributes input)
{
Varyings output;
float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
positionWS = WarpPosition(positionWS);
output.positionHCS = TransformWorldToHClip(positionWS);
output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
output.lightUv = TRANSFORM_TEX(input.uv2, _LightMap);
output.textureData = input.uv2;
output.color = input.color;
output.fogFactor = ComputeFogFactor(output.positionHCS.z);
return output;
}
half4 frag(Varyings input) : SV_Target
{
half4 baseSample = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv);
half4 arraySample = SAMPLE_TEXTURE2D_ARRAY(_TextureArray, sampler_TextureArray, frac(input.uv), input.textureData.x);
half4 lightSample = SAMPLE_TEXTURE2D(_LightMap, sampler_LightMap, input.lightUv);
half4 vertexColor = input.color;
baseSample = lerp(half4(1, 1, 1, 1), baseSample, saturate(_UseBaseMap));
baseSample = lerp(baseSample, arraySample, saturate(_UseTextureArray));
lightSample = lerp(half4(1, 1, 1, 1), lightSample, saturate(_UseLightMap));
vertexColor = lerp(half4(1, 1, 1, 1), vertexColor, saturate(_UseVertexColor));
half4 color = baseSample * lightSample * vertexColor * _BaseColor;
clip(color.a - _AlphaClipThreshold);
if (_UseFog > 0.5)
{
color.rgb = MixFog(color.rgb, input.fogFactor);
}
return color;
}
ENDHLSL
}
}
}