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


79

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

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

Answers:


85

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

可变预选赛

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

  • const –声明具有编译时间常数。
  • 属性–从顶点应用程序传递到顶点着色器的每个顶点可能更改的全局变量。此限定符只能在顶点着色器中使用。对于着色器,这是一个只读变量。请参阅属性部分。
  • 统一–可能随原语而变化的全局变量,这些变量从OpenGL应用程序传递到着色器。该限定符可以在顶点着色器和片段着色器中使用。对于着色器,这是一个只读变量。请参阅统一部分。
  • 可变-用于顶点着色器和片段着色器之间的插值数据。可用于在顶点着色器中编写,而在片段着色器中为只读。参见变化部分。

作为类比,const和Uniform就像C / C ++中的全局变量一样,一个是常量,另一个可以设置。属性是一个伴随顶点的变量,例如颜色或纹理坐标。可变变量可以由顶点着色器更改,但不能由片段着色器更改,因此从本质上讲,它们是沿管道传递信息。


1
只是为了扩展属性:属性不必是数组属性(如果每个顶点的值可以不同,则需要数组属性)。它也可以是常量顶点属性,在这种情况下,该值在所有顶点之间共享。实际上,数组属性需要由gl.enableVertexAttribArray主动启用。
罗伯特·蒙菲拉

高兴

只是成为“那个家伙”,但我在网站上看不到任何暗示将其复制到此处是合法的信息。
gman

63
  • uniform每个原始参数(在整个绘制调用期间恒定);
  • attribute每个顶点的参数(通常是:位置,法线,颜色,UV,...);
  • varying每个片段(或每个像素)的参数:它们像素的不同而不同

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

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

双线性插值变化参数

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


2
答案的实质是正确的,但请记住,对于变化而言,完成的默认插值称为透视校正插值,而不仅仅是双线性插值。当然,可以使用插值限定符 更改此参数noperspective以获取简单的双线性插值,而不是透视校正的插值(由默认限定符标识smooth)。请参阅此示例
legends2k

谢谢,我要为此添加注释。
neeh

10

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

请牢记以下概念:

着色器可以在管道将数据传递到下一个着色器(outinout),而且他们还可以从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也可以使用attribute变量从WebGL应用程序接收数据,可以根据需要启用或禁用该变量。

    // 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可以使用该varying变量将数据传递到Fragment Shader 。请参阅上方的GLSL代码(varying vec3 variableC;)。


1

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

我喜欢来自https://learnopengl.com/Getting-started/Shaders的描述,因为每个基元这个词不直观

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.