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:
Aqui estão algumas imagens para ilustrar o que acontece:
De longe, a caixa azul se processa perfeitamente.
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.
É 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.
fonte
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.Respostas:
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.
fonte
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
fonte