¿Cómo debo manejar los vértices de recorte que están más cerca del ojo que el plano de recorte cercano?


13

Estoy rodando mi propio motor 3D, en JavaScript, y usando solo dibujos de lienzo, no WebGL. Este es otro clon de Minecraft; Me encantan las cajas, no me juzgues.

Hasta ahora, todo funciona maravillosamente, excepto por una cosa: en 3D, cuando algunos vértices van detrás del plano de recorte cercano, su proyección en la pantalla resulta extraña (suponiendo que otros vértices utilizados para trazar un plano estén al frente).

Intenté recortar estos puntos pero luego puedo ver a través de las superficies que usan estos vértices. En WebGL / OpenGL, la tarjeta gráfica se ocupa de estos puntos y el plano se representa correctamente, pero no tengo acceso al hardware, así que debo codificarlo yo mismo.

No estoy muy seguro de qué hacer, actualmente lo último que se me ocurrió es invertir la proyección de puntos detrás del plano de recorte cercano del jugador, lo que parece lógico ya que debo proyectar un punto en una pantalla que está al frente del vértice

Aquí están mis pensamientos:

ingrese la descripción de la imagen aquí

Aquí hay algunas imágenes para ilustrar lo que sucede:

ingrese la descripción de la imagen aquí

Desde la distancia, la caja azul se ve perfectamente bien.

ingrese la descripción de la imagen aquí

Cuando algunos de los vértices van detrás del plano de recorte cercano del jugador, hago la proyección inversa, pero no se ve bien:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

Tenga en cuenta que el cuadro gris detrás se elimina por completo, ya que todos los vértices utilizados para dibujar sus caras están detrás del jugador.

ingrese la descripción de la imagen aquí

Esto es lo que sucede cuando mira hacia arriba o hacia abajo.

No sé qué hacer con las matemáticas detrás de esto, espero que alguien ya haya encontrado el mismo problema y pueda ayudarme.


1
Si los puntos están más cerca del ojo que el plano de recorte cercano, deberían recortarse, y esto podría permitirle ver "a través" de un objeto. Este es el comportamiento típico; La colisión normalmente evita ese artefacto visual en particular. ¿Fue eso lo único malo con su solución de recorte?

@JoshPetrie: Entiendo que los puntos deben recortarse, pero si lo hago, todo el cuadrado desaparecerá ya que faltan uno o dos de los vértices por los que debe pasar la rutina de dibujo (en 2d) y el jugador podrá ver a través de esa plaza. Me gustaría que estuvieran "fuera" del lienzo (en la proyección) para que el cuadrado aún pudiera dibujarse. No estoy seguro si soy lo suficientemente claro.
Solenoide

Lo estás diciendo, es un comportamiento normal y quieres evitar que esto suceda evitando que el jugador se acerque tanto a uno de los cubos. Si realmente quisieras hacer esto, debes recortar pero reconstruir los triángulos (posiblemente). Esto aún se verá inusual, especialmente si tiene texturas. Si lo que digo no tiene sentido, puedes unirte a nosotros en el chat para que no creemos un hilo de comentarios realmente hablador.

Lo que estás diciendo tiene sentido, la reconstrucción lleva demasiado tiempo, por lo que esa no es la solución. Esperaba que todavía hubiera una forma de dibujar ese vértice en el plano 2d que estaba detrás del jugador para que la lineTo(x,y)función aún pudiera llamarse, solo que no sé cómo se comporta ... es una dimensión extraña, estoy de acuerdo.
Solenoide

Respuestas:


1

El propósito del plano de recorte cercano es que es un plano de recorte . Los triángulos que están fuera de un plano de recorte se recortan : se cortan en pedazos para que cada pieza que quede quede dentro de la región de recorte.

Puede intentar ignorar el clip cercano si lo desea. De hecho, OpenGL y D3D tienen formas de desactivar por completo el recorte del plano cercano (aunque el búfer de profundidad todavía tiene un valor cercano mínimo). El problema no es el clip cercano.

El problema es con los vértices que están detrás de la cámara.

No puede renderizar triángulos que están detrás de la cámara. No con una proyección en perspectiva. Tales triángulos no tienen sentido bajo las matemáticas detrás de las proyecciones de perspectiva. Además, también están fuera del tronco.

Apagar el recorte cercano convierte un frustum en una pirámide. La razón por la cual la pirámide se detiene en el punto es porque los puntos por encima de la pirámide están detrás de los cuatro lados de la pirámide. Por lo tanto, cualquier punto detrás de la cámara (la punta de la pirámide) está arriba, abajo, a la izquierda y a la derecha de la región visible de la pantalla. Todo al mismo tiempo.

Como dije: los vértices bajo una proyección en perspectiva que están detrás de la cámara no tienen sentido.

Debe implementar el recorte. Debe detectar cuándo cualquier vértice de un triángulo, en el espacio de clip ( antes de la división de perspectiva) está detrás de la cámara. Si es así, debe recortar ese triángulo, generando solo triángulos que estén frente a la cámara.

Este no es un proceso simple. Implicará matemática que solo tiene sentido si tiene una comprensión completa de los sistemas de coordenadas homogéneas. Alternativamente, podría simplemente eliminar cualquier triángulo si algún vértice está detrás de la cámara.


Hasta ahora, eliminé todo el triángulo, pero luego vi a través del avión (ver fotos arriba). Realmente necesitaba una imagen para entender por qué no tiene sentido geométricamente. La única solución es calcular la intersección de la línea plana cuando uno de los vértices está detrás del plano de recorte y usar esa intersección para trazar la línea desde el vértice que está al frente, desafortunadamente esto es costoso.
Solenoide

0

Si parte del triángulo detrás del plano cercano, ¿podría hacer una verificación por píxel para ver si la posición del píxel está detrás del plano de recorte?

Puede tratar el plano cercano como cualquier otro plano de recorte. Por ejemplo, los planos de recorte se utilizan para cosas como los planos de agua (para reflexiones y refracciones). Creo que este plano de recorte funcionaría igual que el plano de recorte cercano y recortaría por píxel.

Sé cómo manejar planos de recorte en HLSL con DirectX, pero su implementación podría ser propietaria. Si pudiera obtener la información para eso, podría ser útil.

Además, aquí hay un enlace que podría ayudarlo: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html


La prueba por píxel es extremadamente costosa en un lenguaje interpretado como Javascript, ahora estoy obteniendo fps apenas aceptables.
Solenoide
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.