Uczę się podstaw OpenGL, ale zastanawiam się, dlaczego istnieje wezwanie glNormal
do ustawienia normalności wierzchołków.
Jeśli utworzę prosty trójkąt taki jak ten:
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glVertex3f(0,1,0);
glEnd();
Czy normalne nie powinny być definiowane pośrednio przez rodzaj prymitywu geometrycznego? Czy jeśli nie ustawię normalnej wartości, OpenGL ją obliczy?
Odpowiedzi:
Wywoływanie
glNormal
wielokrotnie pomiędzyglBegin/End
pozwala na ustawienie normalnej wartości dla wierzchołka zamiast dla operacji podstawowej.Aby uzyskać bardziej złożoną siatkę złożoną z wielu trójkątów, norma na jednym wierzchołku zależałaby od innych trójkątów otaczającej geometrii, a nie tylko normalnej trójkąta, do którego należy.
Oto przykład tej samej geometrii z:
(0,0,1)
):Domyślny model cienia (
GL_SMOOTH
) powoduje interpolację normalnych wierzchołków twarzy w poprzek twarzy. W przypadku normalnych na wierzchołek daje to gładką cieniowaną kulę, ale dla normalnych na twarz uzyskuje się charakterystyczny wygląd fasetowany.źródło
Nie, GL nie oblicza dla Ciebie normy. Nie może wiedzieć, co powinno być normalne. Twoje prymitywne nic nie znaczą poza rasteryzacją (i kilkoma innymi miejscami). GL nie wie, które ściany (trójkąty) dzielą wierzchołek (obliczanie tego w czasie wykonywania jest bardzo drogie bez użycia różnych struktur danych).
Musisz wstępnie przetworzyć „trójkątną zupę” siatki, aby znaleźć wspólne wierzchołki i obliczyć normalne. Należy to zrobić, zanim gra uruchomi się na szybkość.
Istnieją również przypadki, takie jak twarde krawędzie, w których geometrycznie jest wspólny wierzchołek w rogu, ale chcesz osobne normalne, aby świeciło poprawnie. W modelu renderowania GL / D3D potrzebujesz do tego dwóch osobnych wierzchołków (w tej samej pozycji), każdy z osobną normalną.
Będziesz tego potrzebować także do UV i mapowania tekstur.
źródło
Krótka odpowiedź jest taka, że tak naprawdę wcale nie musisz ustawiać normalności. Zwykłe wektory są używane tylko wtedy, gdy wykonujesz oświetlenie OpenGL (lub może jakieś inne obliczenia, które mogą od nich zależeć), ale jeśli to nie dotyczy ciebie (lub jeśli używasz innej metody do oświetlenia, np. Lightmaps ), możesz całkiem szczęśliwie pominąć wszystkie połączenia glNormal.
Załóżmy więc, że robisz coś tam, gdzie podanie glNormal ma sens, i spójrz na to jeszcze trochę.
glNormal można określić dla operacji pierwotnej lub dla wierzchołka. W przypadku normalnych dla prymitywnych wszystko to oznacza, że wszystkie normalne dla każdego wierzchołka w pierwotnej powierzchni w tym samym kierunku. Czasami jest to, czego chcesz, ale czasem nie jest - przydają się normalne na wierzchołek, ponieważ pozwalają każdemu wierzchołkowi mieć swoją własną stronę.
Weź klasyczny przykład kuli. Gdyby każdy trójkąt w kuli miał taką samą normę, wynik byłby dość fasetowany. Prawdopodobnie nie tego chcesz, zamiast tego potrzebujesz płynnego cieniowania. To, co robisz, to uśrednianie normalnych dla każdego trójkąta, który ma wspólny wierzchołek, i otrzymujesz gładki cieniowany wynik.
źródło
Minimalny przykład ilustrujący niektóre szczegóły
glNormal
działania rozproszonego błyskawicy.Komentarze
display
funkcji wyjaśniają, co oznacza każdy trójkąt.Teoria
W OpenGL każdy wierzchołek ma swój własny normalny wektor.
Wektor normalny określa, jak jasny jest wierzchołek, który jest następnie używany do określenia, jak jasny jest trójkąt.
Kiedy powierzchnia jest prostopadła do światła, jest jaśniejsza niż powierzchnia równoległa.
glNormal
ustawia bieżący wektor normalny, który jest używany dla wszystkich kolejnych wierzchołków.Wartość początkowa dla normalnego zanim wszystko
glNormal
jest0,0,1
.Normalne wektory muszą mieć normę 1, inaczej kolory się zmienią!
glScale
zmienia również długość normalnych!glEnable(GL_NORMALIZE);
sprawia, że OpenGL automatycznie ustawia dla nas swoją normę na 1. Ten GIF pięknie to ilustruje.Bibliografia:
źródło
Potrzebujesz glNormal, aby zaimplementować niektóre funkcje zależne od kodera. Na przykład możesz chcieć utworzyć normalne dane zachowujące twarde krawędzie.
źródło