Witam.
Próbuję napisać prosty silnik raycastingowy, wyświetlający grafikę pseudo-3D (coś podobnego napędza np. Wolfensteina 3D). W skrócie polega to na tym, że z pozycji obserwatora (gracza) wystrzeliwuje się promienie (linie proste) w danym kierunku i pod odpowiednim kątem (zależnym od orientacji gracza) i na podstawie tego w co promienie trafiły, rysuje się klatkę obrazu wyświetlaną na ekranie.
Obrazek poglądowy:
Gdzie zielona kropka tam jest obserwator. Tutaj patrzy dokładnie na północ (w kierunku zielonej kreski), zatem jego orientacja na mapie to 270 stopni. Pierwszy promień z lewej "wystrzeliwany" jest pod kątem 240 stopni, a pierwszy od prawej pod kątem 300 stopni, czyli pole widzenia wynosi 60 stopni. Wyznaczam sobie współrzędne pixeli końcowych lewego i prawego promienia, następnie odczytuję współrzędne wszystkich, kolejnych pixeli, znajdujących się między nimi w linii prostej (oznaczone zieloną kreską). Następnie do tak odczytanych pixeli wysyłam kolejne promienie (tyle promieni, ile pixeli), czego efektem jest ten oto ładny trójkącik powyżej.
Problem mam tego rodzaju, że taki ładny trójkącik wychodzi mi tylko dla orientacji obserwatora równej 90, 180, 270 i 360 stopni. Przy kątach pośrednich, wychodzi mi coś takiego:
Skutkuje to tym, że w przypadku trafienia w jakiś obiekt, informacja zwrotna z promieni nie narysuje tego obiektu w 100% poprawnie, tylko właśnie z dziurami, z uwagi na widoczne na obrazku niedokładności trafień (a to problem, bo obiekt pokryty jest teksturą, a nie jednolitym kolorem). Wiem, że to wynika z zaokrągleń i bywa tak, że np. 2 promienie uderzają w ten sam pixel, dajmy na to o współrzędnych (200, 100), potem żaden nie trafia w (201,100), tylko od razu w (202, 100), przez co powstaje luka i ten pixel nie zostanie narysowany. Myślałem o wyznaczaniu promieni drogą interpolacji, ale problem w tym, że ja chcę uniknąć odczytywania pełnych ścieżek dla wszystkich promieni (np. algorytmem Bresenhama), bo to po prostu za wolne.
Ja robię to tak, że wysyłam promień pod konkretną współrzędną (równą maksymalnej odległości widzenia obserwatora, w tym wypadku 200), a następnie wyznaczam jego funkcję liniową i sprawdzam, czy doszło do kolizji (szukając punktu przecięcia) między tym promieniem, a potencjalnym obiektem, który powinien zostać narysowany (np. ścianą). To dużo szybsze, niż sprawdzanie pixel po pixelu (dla każdego promienia!), czy doszło do trafienia w jakiś obiekt.
Czy ktoś ma jakiś pomysł, jak to rozwiązać? Nie pytam o kod, czy gotowe rozwiązanie programistyczne, tylko samą koncepcję lub algorytm.