Skip to content

Instantly share code, notes, and snippets.

@sirisian
Created June 9, 2022 07:25
Show Gist options
  • Select an option

  • Save sirisian/09fa709300a113cdce360236dc463cf9 to your computer and use it in GitHub Desktop.

Select an option

Save sirisian/09fa709300a113cdce360236dc463cf9 to your computer and use it in GitHub Desktop.
part of a box model shader system
cbuffer worldMatrix : register(b0)
{
matrix worldmat;
};
cbuffer viewMatrix : register(b1)
{
matrix viewmat;
};
cbuffer projMatrix : register(b2)
{
matrix projmat;
};
cbuffer data : register(b3) // 368 bytes
{
// Easier to read than arrays because of the packing 4 byte packing rules
float backgroundGradientIntervals0; // 4
float backgroundGradientIntervals1; // 4
float backgroundGradientIntervals2; // 4
float backgroundGradientIntervals3; // 4
float backgroundGradientIntervals4; // 4
float backgroundGradientIntervals5; // 4
float backgroundGradientIntervals6; // 4
float backgroundGradientIntervals7; // 4
float4 backgroundGradientColors[8]; // 128
float4 borderColorRight; // 16
float4 borderColorTop; // 16
float4 borderColorLeft; // 16
float4 borderColorBottom; // 16
float4 borderThickness; // 16
float2 borderRadiusTopRight; // 8
float2 borderRadiusTopLeft; // 8
float2 borderRadiusBottomLeft; // 8
float2 borderRadiusBottomRight; // 8
float2 borderSlantTopRight; // 8
float2 borderSlantTopLeft; // 8
float2 borderSlantBottomLeft; // 8
float2 borderSlantBottomRight; // 8
bool2 borderSlantInnerTopRight; // 8
bool2 borderSlantInnerTopLeft; // 8
bool2 borderSlantInnerBottomLeft; // 8
bool2 borderSlantInnerBottomRight; // 8
float2 dimensions; // 8
float2 boxShadowOffset; // 8
float boxShadowBlurRadius; // 4
float boxShadowSpread; // 4
bool boxShadowInset; // 4
float backgroundGradientAngle; // 4
float4 boxShadowColor; // 16
matrix backgroundImageTransform; // 64
bool backgroundImageEnabled; // 4
bool backgroundImageOverBackgroundColor; // 4
float padding1; // 4
float padding3; // 4
};
Texture2D<float4> tex0 : register(t0);
SamplerState samp0 : register(s0);
struct VSOutput
{
float4 Position : SV_POSITION;
float2 Texture : TEXCOORD;
float2 Screen : SCREEN;
};
VSOutput VSMain(float3 position : POSITION, float2 tex : TEXCOORD)
{
VSOutput vsOut;
vsOut.Position = mul(float4(position, 1.0), worldmat);
vsOut.Position = mul(vsOut.Position, viewmat);
vsOut.Position = mul(vsOut.Position, projmat);
vsOut.Texture = tex;
vsOut.Screen = position.xy;
return vsOut;
}
/*
float InsideBoxShadow(float2 screen)
{
float boxShadowPixel = 1;
if (any(screen >= dimensions + max(float2(0, 0), boxShadowOffset + boxShadowSpread.xx + boxShadowBlurRadius.xx)))
{
boxShadowPixel = 0;
}
else if (any(screen < min(float2(0, 0), boxShadowOffset - boxShadowSpread.xx - boxShadowBlurRadius.xx)))
{
boxShadowPixel = 0;
}
float2 boxShadowBorderRadiusTopRight = borderRadiusTopRight + boxShadowSpread.xx + boxShadowBlurRadius.xx;
float2 topRightRadiusCenter = dimensions - borderRadiusTopRight;
float2 topRightRadiusCenterToScreen = screen - topRightRadiusCenter;
if (all(boxShadowBorderRadiusTopRight))
{
float topRightOuterMaxRadius = max(boxShadowBorderRadiusTopRight.x, boxShadowBorderRadiusTopRight.y);
float2 topRightOuterRadiusScaled = topRightRadiusCenterToScreen * topRightOuterMaxRadius / boxShadowBorderRadiusTopRight;
if (all(screen >= topRightRadiusCenter) && length(topRightOuterRadiusScaled) >= topRightOuterMaxRadius)
{
boxShadowPixel = 0;
}
}
float2 boxShadowBorderRadiusTopLeft = borderRadiusTopLeft + boxShadowSpread.xx + boxShadowBlurRadius.xx;
float2 topLeftRadiusCenter = float2(borderRadiusTopLeft.x, dimensions.y - borderRadiusTopLeft.y);
float2 topLeftRadiusCenterToScreen = screen - topLeftRadiusCenter;
if (all(boxShadowBorderRadiusTopLeft))
{
float topLeftOuterMaxRadius = max(boxShadowBorderRadiusTopLeft.x, boxShadowBorderRadiusTopLeft.y);
float2 topLeftOuterRadiusScaled = topLeftRadiusCenterToScreen * topLeftOuterMaxRadius / boxShadowBorderRadiusTopLeft;
if (screen.x < topLeftRadiusCenter.x && screen.y >= topLeftRadiusCenter.y && length(topLeftOuterRadiusScaled) >= topLeftOuterMaxRadius)
{
boxShadowPixel = 0;
}
}
float2 boxShadowBorderRadiusBottomLeft = borderRadiusBottomLeft + boxShadowSpread.xx + boxShadowBlurRadius.xx;
float2 bottomLeftRadiusCenter = borderRadiusBottomLeft;
float2 bottomLeftRadiusCenterToScreen = screen - bottomLeftRadiusCenter;
if (all(boxShadowBorderRadiusBottomLeft))
{
float bottomLeftOuterMaxRadius = max(boxShadowBorderRadiusBottomLeft.x, boxShadowBorderRadiusBottomLeft.y);
float2 bottomLeftOuterRadiusScaled = bottomLeftRadiusCenterToScreen * bottomLeftOuterMaxRadius / boxShadowBorderRadiusBottomLeft;
if (all(screen < bottomLeftRadiusCenter) && length(bottomLeftOuterRadiusScaled) >= bottomLeftOuterMaxRadius)
{
boxShadowPixel = 0;
}
}
float2 boxShadowBorderRadiusBottomRight = borderRadiusBottomRight + boxShadowSpread.xx + boxShadowBlurRadius.xx;
float2 bottomRightRadiusCenter = float2(dimensions.x - borderRadiusBottomRight.x, borderRadiusBottomRight.y);
float2 bottomRightRadiusCenterToScreen = screen - bottomRightRadiusCenter;
if (all(boxShadowBorderRadiusBottomRight))
{
float bottomRightOuterMaxRadius = max(boxShadowBorderRadiusBottomRight.x, boxShadowBorderRadiusBottomRight.y);
float2 bottomRightOuterRadiusScaled = bottomRightRadiusCenterToScreen * bottomRightOuterMaxRadius / boxShadowBorderRadiusBottomRight;
if (screen.x >= bottomRightRadiusCenter.x && screen.y < bottomRightRadiusCenter.y && length(bottomRightOuterRadiusScaled) >= bottomRightOuterMaxRadius)
{
boxShadowPixel = 0;
}
}
if (all(borderSlantTopRight))
{
float2 normal = normalize(float2(borderSlantTopRight.y, borderSlantTopRight.x));
float2 topRightOuterSlant = dimensions - float2(borderSlantTopRight.x, 0) + normal * (boxShadowSpread + boxShadowBlurRadius);
float2 topRightOuterSlantToScreen = screen - topRightOuterSlant;
if (topRightOuterSlantToScreen.y > -borderSlantTopRight.y / borderSlantTopRight.x * topRightOuterSlantToScreen.x)
{
boxShadowPixel = 0;
}
}
if (all(borderSlantTopLeft))
{
float2 normal = normalize(float2(-borderSlantTopLeft.y, borderSlantTopLeft.x));
float2 topLeftOuterSlant = float2(borderSlantTopLeft.x, dimensions.y) + normal * (boxShadowSpread + boxShadowBlurRadius);
float2 topLeftOuterSlantToScreen = screen - topLeftOuterSlant;
if (topLeftOuterSlantToScreen.y > borderSlantTopLeft.y / borderSlantTopLeft.x * topLeftOuterSlantToScreen.x)
{
boxShadowPixel = 0;
}
}
if (all(borderSlantBottomLeft))
{
float2 normal = -normalize(float2(borderSlantBottomLeft.y, borderSlantBottomLeft.x));
float2 bottomLeftOuterSlant = float2(borderSlantBottomLeft.x, 0) + normal * (boxShadowSpread + boxShadowBlurRadius);
float2 bottomLeftOuterSlantToScreen = screen - bottomLeftOuterSlant;
if (bottomLeftOuterSlantToScreen.y < -borderSlantBottomLeft.y / borderSlantBottomLeft.x * bottomLeftOuterSlantToScreen.x)
{
boxShadowPixel = 0;
}
}
if (all(borderSlantBottomRight))
{
float2 normal = normalize(float2(-borderSlantBottomRight.y, borderSlantBottomRight.x));
float2 bottomRightOuterSlant = float2(dimensions.x - borderSlantBottomRight.x, 0) + normal * (boxShadowSpread + boxShadowBlurRadius);
float2 bottomRightOuterSlantToScreen = screen - bottomRightOuterSlant;
if (bottomRightOuterSlantToScreen.y < borderSlantBottomRight.y / borderSlantBottomRight.x * bottomRightOuterSlantToScreen.x)
{
boxShadowPixel = 0;
}
}
return boxShadowPixel;
}
float InsideInsetBoxShadow(float2 screen)
{
}
*/
float DistanceFromBoxShadow(float2 screen)
{
float distance = 0;
/*
float spread = max(0, boxShadowSpread - boxShadowBlurRadius);
if (boxShadowBlurRadius < boxShadowSpread)
{
float ratioMinusOne = boxShadowBlurRadius / boxShadowSpread - 1;
1 + ratioMinusOne * ratioMinusOne * ratioMinusOne
}*/
if (screen.x >= dimensions.x + boxShadowSpread && screen.y >= max(borderRadiusBottomRight.y, borderSlantBottomRight.y) && screen.y < dimensions.y - max(borderRadiusTopRight.y, borderSlantTopRight.y))
{
// Right region
distance = screen.x - (dimensions.x + boxShadowSpread);
}
else if (screen.y >= dimensions.y + boxShadowSpread && screen.x >= max(borderRadiusTopLeft.x, borderSlantTopLeft.x) && screen.x < dimensions.x - max(borderRadiusTopRight.x, borderSlantTopRight.x))
{
// Top region
distance = screen.y - (dimensions.y + boxShadowSpread);
}
else if (screen.x < -boxShadowSpread && screen.y >= max(borderRadiusBottomLeft.y, borderSlantBottomLeft.y) && screen.y < dimensions.y - max(borderRadiusTopLeft.y, borderSlantTopLeft.y))
{
// Left region
distance = screen.x + boxShadowSpread;
}
else if (screen.y < -boxShadowSpread && screen.x >= max(borderRadiusBottomLeft.x, borderSlantBottomLeft.x) && screen.x < dimensions.x - max(borderRadiusBottomRight.x, borderSlantBottomRight.x))
{
// Bottom region
distance = screen.y + boxShadowSpread;
}
else
{
if (all(borderRadiusTopRight) || all(borderSlantTopRight))
{
// Top Right corner
float2 topRightRadiusCenter = dimensions - borderRadiusTopRight;
float2 topRightSlantCenter = dimensions - borderSlantTopRight;
// This is WRONG. NEEDS TO HANDLE boxShadowRadiusTopRight when it's negative.
if (all(screen >= min(topRightRadiusCenter, topRightSlantCenter)))
{
if (all(borderRadiusTopRight))
{
float2 topRightRadiusCenterToScreen = screen - topRightRadiusCenter;
float2 boxShadowRadiusTopRight = borderRadiusTopRight + boxShadowSpread.xx;
if (all(boxShadowRadiusTopRight > float2(0, 0)))
{
float topRightOuterMaxRadius = max(boxShadowRadiusTopRight.x, boxShadowRadiusTopRight.y);
float2 topRightOuterRadiusScaled = topRightRadiusCenterToScreen * topRightOuterMaxRadius / boxShadowRadiusTopRight;
if (all(screen >= topRightRadiusCenter) && length(topRightOuterRadiusScaled) >= topRightOuterMaxRadius)
{
distance = length(topRightOuterRadiusScaled) - topRightOuterMaxRadius;
}
}
else
{
float2 topRightRadius = length(screen - (dimensions - boxShadowRadiusTopRight));
}
}
else
{
float2 tangent = float2(borderSlantTopRight.x, -borderSlantTopRight.y);
float2 normal = normalize(float2(borderSlantTopRight.y, borderSlantTopRight.x));
float2 boxShadowSlantX = dimensions - float2(borderSlantTopRight.x, 0);
float2 boxShadowSlantY = dimensions - float2(0, borderSlantTopRight.y);
float2 screenToBoxShadowSlantX = screen - boxShadowSlantX;
float lengthScreenToBoxShadowSlantX = length(screenToBoxShadowSlantX);
float2 screenToBoxShadowSlantY = screen - boxShadowSlantY;
float lengthScreenToBoxShadowSlantY = length(screenToBoxShadowSlantY);
if (dot(screenToBoxShadowSlantX, tangent) >= 0)
{
if (dot(screenToBoxShadowSlantY, tangent) < 0)
{
distance = dot(screenToBoxShadowSlantX, normal) - boxShadowSpread;
}
else if (lengthScreenToBoxShadowSlantY >= boxShadowSpread)
{
distance = lengthScreenToBoxShadowSlantY - boxShadowSpread;
}
}
else if (lengthScreenToBoxShadowSlantX >= boxShadowSpread)
{
distance = lengthScreenToBoxShadowSlantX - boxShadowSpread;
}
}
}
}
}
return distance;
}
float4 PSMain(VSOutput vsOut) : SV_Target
{
float2 screen = vsOut.Screen;
if (!boxShadowInset)
{
screen -= min(float2(0, 0), boxShadowOffset - boxShadowSpread.xx - boxShadowBlurRadius.xx);
}
float4 outColor = float4(1, 1, 1, 1);
bool borderPixel = false;
float4 borderColorAtScreen;
bool4 rhs;
float4 topRightBottomRightRelative = screen.xyxy - float4(dimensions.x, dimensions.y, dimensions.x, 0);
float4 topLeftBottomLeftRelative = screen.xyxy - float4(0, dimensions.y, 0, 0);
float4 borderThicknessSlopes = borderThickness.yyww / borderThickness.xzzx;
rhs.xw = float2(1, -1) * topRightBottomRightRelative.yw < borderThicknessSlopes.xw * topRightBottomRightRelative.xz;
rhs.yz = float2(-1, 1) * topLeftBottomLeftRelative.yw > borderThicknessSlopes.yz * topLeftBottomLeftRelative.xz;
float2 topRightInnerCorner = dimensions - borderThickness.xy;
float2 topLeftInnerCorner = float2(borderThickness.z, dimensions.y - borderThickness.y);
float2 bottomLeftInnerCorner = borderThickness.zw;
float2 bottomRightInnerCorner = float2(dimensions.x - borderThickness.x, borderThickness.w);
bool2 screenBottomLeft = screen >= bottomLeftInnerCorner;
bool2 screenTopRight = screen < topRightInnerCorner;
if (screenBottomLeft.x && all(rhs.xw))
{
borderColorAtScreen = borderColorRight;
}
else if (screenBottomLeft.y && !any(rhs.xy))
{
borderColorAtScreen = borderColorTop;
}
else if (screenTopRight.x && all(rhs.yz))
{
borderColorAtScreen = borderColorLeft;
}
else if (screenTopRight.y && !any(rhs.zw))
{
borderColorAtScreen = borderColorBottom;
}
if (any(screen < borderThickness.zw) || any(screen >= dimensions - borderThickness.xy))
{
borderPixel = true;
}
float2 topRightRadiusCenter = dimensions - borderRadiusTopRight;
float2 topRightRadiusCenterToScreen = screen - topRightRadiusCenter;
float2 borderRadiusTopRightInner = borderRadiusTopRight - borderThickness.xy;
float borderRadiusTopRightInnerMax = max(borderRadiusTopRightInner.x, borderRadiusTopRightInner.y);
if (all(borderRadiusTopRight))
{
if (all(borderRadiusTopRight > borderThickness.xy) && all(screen >= topRightRadiusCenter) && all(screen < topRightInnerCorner))
{
float2 scaledInner = topRightRadiusCenterToScreen * borderRadiusTopRightInnerMax / borderRadiusTopRightInner;
if (length(scaledInner) >= borderRadiusTopRightInnerMax)
{
borderPixel = true;
}
}
}
float2 topLeftRadiusCenter = float2(borderRadiusTopLeft.x, dimensions.y - borderRadiusTopLeft.y);
float2 topLeftRadiusCenterToScreen = screen - topLeftRadiusCenter;
float2 borderRadiusTopLeftInner = borderRadiusTopLeft - borderThickness.zy;
float topLeftInnerMaxRadius = max(borderRadiusTopLeftInner.x, borderRadiusTopLeftInner.y);
if (all(borderRadiusTopLeft))
{
if (all(borderRadiusTopLeft > borderThickness.zy) && screen.x < topLeftRadiusCenter.x && screen.y >= topLeftRadiusCenter.y && screen.x >= topLeftInnerCorner.x && screen.y < topLeftInnerCorner.y)
{
float2 scaledInner = topLeftRadiusCenterToScreen * topLeftInnerMaxRadius / borderRadiusTopLeftInner;
if (length(scaledInner) >= topLeftInnerMaxRadius)
{
borderPixel = true;
}
}
}
float2 bottomLeftRadiusCenter = borderRadiusBottomLeft;
float2 bottomLeftRadiusCenterToScreen = screen - bottomLeftRadiusCenter;
float2 borderRadiusBottomLeftInner = borderRadiusBottomLeft - borderThickness.zw;
float bottomLeftInnerMaxRadius = max(borderRadiusBottomLeftInner.x, borderRadiusBottomLeftInner.y);
if (all(borderRadiusBottomLeft))
{
if (all(borderRadiusBottomLeft > borderThickness.zw) && all(screen < bottomLeftRadiusCenter) && all(screen >= bottomLeftInnerCorner))
{
float2 scaledInner = bottomLeftRadiusCenterToScreen * bottomLeftInnerMaxRadius / borderRadiusBottomLeftInner;
if (length(scaledInner) >= bottomLeftInnerMaxRadius)
{
borderPixel = true;
}
}
}
float2 bottomRightRadiusCenter = float2(dimensions.x - borderRadiusBottomRight.x, borderRadiusBottomRight.y);
float2 bottomRightRadiusCenterToScreen = screen - bottomRightRadiusCenter;
float2 borderRadiusBottomRightInner = borderRadiusBottomRight - borderThickness.xw;
float bottomRightInnerMaxRadius = max(borderRadiusBottomRightInner.x, borderRadiusBottomRightInner.y);
if (all(borderRadiusBottomRight))
{
if (all(borderRadiusBottomRight > borderThickness.xw) && screen.x >= bottomRightRadiusCenter.x && screen.y < bottomRightRadiusCenter.y && screen.x < bottomRightInnerCorner.x && screen.y >= bottomRightInnerCorner.y)
{
float2 scaledInner = bottomRightRadiusCenterToScreen * bottomRightInnerMaxRadius / borderRadiusBottomRightInner;
if (length(scaledInner) >= bottomRightInnerMaxRadius)
{
borderPixel = true;
}
}
}
float2 topRightOuterSlant = dimensions - float2(borderSlantTopRight.x, 0);
float2 topRightOuterSlantToScreen = screen - topRightOuterSlant;
if (any(borderSlantInnerTopRight))
{
float2 slantInner = borderSlantInnerTopRight ? borderThickness.xy : borderThickness.yx;
float2 normal = -normalize(float2(borderSlantTopRight.y, borderSlantTopRight.x));
float4 topRightInnerSlant = topRightOuterSlant.xyxy + normal.xyxy * slantInner.xxyy;
topRightInnerSlant.yz += (topRightInnerSlant.xw - topRightInnerCorner.xy) * borderSlantTopRight.yx / borderSlantTopRight.xy;
if (all(topRightInnerSlant.zy < topRightInnerCorner))
{
topRightInnerSlant.xw = topRightInnerCorner.xy;
topRightInnerSlant = round(topRightInnerSlant);
float2 topRightInnerSlantToScreen = screen.xy - topRightInnerSlant.xy;
float2 slope = topRightInnerSlant.zw - topRightInnerSlant.xy;
if (topRightInnerSlantToScreen.y > slope.y / slope.x * topRightInnerSlantToScreen.x)
{
borderPixel = true;
}
}
}
float2 topLeftOuterSlant = float2(borderSlantTopLeft.x, dimensions.y);
float2 topLeftOuterSlantToScreen = screen - topLeftOuterSlant;
if (any(borderSlantInnerTopLeft))
{
float2 slantInner = borderSlantInnerTopLeft ? borderThickness.zy : borderThickness.yz;
float2 normal = normalize(float2(borderSlantTopLeft.y, -borderSlantTopLeft.x));
float4 topLeftInnerSlant = topLeftOuterSlant.xyxy + normal.xyxy * slantInner.xxyy;
topLeftInnerSlant.yz -= (topLeftInnerSlant.xw - topLeftInnerCorner.xy) * borderSlantTopLeft.yx / borderSlantTopLeft.xy;
if (topLeftInnerSlant.z > topLeftInnerCorner.x && topLeftInnerSlant.y < topLeftInnerCorner.y)
{
topLeftInnerSlant.xw = topLeftInnerCorner.xy;
topLeftInnerSlant = round(topLeftInnerSlant);
float2 topLeftInnerSlantToScreen = screen.xy - topLeftInnerSlant.xy;
float2 slope = topLeftInnerSlant.zw - topLeftInnerSlant.xy;
if (topLeftInnerSlantToScreen.y > slope.y / slope.x * topLeftInnerSlantToScreen.x)
{
borderPixel = true;
}
}
}
float2 bottomLeftOuterSlant = float2(borderSlantBottomLeft.x, 0);
float2 bottomLeftOuterSlantToScreen = screen - bottomLeftOuterSlant;
if (any(borderSlantInnerBottomLeft))
{
float2 slantInner = borderSlantInnerBottomLeft ? borderThickness.zw : borderThickness.wz;
float2 normal = normalize(float2(borderSlantBottomLeft.y, borderSlantBottomLeft.x));
float4 bottomLeftInnerSlant = bottomLeftOuterSlant.xyxy + normal.xyxy * slantInner.xxyy;
bottomLeftInnerSlant.yz += (bottomLeftInnerSlant.xw - bottomLeftInnerCorner.xy) * borderSlantBottomLeft.yx / borderSlantBottomLeft.xy;
if (all(bottomLeftInnerSlant.zy > bottomLeftInnerCorner))
{
bottomLeftInnerSlant.xw = bottomLeftInnerCorner.xy;
bottomLeftInnerSlant = round(bottomLeftInnerSlant);
float2 bottomLeftInnerSlantToScreen = screen.xy - bottomLeftInnerSlant.xy;
float2 slope = bottomLeftInnerSlant.zw - bottomLeftInnerSlant.xy;
if (bottomLeftInnerSlantToScreen.y < slope.y / slope.x * bottomLeftInnerSlantToScreen.x)
{
borderPixel = true;
}
}
}
float2 bottomRightOuterSlant = float2(dimensions.x - borderSlantBottomRight.x, 0);
float2 bottomRightOuterSlantToScreen = screen - bottomRightOuterSlant;
if (any(borderSlantInnerBottomRight))
{
float2 slantInner = borderSlantInnerBottomRight ? borderThickness.xw : borderThickness.wx;
float2 normal = normalize(float2(-borderSlantBottomRight.y, borderSlantBottomRight.x));
float4 bottomRightInnerSlant = bottomRightOuterSlant.xyxy + normal.xyxy * slantInner.xxyy;
bottomRightInnerSlant.yz -= (bottomRightInnerSlant.xw - bottomRightInnerCorner.xy) * borderSlantBottomRight.yx / borderSlantBottomRight.xy;
if (bottomRightInnerSlant.z < bottomRightInnerCorner.x && bottomRightInnerSlant.y > bottomRightInnerCorner.y)
{
bottomRightInnerSlant.xw = bottomRightInnerCorner.xy;
bottomRightInnerSlant = round(bottomRightInnerSlant);
float2 bottomRightInnerSlantToScreen = screen.xy - bottomRightInnerSlant.xy;
float2 slope = bottomRightInnerSlant.zw - bottomRightInnerSlant.xy;
if (bottomRightInnerSlantToScreen.y < slope.y / slope.x * bottomRightInnerSlantToScreen.x)
{
borderPixel = true;
}
}
}
bool backgroundPixel = true;
if (all(borderRadiusTopRight))
{
float topRightOuterMaxRadius = max(borderRadiusTopRight.x, borderRadiusTopRight.y);
float2 topRightOuterRadiusScaled = topRightRadiusCenterToScreen * topRightOuterMaxRadius / borderRadiusTopRight;
if (all(screen >= topRightRadiusCenter) && length(topRightOuterRadiusScaled) >= topRightOuterMaxRadius)
{
backgroundPixel = false;
}
}
if (all(borderRadiusTopLeft))
{
float topLeftOuterMaxRadius = max(borderRadiusTopLeft.x, borderRadiusTopLeft.y);
float2 topLeftOuterRadiusScaled = topLeftRadiusCenterToScreen * topLeftOuterMaxRadius / borderRadiusTopLeft;
if (screen.x < topLeftRadiusCenter.x && screen.y >= topLeftRadiusCenter.y && length(topLeftOuterRadiusScaled) >= topLeftOuterMaxRadius)
{
backgroundPixel = false;
}
}
if (all(borderRadiusBottomLeft))
{
float bottomLeftOuterMaxRadius = max(borderRadiusBottomLeft.x, borderRadiusBottomLeft.y);
float2 bottomLeftOuterRadiusScaled = bottomLeftRadiusCenterToScreen * bottomLeftOuterMaxRadius / borderRadiusBottomLeft;
if (all(screen < bottomLeftRadiusCenter) && length(bottomLeftOuterRadiusScaled) >= bottomLeftOuterMaxRadius)
{
backgroundPixel = false;
}
}
if (all(borderRadiusBottomRight))
{
float bottomRightOuterMaxRadius = max(borderRadiusBottomRight.x, borderRadiusBottomRight.y);
float2 bottomRightOuterRadiusScaled = bottomRightRadiusCenterToScreen * bottomRightOuterMaxRadius / borderRadiusBottomRight;
if (screen.x >= bottomRightRadiusCenter.x && screen.y < bottomRightRadiusCenter.y && length(bottomRightOuterRadiusScaled) >= bottomRightOuterMaxRadius)
{
backgroundPixel = false;
}
}
if (all(borderSlantTopRight))
{
if (topRightOuterSlantToScreen.y > -borderSlantTopRight.y / borderSlantTopRight.x * topRightOuterSlantToScreen.x)
{
backgroundPixel = false;
}
}
if (all(borderSlantTopLeft))
{
if (topLeftOuterSlantToScreen.y > borderSlantTopLeft.y / borderSlantTopLeft.x * topLeftOuterSlantToScreen.x)
{
backgroundPixel = false;
}
}
if (all(borderSlantBottomLeft))
{
if (bottomLeftOuterSlantToScreen.y < -borderSlantBottomLeft.y / borderSlantBottomLeft.x * bottomLeftOuterSlantToScreen.x)
{
backgroundPixel = false;
}
}
if (all(borderSlantBottomRight))
{
if (bottomRightOuterSlantToScreen.y < borderSlantBottomRight.y / borderSlantBottomRight.x * bottomRightOuterSlantToScreen.x)
{
backgroundPixel = false;
}
}
if (!backgroundPixel)
{
borderPixel = false;
}
if (any(screen >= dimensions))
{
borderPixel = false;
backgroundPixel = false;
}
if (borderPixel)
{
outColor = borderColorAtScreen;
}
else if (backgroundPixel)
{
// Gradient
float2 gradientLineToProjectOnto = float2(cos(backgroundGradientAngle), sin(backgroundGradientAngle));
float2 center = (topLeftInnerCorner + bottomRightInnerCorner) / 2;
float dotTopRight = dot(topRightInnerCorner - center, gradientLineToProjectOnto);
float2 topRightProjectedOntoGradientLine = dotTopRight * gradientLineToProjectOnto;
float dotTopLeft = dot(topLeftInnerCorner - center, gradientLineToProjectOnto);
float2 topLeftProjectedOntoGradientLine = dotTopLeft * gradientLineToProjectOnto;
float dotBottomLeft = dot(bottomLeftInnerCorner - center, gradientLineToProjectOnto);
float2 bottomLeftProjectedOntoGradientLine = dotBottomLeft * gradientLineToProjectOnto;
float dotBottomRight = dot(bottomRightInnerCorner - center, gradientLineToProjectOnto);
float2 bottomRightProjectedOntoGradientLine = dotBottomRight * gradientLineToProjectOnto;
float dotScreen = dot(screen - center, gradientLineToProjectOnto);
float2 screenProjectedOntoGradientLine = dotScreen * gradientLineToProjectOnto;
float4 minVector;
minVector.x = sign(dotTopRight) * length(topRightProjectedOntoGradientLine);
minVector.y = sign(dotTopLeft) * length(topRightProjectedOntoGradientLine);
minVector.z = sign(dotBottomLeft) * length(topRightProjectedOntoGradientLine);
minVector.w = sign(dotTopRight) * length(topRightProjectedOntoGradientLine);
float4 maxVector = minVector;
minVector.xy = min(minVector.xy, minVector.zw);
float minValue = min(minVector.x, minVector.y);
maxVector.xy = max(maxVector.xy, maxVector.zw);
float maxValue = max(maxVector.x, maxVector.y);
float screenVector = sign(dotScreen) * length(screenProjectedOntoGradientLine);
float p = clamp((screenVector - minValue) / (maxValue - minValue), 0, 0.9999);
float4 backgroundColor;
if (p < backgroundGradientIntervals3)
{
if (p < backgroundGradientIntervals1)
{
if (p < backgroundGradientIntervals0)
{
backgroundColor = backgroundGradientColors[0];
}
else
{
float blendProportion = (p - backgroundGradientIntervals0) / (backgroundGradientIntervals1 - backgroundGradientIntervals0);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[0] + blendProportion * backgroundGradientColors[1];
}
}
else
{
if (p < backgroundGradientIntervals2)
{
float blendProportion = (p - backgroundGradientIntervals1) / (backgroundGradientIntervals2 - backgroundGradientIntervals1);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[1] + blendProportion * backgroundGradientColors[2];
}
else
{
float blendProportion = (p - backgroundGradientIntervals2) / (backgroundGradientIntervals3 - backgroundGradientIntervals2);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[2] + blendProportion * backgroundGradientColors[3];
}
}
}
else
{
if (p < backgroundGradientIntervals5)
{
if (p < backgroundGradientIntervals4)
{
float blendProportion = (p - backgroundGradientIntervals3) / (backgroundGradientIntervals4 - backgroundGradientIntervals3);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[3] + blendProportion * backgroundGradientColors[4];
}
else
{
float blendProportion = (p - backgroundGradientIntervals4) / (backgroundGradientIntervals5 - backgroundGradientIntervals4);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[4] + blendProportion * backgroundGradientColors[5];
}
}
else
{
if (p < backgroundGradientIntervals6)
{
float blendProportion = (p - backgroundGradientIntervals5) / (backgroundGradientIntervals6 - backgroundGradientIntervals5);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[5] + blendProportion * backgroundGradientColors[6];
}
else if (p < backgroundGradientIntervals7)
{
float blendProportion = (p - backgroundGradientIntervals6) / (backgroundGradientIntervals7 - backgroundGradientIntervals6);
backgroundColor = (1 - blendProportion) * backgroundGradientColors[6] + blendProportion * backgroundGradientColors[7];
}
else
{
backgroundColor = backgroundGradientColors[7];
}
}
}
outColor = backgroundColor;
if (backgroundImageEnabled)
{
float4 backgroundImageColor = tex0.Sample(samp0, mul(float4(vsOut.Texture.xy, 0, 1), backgroundImageTransform).xy);
float4 source;
float4 destination;
if (backgroundImageOverBackgroundColor)
{
source = backgroundImageColor;
destination = outColor;
}
else
{
source = outColor;
destination = backgroundImageColor;
}
outColor.a = source.a + destination.a * (1 - source.a);
outColor.rgb = (source.rgb * source.a + destination.rgb * (1 - source.a)) / outColor.a;
}
}
else if (!boxShadowInset)
{
// Pixel is outside of the edge
/*
// Box Shadow
float boxShadowWeight = 1;
switch (boxShadowBlurRadius)
{
case 1:
boxShadowWeight = InsideBoxShadow(screen + float2(-1, 1)) * 0.077847f + InsideBoxShadow(screen + float2(0, 1)) * 0.123317f + InsideBoxShadow(screen + float2(1, 1)) * 0.077847f +
InsideBoxShadow(screen + float2(-1, 0)) * 0.123317f + InsideBoxShadow(screen + float2(0, 0)) * 0.195346f + InsideBoxShadow(screen + float2(1, 0)) * 0.123317f +
InsideBoxShadow(screen + float2(-1, -1)) * 0.077847f + InsideBoxShadow(screen + float2(0, -1)) * 0.123317f + InsideBoxShadow(screen + float2(1, -1)) * 0.077847f;
break;
case 2:
boxShadowWeight = InsideBoxShadow(screen + float2(-2, 2)) * 0.003765f + InsideBoxShadow(screen + float2(-1, 2)) * 0.015019f + InsideBoxShadow(screen + float2(0, 2)) * 0.023792f + InsideBoxShadow(screen + float2(1, 2)) * 0.015019f + InsideBoxShadow(screen + float2(2, 2)) * 0.003765f +
InsideBoxShadow(screen + float2(-2, 1)) * 0.015019f + InsideBoxShadow(screen + float2(-1, 1)) * 0.059912f + InsideBoxShadow(screen + float2(0, 1)) * 0.094907f + InsideBoxShadow(screen + float2(1, 1)) * 0.059912f + InsideBoxShadow(screen + float2(2, 1)) * 0.015019f +
InsideBoxShadow(screen + float2(-2, 0)) * 0.023792f + InsideBoxShadow(screen + float2(-1, 0)) * 0.094907f + InsideBoxShadow(screen + float2(0, 0)) * 0.150342f + InsideBoxShadow(screen + float2(1, 0)) * 0.094907f + InsideBoxShadow(screen + float2(2, 0)) * 0.023792f +
InsideBoxShadow(screen + float2(-2, -1)) * 0.015019f + InsideBoxShadow(screen + float2(-1, -1)) * 0.059912f + InsideBoxShadow(screen + float2(0, -1)) * 0.094907f + InsideBoxShadow(screen + float2(1, -1)) * 0.059912f + InsideBoxShadow(screen + float2(2, -1)) * 0.015019f +
InsideBoxShadow(screen + float2(-2, -2)) * 0.003765f + InsideBoxShadow(screen + float2(-1, -2)) * 0.015019f + InsideBoxShadow(screen + float2(0, -2)) * 0.023792f + InsideBoxShadow(screen + float2(1, -2)) * 0.015019f + InsideBoxShadow(screen + float2(2, -2)) * 0.003765f;
break;
case 3:
0.000036 0.000363 0.001446 0.002291 0.001446 0.000363 0.000036
0.000363 0.003676 0.014662 0.023226 0.014662 0.003676 0.000363
0.001446 0.014662 0.058488 0.092651 0.058488 0.014662 0.001446
0.002291 0.023226 0.092651 0.146768 0.092651 0.023226 0.002291
0.001446 0.014662 0.058488 0.092651 0.058488 0.014662 0.001446
0.000363 0.003676 0.014662 0.023226 0.014662 0.003676 0.000363
0.000036 0.000363 0.001446 0.002291 0.001446 0.000363 0.000036
break;
}
outColor = boxShadowWeight * boxShadowColor;
*/
float boxShadowWeight = 1 - clamp(DistanceFromBoxShadow(vsOut.Screen) / (boxShadowBlurRadius * 2), 0, 1);
outColor = boxShadowWeight * boxShadowColor;
}
else
{
discard;
}
return outColor;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment