Preciso compensar todos os triângulos (azuis), cada um independentemente dos outros, usando o vertex-shader. Para manipular o triângulo como um todo, criei atributos personalizados (vec3) para cada vértice (vermelho) que representa os vértices vizinhos à esquerda (roxa) e à direita (verde). A partir disso, preciso derivar o ponto laranja, equidistante (no espaço da tela ) de ambas as bordas adjacentes. Com três desses pontos laranja derivados de cada triângulo, o triângulo processado (laranja) é passado para o sombreador do fragmento.
Idealmente, o triângulo será selecionado (como em backfacing / não renderizado) se as compensações negarem qualquer espaço disponível dentro do triângulo, como no segundo triângulo da segunda foto.
Estou usando THREE.BufferGeometry () como minha estrutura de dados.
Aqui está uma captura de tela do efeito que estou buscando:
Respostas:
Dado o triângulo ▲ ABC, dividimos o ângulo ACBAC com a linha AD, derivada do Teorema do Bisetor de Ângulos :
BA / BD = CA / CD O ponto E representa nossa posição refinada objetiva no triângulo de inserção resultante desejado. Como se encontra na bissetriz de ângulo AD, é equidistante dos lados BA e CA, formando triângulos retângulos idênticos ▲ AFE e ▲ AGE. Agora podemos usar Seno para Triângulos Retos para encontrar o comprimento de AE:
EA = EG / Sin (AGEAG)
Isso é tudo o que precisamos, então vamos preparar um GLSL!
Começamos com todos os atributos típicos: matrizes de posição, normal e de transformação, mas como o sombreador de vértice funciona apenas em um único vértice, precisamos adicionar os vértices vizinhos como atributos adicionais. Dessa forma, cada vértice encontrará seu próprio "ponto E", criando o triângulo inserido resultante. (Nota: não os chamo de "B" e "C" aqui, porque eles ainda não estão no espaço da tela .)
Por falar em espaço na tela, também incluo a proporção da tela (e a uniformidade, caso a janela seja redimensionada).
Depois de preparar variáveis normais para o shader de fragmento e transformar a face em espaço de recorte, podemos começar a aplicar a matemática acima:
Este código fornece os resultados abaixo.
Nota, há alguns borda casos que têm a ver com quase triângulos abatidos-Backface sendo capotou por este processo, e eu comecei a abordar isso no código, mas decidiu simplesmente evitar estes casos por agora. Talvez eu o revise quando concluir esse projeto.
fonte
Isso pode ser alcançado sem funções trigonométricas, reduzindo o círculo do triângulo.
incircle()
calcula o incirculo do triângulo formado pelos vérticesA,B,C
, retorna centro e raio comovec4
. Os vérticesX=A,B,C
são então movidos para dentro pela fração de sua distância ao centro do círculo (Q-X
), que é igual à razão da margem desejada para o raio do círculo (m/Q.w
).fonte