Мне нужно сместить все (синие) треугольники, каждый независимо от других, используя вершинный шейдер. Чтобы манипулировать треугольником в целом, я создал пользовательские (vec3) атрибуты для каждой вершины (красный), представляющие соседние вершины влево (фиолетовый) и вправо (зеленый). Из этого мне нужно вывести оранжевую точку, равноудаленную (в пространстве экрана ) от обоих смежных краев. С тремя такими оранжевыми точками, полученными из каждого треугольника, обработанный (оранжевый) треугольник передается фрагментному шейдеру.
В идеале, треугольник будет отбракован (как при возврате / без визуализации), если смещения отменяют любое доступное пространство внутри треугольника, например, во втором треугольнике на втором изображении.
Я использую THREE.BufferGeometry () в качестве моей структуры данных.
Вот снимок экрана с эффектом, к которому я стремлюсь:
Ответы:
Учитывая треугольник ▲ ABC, мы делим пополам угол ACBAC с линией AD, полученной с помощью теоремы Бисектора об углах :
BA / BD = CA / CD Точка E представляет нашу объективную уточненную позицию на желаемом результирующем врезанном треугольнике. Поскольку он лежит на биссектрисе угла AD, он равноудален от сторон BA и CA, образуя одинаковые прямоугольные треугольники ▲ AFE и ▲ AGE. Теперь мы можем использовать синус для прямоугольных треугольников, чтобы найти длину AE:
AE = EG / Sin (AGEAG)
Это все, что нам нужно, так что давайте приготовим немного GLSL!
Мы начнем со всех типичных атрибутов: матрицы положения, нормали и преобразования, но поскольку вершинный шейдер работает только с одной вершиной, нам нужно добавить соседние вершины в качестве дополнительных атрибутов. Таким образом, каждая вершина найдет свою собственную «точку E», создав результирующий треугольник вставки. (Примечание: я не называю их "B" и "C" здесь, потому что они еще не находятся на экране .)
Говоря о пространстве экрана, я также включаю соотношение сторон дисплея (и делаю его равномерным в случае изменения размера окна).
После подготовки различных нормалей к фрагментному шейдеру и преобразования лица в пространство отсечения, мы можем приступить к применению приведенной выше математики:
Этот код дает нам результаты ниже.
Обратите внимание, что есть несколько краевых случаи , имеющие отношение к почти Backface-забиты треугольникам быть перевернуты этим процессом, и я начал решать это в коде, но решил просто избежать этих случаев сейчас. Возможно, я вернусь к нему, когда закончу этот проект.
источник
Этого можно достичь без тригонометрических функций, уменьшив окружность треугольника.
incircle()
вычисляет вкрапление треугольника, образованного вершинамиA,B,C
, возвращает центр и радиус какvec4
. ВершиныX=A,B,C
затем перемещаются внутрь на долю их расстояния до центра вогнутости (Q-X
), которое равно отношению требуемого запаса к радиусу вогнутости (m/Q.w
).источник