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:
Aquí hay algunas imágenes para ilustrar lo que sucede:
Desde la distancia, la caja azul se ve perfectamente bien.
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.
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.
fuente
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.Respuestas:
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.
fuente
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
fuente