294 lines
12 KiB
GLSL
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
|
|
}
|
|
}
|
|
}
|