¿Qué hace exactamente que una superficie se superponga con otra?

10

Realmente no puedo entender qué causa que una superficie se superponga con otra. En un motor 3D que estoy creando, mi técnica falla en casos extremos.

Mi método es ordenar las superficies a pintar desde el más alejado hasta el más cercano. Para determinar la cercanía, estoy comparando los valores promedio de z. A veces, sin embargo, una superficie superpuesta tiene un valor z promedio más alto que el que se superpone. Por lo tanto, la superficie más alejada se pinta sobre la más cercana, lo que resulta en una representación extraña como esta:

Gran cuadrado morado con una sección de rojo en el costado

Lo que uno debe ver es la superficie frontal púrpura del cubo solamente, mientras que la superficie lateral roja está pintada sobre la púrpura. El valor z promedio de la superficie púrpura es más alto y, por lo tanto, está "más lejos". Así que tengo dudas sobre si esta técnica es correcta.

Lo que también intenté es obtener la distancia desde la cámara (es decir, el origen) hasta la superficie, pero luego necesitaba un punto. Elegí el centro de cada superficie, pero esto no siempre parece funcionar porque no todas las superficies son tan grandes como la otra.

Por lo tanto, ¿cuál es una forma confiable de determinar el orden de proximidad de las superficies hacia el origen?

pimvdb
fuente

Respuestas:

11

Parece que estás intentando implementar el algoritmo de pintores . Supongo que estás tratando de escribir un rasterizador desde cero como un ejercicio de aprendizaje, ya que la mayoría del hardware 3D moderno usa lo que Bart ha mencionado (el búfer Z / Depth). Para que el algoritmo de pintores funcione en todos los casos, debe estar preparado para subdividir las superficies a medida que se procesan para resolver posibles escenarios (como el problema de polígono superpuesto que se muestra en la página de Wikipedia).

Al renderizar desde el más cercano al más cercano, también pasa tiempo renderizando píxeles que posiblemente serán ocluidos posteriormente por otros polígonos, que cuando comienza a poner texturas y sombreadores complejos en los polígonos desperdician ciclos preciosos. Esta es la razón por la cual el hardware moderno preferiría que renderice de adelante hacia atrás, utilizando el búfer de profundidad para determinar si el píxel que se representará está más alejado que el de la pantalla (y, por lo tanto, puede descartarse).

Incluso con el hardware de aceleración más moderno, necesitará ordenar y renderizar de atrás hacia adelante cualquier polígono semitransparente, renderizando esto solo una vez que se hayan renderizado todos los polígonos opacos.

Roger Perkins
fuente
Tienes razón al decir que estoy creando un renderizador simple. El punto es que no estoy usando ninguna biblioteca 3D. Estoy haciendo todos los cálculos de proyección y luego dibujo las líneas usando una biblioteca de dibujo 2D. Este no es el más rápido y no estoy haciendo nada por píxel. Solo tengo 4 puntos de cada superficie y relleno la forma rectangular con un color. Como estoy dibujando una superficie completa a la vez, ¿estoy en lo cierto al decir que tengo que retroceder al frente?
pimvdb
Suena muy divertido y una excelente manera de aprender. Volver al frente es su única forma si lo hace sin ningún tipo de búfer de profundidad. Creo que tendrá que calcular todas las coordenadas de pantalla de sus polígonos y luego verificar si hay superposición. Cuando se superponen en profundidad, posiblemente necesitará cortar los polígonos para renderizar, de modo que pueda resolver la clasificación correctamente. También es posible que desee ver la eliminación de la cara posterior como una forma de eliminar los polígonos que no necesariamente deberían ser visibles
Roger Perkins,
Roger Perkins tiene razón. No podrá lograr la ordenación z correcta de esa manera (lo que significa que siempre tendrá algunos casos de borde), a menos que corte los polígonos. Sin embargo, eso puede volverse bastante lento.
bummzack
Lo tengo funcionando! Lo que hice fue una combinación de selección y selección de la cara posterior: en un cubo sólido, algunas caras no son visibles mientras que otras lo son (máx. 3). Así que pinté las partes no visibles primero, y las partes visibles sobre ellas. Esto funciona de maravilla, si elimino uno o más lados, se superponen pero aún se dibujan en el orden correcto. ¡Gracias!
pimvdb
1
Eso solo funcionará para formas convexas simples, como cubos. Me alegro de que actualmente te esté funcionando, pero no es una solución general.
Richard Fabian el
3

Lo que tienes es un problema de visibilidad . Una solución es usar un z-buffer .

Bart van Heukelom
fuente
Gracias, pero el z-buffering requiere renderización por píxel si no me equivoco. No estoy haciendo eso, estoy dibujando líneas rectas entre los puntos proyectados del cubo. ¿Sigue siendo posible el almacenamiento en z?
pimvdb
Incluso si está dibujando líneas rectas, en algún momento antes de que la imagen llegue a la pantalla (o archivo de mapa de bits) estará en formato de píxeles.
Bart van Heukelom el
Eso es correcto, pero mi biblioteca de dibujo es demasiado lenta para hacer renderizado de píxeles con 20 fps. Gracias sin embargo.
pimvdb
2

La clasificación de las caras de acuerdo con su valor z promedio no funciona, porque el valor z promedio no proporciona información sobre el valor z real de los vértices o incluso los píxeles de la superficie.

Ejemplo (advertencia, arte ASCII por delante):

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

Hay dos caras A y B. Desde la perspectiva de la cámara, A está delante de B. Sin embargo, el valor z promedio de B es más pequeño. Veamos los otros valores z:

  • el valor z mínimo de A es 4
  • el valor z máximo de A es 11
  • por lo tanto, el valor z promedio de A es 7.5
  • el valor z mínimo de B es 6
  • el valor z máximo de B es 8
  • por lo tanto, el valor z promedio de B es 7

Podría intentar ordenarlos por sus valores z mínimos, pero hay casos en los que eso tampoco funcionará. Simplemente no hay forma de ordenar las caras arbitrarias correctamente usando solo un valor z.

En el algoritmo de Newell http://en.wikipedia.org/wiki/Newell 's_algorithm lo que haces es ordenar los rangos min / max de los valores z. Si los rangos de dos caras no se superponen, puede saber con certeza cuál está delante. Si lo hacen, a veces absolutamente tienes que dividir las caras. A veces será suficiente rastrear cada vértice para la oclusión o alguna otra técnica.

Jonas Bötel
fuente
Ese diagrama es una vista aérea de lo que iba a adivinar que está sucediendo en su captura de pantalla.
jhocking
1

Es bueno que estés aprendiendo sobre renderizar haciendo. Prestigio. En este caso, no existe una solución de "algoritmo de pintores", en lugar de intentar solucionarlo ordenando, en la PS1 solíamos tratar de mantener los polígonos alrededor del mismo tamaño cuando estaban uno al lado del otro (lo que está haciendo como por lo que puedo decir), y el retroceso de la selección (que no estás haciendo)

Selección de la cara posterior es verificar la superficie normal en el espacio de la pantalla para su dirección (solo obtenga el signo del elemento de profundidad del espacio de la pantalla transformado normal (en nuestro caso era la z de lo normal), o el producto cruzado de dos vectores de triángulo, es decir, cruz (v1-v0, v2-v0))

Si implementa el sacrificio de la cara posterior, también reduce la cantidad de rasterización que está haciendo ... doble victoria.

Richard Fabian
fuente
Gracias por su respuesta. Leí sobre el sacrificio de la cara posterior, pero el punto es que me gustaría poder eliminar un lado. Con un cubo sólido, esto podría funcionar muy bien, pero si elimino un lado, entonces está ocurriendo una ocultación, por lo que todavía necesito ordenarlos, supongo. De todos modos, se me ocurrió la idea de disparar un rayo desde el origen a través del punto medio de una superficie. Si ese rayo cruza otra superficie después, entonces la primera superficie se superpone a la segunda. ¿Podrías decirme si esa idea es correcta? ¡Gracias!
pimvdb
Aunque su idea funcionaría para su caso de ejemplo, hay muchos otros casos en los que no va a funcionar. Por ejemplo, la misma escena que tiene allí, pero con la cámara inclinada para que el centro del quad de renderizado incorrecto no se superponga. Creo que tendrá que testear sus primitivas en piezas más pequeñas.
Richard Fabian