Ответ 1
Как насчет этого...
float sdAxisAlignedRect(vec2 uv, vec2 tl, vec2 br)
{
vec2 d = max(tl-uv, uv-br);
return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));
}
Здесь результат, где зеленый обозначает положительное расстояние и красный негатив (код ниже):
Структура:
-
Получите знаковое расстояние от границ x и y.
u - left
иright - u
- это два расстояния по оси x. Принимая максимум этих значений, вы получаете знаковое расстояние до ближайшей границы. Просмотрd.x
иd.y
отображается отдельно на изображениях ниже. -
Объединить x и y:
-
Если оба значения отрицательные, возьмите максимум (т.е. ближе к границе). Это делается с помощью
min(0.0, max(d.x, d.y))
. -
Если только одно значение положительно, то требуемое расстояние.
-
Если оба значения положительны, ближайшая точка является углом, и в этом случае мы хотим длину. Это можно комбинировать с приведенным выше случаем, принимая длину в любом случае и убедившись, что оба значения положительны:
length(max(vec2(0.0), d))
.
Эти две части уравнения являются взаимоисключающими, т.е. только один будет производить ненулевое значение и может быть суммирован.
-
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
uv -= 0.5;
uv *= vec2(iResolution.x/iResolution.y,1.0);
uv += 0.5;
float d = sdAxisAlignedRect(uv, vec2(0.3), vec2(0.7));
float m = 1.0 - abs(d)/0.1;
float s = sin(d*400.0) * 0.5 + 0.5;
fragColor = vec4(s*m*(-sign(d)*0.5+0.5),s*m*(sign(d)*0.5+0.5),0,1);
}