Jakie są różnice między atrybutem, uniformem i zmienną zmienną w WebGL?

83

Czy istnieje analogia, o której mogę pomyśleć, porównując te różne typy lub jak te rzeczy działają?

Co oznacza ujednolicenie macierzy?

Skorpius
źródło

Odpowiedzi:

90

Skopiowano bezpośrednio z http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/ . Rzeczywista strona zawiera znacznie bardziej szczegółowe informacje i warto byłoby je sprawdzić.

Zmienne kwalifikatory

Kwalifikatory nadają zmiennej specjalne znaczenie. Dostępne są następujące kwalifikatory:

  • const - Deklaracja jest stałą czasu kompilacji.
  • atrybut - zmienne globalne, które mogą się zmieniać w zależności od wierzchołka, które są przekazywane z aplikacji OpenGL do programów do cieniowania wierzchołków. Tego kwalifikatora można używać tylko w programach do cieniowania wierzchołków. W przypadku modułu cieniującego jest to zmienna tylko do odczytu. Zobacz sekcję Atrybut.
  • uniform - zmienne globalne, które mogą się zmieniać w zależności od [...] prymitywu, które są przekazywane z aplikacji OpenGL do modułów cieniujących. Ten kwalifikator może być używany zarówno w Vertex Shader, jak i Fragment Shader. W przypadku shaderów jest to zmienna tylko do odczytu. Zobacz sekcję Uniform.
  • zmienny - używany do interpolowanych danych między Vertex Shaderem a Fragment Shaderem. Dostępne do zapisu w Vertex Shader i tylko do odczytu w Fragment Shader. Zobacz sekcję Różne.

Jeśli chodzi o analogię, const i uniform są jak zmienne globalne w C / C ++, jedna jest stała, a druga może być ustawiona. Atrybut to zmienna towarzysząca wierzchołkowi, na przykład współrzędne koloru lub tekstury. Różne zmienne mogą być zmieniane przez Vertex Shader, ale nie przez Fragment Shader, więc zasadniczo przekazują informacje w dół potoku.

Alfredo Gimenez
źródło
1
Aby trochę rozwinąć atrybuty: atrybut nie musi być atrybutem tablicowym (atrybut tablicowy jest potrzebny, jeśli wartość może być inna dla każdego wierzchołka). Może to być również stały atrybut wierzchołka, w którym to przypadku wartość jest wspólna dla wszystkich wierzchołków. W rzeczywistości atrybut tablicy musi być aktywnie włączony przez gl.enableVertexAttribArray.
Robert Monfera
Dobrze mieć tekst tutaj, ponieważ strona internetowa jest martwa
ziyuang,
Chciałem tylko być „tym gościem”, ale nie widzę na stronie nic, co sugerowałoby, że kopiowanie tego tutaj było legalne.
gman
66
  • uniformsą parametrami na prymityw (stałe podczas całego wywołania remisu);
  • attributesą parametrami na wierzchołek (zazwyczaj: pozycje, normalne, kolory, UV, ...);
  • varyingsą parametrami na fragment (lub piksel ): różnią się one w zależności od pikseli.

Ważne jest, aby zrozumieć, jak varyingdziała programowanie własnych shaderów.
Powiedzmy, że definiujesz zmienny parametr vdla każdego wierzchołka trójkąta wewnątrz Vertex Shader . Kiedy ten zmienny parametr jest wysyłany do Fragment Shader , jego wartość jest automatycznie interpolowana na podstawie położenia piksela do narysowania.

Na poniższym obrazku czerwony piksel otrzymał interpolowaną wartość zmieniającego się parametru v. Dlatego nazywamy je „zmiennymi”.

zmienny parametr interpolowany dwuliniowo

Dla uproszczenia w powyższym przykładzie zastosowano interpolację bilinearną , która zakłada, że ​​wszystkie narysowane piksele znajdują się w tej samej odległości od aparatu. Aby uzyskać dokładne renderowanie 3D, urządzenia graficzne wykorzystują interpolację z poprawną perspektywą, która uwzględnia głębokość piksela.

neeh
źródło
2
Duch odpowiedzi jest właściwy, ale pamiętaj, że w przypadku różnicowania domyślna wykonywana interpolacja jest nazywana interpolacją poprawną perspektywicznie, a nie tylko interpolacją dwuliniową. Oczywiście można to zmienić za pomocą kwalifikatora interpolacji, noperspective aby uzyskać prostą interpolację dwuliniową, a nie interpolację z poprawną perspektywą (identyfikowaną przez domyślny kwalifikator:) smooth. Zobacz ten przykład .
legends2k
Dzięki, dodam notatkę o tym.
neeh
11

Jakie są różnice między atrybutem, uniformem i zmienną zmienną w WebGL?

W OpenGL „program” to zbiór „shaderów” (mniejszych programów), które są połączone ze sobą w potoku.

// "program" contains a shader pipeline:
//   vertex shader -> other shaders -> fragment shader
//
const program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);

Shadery przetwarzają wierzchołki (Vertex Shader), geometrie (Geometry Shader), Teselację (Tessellation Shader), fragmenty (Pixel Shader) i inne zadania przetwarzania wsadowego (Compute Shader) potrzebne do rasteryzacji modelu 3D.

Moduły cieniujące OpenGL (WebGL) są napisane w GLSL (tekstowym języku shaderów skompilowanym na GPU).

// Note: As of 2017, WebGL only supports Vertex and Fragment shaders

<!-- Vertex Shader -->
<script id="shader-vs" type="x-shader/x-vertex">

  // <-- Receive from WebGL application
  uniform vec3 vertexVariableA;

  // attribute is supported in Vertex Shader only
  attribute vec3 vertexVariableB;

  // --> Pass to Fragment Shader
  varying vec3 variableC;

</script>

<!-- Fragment Shader -->
<script id="shader-fs" type="x-shader/x-fragment">

  // <-- Receive from WebGL application
  uniform vec3 fragmentVariableA;

  // <-- Receive from Vertex Shader
  varying vec3 variableC;

</script>

Mając na uwadze te pojęcia:

Moduły cieniujące mogą przekazywać dane do następnego modułu cieniującego w potoku ( out, inout), a także mogą akceptować dane z aplikacji WebGL lub poprzedniego modułu cieniującego ( in).

  • Moduły cieniujące Vertex i Fragment (tak naprawdę każdy moduł cieniujący) mogą używać uniformzmiennej do odbierania danych z aplikacji WebGL.

    // Pass data from WebGL application to shader
    const uniformHandle = gl.glGetUniformLocation(program, "vertexVariableA");
    gl.glUniformMatrix4fv(uniformHandle, 1, false, [0.1, 0.2, 0.3], 0);
    
  • Vertex Shader może również odbierać dane z aplikacji WebGL ze attributezmienną, którą można włączyć lub wyłączyć w razie potrzeby.

    // Pass data from WebGL application to Vertex Shader
    const attributeHandle = gl.glGetAttribLocation(mProgram, "vertexVariableB");
    gl.glEnableVertexAttribArray(attributeHandle);
    gl.glVertexAttribPointer(attributeHandle, 3, gl.FLOAT, false, 0, 0);
    
  • Vertex Shader może przekazywać dane do Fragment Shader za pomocą varyingzmiennej. Zobacz kod GLSL powyżej ( varying vec3 variableC;).

tfmontague
źródło
1

Mundury to kolejny sposób przekazywania danych z naszej aplikacji na CPU do shaderów na GPU, ale uniformy są nieco inne w porównaniu do atrybutów wierzchołków. Przede wszystkim mundury są globalne. Globalna, co oznacza, że ​​zmienna uniform jest unikalna dla każdego obiektu programu modułu cieniującego i można uzyskać do niej dostęp z dowolnego modułu cieniującego na dowolnym etapie programu modułu cieniującego. Po drugie, niezależnie od ustawienia wartości uniform, uniformy zachowają swoje wartości, dopóki nie zostaną zresetowane lub zaktualizowane

Podoba mi się opis z https://learnopengl.com/Getting-started/Shaders , ponieważ słowo per-prymitywne nie jest intuicyjne

Liu Hao
źródło