Algoritmo para 2D Raytracer

Quiero hacer un RayTracer programático en Java con fines de demostración mientras RayTracer una presentación sobre Ray Tracing en general (también menciono 3D, este modelo 2D debe ser solo para facilitar la comprensión y para entrenar mi conocimiento general de Java).

Mi problema es que no sé por dónde empezar todo esto.

Lo primero que intentaré es usar vectores para rastrear cada píxel en la pantalla desde una determinada coordenada (por ejemplo, la posición del cursor de mi mouse). Entonces calcularía si el vector se cruza con un polígono y luego detendría el vector allí y lo dibujaré solo en este punto específico.

Tal vez incluso podría dibujar algunas sombras calculando lo normal y reflejar el vector en la otra dirección con una intensidad más baja.

Entonces, ¿sería una buena idea dibujar un vector de A = {everypixelonthescreen} a un Point P específico y calcular las intersecciones?

La versión final debería verse algo así:

enter image description here

Me temo que este tipo de aplicación de rastreo de rayos que está proponiendo es un poco más engañoso que utilizar un rastreador de rayos 3D real.

  • Los trazadores de rayos 2D se usan de forma un poco diferente
  • y esto puede confundir mucho a tu audiencia

Intentaría elegir más uso de trazado de rayos 2D nativo como:

  1. Simulación óptica

    Esto se usa para simular ópticas de lentes y espejos. Aquí la imagen de una de las antiguas simulaciones 2D de trazos de rayos:

    sim óptica

    1. Almacena tu mundo

      Obtuviste lentes en forma de polilíneas + índice de difracción y espejos también como polilíneas. Usted tiene el índice mundial de difracción

    2. lanzar rayos R, G, B desde la fuente de luz

      Eche solo los más importantes o todos. Usa la ley de Snell para simular la óptica

    Como puede ver, el error cromático es visible (cada color tiene su propia longitud de onda, por lo que el índice de difracción es diferente). También puede usar la representación de MultiBand .

    Utilicé esto para ajustar los sistemas ópticos personalizados si agrega la capacidad de arrastrar y soltar que obtuvo Optic Lab

  2. Demo de Wolfenstein

    Este juego pseudo 3D utiliza motor de proyección de rayos 2D ver Wiki: Wolfenstein_3D_engine . Esta imagen fue tomada de este enlace:

    wolf3d

    1. primero dibuja el piso y el cielo / cielo como 2 medias pantallas (pantalla dividida por el horizonte)
    2. entonces tienes un mapa 2D de tu laberinto / mundo (derecha)

      Así que arroje rayos desde su posición actual en todas las direcciones visibles (similar a su imagen, pero generalmente se usa una vista de 60 grados). Los rayos se deben hacer con precisión subpíxel (celular). donde su rayo golpee la pared (en el mapa) obtenga la posición del subpíxel (celda). Indica qué parte de la textura de la pared es golpeada

    3. dibuje la columna apropiada (línea vertical) en la pantalla para cada golpe Ray

      El tamaño y la escala de este se determinan por el origen del rayo de forma de distancia. La corrección del ojo de pez se aplica si mi memoria sirve, se hizo utilizando solo la distancia perpendicular (multiplicar la distancia por cos(ray_angle-player_angle) ).

    Aquí un ejemplo de lo que busqué por diversión ahora mismo:

    mi Wolf3D

    Se realiza en C ++ con GDI puro (utilizando solo la línea de escaneo de mapas de bits) sin ninguna otra biblioteca de terceros. Utiliza una sola textura, iluminación difusa + ambiental, emisión de rayos 2D. Tiene 2 mapas de bits (pantalla, atlas de textura) y un mapa 2D individual. El código es menos de 9 KByte incluyendo rems. Solo está controlado por el teclado (el mouse se usa para editar el laberinto en la ventana secundaria del mapa).

    Aquí el ejemplo de GIF animado:

    Wolf3D

    Si está interesado, consulte la garantía de calidad relacionada:

    • Wolfenstein con altura variable de celdas

A mi entender, el problema se abordaría de manera diferente. Dada una posición (posición actual del mouse o algo similar), el entorno se rastrearía desde allí en el rango de un ángulo dado (como 90 grados, en su imagen esto se ve como 360 grados). En la resolución deseada del ángulo, los rayos de la posición inicial se cruzan con los polígonos mencionados. Los puntos de intersección más cercanos se representan. Este enfoque debería representar los puntos que son ‘visibles’ desde la posición dada.