En WebGL, ¿cuáles son las diferencias entre un atributo, un uniforme y una variable variable?

83

¿Hay alguna analogía en la que pueda pensar al comparar estos diferentes tipos, o cómo funcionan estas cosas?

Además, ¿qué significa uniformar una matriz?

Skorpius
fuente

Respuestas:

90

Copiado directamente de http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/ . El sitio actual tiene información mucho más detallada y valdría la pena revisarlo.

Calificadores variables

Los calificadores dan un significado especial a la variable. Están disponibles los siguientes calificadores:

  • const: la declaración es una constante de tiempo de compilación.
  • atributo: variables globales que pueden cambiar por vértice, que se pasan de la aplicación OpenGL a los sombreadores de vértices. Este calificador solo se puede usar en sombreadores de vértices. Para el sombreador, esta es una variable de solo lectura. Consulte la sección de atributos.
  • uniform - Variables globales que pueden cambiar por primitiva [...], que se pasan de la aplicación OpenGL a los sombreadores. Este calificador se puede utilizar tanto en sombreadores de vértices como de fragmentos. Para los sombreadores, esta es una variable de solo lectura. Consulte la sección Uniforme.
  • variable: se utiliza para datos interpolados entre un sombreador de vértices y un sombreador de fragmentos. Disponible para escribir en el sombreador de vértices y de solo lectura en un sombreador de fragmentos. Consulte la sección Variante.

En cuanto a una analogía, const y uniform son como variables globales en C / C ++, una es constante y la otra se puede establecer. El atributo es una variable que acompaña a un vértice, como coordenadas de color o textura. El sombreador de vértices puede alterar las variables variables, pero no el sombreador de fragmentos, por lo que, en esencia, están pasando información por la tubería.

Alfredo Giménez
fuente
1
Solo para expandir un poco los atributos: un atributo no necesita ser un atributo de matriz (se necesita un atributo de matriz si el valor puede ser diferente para cada vértice). También puede ser un atributo de vértice constante, en cuyo caso el valor se comparte entre todos los vértices. De hecho, gl.enableVertexAttribArray debe habilitar activamente el atributo de matriz.
Robert Monfera
Es bueno tener el texto aquí porque el sitio web está muerto
ziyuang
Solo para ser "ese tipo", pero no veo nada en el sitio que sugiera que era legal copiar esto aquí.
gman
66
  • uniformson parámetros por primitiva (constantes durante una llamada de dibujo completa);
  • attributeson parámetros por vértice (típicamente: posiciones, normales, colores, UV, ...);
  • varyingson parámetros por fragmento (o por píxel ): varían de un píxel a otro.

Es importante comprender cómo varyingfunciona programar sus propios sombreadores.
Digamos que define un parámetro variable vpara cada vértice de un triángulo dentro del sombreador de vértices . Cuando este parámetro variable se envía al sombreador de fragmentos , su valor se interpola automáticamente en función de la posición del píxel a dibujar.

En la siguiente imagen, el píxel rojo recibió un valor interpolado del parámetro variable v. Por eso los llamamos "variables".

Parámetro variable interpolado bilinealmente

En aras de la simplicidad, el ejemplo anterior utiliza la interpolación bilineal , que asume que todos los píxeles dibujados tienen la misma distancia de la cámara. Para una representación 3D precisa, los dispositivos gráficos utilizan una interpolación de perspectiva correcta que tiene en cuenta la profundidad de un píxel.

neeh
fuente
2
El espíritu de la respuesta es correcto, pero recuerde que para variar , la interpolación predeterminada realizada se denomina interpolación de perspectiva correcta y no meramente interpolación bilineal. Por supuesto, esto se puede cambiar con el calificador de interpolación noperspective para obtener una interpolación bilineal simple y no una interpolación de perspectiva correcta (identificada por el calificador predeterminado :) smooth. Vea este ejemplo .
legends2k
Gracias, voy a agregar una nota sobre esto.
neeh
11

En WebGL, ¿cuáles son las diferencias entre un atributo, un uniforme y una variable variable?

En OpenGL, un "programa" es una colección de "sombreadores" (programas más pequeños), que están conectados entre sí en una tubería.

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

Los sombreadores procesan vértices (sombreador de vértices), geometrías (sombreador de geometría), teselación (sombreador de teselación), fragmentos (sombreador de píxeles) y otras tareas de proceso por lotes (sombreador de cálculo) necesarias para rasterizar un modelo 3D.

Los sombreadores OpenGL (WebGL) están escritos en GLSL (un lenguaje de sombreado basado en texto compilado en la 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>

Teniendo en cuenta estos conceptos:

Los sombreadores pueden pasar datos al siguiente sombreador de la canalización ( out, inout) y también pueden aceptar datos de la aplicación WebGL o un sombreador anterior ( in).

  • Los sombreadores de vértices y fragmentos (cualquier sombreador en realidad) pueden usar una uniformvariable para recibir datos de la aplicación 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 también puede recibir datos de la aplicación WebGL con la attributevariable, que se puede habilitar o deshabilitar según sea necesario.

    // 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 puede pasar datos al Fragment Shader usando la varyingvariable. Vea el código GLSL arriba ( varying vec3 variableC;).

tfmontague
fuente
1

Los uniformes son otra forma de pasar datos de nuestra aplicación en la CPU a los sombreadores en la GPU, pero los uniformes son ligeramente diferentes en comparación con los atributos de vértice. Primero que nada, los uniformes son globales. Global, lo que significa que una variable uniforme es única por objeto de programa de sombreado y se puede acceder a ella desde cualquier sombreador en cualquier etapa del programa de sombreado. En segundo lugar, independientemente de lo que establezca el valor uniforme, los uniformes mantendrán sus valores hasta que se restablezcan o actualicen

Me gusta la descripción de https://learnopengl.com/Getting-started/Shaders , porque la palabra per-primitiva no es intuitiva

Liu Hao
fuente