90

在比较这些不同类型或这些东西如何工作时,我能想到一个类比吗?

另外,统一矩阵是什么意思?

4

4 回答 4

98

直接从http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/复制。实际站点有更详细的信息,值得一试。

变量限定符

限定符赋予变量特殊的含义。以下限定符可用:

  • const – 声明是编译时常量。
  • 属性——每个顶点可能改变的全局变量,从 OpenGL 应用程序传递到顶点着色器。此限定符只能在顶点着色器中使用。对于着色器,这是一个只读变量。请参阅属性部分。
  • uniform – 全局变量,每个基元可能会改变 [...],从 OpenGL 应用程序传递到着色器。此限定符可用于顶点着色器和片段着色器。对于着色器,这是一个只读变量。见统一部分。
  • 变化的——用于顶点着色器和片段着色器之间的插值数据。可用于在顶点着色器中写入,在片段着色器中为只读。见变化部分。

打个比方,const和uniform就像C/C++中的全局变量,一个是常量,一个是可以设置的。属性是伴随顶点的变量,如颜色或纹理坐标。可变变量可以由顶点着色器更改,但不能由片段着色器更改,因此实质上它们是在将信息传递到管道中。

于 2013-07-09T20:20:40.980 回答
89
  • uniform每个基元的参数(在整个绘图调用期间是常量);
  • attribute每个顶点的参数(通常:位置,法线,颜色,UV,...);
  • varying每片段(或每像素)参数:它们像素而异。

了解如何varying编写自己的着色器非常重要。
假设您为顶点着色器v内的三角形的每个顶点定义了一个可变参数。当这个变化的参数被发送到片段着色器时,它的值会根据要绘制的像素的位置自动插值。

在下图中,红色像素收到了一个可变参数的插值v。这就是为什么我们称它们为“变化的”。

变化的参数被双线性插值

为简单起见,上面给出的示例使用双线性插值,它假设所有绘制的像素与相机的距离相同。为了准确的 3D 渲染,图形设备使用考虑到像素深度的透视校正插值。

于 2017-02-04T18:53:36.993 回答
12

在 WebGL 中,属性、统一和可变变量之间有什么区别?

在 OpenGL 中,“程序”是“着色器”(较小的程序)的集合,它们在管道中相互连接。

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

着色器处理顶点(vertex shader)、几何图形(geometry shader)、曲面细分(tessellation shader)、片段(pixel shader),以及光栅化3D模型所需的其他批处理任务(compute shader)。

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)。

  • Vertex 和 Fragment 着色器(实际上是任何着色器)可以使用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);
    
  • 顶点着色器还可以使用变量从 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;)。

于 2017-01-30T00:18:04.323 回答
2

Uniform 是将数据从 CPU 上的应用程序传递到 GPU 上的着色器的另一种方式,但与顶点属性相比,uniform 略有不同。首先,制服是全球性的。全局,这意味着统一变量对于每个着色器程序对象都是唯一的,并且可以在着色器程序的任何阶段从任何着色器访问。其次,无论您将制服值设置为什么,制服都会保留其值,直到它们被重置或更新

我喜欢https://learnopengl.com/Getting-started/Shaders的描述,因为per-primitive这个词不直观

于 2018-06-26T12:14:16.337 回答