WebGL maneja correctamente la relación entre objetos antes y después: eliminación de superficie oculta (prueba de profundidad)/conflicto de profundidad

Tabla de contenido

Prefacio

Verifique las reglas de WebGL para manejar el contexto de los objetos: los gráficos dibujados más tarde sobrescriben los gráficos dibujados anteriormente 

Eliminación de superficies ocultas (prueba de profundidad)

Para activar la función de eliminación de superficies ocultas, debe seguir los dos pasos siguientes:

1. Active la función de eliminación de superficies ocultas.

especificación de la función gl.enable()

2. Antes de dibujar, borre el búfer de profundidad. 

gl.clear(gl.DEPTH_BUFFER_BIT)

Ocultar código de muestra de superficie de eliminación (DepthBuffer) 

Efecto de ejemplo

conflicto profundo

efecto de conflicto profundo

Razones del conflicto profundo 

Para activar la función de desplazamiento de polígono, también debe seguir los dos pasos siguientes:

1. Habilite el desplazamiento del polígono.

2. Especifique los parámetros utilizados para calcular el desplazamiento antes de dibujar. 

Especificación de la función gl.polygonOffset()

Código de muestra de conflicto profundo (Zfighting)

Efecto de ejemplo


Prefacio

En el mundo real, si colocas dos cajas una detrás de la otra sobre una mesa, como se muestra en la imagen a continuación, la caja de enfrente bloqueará parcialmente la caja de atrás.

Verifique las reglas de WebGL para manejar el contexto de los objetos: los gráficos dibujados más tarde sobrescriben los gráficos dibujados anteriormente 

Eche un vistazo al efecto del programa de muestra de blog-CSDN del blog blog-CSDN de la matriz de proyección de la vista del modelo WebGL PerspectiveView_mvp , como se muestra en la siguiente figura. El triángulo verde está parcialmente bloqueado por los triángulos amarillo y azul. Parece que WebGL está especialmente diseñado para gráficos tridimensionales, puede analizar automáticamente la distancia de objetos tridimensionales y manejar correctamente la relación de oclusión. 

 Lamentablemente, la realidad no es tan buena como se imagina. De forma predeterminada, WebGL procesa los vértices en el orden en que están en el búfer para acelerar las operaciones de dibujo. Los programas anteriores definían primero los objetos lejanos y luego los objetos cercanos, produciendo así el efecto correcto.

Por ejemplo, en PerspectiveView_mvp , definimos los vértices y los datos de color del triángulo en el siguiente orden: preste atención a la coordenada Z que se muestra en negrita.

WebGL dibuja los vértices en el orden en que están en el búfer (el primero es el triángulo verde más lejano, el segundo es el triángulo amarillo del medio y el tercero es el triángulo azul más cercano). Los gráficos dibujados más adelante cubrirán los gráficos que se han dibujado, lo que producirá el efecto del triángulo cercano bloqueando el triángulo lejano, como se muestra en la figura anterior. 

Para verificar esto, ajustamos el orden de los datos de los vértices del triángulo en el búfer y definimos el triángulo azul cercano al frente, luego el triángulo amarillo en el medio y finalmente el triángulo verde distante, como se muestra a continuación:

Ejecute el programa y encontrará que el triángulo verde que debería aparecer en el lado más alejado bloquea de forma antinatural los triángulos amarillo y azul cercanos, como se muestra en la siguiente figura. 

De forma predeterminada, WebGL dibuja gráficos en el orden en el búfer y los gráficos dibujados más tarde sobrescriben los dibujados antes porque es eficiente. Si los objetos en la escena no se mueven y el estado del observador es único, entonces no hay problema con este enfoque. Pero si, por ejemplo, desea seguir moviendo el punto de vista y ver objetos desde diferentes ángulos, entonces no podrá decidir de antemano el orden en que aparecerán los objetos. 

Eliminación de superficies ocultas (prueba de profundidad)

Para resolver este problema, WebGL proporciona una función de eliminación de superficies ocultas . Esta función nos ayudará a eliminar aquellas superficies ocluidas (superficies ocultas). Puedes dibujar la escena sin preocuparte por el orden de los objetos en el buffer, porque esos objetos distantes automáticamente serán bloqueados por objetos cercanos. Esta funcionalidad ya está integrada en WebGL, solo necesita activarla.

Para activar la función de eliminación de superficies ocultas, debe seguir los dos pasos siguientes:

1. Active la función de eliminación de superficies ocultas.

gl.enable(gl.DEPTH_TEST)

La llamada detección de profundidad (DEPTH_TEST) puede parecer extraña, pero en realidad se llama así porque el mecanismo determina si se dibuja detectando la profundidad del objeto (para cada píxel). 

La función gl.enable() utilizada en el paso 1 en realidad puede habilitar varias funciones en WebGL y sus especificaciones son las siguientes: 

especificación de la función gl.enable()

 

2. Antes de dibujar, borre el búfer de profundidad. 

gl.clear(gl.DEPTH_BUFFER_BIT)

 Paso 2, utilice el método gl.clear() para borrar el búfer de profundidad. El búfer de profundidad es un objeto intermedio cuya función es ayudar a WebGL a eliminar superficies ocultas. WebGL dibuja figuras geométricas en el búfer de color y muestra el búfer de color en el <lienzo> una vez completado el dibujo. Si desea eliminar superficies ocultas, debe conocer la información de profundidad de cada figura geométrica y el búfer de profundidad se utiliza para almacenar información de profundidad. Dado que la dirección de profundidad suele ser la dirección del eje Z, a veces también la llamamos zona de influencia Z.

Amortiguador de profundidad y eliminación de superficies ocultas

Antes de dibujar cualquier fotograma, se debe borrar el búfer de profundidad para eliminar los rastros que quedaron en él cuando se dibujó el fotograma anterior. Si no hace esto, obtendrá resultados erróneos. Llamamos a la función gl.clear() y pasamos el parámetro gl.DEPTH_BUFFER_BIT para borrar el búfer de profundidad: 

gl.clear(gl.DEPTH_BUFFER_BIT)

Por supuesto, también es necesario borrar el buffer de color. Utilice el símbolo OR bit a bit (|) para conectar gl.DEPTH_BUFFER_BIT y gl.COLOR_BUFFER_BIT y páselos a gl.clear() como parámetros:

De manera similar, se puede usar OR bit a bit al borrar dos buffers al mismo tiempo.

A la función gl.enable() corresponde la función gl.disable(), cuyas especificaciones son las siguientes: la primera habilita una determinada función y la segunda la deshabilita.

especificación de la función gl.disable() 

Ocultar código de muestra de superficie de eliminación (DepthBuffer) 

El programa de muestra se llama DepthBuffer .js y agrega código relacionado con la eliminación de superficies ocultas según la proyección de la vista del modelo WebGL Matrix_ blog de Hawthorn Tree - blog CSDN PerspectiveView_mvp.js . Tenga en cuenta que el orden de los vértices en el búfer no ha cambiado. El programa todavía dibuja triángulos en el orden cercano (azul), medio (amarillo) y lejano (verde) (pero el orden de dibujo se invierte: azul -> amarillo). -> verde) . El efecto de la ejecución del programa es exactamente el mismo que PerspectiveView_mvp , el código del programa es el siguiente.

Efecto de ejemplo

Al ejecutar DepthBuffer , se puede ver que el programa elimina con éxito las superficies ocultas y los triángulos ubicados cerca bloquean los triángulos lejanos. Este procedimiento demuestra que las superficies ocultas se pueden eliminar independientemente de la ubicación del punto de vista. En cualquier escena 3D, debes habilitar la eliminación de superficies ocultas y borrar el búfer de profundidad en el momento adecuado (normalmente antes de dibujar cada fotograma).

 Cabe señalar que el requisito previo para la eliminación de superficies ocultas es configurar correctamente el espacio visible; de ​​lo contrario, se pueden producir resultados erróneos. Ya sea un espacio de proyección ortográfica en forma de caja o un espacio de proyección en perspectiva en forma de pirámide, debe utilizar uno.

conflicto profundo

La eliminación de superficies ocultas es una característica compleja y poderosa de WebGL y, en la gran mayoría de los casos, hace bien su trabajo. Sin embargo, cuando las dos superficies de una figura geométrica u objeto están extremadamente cerca, surgirán nuevos problemas, haciendo que la superficie luzca moteada , como se muestra a continuación. Este fenómeno se llama lucha Z. Ahora, dibujemos dos triángulos con exactamente el mismo valor Z.

efecto de conflicto profundo

Razones del conflicto profundo 

 La razón por la que ocurren conflictos de profundidad es porque las dos superficies están demasiado cerca y la precisión limitada del buffer de profundidad ya no puede distinguir cuál está delante y cuál detrás. Estrictamente hablando, si prestas atención a los valores de profundidad de los vértices durante la creación del modelo 3D, puedes evitar conflictos de profundidad. Sin embargo, cuando hay varios objetos en movimiento en la escena, es casi imposible lograrlo.

WebGL proporciona un mecanismo llamado desplazamiento de polígono para resolver este problema. Este mecanismo agregará automáticamente un desplazamiento al valor Z. El valor de desplazamiento está determinado por el ángulo de la superficie del objeto en relación con la línea de visión del observador. Habilitar este mecanismo solo requiere dos líneas de código:

Para activar la función de desplazamiento de polígono, también debe seguir los dos pasos siguientes:

1. Habilite el desplazamiento del polígono.

gl.enable(gl.POLYGON_OFFSET_FILL)

2. Especifique los parámetros utilizados para calcular el desplazamiento antes de dibujar. 

gl.polygonOffset(1.0, 1.0)

Llamado en este momento mientras dibujaba dos objetos en conflicto.

 En el paso 1, se llama a gl.enable() para habilitar el desplazamiento del polígono. Tenga en cuenta que esta función también se usa para habilitar la eliminación de superficies ocultas, pero se pasan diferentes parámetros. La especificación de la función gl.polygonOffset() en el paso 2 es la siguiente.

Especificación de la función gl.polygonOffset()

Considere el programa de ejemplo Zfighting , que utiliza desplazamientos de polígonos para evitar conflictos de profundidad. 

Código de muestra de conflicto profundo (Zfighting)

Se puede ver que el valor de la coordenada Z de todos los vértices es el mismo, que es -0,5 (línea 80), pero no hay conflicto de profundidad. 

En el resto del código, activamos el mecanismo de desplazamiento de polígonos (línea 70) y luego dibujamos un triángulo verde (línea 72) y un triángulo amarillo (línea 74). Los datos de los dos triángulos se almacenan en el mismo búfer, por lo que debe prestar especial atención al segundo y tercer parámetro de gl.drawArrays(). El segundo parámetro representa el número de vértices para comenzar a dibujar y el tercer parámetro representa el número de vértices dibujados en esta operación. Por lo tanto, primero dibujamos un triángulo verde, luego configuramos los parámetros de desplazamiento del polígono a través de gl.polygonOffset(), de modo que los dibujos posteriores se vean afectados por el mecanismo de desplazamiento del polígono, y luego dibujamos un triángulo amarillo. Ejecute el programa y verá que no hay conflicto de profundidad entre los dos triángulos, como se muestra en la siguiente figura). Comente la línea 73 y ejecute el programa nuevamente, y el conflicto de profundidad aparecerá nuevamente, como se muestra arriba: el efecto de conflicto de profundidad.

Efecto de ejemplo

Supongo que te gusta

Origin blog.csdn.net/dabaooooq/article/details/132892256
Recomendado
Clasificación