Skąd Shader fragmentu wie, jakiej zmiennej użyć dla koloru Piksela?

Widzę wiele różnych shaderów fragmentów,

#version 130

out vec4 flatColor;

void main(void)
{
    flatColor = vec4(0.0,1.0,0.0,0.5);
}

I wszystkie używają innej zmiennej dla "out color" (w tym przypadku flatColor). Więc skąd OpenGL wie, co próbujesz zrobić?

Zgaduję, że to działa, ponieważ flatColor jest jedyną zmienną zdefiniowaną jako out, ale możesz dodać więcej out zmiennych, prawda? A może po prostu się rozbije?


[[9]}właściwie, jako test, po prostu uruchomiłem to:
#version 330

in vec2 TexCoord0;

uniform sampler2D TexSampler;

out vec4 x;
out vec4 y;

void main()
{
    y = texture2D(TexSampler, TexCoord0.xy);
}

Zadziałało bez względu na to czy użyłem x czy y.


Ponadto mamy predefiniowaną gl_FragColor. Jaka jest różnica i dlaczego ludzie zazwyczaj nalegają na używanie własnych zmiennych?

 68
Author: mpen, 2012-02-10

2 answers

Ponadto mamy predefiniowany gl_FragColor.

Zacznijmy od tego. Nie, ty nie masz predefiniowane gl_FragColor. To zostało usunięte z rdzenia OpenGL 3.1 i wyżej. Jeśli nie używasz zgodności (w takim przypadku shadery 3.30 powinny być napisane #version 330 compatibility na górze), nigdy nie powinieneś tego używać.

Teraz wracamy do zdefiniowanych przez użytkownika wyjść shadera fragmentów. Ale najpierw krótka analogia.

Pamiętasz, jak w shaderach wierzchołków masz wejścia? Oraz te wejścia reprezentują indeksy atrybutów wierzchołków, liczby, które przekazujesz glVertexAttribPointer i glEnableVertexAttribArray i tak dalej? Ustawiasz, które wejście pobiera z którego atrybutu. W GLSL 3.30 używasz składni:

layout(location = 2) in color;

Ustawia wejście shadera wierzchołków color z atrybutu location 2. Przed 3.30( lub bez ARB_explicit_attrib_location), musisz albo skonfigurować to jawnie z glBindAttrbLocation przed połączeniem lub zapytaniem programu o indeks atrybutów z glGetAttribLocation. Jeśli jeśli nie podasz bezpośrednio atrybutu location, GLSL przypisze lokalizację arbitralnie (tj. w sposób zdefiniowany w implementacji).

Ustawienie go w shaderze jest prawie zawsze lepszą opcją.

W każdym razie wyjścia modułu shadera fragmentów działają prawie dokładnie tak samo. Shadery fragmentów mogą zapisywać do wiele kolorów wyjściowych, które same w sobie są mapowane do wielu buforów w buforze ramki. Dlatego musisz wskazać, które wyjście przechodzi do którego koloru wyjściowego fragmentu.

Ten proces rozpoczyna się od wyjściowej wartości lokalizacji fragmentu. Jest ustawiony bardzo podobnie do lokalizacji wejściowych Vertex shader:

layout(location = 1) out secColor;

Istnieją również funkcje APIglBindFragDataLocation oraz glGetFragDataLocation, które są analogiczne do glBindAttribLocation i glGetAttribLocation.

Jeśli nie wykonujesz żadnych jawnych przydziałów, implementacje zazwyczaj przypisują jedną ze zmiennych wyjściowych do lokalizacji 0. Jednak standard OpenGL nie wymaga to zachowanie, więc nie powinieneś na nim polegać.

Aby być uczciwym, Twój program powinien mieć nie powiodło się , aby połączyć się, gdy użyłeś dwóch wyjść, które nie otrzymały różnych lokalizacji wyjściowych. Prawdopodobnie Twój kompilator zoptymalizował Ten, do którego nie napisałeś, więc trochę o tym zapomniał, gdy przyszedł czas na sprawdzenie błędów linkera.

 127
Author: Nicol Bolas,
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
2017-01-22 03:15:38

Chciałbym to określić dla OpenGLES 3.1, który używa GLSL_ES_3. 10 link :

§4.4.2

Jeśli istnieje tylko jedno wyjście [w cieniowaniu fragmentów] , lokalizacja nie musi być określona, w takim przypadku domyślnie zero.

 7
Author: Lorenzo Belli,
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
2016-01-26 11:56:38