Como devo lidar com vértices de recorte mais próximos do olho do que o plano do clipe próximo?

13

Estou rodando meu próprio mecanismo 3D, em JavaScript, e usando apenas desenho de tela, sem WebGL. Este é outro clone do Minecraft; Eu amo caixas, não me julgue.

Até agora, tudo funciona maravilhosamente, exceto por uma coisa: em 3D, quando alguns vértices ficam atrás do plano de recorte próximo, sua projeção na tela fica estranha (supondo que outros vértices usados ​​para rastrear um plano estejam na frente).

Tentei recortar esses pontos, mas depois vejo as superfícies que usam esses vértices. No WebGL / OpenGL, a placa gráfica cuida desses pontos e o avião é renderizado corretamente, mas como não tenho acesso ao hardware, devo codificar isso sozinho.

Não sei bem o que fazer, atualmente a última coisa que me veio à mente é reverter a projeção de pontos atrás do plano de recorte próximo do jogador, o que parece lógico, pois preciso projetar um ponto em uma tela à frente do vértice.

Aqui estão os meus pensamentos:

insira a descrição da imagem aqui

Aqui estão algumas imagens para ilustrar o que acontece:

insira a descrição da imagem aqui

De longe, a caixa azul se processa perfeitamente.

insira a descrição da imagem aqui

Quando alguns dos vértices ficam atrás do plano de recorte próximo do jogador, faço a projeção reversa, mas não parece correto:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Observe que a caixa cinza atrás é completamente removida, pois todos os vértices usados ​​para desenhar suas faces estão atrás do jogador.

insira a descrição da imagem aqui

É o que acontece quando se olha para cima ou para baixo.

Não sei o que fazer com a matemática por trás disso, espero que alguém já tenha encontrado o mesmo problema e possa me ajudar.

Solenóide
fonte
1
Se os pontos estiverem mais próximos do olho do que o plano do clipe próximo, eles devem ser cortados - e isso pode realmente permitir que você veja "através" de um objeto. Esse é o comportamento típico; a colisão normalmente impede esse artefato visual específico. Essa foi a única coisa errada com sua solução de recorte?
@ JoshPetrie: Eu entendo que os pontos devem ser cortados, mas se eu fizer isso, todo o quadrado desaparecerá como um ou dois dos vértices pelos quais a rotina de desenho deve passar estão ausentes (em 2d) e o jogador poderá ver através desse quadrado. Eu gostaria que eles estivessem "fora" da tela (na projeção) para que o quadrado ainda pudesse ser desenhado. Não tenho certeza se sou clara o suficiente.
Solenóide
Você está - estou dizendo que esse é um comportamento normal e você deseja impedir que isso aconteça, impedindo que o jogador chegue tão perto de um dos cubos. Se você realmente quis fazer isso, recorte, mas reconstrua os triângulos (possivelmente). Isso ainda parecerá incomum, especialmente se você tiver texturas. Se o que estou dizendo não faz sentido, você pode se juntar a nós no bate - papo para não criar um tópico de comentário realmente falador.
O que você está dizendo faz sentido, reconstruir leva muito tempo, então essa não é a solução. Eu esperava que ainda houvesse uma maneira de desenhar esse vértice no plano 2D que estava atrás do jogador, para que a lineTo(x,y)função ainda pudesse ser chamada, só que eu não sei como ela se comporta ... é uma dimensão bizarra, eu concordo.
Solenóide

Respostas:

1

O objetivo do plano de recorte próximo é que ele é um plano de recorte . Os triângulos que estão fora de um plano de recorte são recortados : recorte em pedaços para que cada peça restante fique na região de recorte.

Você pode tentar ignorar o clipe próximo, se desejar. De fato, o OpenGL e o D3D têm maneiras de desativar completamente o recorte próximo ao plano (embora o buffer de profundidade ainda tenha um valor próximo mínimo). O problema não é o clipe próximo.

O problema está nos vértices que estão atrás da câmera.

Você não pode renderizar triângulos atrás da câmera. Não com uma projeção em perspectiva. Tais triângulos não fazem sentido sob a matemática por trás das projeções em perspectiva. Além disso, eles também estão fora do frustum.

Desligar próximo ao recorte transforma um frustum em uma pirâmide. A razão pela qual a pirâmide para no ponto é porque os pontos acima da pirâmide estão atrás de todos os quatro lados da pirâmide. Portanto, qualquer ponto atrás da câmera (a ponta da pirâmide) está acima, abaixo, à esquerda e à direita da região visível da tela. Tudo ao mesmo tempo.

Como eu disse: vértices sob uma projeção em perspectiva que estão por trás da câmera não fazem sentido.

Você deve implementar o recorte. Você deve detectar quando qualquer vértice de um triângulo, no espaço do clipe ( antes da divisão da perspectiva) está atrás da câmera. Se for, você deve cortar esse triângulo, gerando apenas triângulos que estão na frente da câmera.

Este não é um processo simples. Isso envolverá matemática que só faz sentido se você tiver uma compreensão completa dos sistemas de coordenadas homogêneas. Como alternativa, você pode simplesmente selecionar qualquer triângulo, se houver algum vértice atrás da câmera.

Nicol Bolas
fonte
Até agora, eu selecionei todo o triângulo, mas depois vi através do avião (veja as fotos acima). Eu realmente precisava de uma imagem para entender por que não faz sentido geometricamente. A única solução é calcular a interseção da linha plana quando um dos vértices estiver atrás do plano de recorte e usar essa interseção para rastrear a linha a partir do vértice que está na frente, infelizmente isso é caro.
Solenóide
0

Se parte do triângulo atrás do plano próximo, você poderia fazer uma verificação por pixel para ver se a posição do pixel está atrás do plano de recorte?

Você pode tratar o plano próximo como qualquer outro plano de corte. Por exemplo, os planos de recorte são usados ​​para itens como planos de água (para reflexões e refrações). Eu acho que esse plano de recorte funcionaria exatamente como o plano de recorte próximo e recorte por pixel.

Eu sei como lidar com planos de recorte no HLSL com DirectX, mas sua implementação pode ser proprietária. Se você puder obter informações sobre essas informações, pode ser útil.

Além disso, aqui está um link que pode ajudá-lo: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html

Nic Foster
fonte
O teste por pixel é extremamente caro em uma linguagem interpretada como Javascript, estou recebendo fps quase aceitável agora.
Solenóide