O que exatamente faz com que uma superfície se sobreponha a outra?


10

Eu realmente não consigo descobrir o que faz uma superfície se sobrepor a outra. Em um mecanismo 3D que estou criando, minha técnica está falhando em casos extremos.

Meu método é classificar as superfícies a serem pintadas da mais distante para a mais próxima. Para determinar a proximidade, estou comparando os valores médios de z. Às vezes, no entanto, uma superfície sobreposta tem um valor z médio mais alto do que aquele sobreposto. Assim, a superfície mais distante é pintada sobre a mais próxima - resultando em renderizações bizarras como esta:

Quadrado roxo grande com uma seção de vermelho no lado

O que se pretende ver é apenas a superfície frontal roxa do cubo, enquanto a superfície lateral vermelha é pintada sobre a roxa. O valor médio de z da superfície roxa é mais alto e, portanto, 'mais distante'. Então, eu estou tendo alguma dúvida se esta técnica está correta.

O que eu também tentei é distanciar a câmera (ou seja, a origem) da superfície, mas então precisava de um ponto. Eu escolhi o meio de cada superfície, mas isso nem sempre parece funcionar porque nem todas as superfícies são tão grandes quanto as outras.

Portanto, qual é uma maneira confiável de determinar a ordem de proximidade das superfícies em relação à origem?

Respostas:


11

Você parece estar tentando implementar o algoritmo do Painters . Suponho que você esteja tentando escrever um rasterizador do zero como um exercício de aprendizado, pois a maioria dos hardwares 3D modernos usa o que Bart mencionou (o buffer Z / Depth). Para que o algoritmo dos pintores funcione em todos os casos, você precisa estar preparado para subdividir as superfícies conforme elas são renderizadas para resolver possíveis cenários (como o problema de polígono sobreposto mostrado na página da Wikipedia).

Ao renderizar do mais longe para o mais próximo, você também gasta tempo renderizando pixels que possivelmente serão ocluídos por outros polígonos, que quando você começa a colocar texturas e shaders complexos nos polígonos desperdiçam ciclos preciosos. Essa é a razão pela qual o hardware moderno prefere renderizar da frente para trás, usando o buffer de profundidade para determinar se o pixel a ser renderizado está mais distante do que o da tela (e, portanto, pode ser descartado).

Mesmo com o hardware de aceleração mais moderno, você ainda precisará classificar e renderizar de trás para frente quaisquer polígonos semitransparentes, renderizando isso apenas quando todos os polígonos opacos tiverem sido renderizados.


Você está certo ao dizer que estou criando um renderizador simples. O ponto é que não estou usando nenhuma biblioteca 3D. Estou fazendo todos os cálculos de projeção e desenhando as linhas usando uma biblioteca de desenhos 2D. Este não é o mais rápido lá fora, e eu não estou fazendo nada por pixel. Eu só tenho 4 pontos de cada superfície e preencha a forma retangular com uma cor. Como estou desenhando uma superfície completa de uma só vez, estou correto ao dizer que preciso recuar para a frente?
— Pimvdb

Parece muito divertido e uma ótima maneira de aprender. Voltar para a frente é o seu único caminho, se você estiver fazendo isso sem qualquer forma de buffer de profundidade. Acho que você terá que elaborar todas as coordenadas de tela dos seus polígonos e depois verificar se há sobreposição. Onde eles se sobrepõem em profundidade, você potencialmente precisará cortar os polígonos para renderizar, para poder resolver a classificação corretamente. Você também pode querer olhar em volta da cara Culling como uma maneira de remover polígonos que não deve ser necessariamente visível
— Roger Perkins

Roger Perkins está certo. Você não poderá obter a classificação z correta dessa maneira (o que significa que sempre terá alguns casos extremos), a menos que você corte os polígonos. Isso pode se tornar bastante lento.
— bummzack

Eu consegui! O que fiz foi uma combinação de seleção e classificação da face posterior: em um cubo sólido, algumas faces não são visíveis enquanto outras são (máximo de 3). Então pintei as partes não visíveis primeiro e as partes visíveis sobre elas. Isso funciona como um encanto, se eu remover um ou mais lados, eles estarão sobrepostos, mas ainda serão desenhados na ordem correta. Obrigado!
— Pimvdb

1
Isso só funciona para formas convexas simples, como cubos. Estou feliz que esteja funcionando atualmente para você, mas não é uma solução geral.
— Richard Fabian

3

O que você tem é um problema de visibilidade . Uma solução está usando um buffer z .


Obrigado, mas o z-buffering requer renderização por pixel, se não me engano. Não estou fazendo isso - estou desenhando linhas retas entre os pontos projetados do cubo. O buffer z ainda é possível?
— Pimvdb

Mesmo se você estiver desenhando linhas retas, em algum momento antes da imagem chegar à tela (ou arquivo de bitmap), ela estará no formato de pixel.
— Bart van Heukelom 12/04

Está correto, mas minha biblioteca de desenhos é muito lenta para renderizar pixels com 20fps. Obrigado embora.
— Pimvdb

2

Classificar as faces de acordo com o valor z médio não funciona, porque o valor z médio não fornece informações sobre o valor z real dos vértices ou mesmo dos pixels da superfície.

Exemplo (aviso, arte ASCII adiante):

          /
         /
cam     /
-->    / 
      /
     /--       <--B
    /
    ^--A

Existem duas faces A e B. Na perspectiva da câmera, A está na frente de B. No entanto, o valor z médio de B é menor. Vejamos os outros valores z:

  • o valor z mínimo de A é 4
  • o valor z máximo de A é 11
  • portanto, o valor z médio de A é 7,5
  • o valor z mínimo de B é 6
  • o valor z máximo de B é 8
  • portanto, o valor z médio de B é 7

Você pode tentar classificá-los pelos valores z mínimos, mas há casos em que isso também não funciona. Não há como classificar faces arbitrárias corretamente usando apenas um valor z.

No algoritmo de Newell http://en.wikipedia.org/wiki/Newell 's_algorithm, o que você faz é classificar os intervalos mínimo / máximo dos valores-z. Se os intervalos de duas faces não se sobrepuserem, você pode saber com certeza qual deles está na frente. Se o fizerem, às vezes é absolutamente necessário dividir os rostos. Às vezes, basta rastrear todos os vértices para oclusão ou alguma outra técnica.


Esse diagrama é uma visão geral do que eu acho que está acontecendo em sua captura de tela.
— jhocking

1

É bom que você esteja aprendendo sobre renderização fazendo. Parabéns. Nesse caso, não existe uma solução de "algoritmo de pintores", em vez de tentar corrigi-lo por classificação, no PS1, costumávamos tentar manter os polígonos do mesmo tamanho quando estavam próximos um do outro (o que você está fazendo como até onde eu sei) e abate da face posterior (o que você não está fazendo)

A seleção da face posterior está verificando a superfície normal no espaço da tela em relação à sua direção (basta obter o sinal do elemento de profundidade no espaço da tela transformado normal (no nosso caso, era o z do normal) ou o produto cruzado de dois vetores do triângulo, ou seja, cruz (v1-v0, v2-v0))

Se você implementa a seleção de backface, também reduz a quantidade de rasterização que está fazendo .. dupla vitória.


Obrigado pela sua resposta. Eu li sobre a seleção de backface, mas o ponto é que eu gostaria de poder remover um lado. Com um cubo sólido, isso pode funcionar muito bem, mas se eu remover um lado, ocorrerá ocultação - então ainda preciso classificá-los, acho. De qualquer forma, tive a idéia de disparar um raio da origem através do ponto médio de uma superfície. Se esse raio cruzar outra superfície posteriormente, a primeira superfície se sobrepõe à segunda. Você poderia me dizer se essa ideia está correta? Obrigado!
— Pimvdb

Embora sua ideia funcione para o seu exemplo, existem muitos outros casos em que não vai funcionar. Por exemplo, a mesma cena que você tem lá, mas com a câmera inclinada para que o centro do quadrilátero de renderização incorreto não se sobreponha. Acho que você precisará separar suas primitivas em pedaços menores.
— Richard Fabian
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.