kategoria: ANSI C
[#181] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@michal_zukowski, post #180

Rozumiem, raczej die nie przyda bo mam różne textury..

Ale akurat ściany mam nieźle zoptymalizowane..

Natomiast wczoraj zrobiłem coś podobnego z podłogami tj. Zrobiłem takie odbicie, myślałem że to będzie możliwe tylko przy nieruchomej głowie gdzie podłoga I sufit są symetryczne.. ale można i tak tylko trzeba korzystać z tej części której wiecej widac oczywiście.. I tez zyskałem kopa dość dużego.

Teraz to co mi zmniejsza wydajność to sięganie do tablic intensywności.. ale może to teraz zastąpię obliczeniami skoro mam wydajniejszy kod..

Ale jest dużo lepiej niż na ostatnim video..
[#182] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #181

Cześć,
Czy jakaś dobra asemblerowa dusza zerknie na ten asemblerowy kod?

Ta funkcja rysuje texturowaną podłogę i sufit na całym ekranie 320x200x32
- w wariancie szybkim podaje zafixowany index textury o numerze 0, czyli wszsytko jest wytexturowane tylko jedną texturą.
- w wariancie wolnym zamiast stałej jest już zmienna texture_index która zależy od tego na jaką texsturę natrafiliśmy podczas rysowania.

róznią się tylko tą linijką:

WARIANT SZYBKI ok: 50 fps;
// get pixel coords in texture
u_int32 texture_current_pixel = level_textures[0].row[texture_pixel_x][texture_pixel_y];


WARIANT WOLNY: ok. 20 fps
// get pixel coords in texture
u_int32 texture_current_pixel = level_textures[texture_index].row[texture_pixel_x][texture_pixel_y];


Wygenerowałem różnice w kodzie asm, w porównywarce jest bardzo wiele zmian odnośnie tych dwóch
wariantów. Zastanawia mnie po prostu czy w tym wolnym wariantcie wszsytko jest OK tak jak ma być, czy kompilator jakiś głupot nie porobił. Bo jak mówię jest bardzo duża różnica w wygenerowanym kodzie, poniżej link do porównywarki:

https://www.diffchecker.com/1a3U053H

i ewentualnie do porównania profilera:
https://www.diffchecker.com/hLae6GRA

Kod funkcji w C wygląda tak:

WARIANT SZYBKI:
inline void RC_Raycast_Floor_Ceiling()
{
    // get local copy of RC_level_textures
    sBM_Bitmap_row* level_textures = RC_level_textures;

    // ray direction for leftmost ray (x = 0) and rightmost ray (x = width)
    float32 r_dx0 = RC_pp_dx - RC_pp_nsize_x_d2;
    float32 r_dy0 = RC_pp_dy - RC_pp_nsize_y_d2;

    float32 r_dx1 = RC_pp_dx + RC_pp_nsize_x_d2;
    float32 r_dy1 = RC_pp_dy + RC_pp_nsize_y_d2;

    // precalculated helpers for performance
    float32 r_dx1_m_dx0_div_width = (r_dx1 - r_dx0) * RC_render_width_1d_f;
    float32 r_dy1_m_dy0_div_width = (r_dy1 - r_dy0) * RC_render_width_1d_f;

    // casting floor and ceiling - horizontal line by line - from left to right
    for (u_int16 ry = 0; ry < RC_render_height_i; ++ry)
    {
        // whether this section is floor or ceiling
        u_int8 is_floor = ry > RC_render_height_d2_i + RC_player_pitch;

        // current ray y position compared to the center of the screen (the horizon)
        float32 ry_pos = (float32)(is_floor ? (ry - RC_render_height_d2_i - RC_player_pitch) : (RC_render_height_d2_i - ry + RC_player_pitch));

        // vertical position of projection plane, 0.5 is between floor and ceiling
        float32 pp_z = (float32)(is_floor ? (RC_render_height_d2_i + RC_player_z) : (RC_render_height_d2_i - RC_player_z));

        float32 straight_distance_to_point = pp_z / ry_pos;

        // calculate the real world step vector we have to add for each x (parallel to camera plane)
        // adding step by step avoids multiplications with a weight in the inner loop
        float32 floor_step_x = straight_distance_to_point * r_dx1_m_dx0_div_width;
        float32 floor_step_y = straight_distance_to_point * r_dy1_m_dy0_div_width;

        float32 floor_x = RC_player_x + straight_distance_to_point * r_dx0;
        float32 floor_y = RC_player_y + straight_distance_to_point * r_dy0;

        // convert that values to fixed point
        int32 floor_x__fp = (int32)(floor_x * 65536.0f);
        int32 floor_y__fp = (int32)(floor_y * 65536.0f);

        int32 floor_step_x__fp = (int32)(floor_step_x * 65536.0f);
        int32 floor_step_y__fp = (int32)(floor_step_y * 65536.0f);

        u_int32 ry_m_render_width = ry * RC_render_width_i;

        // drawing floor and ceiling from left to right
        for (u_int16 ry_x = 0; ry_x < RC_render_width_i; ++ry_x)
        {
            u_int32 output_pixel_index = ry_x + ry_m_render_width;

            floor_x += floor_step_x;
            floor_y += floor_step_y;

            floor_x__fp += floor_step_x__fp;
            floor_y__fp += floor_step_y__fp;

            // the cell coord is simply got from the integer parts of floorX and floorY
            u_int32 curr_cell_x = (floor_x__fp & FP_INTEGER_MASK_16) >> 16;
            u_int32 curr_cell_y = (floor_y__fp & FP_INTEGER_MASK_16) >> 16;

            // prevent overflow
            curr_cell_x &= LV_MAP_SIZE_m1;
            curr_cell_y &= LV_MAP_SIZE_m1;

            u_int32 curr_cell_x_fraction__fp = (floor_x__fp & FP_FRACTION_MASK_16) >> 8;
            u_int32 curr_cell_y_fraction__fp = (floor_y__fp & FP_FRACTION_MASK_16) >> 8;

            // get the texture coordinate from the fractional part, masking avoids overflow
            u_int32 texture_pixel_x = (u_int32)((128 * 256 * curr_cell_x_fraction__fp) >> 16);
            u_int32 texture_pixel_y = (u_int32)((128 * 256 * curr_cell_y_fraction__fp) >> 16);

            // get the texture index depending on the cell
            u_int8 texture_index;

            if (is_floor)
            {
                texture_index = RC_level->map[curr_cell_x + (curr_cell_y << LV_MAP_SIZE_BITSHIFT)].floor_id;
            }
            else
            {
                texture_index = RC_level->map[curr_cell_x + (curr_cell_y << LV_MAP_SIZE_BITSHIFT)].ceil_id;
            }

   // ----------------------------------------- DIFFERENCE - level_textures[0]


            // get pixel coords in texture
            u_int32 texture_current_pixel = level_textures[0].row[texture_pixel_x][texture_pixel_y];


   // ----------------------------------------- -------------------------------------------------

            RC_output_buffer_32[output_pixel_index] = texture_current_pixel;
        }
    }
}



WARIANT WOLNY:
inline void RC_Raycast_Floor_Ceiling()
{
    // get local copy of RC_level_textures
    sBM_Bitmap_row* level_textures = RC_level_textures;

    // ray direction for leftmost ray (x = 0) and rightmost ray (x = width)
    float32 r_dx0 = RC_pp_dx - RC_pp_nsize_x_d2;
    float32 r_dy0 = RC_pp_dy - RC_pp_nsize_y_d2;

    float32 r_dx1 = RC_pp_dx + RC_pp_nsize_x_d2;
    float32 r_dy1 = RC_pp_dy + RC_pp_nsize_y_d2;

    // precalculated helpers for performance
    float32 r_dx1_m_dx0_div_width = (r_dx1 - r_dx0) * RC_render_width_1d_f;
    float32 r_dy1_m_dy0_div_width = (r_dy1 - r_dy0) * RC_render_width_1d_f;

    // casting floor and ceiling - horizontal line by line - from left to right
    for (u_int16 ry = 0; ry < RC_render_height_i; ++ry)
    {
        // whether this section is floor or ceiling
        u_int8 is_floor = ry > RC_render_height_d2_i + RC_player_pitch;

        // current ray y position compared to the center of the screen (the horizon)
        float32 ry_pos = (float32)(is_floor ? (ry - RC_render_height_d2_i - RC_player_pitch) : (RC_render_height_d2_i - ry + RC_player_pitch));

        // vertical position of projection plane, 0.5 is between floor and ceiling
        float32 pp_z = (float32)(is_floor ? (RC_render_height_d2_i + RC_player_z) : (RC_render_height_d2_i - RC_player_z));

        float32 straight_distance_to_point = pp_z / ry_pos;

        // calculate the real world step vector we have to add for each x (parallel to camera plane)
        // adding step by step avoids multiplications with a weight in the inner loop
        float32 floor_step_x = straight_distance_to_point * r_dx1_m_dx0_div_width;
        float32 floor_step_y = straight_distance_to_point * r_dy1_m_dy0_div_width;

        float32 floor_x = RC_player_x + straight_distance_to_point * r_dx0;
        float32 floor_y = RC_player_y + straight_distance_to_point * r_dy0;

        // convert that values to fixed point
        int32 floor_x__fp = (int32)(floor_x * 65536.0f);
        int32 floor_y__fp = (int32)(floor_y * 65536.0f);

        int32 floor_step_x__fp = (int32)(floor_step_x * 65536.0f);
        int32 floor_step_y__fp = (int32)(floor_step_y * 65536.0f);

        u_int32 ry_m_render_width = ry * RC_render_width_i;

        // drawing floor and ceiling from left to right
        for (u_int16 ry_x = 0; ry_x < RC_render_width_i; ++ry_x)
        {
            u_int32 output_pixel_index = ry_x + ry_m_render_width;

            floor_x += floor_step_x;
            floor_y += floor_step_y;

            floor_x__fp += floor_step_x__fp;
            floor_y__fp += floor_step_y__fp;

            // the cell coord is simply got from the integer parts of floorX and floorY
            u_int32 curr_cell_x = (floor_x__fp & FP_INTEGER_MASK_16) >> 16;
            u_int32 curr_cell_y = (floor_y__fp & FP_INTEGER_MASK_16) >> 16;

            // prevent overflow
            curr_cell_x &= LV_MAP_SIZE_m1;
            curr_cell_y &= LV_MAP_SIZE_m1;

            u_int32 curr_cell_x_fraction__fp = (floor_x__fp & FP_FRACTION_MASK_16) >> 8;
            u_int32 curr_cell_y_fraction__fp = (floor_y__fp & FP_FRACTION_MASK_16) >> 8;

            // get the texture coordinate from the fractional part, masking avoids overflow
            u_int32 texture_pixel_x = (u_int32)((128 * 256 * curr_cell_x_fraction__fp) >> 16);
            u_int32 texture_pixel_y = (u_int32)((128 * 256 * curr_cell_y_fraction__fp) >> 16);

            // get the texture index depending on the cell
            u_int8 texture_index;

            if (is_floor)
            {
                texture_index = RC_level->map[curr_cell_x + (curr_cell_y << LV_MAP_SIZE_BITSHIFT)].floor_id;
            }
            else
            {
                texture_index = RC_level->map[curr_cell_x + (curr_cell_y << LV_MAP_SIZE_BITSHIFT)].ceil_id;
            }

   // ----------------------------------------- DIFFERENCE - level_textures[texture_index]


            // get pixel coords in texture
            u_int32 texture_current_pixel = level_textures[texture_index].row[texture_pixel_x][texture_pixel_y];


   // ----------------------------------------- -------------------------------------------------

            RC_output_buffer_32[output_pixel_index] = texture_current_pixel;
        }
    }
}
[#183] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #182

Na szybko:

1: Sprawdzenie w każdym pikselu czy musisz zmienić podłogę to 'lekka' strata czasu. Powinieneś mieć tak podzielony ekran żeby renderować ciągłe linie które używają tej samej tekstury.

2: Jeżeli indeksujesz jakąś strukturę w głównej pętli to zrób tak, żeby jej rozmiar był potęgą 2. Zamiast mnożenia będziesz miał przesunięcie bitowe w kodzie (widziałem mnożenia przez 12)

3: Jeżeli kompilujesz dla 040/060 to ktokolwiek konfigurował backend w kompilatorze nieźle to spaprał. Używanie 'bfextu' zamiast prostego maskowania i przesunięcia to masakra. 6x wolniej?

4: O ile nie musisz nie używaj konstrukcji level_textures[texture_index].row[texture_pixel_x][texture_pixel_y] w przypadku kiedy row[] jest tablicą wskaźników (tutaj chyba jest). Dodaje to kolejny poziom przy dostępie do danych (najpierw musi być wczytany adres wiersza a dopiero potem indeksowany jest wiersz). Używaj tablic o stałej 'szerokości' która jest potęgą 2. Wysokość nie ma znaczenia. Lepiej jest upakować tekstury w dużej bitmapie i po prostu dopasować U i V.

Ostatnia aktualizacja: 21.04.2021 18:56:44 przez kiero
3
[#184] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@kiero, post #183

Dzięki @kiero

- test na V6: SZYBKA ok 70fps, WOLNA ok. 37 fps - wiec podobnie jak na winuae ponad 2x wolniej

- używam GCC od Bebbo 6.5.

- sprawdzę jeszcze jaki output robi ten kompilator z jego strony i porównam czy jest podobnie, wrzucę link.

- tą konstrukcję level_textures robiłem pierwotnie pod ściany gdzie się używa pionowych pasków, wcześniej obracając texturę, i dawalo mi to kopa, ale fakt, myślałem o tym żeby zaalokować jeden duży ciągły fragment i włądować tam hurtem textury.. ale jeszcze tego nie zrobiłem..

- najbardziej w tym momencie mnie interesuje ską się wzieły tak wielkie różnice w kodzie asm, tzn. czy to jest standard, czy faktycznie kompilator coś wymyślił po swojemu?

- to co podesłałem to uproszczony kod, który po prostu leci z góry na dół i renderuje, nawet bez iluminacji tylko same kolory z textur, zeby bylo jak najprościej.. robiłłem różne optymalizacje, ostatnio odbijałem w pionie, ale jak dochodziły zmienne texture_index to znowu wracałem do punktu wyjścia, i wszelkie optymalizacje praktycznie traciły znaczenie.. (Stąd prosty kod)

- np. odnośnie sprawdzania w pętli czy mamy podłogę czy sufit - to wcześniej rozbiłem render na dwie części sufit/podłoga wywalają ten warunek z gęstej pętli itp..


- użyte flagi: "-Wall", "-Wno-pointer-sign", "-noixemul", "-O3", "-m68080", "-mtune=68080", "-mhard-float", "-fomit-frame-pointer", "-lm", wyrzuciłem -funroll-loops (było przyśpieszenie spore jak wyrzuciłem)


.. ale koniec końców mimo super optymalizacji które mi dawały duze fps.. po dorzuceniu texture_index lub tablicy iluminacji itp. dostawałem momentalnie "kopa w ryj" i fps spadały włąśnie o takie grube wartośći...

..jeśli to błąd kompilatora to szarpię się z koniem

Ostatnia aktualizacja: 21.04.2021 21:38:50 przez mateusz_s
[#185] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #184

[- test na V6: SZYBKA ok 70fps, WOLNA ok. 37 fps - wiec podobnie jak na winuae ponad 2x wolniej]

Większość tego co napisałem tyczy się oryginalnego procesora motoroli. Nie mam pojęcia ile cykli zjada bfext na vampire. Nie mam pojęcia ile zjadają mnożenia. Tak gwoli ścisłości.

[- użyte flagi: "-Wall", "-Wno-pointer-sign", "-noixemul", "-O3", "-m68080", "-mtune=68080", "-mhard-float", "-fomit-frame-pointer", "-lm", wyrzuciłem -funroll-loops (było przyśpieszenie spore jak wyrzuciłem)]

I wszystko jasne. To jest kompilowane pod vampire. Nie polecam uruchamiania tego kodu na 040/060. Bardzo nie polecam.

[- tą konstrukcję level_textures robiłem pierwotnie pod ściany gdzie się używa pionowych pasków, wcześniej obracając texturę, i dawalo mi to kopa, ale fakt, myślałem o tym żeby zaalokować jeden duży ciągły fragment i włądować tam hurtem textury.. ale jeszcze tego nie zrobiłem..]

Jeżeli odnosisz się do trzymania tablicy wskaźników to nie o to chodzi. To co piszesz to optymalizacja pod cache. To co ja napisałem to po prostu eliminacja jednego kroku przy pobieraniu wartości teksela. Bez znaczenia czy masz teksturę obróconą czy nie.

[- najbardziej w tym momencie mnie interesuje ską się wzieły tak wielkie różnice w kodzie asm, tzn. czy to jest standard, czy faktycznie kompilator coś wymyślił po swojemu?]

Nie przeglądałem kodu, ale indeksowanie tablicy stałą wartością powoduje, że kompilator po prostu wywala to poza pętlę i eliminuje sporo obliczeń. Stąd różnica.
[#186] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@kiero, post #185

Wersja inteaktywna FAST:
http://franke.ms/cex/z/bMTKj5

Wersja interaktywna SLOW:
http://franke.ms/cex/z/Wq1qz7



I wszystko jasne. To jest kompilowane pod vampire. Nie polecam uruchamiania tego kodu na 040/060. Bardzo nie polecam.


na winuae mam ustawiony na 060 i działa tak samo jak na Warp1260, tzn. ta flaga.. efekt jest podobny,
wstawiałem też -060 ale nie widziałem różnicy w działaniu wiec zostawiłem na -080

Ostatnia aktualizacja: 21.04.2021 22:16:18 przez mateusz_s
[#187] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #186

Myślałem trochę nad zmianą podejścia do renderingu całości..

1. Obecny sposób nr 1
- rysuje najpierw na całym ekranie podłogę i sufit (baz żadnego wykrywania gdzie będzie widoczny)
- a następnie na tym "tle" rysuje ściany już tylko te które są widoczne

PLUS: brak dodatkowych obliczeń i czyszczenia ekranu.
MINUS: strata czasu na renderowanie niewidocznych sufitów i podłóg, które sięgają "daleko" i mogą mieć różne textury itp.

2. Obecny sposób nr 2
- czyszczę bufor kolorem czarnym "0"
- rysuje ściany przy okazji zapamiętując najwyższy i najniższy punkt najdalszej widocznej ściany
- rysuje podłogi i sufit na wstępnie odrzucając te linie które nie będą widoczne za najdalszą ścianą,
a następnie umieszczam kolejne pixele tylko tam gdzie kolor bufora jest "0" czyli tam gdzie nie ma ściany

PLUS: nieco szybsze działanie
MINUS: sprawdzanie poszczególnych pixeli w pętli obciąża wydajność

Zastanawiałem się nad tym co napisał @kiero, o ile dobrze zrozujmiałem, to żeby na suficie i podłogach, rysować z podziałem na textury, tzn. np. najpierw rysujemy texture 0,1,2 itp.. u mnie na suficie i podłodze może być wiele textur - nie w sensie że na suficie jest jedna z na podłodze druga..

3. Pomysł:
- czyszczę mały bufor typu BYTE o rozmiarze 2xWIDTH
- rysuje ściany, a do małego bufora są zapisywane górna i dolna wartość danej kolumny tworzącej ściany (zapamiętuje jakby obrys ścian)
- na podstawie małego bufora - tworzę listę segmentów (segment jest poziomą linia która ma początek i koniec) - które określają w których miejscach będzie widoczny sufit i podłoga
- na podstawie wygenerowanej listy segmentów - robię pierwszy przebieg dla ścian i sufitów, który dodatkowo mi określa jakie textury będą użyte w widocznych miejscach - ale przechodzę tylko przez te miejsca wskazane przez listę segmentów..
- na podstawie powyższej struktury - zaczynam rysować sufit i podłogę tam gdzie trzeba, ale po kolei wg textur, czyli jak narysuje wszsytko z texutrą 0 to rysuje nastpenie z texturą 1..2.3. itp..

Może się to wydawać bardziej skomplikowane, ale wydajnościowo może być lepiej..
[#188] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #187

Bedzie lepiej, ktorys ze starych enginow na pc (Build?) stosowal podobna metode.

Ostatnia aktualizacja: 22.04.2021 21:58:36 przez docent
1
[#189] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #187

****
UPDATE 1 POSTU,
dodałem bardzo fajne źródło, patrz punkt 11:
https://www.ppa.pl/forum/programowanie/42708/moje-raycasterowe-zabawy-progresy-testy#m714808

bardzo dobry tutorial, gdzie facet tworzy od podstawy zwykły 3d renderer oparty o siatki
***

Odnośnie 3 pomysłu we wcześniejszym poście, to jednak nie jestem pewien czy to dobry pomysł..
raczej na jedno wyjdzie.. zacząłem robić optymalizację, skupiając się na razie na obliczeniach,
gdzie nawet nie dotykam textur, czyli że nie obarczam wydajności poprzez 32bitowy tryb i generalnie
wychodzi mi, że podłogi i sufity są jednak zbyt skomplikowane obliczeniowo.. już nawet nie chodzi o wypełnianie
bufora kolorem. Poświęciłem jeszcze trochę czasu jeszcze wyciskając całkiem sporo z samych obliczeń ścian.

Natomiast mam kolejny, 4 pomysł o zupełnie innym podejściu, z którym wiąże na razie pewne nadzieje, a mianowicie:
- w czasie gdy przechodzę przez siatkę mojej mapy w czasie szukania ścian, od razu zapamiętać "puste" komórki
na których będą widoczen ściany lub podłoga i przy okazji od razu zapamiętać ich id textur; to właściwie bezkosztowa operacja, robiona przy okazji.
- takich widocznych kafelków nie jest dużo, w zalezności od pomieszczenia, np. od kilku do kilkunastu, rzadziej kilkadziesiąt.
- w osobnej pętli usunąć duplikaty i (ewentualnie) szybko posortować wg. texture id.
- rysowanie odbywało by się poprzez przejście tylko przez tą widoczną ilość kafleków..
- każdy kafelek trzeba by zrasteryzować osobno jako rzut na ekran i rasteryzacje takiego prostopadłościanu poprzez scanline
[#190] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #189

Czołem,
Pracowałem ostatnio nad innym sposobem tworzenia podłóg i sufitów, o którym wspomniałem powyżej,
trochę schodziło, bo trzeba było zrobić kilka rzeczy:
- zrobić listę kwadracików
- posortować je wg textury
- zrzutować punkty tworzące dany kwadracik ze świata na ekran
- podzielić każdy kwadracik na 2 trójkaty
- mieć szybki algorytm rasteryzujacy trojkaty
- dorzucić texturowanie tych trojkatów

- co ciekawe mimo takiej złożoności testy pokazaly ze ten sposób jest bardziej wydajny niż poprzedni.. jak na razie przynajmniej

sprawdziłem 3 rózne algorytmy rasteryzujace trojkaty, udalo mi sie znaleźć dość szybki oparty na fixed pointach, źródła do niego załaczyłem w pierwszym poście w punkcie 11..


niestety doszedłem teraz do jednego problemu, nie jestem pewniem ale to chyba tzn. "perspective correction" - problem ktory sie pojawia przy rasteryzacji quadów zbudowanych z 2 trójkatów.. wporównaniu do porzedniego sposobu - textura jest zupelnie inaczej zniekształcona - kwadracik jest w tym samym miejscu.. - trochę się boję, że wprowadzenie korekty (ktora zdaje sie wymaga dzielenia) moze z powrotem zamulić.. jeszcze nie wiem jak ta korekcję zrobić, dopiero bede nad tym siedział (o ile to właśnie jest to, a nie coś innego)

- w razie czego mam jeszcze jeden pomysł - taki hybrydowy, czyli polaczenie pierwszego z drugim.. ale to potem.. jeszce powalcze z tym co teraz mam..
4
[#191] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #190

niezły pomysł mi wpadł do głowy na optymalizację

jednym z bootlenecków jest cieniowanie
(a raczej ilość operacji konwersji pixela 4 bajt do składowych i z powrotem), teraz to wygląda tak, np:

*(output_buffer_32__ptr - 1) = intensity_premultipled_CH1[prev_texture_pixel >> 16 & 0xff] |
                    intensity_premultipled_CH2[prev_texture_pixel >> 8 & 0xff] |
                    intensity_premultipled_CH3[prev_texture_pixel & 0xff];


czyli mam 7 operacji + 3 pobory z tablicy i to jest w wewnętrzej pętli wiec sie wykonuje kupe czasu,
nie za bardzo mogę to zoptymalizować - najlepiej jakby jakimś cudem dało się przyciemnić od rtazu cały kolor w 5 bajtach, proowałem to robić poprzez & ale działa tylko dla pełnych kolorów np. 255,255,0 itp - ale wzrost jest bardzo duży, bo zostaje mi tylko 1 operacja + 1 pobór z tablicy

-- i wpadł mi do głowy ciekawy pomysł, myslę, że powonien dać podobnego kopa, a mianowicie: - używam textur 128x128, to nie wiele - nie ma potrzeby żeby kazda textura była w full kolor, ze względu na mały rozmiar bedzie praktyczeni tak samo wygladać przy 256 lub 128 kolorach a moze nawet w 64 w zależności od textury - wtedy mam tablicę kolorów do każdej textury - mogę wiec dla każdej textury przygotować 256 tablic kolorów ze spadającą intensywnością - max. koszt takiej textury to ok. 270kb - przy 30 texturach to ok 8-9 MB więc pryszcz.. ale zyskał bym wiele tj pixel bym wsadzał w ten sposób:

poza petla:
 u_int32* intensity_premultipled = &intensity_premultipliedLUT[intensity_value];

petla
{
u_int8 tex_index = current_texture_columnptr[current_v];
*bufor = intensity_premultipled[tex_index];
}


o ile czegoś nie popieprzyłem - i wychodzi nawet mniej operacji niż poprzednio..
3
[#192] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #191

Hej,
W nawiązaniu do poprzedniego wpisu,
Pomysl z zamiana textur z true color na indexed
Okazał się bardzo dobry, nie ma różnicy w jakości a przyrost predkosci jest bardzo duży, w przypadku V4 ponad 80 fps przy texturach 256 kol. Jeśli zmniejszyć jeszcze ilość kolorów to prędkość jeszcze trochę wzrasta.

Problemem nadal jest podlogo-sufit, że względu na średnio wydajny algorytm który mam obecnie. Ale możliwe że nastąpi samo jakieś Przyspieszenie że względu juz na zupełnie inne użycie pamieci przez textury.

Wyniki, przy cieniowanych ścianach z texturami beż podłóg I sufitów w 32bit w 320x240:

V4 - blisko 160fps
V500 - ok. 140fps
Warp - ok. 40fps
4
[#193] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #192

Czołem,

niezły wynik udało mi się znowu osiągnąć.. po dzisiejszym "posiedzeniu". pomysł

mianowicie, ponieważ kod zaczynal mi sie robić troche nieczytelny i postanowiłem jeszcze raz go prfzepisać bazujac na "czystym" algorytmie Lodeva, i przy okazji od razu zrobiłem lepsze wykorzystanie fixed pointów (w poprzednim było troche hybrydowo) teraz przy scianach nie mam żadnych floatów. To plus reszta pozystałych optymalizacji ładnie podniosło wynik do 120 fps przy jakości 1:1 czyli bez żadnego uzupełniania. Następnie przy rysowaniu paska ściany - rozwinąlem trochę tą petlę - w sensie jesli wysokosc paska jest podzielna przez 2 to w tej jednej petli wstaw od razu 2 pixele.. no i pięknie znowu skoczyło do 151 fps i to nadal przy 1:1.. poprzedni test w którym było 160 fps był co drugi promień liczony i miał uzupełnianie przy czym ten fps spadał kiedy musiałem pozaznaczać w buforze gdzie bedzie sciana a gdzie sufit.. chyba spadało do coś ok. 126 fps. przez to... teraz tego nie muszę robić bo sprawdzam ten drugi algorytm podłogowy czyli rysowanie pionowe - robi sie je od razu po narysowaniu danego paska ściany - i okazuje sie ze nie jest aż taki bardziej wolny od poziomego. A dodatkowo daje mi on pewne możliwości.. także teraz do podłogi uderzam ze startową predkościa 150fps - wiec znowu mały rekordzik OK jeśli dorzucił bym do tego co drugi pasek ściany z uzupełnianiem pewnie by było ok 200fps.

Ale nie ekscytuje się aż tak bardzo, bo za każdym razem podłoga daje w kość.. ale jak wspomniałem dzieki temu pionowemu algorytmowi bede mogł ją liczyć np. co drugi pasek lub trzeci pasek bez wiekszego problemu i może tym razem uda się coś ugrać pomysł





Ostatnia aktualizacja: 07.06.2021 00:38:58 przez mateusz_s
2
[#194] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #193


ps.
jakbym nie podchodził - to podłoga jest strasznym wrzodem na dupie.. nawet rysowanie tylko samego sufitu czy samej podlogi prawie tak samo dają w kość.. dać jednolity kolor z cieniowaniem to nie problem, ale nie wygląda to już tak fajnie jak z texturami.. jakaś nadzieję jeszcze widzę właśnie w sensownym uzupełnianiu pustych linii przy rysowaniu np. co drugi promień..

Ostatnia aktualizacja: 07.06.2021 01:06:13 przez mateusz_s
1
[#195] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #194

W najgorszym razie zrób podłogę mode7. Będzie wszędzie taka sama tekstura ale szybkość razy 10.
[#196] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@Kefir_Union, post #195

tylko że nie wiem jak do tego podejść.. bo wszystkie przykłady które widziałem w mode7 to brały jedną texturę i z niej robiły podłogę, np. niekończącą się. A u mnie każdy kafelek może mieć inną texturę. Czyli to musiałoby być jakoś że każdy kafelek byłby osobno liczony i odpowiednio ustawiony.. nie wiem za bardzo

raz próbowałem implementować mode7 i właśnie to było jako jedna textura i było nieźle.. albo robić "merge" np. kilku takich kafelków 128x128 w jedną texturę i ją transformować..
no nie wiem.. jest sporo rozwiazań i podejść..

ale jakby nie patrzeć to większość planu wykonałem OK tzn. stworzyłem raycaster działający płynnie w 32bitach w 320x240 i 640x480 i z 128x128 texturami pomysł ... czyli się da.. podłoga to szczegół jednolity kolor + cieniowanie dziala szybko.. wiec można założyć że w danym pomieszczeniu jest bardzo czysta podłoga w jednym kolorze

Ostatnia aktualizacja: 07.06.2021 12:15:07 przez mateusz_s
[#197] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #196

To co? Czas na Ray9?
[#198] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@waldiamiga, post #197

teraz juz 11 mam :)
zastanawiam sie czy by nie opublikować obecną wersję, tj. bez podłog i sufitów, ale za to z cieniowaniem,
też wygląda spoko.. potem cos pomyślę..
[#199] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #198

fajne,
jak liczona jest pojedyncza klatka w Doomie:





Ostatnia aktualizacja: 28.06.2021 22:18:20 przez mateusz_s
5
[#200] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #199

W nawiązaniu do poprzedniego, podobny filmik, skupiajacy się na podziale przeastrzeni i rysowaniu gołych ścianek:

1
[#201] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #200

Cześć,
po dłuższej przerwie znowu przysiadłem. Zmieniłem algorytm rysowania podłóg na zupełnie inny,
trochę przypominający Doom-a. A mianowicie podczas rysowania ścian są gromadzone informacje,
które pozwalają mi rysować potem podłogi z podziałem na poszczególne kafelki, czyli:

dla każdego kafelka
dla każdej lini poziomej kafelka
wstaw pixel od xmin do xmax


To pozwoliło pobierać texturę tylko raz i wywalić kilka obliczeń poza wewnetrzą pętlę,
wcześniej dla każdego pixela był sprawdzany jaki to kafelek i pobierana byla textura,
wiec masakra..

I jako że w końcu doczekałem sie VAMPIORZA 1200 - to przeprowadzałem test,
i muszę powiedzieć że jest nieźle.. obecnie cofnąłem się do wersji niezoptymalizowanej działającej na floatach
i beż zadnych przyśpieszeń i przy 320x240x32 miałem ok 20 fps..
zresztą sami zobaczcie.. ciężko powiedzień czy po optymalizacjach będzie stabilne 50fps, ale kto wie,
z porzednich testów samo przejście z float na int dawało mega potężnego kopa,
zmienię też sposób dostępu do textur i działąnia na nich, wiec tutaj może też się coś urwie..
obecnie w 640x480x32 było jakieś 5 fps :P wiec końcowo moze z 15-20 by było - na pewno dużo lepiej wygląda..

troceh szitowato wygląda ale bedzie lepiej, filmik poniżej:
https://files.fm/f/5nedxw43t
4
[#202] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #201

No to katuj tego Vampa Twoim Raycasterem. Naprawdę może być z tego fajny silniczek OK
1
[#203] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #201

Cześć,
wrzucam filmik o nazwie Ray-20 jako punkt odniesienia.
Nagrywane z kartą V1200, w trybach:
- 320x200x32 (17 fps)
- 640x400x32 (5 fps)

Tekstury na razie "z dupy", docelowo chcę żeby tektury były zróżnicowane poprzez np.
dorysowane oświetlenie lub cienie, które wzajemnie by ze sobą współgrały tj. odpowiednie tekstury
podłóg i sufitów przy ścianach. Czyli po prostu więcej wariantów tekstur aby tworzyć ciekawsze lokalizacje.

obecnie zaimplementowane rzeczy (na razie minimum):
- textury podłóg, ścian i sufitów
- mouse lookaround
- cieniowanie distant + side

użyte metody:
- na razie brak optymalizacji, dość luźny kod
- na razie wszystko na liczbach zmiennoprzecinkowych (float)
- ściany mają swój osoby zestaw textur, a podłogi i sufity osobny.
każdy zestaw tekstur jest jako bitmapa indeksowana czyli max 256 kolorów.
każdy zestaw ma również wygenerowaną paletę 256 kolorów w 256 odcieniach,
która służy do szybkiego cieniowania
- każdy zestaw jest wczytywany jako całość do pamięci a dostęp do początku danej tekstury jest tylko przez offset
- zestaw dla ścian jest dodatkowo obrócony o 90 stopni przy wczytywaniu - wiadomo dlaczego
- do renderowania podłóg i sufitów wykorzystałem algorytm o którym pisałem we wcześniejszym poście,
a który okazał się bardzo szybki. Jest trochę podobny do algorytmu z Dooma, tj. podczas obliczania i rysowania ścian zapisywana są dodatkowe informacje, a promień musi również pobrać dane z każdego grida na który na trafi (nie tylko z tego który ma w sobie ścianę jak dotychczas), te informacje pozwalają potem renderować podłogę i sufit z podziałem na poszczególne "kafelki" - nie używam sortowania.
- obecnie podłoga i sufit sa renderowane niezależnie, tj. na razie nie wykorzystuje już raz obliczanych wartości (pole do optymalizacji)

na razie tyle, funkcji jest minimum, bo skupiam się na podstawach silnika, po kawałku teraz będę optymalizował
i liczył FPS-y :)

6
[#204] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #203

Ekstra!OK
A sznurek do archiwum to...?
[#205] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@waldiamiga, post #204

Dorzucam linka, jeśli Ktoś ma ochotę sobie na czymś odpalić:
https://mstanisz.website.pl/tmp/amiga/ray-20.zip

- skompilowane pod 060
- działa chyba tylko tryb 32 bit
- można odpalić w okienku
- nie wybierać szerokości większej niż 400 bo się zawiesi :)
[#206] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #205

Wiechliwe to co nieco, ale 123fps przy 320x240x32 (RGBA fullscreen) na WinUAE.
Działa na MorphOSie, na iMacu G5 tej samej rozdziałce co w WinUAE mam 66fps.
[#207] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #203

mysle, ze powinienes rozwijac swoja gre na PC. Gdybys to ulepszyl to moze nawet bedzie jakis maly sukces OK

Na Amidze nie ma to prawa zadzialac, przynajmniej nie na klasyku.
I wlasnie ten przyklad pokazuje dobitnie, juz dawno postawiona teze, ze Amiga do gier 3D FPP sie nie nadaje ok, racja
[#208] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@selur, post #207

Na Amidze nie ma to prawa zadzialac, przynajmniej nie na klasyku.
I wlasnie ten przyklad pokazuje dobitnie, juz dawno postawiona teze, ze Amiga do gier 3D FPP sie nie nadaje


Dlatego będzie na Vampira ok, racja
[#209] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@selur, post #207

Od początku celowałem w te nowsze karty amigowe z rtg, po prostu byłem ciekawy ile dam rade z tego wyciągnąć, przy czym interesował mnie nie tryb chunky z 256 kolorów tylko 24/32 tak żeby nie babrac się z ograniczonymi paletami itp, mieć ładne cieniowanie, po chyba ponad roku babrania się w kodzie udało mi się dopiero teraz dojsc do dobrego punktu startowego :)

Największym bólem, jak wielokrotnie wspominałem był sposób rysowania podłóg i sufitów, dopiero niedawno udało się mi to jakoś ogarnąć..

Ale też nie będę ukrywał że straciłem dużo pary..
[#210] Re: [C, RTG] Moje Raycasterowe zabawy, progresy, testy..

@mateusz_s, post #209

Jak dla mnie bomba. Wiele ambitniejszych projektów indie stylizuje sie na retro i uzywa pixelizerów ( post proces / shader ) i to wyglada jakoś właśnie tak. Dobra robota. Szacun.
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem