Skocz do zawartości

Jak porządnie zoptymalizować billboardy


Rekomendowane odpowiedzi

  • Filar Społeczności

Moja gra jak wiecie opiera się na niemalże samych billboardach. No i się nasuwa problem, bo tutaj trawa, tutaj drzewka, no paręset obiektów jest i nie wpływa to dobrze na fpsy. Jedyny krok jaki wykonałem w stronę optymalizacji to użycie zmiennych globalnych na teksturę, ale to wszystko. Są jakieś jeszcze dobre metody? Wiem, że może mnie wspomóc ta śmieszna rzecz, jaką jest parent, ale ni cholery właściwie nie wiem czemu ona ma służyć i nigdy jej nie użyłem. Jakieś rady, chłopcy?

 

edit: no i moje nieszczęsne

GML
if (point_distance(x,y,gracz.x,gracz.y) > 600) exit;
Odnośnik do komentarza
Udostępnij na innych stronach

Oczywiście mozesz ukryć wszystko co jest za plecami.

 

GML
if(angle_difference(gracz.direction,point_direction(x,y,gracz.x,gracz.y))<120)

{

//draw

}

 

  • angle_difference() to funkcja z gmlscripts (jest też wbudowana w GM:S)
  • gracz.direction to kierunek kamery
  • 120 to zasięg widzenia, w tym wypadku 1/3 koła czyli chyba tyle ile człowiek widzi. Dopasuj sobie.
Odnośnik do komentarza
Udostępnij na innych stronach

@Threef: do tego sluzy zoptymalizowana wersja algorytmu, zwana Dot Product:

GML
if( dot_product_normalised( x - player.x, y - player.y, player.forward_x, player.forward_y ) < global.cosinus_fov ) exit;

gdzie:

global.cosinus_fov to wyliczona raz wartosc cosinusa z kata widocznosci, czyli np:

GML
global.cosinus_fov = cos( degtorad( 45 ) );

player.forward_x i player.forward_y to wyliczone wartosci X i Y jednostkowe wektora kierunku co zmiane obrotu playera, czyli:

GML (player)
var dir_rad = degtorad( direction );

forward_x = cos( dir_rad );

forward_y = sin( dir_rad );

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Oczywiście mozesz ukryć wszystko co jest za plecami.

 

GMLif(angle_difference(gracz.direction,point_direction(x,y,gracz.x,gracz.y))<120)

{

//draw

}

 

  • angle_difference() to funkcja z gmlscripts (jest też wbudowana w GM:S)
  • gracz.direction to kierunek kamery
  • 120 to zasięg widzenia, w tym wypadku 1/3 koła czyli chyba tyle ile człowiek widzi. Dopasuj sobie.

 

Wstępnie widzę, że jakoś działa, ale nie dobrze. Tzn pole widzenia kończy się pośrodku kadru i po lewej widzę obiekty, a po prawej nie. No nic, pokombinuję, zobaczę co się z czym je. Jakbyście wiedzieli w czym tkwi problem, mówcie.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy
@Threef: do tego sluzy zoptymalizowana wersja algorytmu, zwana Dot Product:

GML
if( dot_product_normalised( x - player.x, y - player.y, player.forward_x, player.forward_y ) < global.cosinus_fov ) exit;

gdzie:

global.cosinus_fov to wyliczona raz wartosc cosinusa z kata widocznosci, czyli np:

GML
global.cosinus_fov = cos( degtorad( 45 ) );

player.forward_x i player.forward_y to wyliczone wartosci X i Y jednostkowe wektora kierunku co zmiane obrotu playera, czyli:

GML (player)
var dir_rad = degtorad( direction );

forward_x = cos( dir_rad );

forward_y = sin( dir_rad );

 

Może i zoptymalizowana, ale wymagająca więcej linijek :D

Odnośnik do komentarza
Udostępnij na innych stronach

@Threef: do tego sluzy zoptymalizowana wersja algorytmu, zwana Dot Product:

GML
if( dot_product_normalised( x - player.x, y - player.y, player.forward_x, player.forward_y ) < global.cosinus_fov ) exit;

gdzie:

global.cosinus_fov to wyliczona raz wartosc cosinusa z kata widocznosci, czyli np:

GML
global.cosinus_fov = cos( degtorad( 45 ) );

player.forward_x i player.forward_y to wyliczone wartosci X i Y jednostkowe wektora kierunku co zmiane obrotu playera, czyli:

GML (player)
var dir_rad = degtorad( direction );

forward_x = cos( dir_rad );

forward_y = sin( dir_rad );

 

No tylko zamienił bym tą globlaną na stałą bo globalne są wolne w uj.

Odnośnik do komentarza
Udostępnij na innych stronach

Wstępnie widzę, że jakoś działa, ale nie dobrze. Tzn pole widzenia kończy się pośrodku kadru i po lewej widzę obiekty, a po prawej nie. No nic, pokombinuję, zobaczę co się z czym je. Jakbyście wiedzieli w czym tkwi problem, mówcie.

bo Twoje direction jest obrocone o 90 stopni w ktoras strone wzgledem faktycznego kierunku patrzenia. dodaj lub odejmij 90 przy direction.

 

Może i zoptymalizowana, ale wymagająca więcej linijek :D

lenistwo najwiekszym wrogiem optymalizacji ;)

 

No tylko zamienił bym tą globlaną na stałą bo globalne są wolne w uj.

ze w GM:S?

Odnośnik do komentarza
Udostępnij na innych stronach

aż zrobię test, bo wierzyć mi się nie chce :0

Odnośnik do komentarza
Udostępnij na innych stronach

aż zrobię test, bo wierzyć mi się nie chce :0

https://www.yoyogames.com/tech_blog/30

 

Global Variables

Using global variables is a fine way to have controller variables that are accessible to all instances. However it should be noted that script calls which reference them (especially when compiling to the YYC) can be slowed down by multiple lookups of global variables. For example, consider this script:

GML
repeat(argument0)

 

{

 

with (obj_Parent)

 

{

 

if place_meeting(global.px, global.py, argument1) instance_destroy();

 

}

 

}

The issue here is that each iteration of the repeat loop has to look up the values for the global variables, which is very slow. To avoid this, you should always assign any gobal variables that are going to be used like this to a local variable. So our code example would become:

GML
var xx = global.px;

 

var yy = global.py;

 

repeat(argument0)

 

{

 

with (obj_Parent)

 

{

 

if place_meeting(xx, yy, argument1) instance_destroy();

 

}

 

}

Odnośnik do komentarza
Udostępnij na innych stronach

lul, Brzoza dostal w tym temacie bombe optymalizacyjnego stuffu :D

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

wrócił po braku internetu i sam jakoś wpadł na odjęcie 90 stopni, ale mimo wszystko dzięki wielkie. Zrobię sobie z tego zakładkę i wrócę jak przestanę być głupi :)

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

a tak na marginesie, czy nie optymalniej by było po prostu rysować jakąś trójkątnopodobną długą figurę imitującą pole widzenia, obracającą się wraz z graczem, a obiektom ustawić w kolizji z nią exit (edit: znaczy w drugą stronę)? Dodam jeszcze, że i tak mają exit przy zbyt dużej odległości, jak już wspomniałem na początku, więc problem nieskończonej długości takiegoż pola jest rozwiązany

Odnośnik do komentarza
Udostępnij na innych stronach

nope. broń borze.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Mnie tylko zastanawia, jak wykonywanie 6 funkcji (dot_product_normalised, cos x2, degtorad x2, sin) ma być szybsze i niż dwóch (angle_difference, point_direction) :)

 

Btw. z tego co wiem to:

 

GML
sin(degtorad( a )) == dsin(a);

cos(dogtorad( a )) == dcos(a);

 

Dodano takie funkcje :)

Odnośnik do komentarza
Udostępnij na innych stronach

czy nie optymalniej by było po prostu rysować jakąś trójkątnopodobną długą figurę imitującą pole widzenia, obracającą się wraz z graczem, a obiektom ustawić w kolizji z nią exit (edit: znaczy w drugą stronę)?

Teoretycznie istnieje funkcja point_in_triangle(px,py,x1,y1,x2,y2,x3,y3). x1 i y1 to współrzędne kamery, x2,y2 to wierzchołek na lewo od kamery (np. x1+lengthdir_x(zasieg_widzenia,kamera_direction-60),y2+lengthdir_y(zasieg_widzenia,kamera_direction-60), podobnie z x3 i y3. px i py to współrzędna obiektu, który testujemy na obecność w polu widzenia. Nie mam pojęcia, czy to będzie szybsze, ale w tym przypadku funkcje sin() i cos() wykonuje się tylko raz na step (o ile pozycje wierzchołków zapiszesz sobie w jakichś zmiennych).

Odnośnik do komentarza
Udostępnij na innych stronach

dot product to wlasnie roznica katow, tylko ze zwraca wynik w cosinusie kata, nie w kacie i jest szybsze niz angle_difference().

angle_difference() lezy dlatego, ze w srodku liczy kosztowne atan().

 

EDIT: choc jesli angle_difference() to taki kod:

GML
return ((((argument0 - argument1) mod 360) + 540) mod 360) - 180;

to trzeba przetestowac co sie dluzej liczy..

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności

ej, a jeszcze pytanie co do samej kolizji z obiektami. Klasycznie można to robić na bazie eventu collision, ale z racji, że to billboardy, przyszło mi do głowy takie coś:

GML
if (point_distance(x,y,gracz.x,gracz.y) < 20) global.prędkość_gracza=0;

Jakby taki kod miał się w obliczu paruset takich obiektów w jednym roomie?

Odnośnik do komentarza
Udostępnij na innych stronach

ej, a jeszcze pytanie co do samej kolizji z obiektami. Klasycznie można to robić na bazie eventu collision, ale z racji, że to billboardy, przyszło mi do głowy takie coś:

GML
if (point_distance(x,y,gracz.x,gracz.y) < 20) global.prędkość_gracza=0;

Jakby taki kod miał się w obliczu paruset takich obiektów w jednym roomie?

Bardzo dobrze. Wystarczy że nie doprowadzasz do tego aby postać podeszła za blisko. Rozwiązanie idealne.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Filar Społeczności
Bardzo dobrze. Wystarczy że nie doprowadzasz do tego aby postać podeszła za blisko. Rozwiązanie idealne.

 

dz4slg.png

Odnośnik do komentarza
Udostępnij na innych stronach

bardzo zle, bo dzieki temu gracz nie bedzie mogl sie ruszyc po wejsciu w zasieg innego bilboardu, tj. nie ucieknie :>

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...