45 lines
1.1 KiB
Plaintext
45 lines
1.1 KiB
Plaintext
static const float PI = 3.14159265358979323846;
|
|
|
|
float2 rotateAroundCenter(float2 uv, float radians)
|
|
{
|
|
float2 centered = uv - 0.5;
|
|
float s = sin(radians);
|
|
float c = cos(radians);
|
|
return float2(c * centered.x - s * centered.y, s * centered.x + c * centered.y) + 0.5;
|
|
}
|
|
|
|
float mirroredCoordinate(float coordinate)
|
|
{
|
|
float wrapped = frac(coordinate * 0.5) * 2.0;
|
|
return wrapped <= 1.0 ? wrapped : 2.0 - wrapped;
|
|
}
|
|
|
|
float2 applyEdgeMode(float2 uv, out bool inside)
|
|
{
|
|
inside = uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0;
|
|
|
|
if (edgeMode == 1)
|
|
return clamp(uv, 0.0, 1.0);
|
|
if (edgeMode == 2)
|
|
return frac(uv);
|
|
if (edgeMode == 3)
|
|
return float2(mirroredCoordinate(uv.x), mirroredCoordinate(uv.y));
|
|
|
|
return uv;
|
|
}
|
|
|
|
float4 shadeVideo(ShaderContext context)
|
|
{
|
|
float safeZoom = max(zoom, 0.001);
|
|
float2 sourceUv = (context.uv - 0.5) / safeZoom + 0.5;
|
|
sourceUv -= pan;
|
|
sourceUv = rotateAroundCenter(sourceUv, -rotationDegrees * (PI / 180.0));
|
|
|
|
bool inside = false;
|
|
float2 sampledUv = applyEdgeMode(sourceUv, inside);
|
|
if (!inside && edgeMode == 0)
|
|
return outsideColor;
|
|
|
|
return sampleVideo(sampledUv);
|
|
}
|