Formas 3D com raymarching
Desenhar cenas 3D inteiras a partir de funções de distância dentro de um único shader de fragmento, sem nenhuma malha.
Cards
Um exemplo ao vivo para ajustar, aprender e copiar.
Como funciona
A maior parte dos gráficos 3D começa por triângulos. O raymarchingDesenhar uma cena lançando um raio por cada pixel e avançando por ele pela distância até a superfície mais próxima, lida de uma função de distância com sinal, até acertar. Raymarching Desenhar uma cena lançando um raio por cada pixel e avançando por ele pela distância até a superfície mais próxima, lida de uma função de distância com sinal, até acertar. Campo de distância com sinal (SDF) Uma função que devolve a distância de um ponto até a borda de uma forma, negativa dentro e positiva fora. O zero é o próprio contorno. Mínimo suave Uma versão do min que arredonda o canto onde dois valores se cruzam. Aplicado a dois campos de distância, funde as formas numa só, com a largura da fusão definida por k.circle(p) = |p| − r em 3D: entregue a ela qualquer ponto e ela devolve a que
distância ele está da superfície mais próxima. Uma esfera é length(p) - r; uma caixa, um toro ou uma cápsula pedem uma
ou duas linhas cada; e os operadores da composição 2D funcionam sem mudança, então min junta formas e um
mínimo suaveUma versão do min que arredonda o canto onde dois valores se cruzam. Aplicado a dois campos de distância, funde as formas numa só, com a largura da fusão definida por k.h = clamp(0.5 + 0.5 (b − a) / k, 0, 1); smin = mix(b, a, h) − k h (1 − h)
Para ver a cena, um shader de fragmento sobre um quad de tela cheia dispara um raio por pixel a partir de uma câmera
virtual. Ele avança pelo raio na distância da cena, que é sempre um passo seguro porque nada está mais perto, até a
distância ficar quase zero: o raio acertou. A normalUm vetor unitário perpendicular a uma superfície, apontando para onde ela está virada. Iluminação e efeitos Fresnel o comparam com outras direções. Normal Um vetor unitário perpendicular a uma superfície, apontando para onde ela está virada. Iluminação e efeitos Fresnel o comparam com outras direções. Produto escalar Multiplica dois vetores componente a componente e soma os resultados. Para vetores unitários é o cosseno do ângulo entre eles, de 1 (mesma direção) a -1 (opostos).dot(a, b) = |a| |b| cos θ
O que você ganha é um tipo de geometria que triângulos não dão com facilidade: formas que se fundem suavemente, que se
repetem ao infinito com um mod no ponto, que dobram e torcem, todas exatas em qualquer zoom e mudando a cada quadro
sem malha nenhuma para reconstruir. O preço é um laço em cada pixel, e cada passo avalia a cena inteira. Isso faz dele a
ferramenta para demos de tela cheia, fundos, telas de título e efeitos dentro de uma caixa, e a ferramenta errada para a
geometria principal de um jogo.
Numa engine, ele roda num retângulo de tela cheia (o ColorRect do Godot, um quad na frente da câmera nas outras). Misturá-lo com as malhas da própria engine exige escrever a profundidade do ponto atingido, e cada engine trata isso de um jeito.
Leitura complementar
- dot (abre em uma nova aba)Referência
- Dot product (abre em uma nova aba)Referência
- Basic Lighting (abre em uma nova aba)Artigo
- Normal (geometry) (abre em uma nova aba)Referência
- Normal Mapping (abre em uma nova aba)Artigo
- Distance functions (abre em uma nova aba)Artigo
- Normals for an SDF (abre em uma nova aba)Artigo
- Signed distance function (abre em uma nova aba)Referência
- Smooth minimum (abre em uma nova aba)Artigo
- Domain repetition (abre em uma nova aba)Artigo
- mod (abre em uma nova aba)Referência
- Distance functions (abre em uma nova aba)Artigo
- Normals for an SDF (abre em uma nova aba)Artigo
- Ray marching (abre em uma nova aba)Referência
- Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces (abre em uma nova aba)Paper