Como traçar superfícies de Bezier?


18

Tentei essa pergunta em math.SE e, surpreendentemente, a resposta foi "as equações são muito desagradáveis, basta alimentar a função com um localizador de raiz numérico". Mas se você se considera "um cara gráfico" como eu, e já brincou bastante com as curvas de Bezier para o trabalho de design, acredito que é possível fazer melhor. Existe um algoritmo publicado por Kajiya que eu não tenho o conhecimento necessário para entender (Sylvester Matrices), mas os conselhos relacionados sobre matemática. numericamente. Eu tive outra ideia com resultado semelhante .

Então, é um sonho total esperar resolver algebricamente a interseção Ray / Bezier-superfície, tornando possível codificar explicitamente e ter uma super suavidade super rápida?

Salvo isso, qual é o método mais rápido para realizar esse cálculo? Você pode "encontrar as manobras" para obter um limite (e um alvo) para a subdivisão recursiva? Se você precisar usar um localizador de raiz numérico (suspiro), de quais propriedades ele precisa e qual a melhor opção para velocidade?

Meu pensamento original era sobre a preparação para uma superfície específica, semelhante à expansão de Laplace, conforme descrito na resposta à minha outra pergunta matemática sobre triângulos . Mas eu também estaria interessado em métodos gerais. Só estou pensando em um conjunto fixo de formas, como o bule de chá de Utah . Mas eu estaria muito interessado em maneiras de otimizar a coerência temporal através de quadros animados.


Você está procurando um método geral que possa ser aplicado a uma superfície arbitrária de Bezier ou uma maneira de preparar um método rápido para uma superfície específica? O formato da sua superfície será corrigido antes do tempo de execução?
tricoplax

11
Observe que você pode raymarch bezier de superfícies muito mais fácil do que traçá-lo. Você também pode criar superfícies univariadas raytrace ou raymarch muito mais facilmente do que outros tipos! blog.demofox.org/2015/07/28/rectangular-bezier-patches
Alan Wolfe

Respostas:


14

Primeiro, aqui está o método Kajiya em que você está pensando: Kajiya, Patches paramétricos Ray Tracing , SIGGRAPH 82. A versão do relatório técnico pode ser mais informativa.

O que espero que você tire disso é que não é impossível e não é conceitualmente difícil se você não se importa de sujar as mãos com alguma geometria algébrica e números complexos. No entanto, fazê-lo diretamente é absurdamente caro.

Os marcadores de raios "reais" tendem a fazer uma combinação de duas coisas:

  • Colocar uma hierarquia delimitadora (por exemplo, AABBs) no patch para obter um bom "valor inicial" para um localizador de raiz numérico. Se você fizer isso bem, poderá evitar o problema de "rugas".
  • Colocar o patch em mosaico camadas de DDG e traçá-las como malhas poligonais.

Esse último ponto parece que mata o requisito de "super suavidade", mas não é tão ruim quanto isso se você estiver usando diferenciais de raios . Combinar o nível de mosaico com o "tamanho" do raio limita muito bem o erro. Além disso, você provavelmente precisará de diferenciais para coordenadas de textura, portanto, você também pode usá-lo para controlar a precisão do teste de interseção.

Explorar a coerência temporal não é uma má idéia, mas exatamente como você faria isso depende muito da representação do gráfico da cena. Você pode querer observar a coerência dos raios. Pergunte ao seu mecanismo de pesquisa favorito sobre rastreamento de pacotes de raios e reordenação de raios .


9

é um sonho total esperar resolver algebricamente a interseção de Ray / Bezier-superfície

Sim, é um sonho. Um adesivo bicúbico de Bezier é uma superfície algébrica de grau 18. Para cruzar um raio com essa superfície, é necessário encontrar as raízes de um polinômio de grau 18. Não existe uma fórmula para essas raízes - você deve encontrá-las por métodos numéricos . De fato, existem resultados matemáticos ( o teorema de Abel-Ruffini ) nos dizendo que nunca pode haver fórmulas para raízes de equações além do grau 4. A matemática não diz apenas que as fórmulas ainda não foram encontradas; diz que eles nunca serão encontrados, porque não podem existir.

Se você realmente deseja fazer o traçado analítico (algébrico) de formas curvilíneas, tente usar os patches de Steiner . Eles possuem grau 4, de modo que a interseção raio-remendo pode ser calculada encontrando as raízes de um quártico (isto é, um polinômio de grau 4). Existem fórmulas para encontrar raízes de quartics, mas são bastante desagradáveis ​​e é surpreendentemente difícil escrever código que implemente as fórmulas de maneira confiável.


5

Outra opção, que eu usei algumas décadas atrás (caramba!), É usar o esquema de Toth de 1985 que empregava aritmética de intervalo para diminuir o espaço de pesquisa. IIRC, eventualmente recorrerá a Newton-Rhapson, mas, novamente, IIRC, acho que raramente foi necessário mais de um ou dois passos para chegar a uma boa solução.

Embora eu não tenha olhado para ela (bem, além de uma rápida olhada), Mitchell publicou alguns trabalhos mais recentes sobre traçado de raios com matemática de intervalo.

(Devo acrescentar que, se você estiver fazendo apenas superfícies de Bezier, o método do intervalo poderá ser um pouco "exagero", pois você pode usar truques como florescer para obter limites e derivativos. Se, no entanto, você combinar curvas de Bezier com outras funções, por exemplo, rotação em torno de um eixo, sua generalidade é mais útil.)


1

https://www.shadertoy.com/results?query=bezier classifique por idade, em caso de problemas de compatibilidade:

, ... mostra muitas soluções de muitos subconjuntos de splines, retornando a distância para um spline 2D ou rastreando um patch 3D. Splines e patches vêm de várias formas. O céu é mais simples, o bezier é simples, os nurbs são excessivamente complexos. Quanto mais restrições você adicionar ao seu spline, mais simples ele fica. NURBS é um exagero na extensão; - sua não uniformidade de pesos (o "NU") diminui a eficiência em comparação com estrias mais simétricas - seu racionamento-al-ness (o R) também acrescenta alguma complexidade para segmentar (racionar) e misturar com segmentos próximos (resolvido recursivamente).

O bezier-patch-tracing é a solução de raiz e, com isso, a priorização contextual da precisão; em que ordem para resolver a equação quadrática. isso se torna impraticável em expoentes mais altos que os cúbicos, devido à complexidade exponencial e à perda de precisão.

ray-marching == tracking da esfera é a abordagem heurística mais simples para a solução de raízes, que parece ser a solução mais simples e eficiente para renderizar a maioria dos patches de splines.

A representação de Lagrange simplifica o rastreamento / marcha (como os pontos L estão ON no spline, enquanto os pontos ControlVector (exatamente do mesmo spline) raramente estão no spline)

O caso especial de um spline sino-céu, onde as primeiras derivadas de stat e end são == 0. simplifica a continuidade e envolve menos diferenciais (menos subtração). Um patch pesado pode ser rastreado eficientemente em uma única passagem: https://www.shadertoy.com/view/4djfW3, enquanto outros splines cúbicos (ou superiores) tornam a abordagem heurística de rastreamento de esfera / marcha de raios mais eficiente (e " preciso o suficiente ") do que ousar calcular analiticamente todas as raízes para manter a menor raiz positiva (com erros de precisão acumulando exponencialmente para cada raiz).


Na computação gráfica, splines e patches foram quase completamente substituídos pelo z-brushing em 2006. O z-brushing usa mapas de deslocamento com coordenadas homogêneas ou mesmo usando um "tipo" que nos une a esfera e os segmentos de linha (os segmentos de linha têm um raio de 0, as esferas têm um comprimento de 0, uma união é simples e útil). Para uma pequena perda de precisão e um grande ganho de desempenho a um custo de memória relativamente baixo para uma tabela de consulta, isso é facilmente dinamizado em uma gpu.


Deixa pra lá. todas as soluções de patches 3d são feitas por rastreamento de esfera.
ollj

apenas aumenta significativamente o desempenho e a precisão quando o patch é mais simples. a um ponto onde um pedaço de heavensines Seamess você fica muito longe em poucas iterações:
ollj

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.