В чем разница между атрибутом, униформой и переменной в WebGL?


83

Есть ли аналогия, которую я могу придумать, сравнивая эти разные типы, или как они работают?

Кроме того, что означает униформа матрицы?

Ответы:


90

Скопировано прямо с http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/ . Фактический сайт содержит гораздо более подробную информацию, и его стоит проверить.

Квалификаторы переменных

Квалификаторы придают переменной особое значение. Доступны следующие квалификаторы:

  • const - Объявление константы времени компиляции.
  • attribute - Глобальные переменные, которые могут изменяться для каждой вершины, которые передаются из приложения OpenGL в вершинные шейдеры. Этот квалификатор можно использовать только в вершинных шейдерах. Для шейдера это переменная только для чтения. См. Раздел Атрибуты.
  • uniform - Глобальные переменные, которые могут изменяться для [...] примитива, которые передаются из приложения OpenGL шейдерам. Этот квалификатор можно использовать как в вершинных, так и в фрагментных шейдерах. Для шейдеров это переменная только для чтения. См. Раздел «Униформа».
  • варьирующийся - используется для интерполированных данных между вершинным шейдером и фрагментным шейдером. Доступно для записи в вершинном шейдере и только для чтения во фрагментном шейдере. См. Раздел «Варьирование».

Что касается аналогии, const и uniform похожи на глобальные переменные в C / C ++, одна постоянна, а другая может быть установлена. Атрибут - это переменная, которая сопровождает вершину, например координаты цвета или текстуры. Варьирующие переменные могут быть изменены вершинным шейдером, но не фрагментным шейдером, поэтому, по сути, они передают информацию по конвейеру.


1
Просто чтобы немного расширить атрибуты: атрибут не обязательно должен быть атрибутом массива (атрибут массива необходим, если значение может быть различным для каждой вершины). Это также может быть постоянный атрибут вершины, и в этом случае значение распределяется между всеми вершинами. Фактически, атрибут массива должен быть активно включен gl.enableVertexAttribArray.
Роберт Монфера

Хорошо, что текст здесь, потому что веб-сайт мертв
ziyuang

Просто чтобы быть «этим парнем», но я не вижу на сайте ничего, что предполагало бы, что копирование здесь было законным.
gman

66
  • uniformявляются примитивными параметрами (постоянными в течение всего вызова отрисовки);
  • attributeпараметры для каждой вершины (обычно: позиции, нормали, цвета, UV, ...);
  • varyingпараметры для каждого фрагмента (или для каждого пикселя ): они варьируются от пикселей к пикселям.

Важно понимать, как varyingработает программирование собственных шейдеров.
Допустим, вы определяете переменный параметр vдля каждой вершины треугольника внутри вершинного шейдера . Когда этот изменяющийся параметр отправляется фрагментному шейдеру , его значение автоматически интерполируется в зависимости от положения пикселя для рисования.

На следующем изображении красный пиксель получил интерполированное значение изменяющегося параметра v. Вот почему мы называем их «разными».

переменный параметр билинейно интерполируется

Для простоты в приведенном выше примере используется билинейная интерполяция , которая предполагает, что все нарисованные пиксели находятся на одинаковом расстоянии от камеры. Для точного 3D-рендеринга графические устройства используют интерполяцию с коррекцией перспективы, которая учитывает глубину пикселя.


2
Суть ответа верна, но помните, что для изменения выполняемая по умолчанию интерполяция называется интерполяцией с коррекцией перспективы, а не просто билинейной интерполяцией. Конечно, это можно изменить с помощью квалификатора интерполяции, noperspective чтобы получить простую билинейную интерполяцию, а не интерполяцию с правильной перспективой (определяется квалификатором по умолчанию:) smooth. См. Этот пример .
legends2k

Спасибо, я добавлю об этом примечание.
neeh

11

В чем разница между атрибутом, униформой и переменной в WebGL?

В OpenGL «программа» - это набор «шейдеров» (небольших программ), которые соединены друг с другом в конвейер.

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

Шейдеры обрабатывают вершины (вершинный шейдер), геометрию (геометрический шейдер), тесселяцию (тесселяционный шейдер), фрагменты (пиксельный шейдер) и другие задачи пакетной обработки (вычисление шейдера), необходимые для растеризации 3D-модели.

Шейдеры OpenGL (WebGL) написаны на GLSL (текстовом языке шейдеров, скомпилированном на 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>

Помня об этих концепциях:

Шейдеры могут передавать данные следующему шейдеру в конвейере ( out, inout), а также могут принимать данные из приложения WebGL или предыдущего шейдера ( in).

  • Вершинные и фрагментные шейдеры (на самом деле любой шейдер) могут использовать uniformпеременную для получения данных из приложения 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 также может получать данные из приложения WebGL с attributeпеременной, которую можно включать или отключать по мере необходимости.

    // 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);
    
  • Вершинный шейдер может передавать данные во фрагментный шейдер с помощью varyingпеременной. См. Код GLSL выше ( varying vec3 variableC;).


1

Униформы - это еще один способ передачи данных из нашего приложения на CPU шейдерам на GPU, но униформы немного отличаются от атрибутов вершин. Во-первых, униформа глобальна. Глобальная, что означает, что универсальная переменная уникальна для каждого объекта программы шейдера и может быть доступна из любого шейдера на любом этапе программы шейдера. Во-вторых, какое бы значение вы ни установили для униформы, униформы сохранят свои значения до тех пор, пока они не будут сброшены или обновлены.

Мне нравится описание с https://learnopengl.com/Getting-started/Shaders , потому что слово per-primitive не интуитивно понятно

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.