Podczas konfigurowania lokalizacji atrybutów dla programu cieniującego OpenGL masz do wyboru dwie opcje:
glBindAttribLocation () przed połączeniem, aby jawnie zdefiniować lokalizację atrybutu.
lub
glGetAttribLocation () po połączeniu w celu uzyskania automatycznie przypisanej lokalizacji atrybutu.
Jakie jest narzędzie do używania jednego nad drugim?
A który z nich jest preferowany w praktyce?
glBindAttribLocation
w moim silniku graficznym, który ładnie działał na Linuksie. Kiedy przeportowałem do systemu Windows, używał moich normalnych jako wierzchołków - musiałem wyraźnie powiedzieć mu kolejność zmiennych w moim module cieniującym przezglBindAttribLocation
, aby działał ...Odpowiedzi:
Znam jeden dobry powód, by preferować jednoznaczną definicję lokalizacji.
Weź pod uwagę, że przechowujesz dane geometryczne w Vertex Array Objects. Dla danego obiektu tworzysz VAO w taki sposób, aby indeksy odpowiadały np .:
Teraz zastanów się, czy chcesz narysować jeden obiekt za pomocą dwóch różnych shaderów . Jeden moduł cieniujący wymaga danych dotyczących pozycji i normalnych jako danych wejściowych, a drugi - pozycji i współrzędnych tekstur .
Jeśli skompilujesz te moduły cieniujące, zauważysz, że pierwszy moduł cieniujący będzie oczekiwał pozycji o indeksie atrybutu 0, a normalnych o wartości 1. Drugi będzie oczekiwał pozycji na 0, ale współrzędnych tekstur na 1.
Cytując https://www.opengl.org/wiki/Vertex_Shader :
Oznacza to, że nie byłbyś w stanie używać swojego VAO z obydwoma shaderami. Zamiast jednego VAO na, powiedzmy, obiekt, potrzebujesz - w najgorszym przypadku - oddzielnego VAO na obiekt na moduł cieniujący .
Zmuszenie shaderów do używania własnej konwencji numerowania atrybutów poprzez
glBindAttribLocation
może łatwo rozwiązać ten problem - wszystko, co musisz zrobić, to zachować spójną relację między atrybutami a ich ustalonymi identyfikatorami i zmusić shadery do korzystania z tej konwencji podczas łączenia.(To nie jest duży problem, jeśli nie używasz oddzielnych VAO, ale mimo to może sprawić, że kod będzie bardziej przejrzysty).
BTW:
W OpenGL / GLSL 3.3 jest trzecia opcja: Określ lokalizację bezpośrednio w kodzie modułu cieniującego . To wygląda tak:
Ale to nie jest obecne w języku shaderów GLSL ES.
źródło
Inną odpowiedzią jest to, że glGetAttribLocation zwraca dane do obiektu wywołującego, co oznacza, że niejawnie wymaga opróżnienia potoku. Jeśli wywołasz to zaraz po skompilowaniu programu, zasadniczo wymuszasz synchroniczną kompilację asynchroniczną.
źródło
glGetUniformLocation
; czy ta szczególna uwaga jest nadal aktualna?Trzecia opcja, czyli
layout(location=0) in vec4 position;
w kodzie shadera, jest teraz dostępna w OpenGL ES 3.0 / GLSL 300 es. Jednak tylko dla zmiennych wejściowych Vertex Shader.źródło