Как @Newbie опубликовал в комментариях,
@ quixoto: откройте свое изображение в программе Paint, щелкните инструментом заливки где-нибудь в шве, и вы увидите, что он образует линию угла 90 градусов... означает, что есть только 1 цвет, нигде не ярче в «шве».это просто иллюзия.
Верно.Хотя я не знаком с этой частью математики в OpenGL, я считаю, что это неявный результат того, как выполняется интерполяция цветов между вершинами треугольника ... Я уверен, что это называется "Билинейная интерполяция".
Так что же делать, чтобы это решить?Одна возможность - использовать текстуру и просто нарисовать текстурированный квад (или несколько текстурированных квадратов).
Тем не менее, легко создать такую границу в фрагментном шейдере .
Хорошее решение с использованием шейдера GLSL ...
Предположим, вы рисуете прямоугольник с левым нижним углом, координаты текстуры которого равны (0,0), а верхний-правильный угол с (1,1).
Тогда генерация "митры" процедурно в фрагментном шейдере выглядела бы так, если я прав:
varying vec2 coord;
uniform vec2 insetWidth; // width of the border in %, max would be 0.5
void main() {
vec3 borderColor = vec3(0,0,1);
vec3 backgroundColor = vec3(1,1,1);
// x and y inset, 0..1, 1 means border, 0 means centre
vec2 insets = max(-coord + insetWidth, vec2(0,0)) / insetWidth;
Если я 'На данный момент значение m корректно, тогда для каждого пикселя значение insets.x
имеет значение в диапазоне [0..1]
, определяющее, насколько глубоко данная точка находится в границе по горизонтали, а insets.y
имеет аналогичное значение.значение для вертикальной глубины.
Левая вертикальная полоса имеет insets.y == 0,
, нижняя горизонтальная полоса имеет insets.x = 0,
, а нижний левый угол имеет пару (insets.x, insets.y), охватывающую весь 2Dдиапазон от (0,0) до (1,1).См. Рис. Для ясности:
Теперь мы хотим преобразование, которое для данной пары (x, y) даст нам ОДНО значение [0..1]
, определяющее, как смешивать фон ицвет переднего плана.1 означает границу 100%, 0 означает границу 0%.И это можно сделать несколькими способами!
Функция должна соответствовать требованиям:
- 0, если x == 0, и y == 0
- 1, еслилибо x == 1, либо y == 1
- сглаживание значений между ними.
Предположим, что такая функция:
float bias = max(insets.x,insets.y);
Она удовлетворяет этим требованиям.На самом деле, я уверен, что эта функция даст вам тот же «острый» край, что и у вас выше.Попробуйте вычислить его на бумаге для выбора координат внутри этого нижнего левого прямоугольника.
Если мы хотим, чтобы там была гладкая круглая срезка, нам просто нужна другая функция.Я думаю, что что-то вроде этого было бы достаточно:
float bias = min( length(insets) , 1 );
Функция length()
здесь просто sqrt(insets.x*insets.x + insets.y*insets.y)
.Что важно: это означает: «чем дальше (с точки зрения евклидова расстояния) мы от границы, тем более заметной должна быть граница», а min () просто для того, чтобы результат был не больше 1 (=100%).
Обратите внимание, что наша исходная функция придерживается точно такого же определения, но расстояние рассчитывается по метрике Шахматная доска (Чебышев), а не по евклидовой метрике.
Это означает, чтоиспользуя, например, манхэттенскую метрику, вы получите третью возможную форму митры!Это будет определено так:
float bias = min(insets.x+insets.y, 1);
Я предсказываю, что у этого также будет видимая "диагональная линия", но диагональ будет в другом направлении ("\"
).
ОК, поэтому для остальной части кода, когда у нас есть смещение [0..1], нам просто нужно смешать цвет фона и переднего плана:
vec3 finalColor = mix(borderColor, backgroundColor, bias);
gl_FragColor = vec4(finalColor, 1); // return the calculated RGB, and set alpha to 1
}
И это все!Использование GLSL с OpenGL делает жизнь проще.Надеюсь, это поможет!