【问题标题】:Why is 'gl_Position' a different data type than 'position'为什么“gl_Position”与“位置”是不同的数据类型
【发布时间】:2015-06-29 20:54:24
【问题描述】:

我正在从代码示例中了解 GLSL 着色器,但我对以下内容感到困惑:gl_Position 是 vec4 数据类型,position 是 vec3 数据类型,为什么?这个“位置”变量到底是什么,我在哪里可以找到某种文档?我能找到的只是 gl_Position 参考,gl_projectionMatrix 与 projectionMatrix 相同。 projectionMatrix 即使在 GLSL 备忘单中也没有定义。

<script type="x-shader/x-vertex" id="vertexshader">

    varying vec3 col;

    void main()
    {
        col         = vec3( uv, 1.0 );
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }

</script>

<script type="x-shader/x-fragment" id="fragmentshader">

    varying vec3 col;

    void main()
    {
        gl_FragColor = vec4(col, 1);
    }

</script>

【问题讨论】:

    标签: opengl-es webgl


    【解决方案1】:

    position 是一个用户命名的变量。 position 对 WebGL 没有任何意义。它可能被称为foobarwhatever。它对 WebGL 没有意义,就像变量 xyz 在 JavaScript 中没有意义一样

    JavaScript

    var xyz = 123;      // this has no meaning to JavaScript, only to the programmer
    var position = 789; // this has no meaning to JavaScript either.
    

    WebGL GLSL

    attribute vec3 xyz;       // this has no meaning to WebGL
    attribute vec3 position;  // this has no meaning to WebGL either
    

    projectionMatrix 也是如此。它是程序员制作的变量。 WebGL 不在乎名称是什么。如果您正在使用某个库(例如 three.js),它可能会为变量组成一些名称,但这些变量和选择的名称是库的一部分,而不是 WebGL 的一部分。日本程序员可能会使用 haichishaeigyouretu 之类的名称,而不是 positionprojectionMatrix

    gl_ 开头的变量是特殊的全局变量。在WebGL Quick Reference Card 上有一个列表。 所有其他变量均由程序员编写

    内置输入、输出和常量 [7]

    着色器程序使用特殊变量与管道的固定功能部分进行通信。输出特殊变量可以在写入后读回。输入特殊变量是只读的。所有特殊变量都具有全局范围。

    顶点着色器特殊变量 [7.1]

    Outputs:
    Variable                   |Description           | Units or coordinate system
    ---------------------------+----------------------+------------------
    highp vec4 gl_Position;    |transformed vertex    |clip coordinates
                               |position              | 
    ---------------------------+----------------------+------------------
    mediump float gl_PointSize;|transformed point size|pixels
                               |(point rasterization  |
                               |only)                 |
    ---------------------------+----------------------+------------------
    

    片段着色器特殊变量 [7.2]

    片段着色器可以写入gl_FragColorgl_FragData[] 的一个或多个元素,但不能同时写入。 gl_FragData 数组的大小由内置常量 gl_MaxDrawBuffers 给出。

    Inputs:
    Variable                   |Description           | Units or coordinate system
    ---------------------------+----------------------+------------------
    mediump vec4 gl_FragCoord; |fragment position     | window coordinates
                               | within frame buffer  |
    ---------------------------+----------------------+------------------
    bool gl_FrontFacing;       |fragment belongs to a | Boolean
                               |front-facing primitive|
    ---------------------------+----------------------+------------------
    mediump vec2 gl_PointCoord;|fragment position     | 0.0 to 1.0 for
                               |within a point (point | each component
                               |rasterization only)   | 
    ---------------------------+----------------------+------------------
    
    Outputs:
    Variable                   |Description           | Units or coordinate system
    ---------------------------+----------------------+------------------
    mediump vec4 gl_FragColor; |fragment color        | RGBA color
    ---------------------------+----------------------+------------------
    mediump vec4 gl_FragData[n]|fragment color for    | RGBA color
                               |color attachment n    |
    ---------------------------+----------------------+------------------
    

    具有最小值的内置常量 [7.4]

    Built-in Constant                                 | Minimum value
    --------------------------------------------------+------------------
    const mediump int gl_MaxVertexAttribs             | 8
    --------------------------------------------------+------------------
    const mediump int gl_MaxVertexUniformVectors      | 128
    --------------------------------------------------+------------------
    const mediump int gl_MaxVaryingVectors 8          |
    --------------------------------------------------+------------------
    const mediump int gl_MaxVertexTextureImageUnits   | 0
    --------------------------------------------------+------------------
    const mediump int gl_MaxCombinedTextureImageUnits | 8
    --------------------------------------------------+------------------
    const mediump int gl_MaxTextureImageUnits         | 8
    --------------------------------------------------+------------------
    const mediump int gl_MaxFragmentUniformVectors    | 16
    --------------------------------------------------+------------------
    const mediump int gl_MaxDrawBuffers               | 1
    --------------------------------------------------+------------------
    

    内置统一状态 [7.5]

    在窗口坐标中指定深度范围。如果一个实现确实 在片段语言中不支持 highp 精度,并且 state 被列为 highp,那么该 state 在片段中将仅作为 mediump 可用 语言。

    struct gl_DepthRangeParameters {
       highp float near; // n
       highp float far; // f
       highp float diff; // f - n
    };
    
    uniform gl_DepthRangeParameters gl_DepthRange;
    

    作为 var 和 position 一样,作为 vec3,这也是程序员的决定。成为vec4float 或任何你想要的都一样好。

    虽然着色器可以是您想要的任何东西,并且可以使用您想要的任何变量名称,但最常见的顶点着色器可能类似于

    attribute vec4 position;
    uniform mat4 projectionMatrix;
    uniform mat4 modelViewMatrix;
    
    void main() {
      gl_Position = projectionMatrix * modelViewMatrix * position;
    }
    

    一些程序员将vec3 用于position,但无论如何他们都必须将其强制转换为vec4

    attribute vec3 position;
    uniform mat4 projectionMatrix;
    uniform mat4 modelViewMatrix;
    
    void main() {
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1);
    }
    

    而且由于 vec4 属性的 w 值默认为 1.0,因此没有理由手动进行。

    You might find these articles helpful in explaining WebGL

    【讨论】:

    • 因其非常全面和完整的答案而受到赞誉。这应该是正确的答案。
    • 看来w 做了一些缩放(奇怪地低于零会使绘图变大)...知道为什么会包含在gl_Position 中吗?是因为它使一些矩阵操作更快?
    • 因为当 WebGL 使用 gl_Position 中的值时,它会除以 w。见thisthis
    【解决方案2】:

    gl_Position 是一个内置的顶点着色器输出变量,其类型由 OpenGL 规范定义为vec4

    position 是一个顶点着色器属性,并且由于引入了可编程着色器,(作为开发人员)可以完全控制其格式。

    很可能,您有每个顶点的 3D 坐标(因此,每个顶点只有 3 个浮点数),您通过调用 glVertexAttribPointer(或类似函数)将其配置为顶点着色器输入,告诉 OpenGL 拉 3 个浮点数position 属性的缓冲区中的时间。由于 gl_Position 需要 4 个浮点数,因此在顶点着色器中需要扩展为 vec4(通过将 w 填充为 1.0)。

    【讨论】:

    • 还需要注意的是,如果您使用 ShaderMaterial,threejs 会自动将位置属性(作为 vec3)添加到顶点着色器。可能是 OP 感到困惑的原因。
    猜你喜欢
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    相关资源
    最近更新 更多