Was sind in WebGL die Unterschiede zwischen einem Attribut, einer Uniform und einer variierenden Variablen?

79

Gibt es eine Analogie, die mir beim Vergleich dieser verschiedenen Typen einfällt, oder wie diese Dinge funktionieren?

Was bedeutet es auch, eine Matrix zu vereinheitlichen?

Skorpius
quelle

Antworten:

85

Direkt von http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/ kopiert . Die eigentliche Seite enthält viel detailliertere Informationen und es lohnt sich, sie sich anzusehen.

Variable Qualifikatoren

Qualifizierer geben der Variablen eine besondere Bedeutung. Folgende Qualifikanten stehen zur Verfügung:

  • const - Die Deklaration ist eine Kompilierungszeitkonstante.
  • Attribut - Globale Variablen, die sich pro Scheitelpunkt ändern können und von der OpenGL-Anwendung an Scheitelpunkt-Shader übergeben werden. Dieses Qualifikationsmerkmal kann nur in Vertex-Shadern verwendet werden. Für den Shader ist dies eine schreibgeschützte Variable. Siehe Abschnitt Attribut.
  • uniform - Globale Variablen, die sich pro Grundelement ändern können [...] und von der OpenGL-Anwendung an die Shader übergeben werden. Dieses Qualifikationsmerkmal kann sowohl in Vertex- als auch in Fragment-Shadern verwendet werden. Für die Shader ist dies eine schreibgeschützte Variable. Siehe Abschnitt Uniform.
  • Variieren - Wird für interpolierte Daten zwischen einem Vertex-Shader und einem Fragment-Shader verwendet. Verfügbar zum Schreiben im Vertex-Shader und schreibgeschützt in einem Fragment-Shader. Siehe Abschnitt Variieren.

In einer Analogie sind const und uniform wie globale Variablen in C / C ++, eine ist konstant und die andere kann gesetzt werden. Attribut ist eine Variable, die einen Scheitelpunkt wie Farb- oder Texturkoordinaten begleitet. Unterschiedliche Variablen können vom Vertex-Shader geändert werden, nicht jedoch vom Fragment-Shader. Daher leiten sie im Wesentlichen Informationen über die Pipeline weiter.

Alfredo Gimenez
quelle
1
Nur um Attribute etwas zu erweitern: Ein Attribut muss kein Array-Attribut sein (ein Array-Attribut wird benötigt, wenn der Wert für jeden Scheitelpunkt unterschiedlich sein kann). Es kann auch ein konstantes Scheitelpunktattribut sein. In diesem Fall wird der Wert von allen Scheitelpunkten geteilt. Tatsächlich muss das Array-Attribut von gl.enableVertexAttribArray aktiv aktiviert werden.
Robert Monfera
Gut, den Text hier zu haben, weil die Website tot ist
ziyuang
63
  • uniformsind pro-primitive Parameter (konstant während eines gesamten Draw-Aufrufs);
  • attributesind Per-Vertex- Parameter (normalerweise: Positionen, Normalen, Farben, UVs, ...);
  • varyingsind Parameter pro Fragment (oder pro Pixel ): Sie variieren von Pixel zu Pixel.

Es ist wichtig zu verstehen, wie Sie varyingIhre eigenen Shader programmieren.
Angenommen, Sie definieren einen variierenden Parameter vfür jeden Scheitelpunkt eines Dreiecks im Scheitelpunkt-Shader . Wenn dieser variierende Parameter an den Fragment-Shader gesendet wird , wird sein Wert automatisch basierend auf der Position des zu zeichnenden Pixels interpoliert.

Im folgenden Bild erhielt das rote Pixel einen interpolierten Wert des variierenden Parameters v. Deshalb nennen wir sie "variierend".

variierender Parameter wird bilinear interpoliert

Der Einfachheit halber verwendet das oben angegebene Beispiel eine bilineare Interpolation , bei der davon ausgegangen wird , dass alle gezeichneten Pixel den gleichen Abstand von der Kamera haben. Für ein genaues 3D-Rendering verwenden Grafikgeräte eine perspektivisch korrekte Interpolation, die die Tiefe eines Pixels berücksichtigt.

neeh
quelle
2
Der Geist der Antwort ist richtig, aber denken Sie daran, dass die Standardinterpolation zum Variieren als perspektivisch korrekte Interpolation und nicht nur als bilineare Interpolation bezeichnet wird. Dies kann natürlich mit dem Interpolationsqualifikator geändert werden noperspective, um eine einfache bilineare Interpolation und keine perspektivisch korrekte Interpolation zu erhalten (gekennzeichnet durch das Standardqualifikationsmerkmal :) smooth. Siehe dieses Beispiel .
Legends2k
Danke, ich werde eine Notiz dazu hinzufügen.
Neeh
10

Was sind in WebGL die Unterschiede zwischen einem Attribut, einer Uniform und einer variierenden Variablen?

In OpenGL ist ein "Programm" eine Sammlung von "Shadern" (kleineren Programmen), die in einer Pipeline miteinander verbunden sind.

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

Shader verarbeiten Scheitelpunkte (Vertex-Shader), Geometrien (Geometrie-Shader), Tessellation (Tessellation-Shader), Fragmente (Pixel-Shader) und andere Stapelprozessaufgaben (Compute-Shader), die zum Rastern eines 3D-Modells erforderlich sind.

OpenGL (WebGL) -Shader sind in GLSL (einer auf der GPU kompilierten textbasierten Shader-Sprache) geschrieben.

// 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>

Beachten Sie diese Konzepte:

Shader können Daten an den nächsten Shader in der Pipeline übergeben ( out, inout) und sie können auch Daten aus der WebGL-Anwendung oder einem vorherigen Shader ( in) akzeptieren .

  • Die Vertex- und Fragment-Shader (wirklich jeder Shader) können eine uniformVariable verwenden, um Daten von der WebGL-Anwendung zu empfangen.

    // 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);
    
  • Der Vertex Shader kann auch Daten von der WebGL-Anwendung mit der attributeVariablen empfangen , die bei Bedarf aktiviert oder deaktiviert werden können.

    // 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);
    
  • Der Vertex Shader kann mithilfe der varyingVariablen Daten an den Fragment Shader übergeben . Siehe GLSL-Code oben ( varying vec3 variableC;).

tfmontague
quelle
1

Uniformen sind eine weitere Möglichkeit, Daten aus unserer Anwendung auf der CPU an die Shader auf der GPU zu übergeben. Uniformen unterscheiden sich jedoch geringfügig von Vertex-Attributen. Erstens sind Uniformen global. Global, was bedeutet, dass eine einheitliche Variable pro Shader-Programmobjekt eindeutig ist und von jedem Shader zu jedem Zeitpunkt im Shader-Programm aus aufgerufen werden kann. Zweitens behalten Uniformen ihre Werte bei, bis sie entweder zurückgesetzt oder aktualisiert werden

Ich mag die Beschreibung von https://learnopengl.com/Getting-started/Shaders , weil das Wort pro Primitiv nicht intuitiv ist

Liu Hao
quelle