Evitar peleas z con superficies coincidentes


26

Al renderizar dos superficies coplanares superpuestas, un problema común es la "lucha z", donde el renderizador no puede decidir cuál de las dos superficies está más cerca de la cámara, lo que genera artefactos visuales en el área de superposición.

La solución estándar para esto es dar a las superficies un ligero desplazamiento al diseñar el modelo. hay alguna otra solucion?


2
Podrías pagar buffers de profundidad logarítmica. Hay un artículo sobre gamasutra
Soapy

1
Cuando dice "coplanar", ¿quiere decir "casi" o "exactamente" coplanar y, si es esto último, ¿esas superficies son siempre superficies / triángulos idénticos? El hardware de renderizado debe ser determinista (suponiendo que no esté enviando en orden aleatorio) para el último caso y no tener peleas. Si se trata de superficies no idénticas pero exactamente coplanares, ¿podría actualizar el modelo para dividir las superficies en porciones superpuestas y no superpuestas?
Simon F

@SimonF, por "coplanar" quiero decir "exactamente coplanar". La solución de Soapy solo funciona en el caso "casi coplanar".
Mark

¿Podría dar un ejemplo de sus superficies? Lo único que puedo pensar fuera de mi cabeza es triángulos duplicados como mencionó @SimonF.
RichieSams

@RichieSams, el caso más común en el que puedo pensar es en calcomanías, donde no necesitas triángulos duplicados exactamente.
rys

Respuestas:


10

Si las superficies son exactamente alisadoras, tu destino depende de los dioses de la FPU; lo más probable es que tengas Z-fighting. Si los triángulos son idénticos y que hacen la exacta misma matemáticas para cada uno, que va a terminar con las mismas Z-valores para ambos. Pero nuevamente, esto solo sucederá si sus operaciones matemáticas son idénticas para ambos. (Dado que, en general, las operaciones de FPU no son conmutativas)

Una posible solución es no usar el Z-buffer en absoluto. Por el contrario, puede utilizar el algoritmo del pintor . De acuerdo, esto viene con todos los problemas del algoritmo de pintores también. Pero, resolvería la lucha Z.

En su caso de ejemplo de calcomanías de espacio de pantalla (SSD), la solución común es utilizar un desplazamiento, también conocido como un simple cubo delgado. Consulte la presentación de Warhammer 40k sobre SSD para referencia. O la publicación de Bart Wronski que aborda algunos otros problemas con las calcomanías, pero también enlaces a algunas otras presentaciones sobre SSD


55
Volver a representar la misma geometría con las mismas transformaciones genera de manera confiable los mismos valores de profundidad cada vez. (Es decir, no es un poder , es un testamento ). Es por eso que la iluminación de avance múltiple funciona, por ejemplo.
Nathan Reed

@NathanReed corregido. Gracias por la aclaración
RichieSams

1
Para obtener esa funcionalidad, debe usar el calificador invariante en glsl: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu

Tenga en cuenta que las expresiones de sombreador idénticas (y las entradas, obviamente) al evaluar las posiciones de vértice pueden no ser suficientes para obtener resultados idénticos, ya que algunas optimizaciones pueden depender del resto del sombreador. GLSL tiene la palabra clave "invariante" para declarar salidas de sombreador que deben evaluarse de manera idéntica en diferentes sombreadores.
Firadeoclus

2

Así es como he resuelto esto en el pasado:

  1. Dibuje el primer objeto (el que debería aparecer detrás del otro objeto) mediante pruebas de profundidad, pero no escribiendo en profundidad.
  2. Dibuje el segundo objeto mediante pruebas de profundidad y escritura de profundidad. Esto no causará peleas en z ya que no escribimos ninguna profundidad en el paso 1.
  3. Dibuje el primer objeto escribiendo solo en el búfer de profundidad y no en el búfer de color. Esto garantiza que el búfer de profundidad esté actualizado para los píxeles cubiertos por el objeto 1 pero no por el objeto 2.

Tenga en cuenta que los objetos deben dibujarse consecutivamente para que esto funcione.


0

Dependiendo de su renderizador, podría hacer que las superficies sean más "difusas" aplicando un desplazamiento minúsculo en profundidad de muestreo múltiple utilizando un algoritmo similar al ruido. Esto debería dar como resultado una especie de efecto de fusión para superficies en proximidad de profundidad. Por lo que sé, establecer la profundidad por muestra en el sombreador de fragmentos es bastante reciente en OpenGL y luego solo como una extensión.

OpenGL tiene PolygonOffset pero requiere saber de antemano que está a punto de representar algo coplanar. Si bien no es factible para superficies dentro de un solo modelo, podría funcionar bien, por ejemplo, cuando se renderiza una carretera superpuesta en un terreno.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.