Jak zaprojektować prosty wrapper GLSL do użycia w shader

Aktualizacja: ponieważ potrzebowałem czegoś od razu, stworzyłem prosty wrapper shaderów, który robi to, czego potrzebuję. Możesz go znaleźć tutaj: ShaderManager na GitHub . Zauważ, że jest przeznaczony dla Objective - C / iOS, więc może nie być przydatny dla wszystkich. Jeśli masz jakieś sugestie dotyczące ulepszeń projektowych, daj mi znać!

Oryginalny Problem:

Jestem nowy w używaniu shaderów GLSL. Znam wystarczająco język GLSL i interfejs OpenGL, ale Mam problem z zaprojektowaniem prostego API, dzięki któremu będę mógł korzystać z shaderów.

[5]} interfejs C OpenGL do interakcji z shaderami wydaje się kłopotliwy. Nie mogę znaleźć żadnych samouczków w sieci, które obejmują projektowanie API takich rzeczy.

Moje pytanie jest takie: czy ktoś ma dobry, prosty, API projekt lub wzór do zawijania programu OpenGL shader API?

Weźmy następujący prosty przykład. Powiedzmy, że mam jeden vertex shader, który emuluje stałą funkcjonalność, i dwa shadery fragmentów-jeden do rysowania gładkich prostokątów i jeden do rysowania gładkich okręgów. Mam następujące pliki:

Shader.vsh : Simple vertex shader, with the following inputs/outputs:
    -- Uniforms: mat4 Model, mat4 View, mat4 Projection
    -- Attributes: vec4 Vertex, vec2 TexCoord, vec4 Color
    -- Varying: vec4 vColor, vec2 vTexCoord

Square.fsh : Fragment shader for drawing squares based on tex coord / color
Circle.fsh : Fragment shader for drawing circles based on tex coord / color

Podstawowe Linkowanie

Jaki jest standardowy sposób ich użycia? Czy Mogę połączyć powyższe shadery w dwa programy shaderów OpenGL? Czyli:

Shader.vsh + Square.fsh = SquareProgram
Shader.vsh + Circle.fsh = CircleProgram

Czy zamiast tego utworzyć jeden duży program, w którym shadery fragmentów sprawdzają niektóre warunkowe jednolite zmienne i wywołują funkcję shadera, aby wygenerować wynik. Np.:

Shader.vsh + Square.fsh + Circle.fsh + Main.fsh = ShaderProgram
//Main.fsh here would simply check whether to call out to square or circle

Z dwoma poszczególne programy, które prawdopodobnie będę musiał wywołać

glUseProgram(CircleProgram); or glUseProgram(SquareProgram);

Przed każdym typem elementu chcę narysować. Musiałbym wtedy ustawić uniformy (Model / Widok / projekcja) i atrybuty każdego programu, zanim go użyję. To wydaje się takie nieporęczne.

Z opcją single ShaderProgram nadal musiałbym ustawić jakiś przełącznik logiczny (okrąg lub kwadrat) w cieniowaniu fragmentów, który byłby sprawdzany przed narysowaniem każdego piksela. To też wydaje się skomplikowane.

jako na marginesie, Czy Mogę połączyć dwa shadery fragmentów, każdy z funkcją main (), w JEDEN program shaderów? Skąd OpenGL miałby wiedzieć, do którego zadzwonić?

Ustawianie Zmiennych

Wywołania:

glUniform*
glVertexAttribPointer

Są używane do ustawiania uniformów i lokalizacji wskaźników atrybutów w bieżącym programie.

Różne klasy i struktury mogą wymagać dostępu i ustawiania zmiennych w bieżącym shaderze (lub zmiany bieżącego shadera) z różnych miejsc w kodzie. I can ' t think of dobry sposób, aby to zrobić, który oddziela kod shadera od kodu, który chce go użyć.

Oznacza to, że każdy kształt, który chcę narysować, będzie musiał ustawić atrybuty współrzędnych wierzchołków i tekstur - wymagając uchwytów do atrybutów generowanych przez OpenGL.

Kamera będzie musiała ustawić swoją matrycę projekcji jako uniform w cieniowaniu wierzchołków, podczas gdy Klasa zarządzająca stosem macierzy modelu będzie musiała ustawić własny uniform w cieniowaniu wierzchołków.

Zmiana shaderów rysowanie sceny oznaczałoby, że wszystkie te klasy będą musiały ponownie ustawić swoje mundury i atrybuty.

Jak większość ludzi projektuje wokół tego?

Globalny słownik shaderów dostępnych według uchwytu lub nazwy, z geterami i seterami dla ich parametrów?

Projekt OO z obiektami shader, z których każdy ma parametry?

Spojrzałem na następujące opakowania:

Jona ' s Teapot: GLSL Shader Manager - to zawija shadery w klasy C++. Wydaje się, że jest to coś więcej niż wrapper, który wymusza Zasady OO na C API, co skutkuje API C++, które jest tak samo.

W przeciwieństwie do innych programów cieniujących, Shader nie może być używany w programach cieniujących i nie może być używany w programach cieniujących.]}
Author: Sisyphus, 2011-05-29

2 answers

Podstawowe Linkowanie:

Nie ma tu standardowej drogi. Istnieją co najmniej 2 podejścia ogólne:

  1. Monolityczny-jeden shader obejmuje wiele przypadków, przy użyciu jednolitych przełączników logicznych. Gałęzie te nie szkodzą wydajności, ponieważ wynik warunku jest stały dla każdej grupy fragmentów (właściwie dla wszystkich fragmentów).

  2. Komponowanie programów wielobiektowych - main shader deklaruje zestaw punktów wejścia (takich jak 'get_diffuse', 'get_specular', itd), które są zaimplementowane w dołączonych osobnych obiektach shader. Oznacza to indywidualny shader dla każdego obiektu, ale każdy rodzaj buforowania pomaga.

Ustawianie Zmiennych: Uniforms

Opiszę tylko podejście, które opracowałem.

Każdy program shader ma listę jednolitych słowników. Służy do wypełniania jednolitej listy źródeł przy ponownym linkowaniu programu. Gdy program jest aktywowany, przechodzi przez Jednolitą listę, pobiera wartości z ich źródeł i wgrywa je do GL. W rezultacie dane nie są bezpośrednio połączone z programem user shader, a cokolwiek nim zarządza, nie obchodzi go program z niego korzystający.

Jednym z tych słowników może być na przykład podstawowy, zawierający model, transformacje widoku, projekcję kamery i może coś jeszcze.

Ustawianie Zmiennych: Atrybuty

Po pierwsze, program shader jest konsumentem atrybutów, więc to on musi wyodrębnić te atrybuty z siatki (lub dowolnego inne przechowywanie danych) i przesłać je do GL w sposób, którego potrzebuje. Powinien również upewnić się, że typy podanych atrybutów pasują do żądanych typów.

W przypadku użycia z podejściem monolithic shader, istnieje możliwa nieprzyjemna sytuacja, gdy jedna z wyłączonych gałęzi ways wymaga atrybutu vertex, który nie jest dostarczany. Radziłbym użyć danych innego atrybutu do dostarczenia brakującego, ponieważ nie dbamy o rzeczywiste wartości w tym przypadku.

P. S. Można znaleźć rzeczywisty realizacja tych pomysłów tutaj: http://code.google.com/p/kri/

 5
Author: kvark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-29 16:50:00

Widzę, że jest to oznaczone iOS, więc jeśli jesteś częściowy do Objective-C, chciałbym dobrze przyjrzeć się klasie wrappera GLProgram Jeffa LaMarche ' a, który opisuje TUTAJ i ma źródło dostępne TUTAJ. Używałem go w moich własnych aplikacjach, aby uprościć niektóre konfiguracje programu shader i uczynić kod nieco czystszym.

Na przykład, możesz skonfigurować shader oraz jego atrybuty i uniformy za pomocą następującego kodu:

sphereDepthProgram = [[GLProgram alloc] initWithVertexShaderFilename:@"SphereDepth" fragmentShaderFilename:@"SphereDepth"];
[sphereDepthProgram addAttribute:@"position"];
[sphereDepthProgram addAttribute:@"inputImpostorSpaceCoordinate"];
if (![sphereDepthProgram link])
{
    NSLog(@"Depth shader link failed");
    NSString *progLog = [sphereDepthProgram programLog];
    NSLog(@"Program Log: %@", progLog); 
    NSString *fragLog = [sphereDepthProgram fragmentShaderLog];
    NSLog(@"Frag Log: %@", fragLog);
    NSString *vertLog = [sphereDepthProgram vertexShaderLog];
    NSLog(@"Vert Log: %@", vertLog);
    [sphereDepthProgram release];
    sphereDepthProgram = nil;
}

sphereDepthPositionAttribute = [sphereDepthProgram attributeIndex:@"position"];
sphereDepthImpostorSpaceAttribute = [sphereDepthProgram attributeIndex:@"inputImpostorSpaceCoordinate"];
sphereDepthModelViewMatrix = [sphereDepthProgram uniformIndex:@"modelViewProjMatrix"];
sphereDepthRadius = [sphereDepthProgram uniformIndex:@"sphereRadius"];

Kiedy trzeba użyć program shader, następnie wykonujesz coś w stylu:

[sphereDepthProgram use];

To nie rozwiązuje problemów rozgałęziania w porównaniu z pojedynczymi shaderami, które poruszyłeś powyżej, ale implementacja Jeffa zapewnia ładną enkapsulację niektórych kodu konfiguracji shaderów OpenGL ES boilerplate.

 8
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-16 01:32:33