5

我发现自己在 webGl 中使用的许多符号和域约定中有点迷失了。看一下这个 regl 示例(它显示了狒狒测试图像)。以下是我对它的理解:

  • 未指定原语;它很可能推断GL_TRIANGLE
  • 因此,它在世界空间中创建了一个具有顶点(-2, 0)(0, -2)、的三角形表面。(2, 2)在纸上画出来,似乎是专门选择了这个,因为它包含了这个区域[0,1] x [0,1]
  • uv从世界空间中获取它的值,包括这个[0,1] x [0,1]区域(它是 的域texture2d)。如果我理解正确,约定是+u指向图像的右边缘+v指向顶部
  • gl_Position设置为1 - 2*uv,以便图像占据[-1,1] x [-1,1], z=0“剪辑空间”,无论是什么。
  • 更重要的是,这也意味着方向对应+{u,v}-{x,y}
  • 显示的图像,实际上是水平镜像的!!与此相比)但它不是垂直镜像的。 在与屏幕像素坐标的最终转换过程中必须有其他东西抵消了 y 中的负因子。
  • 然而,谷歌搜索并没有发现gl_Position任何与屏幕相关的证据。我看到讨论说它是左撇子,但这只是z相对于世界坐标的否定。(例如这里的这个问题)

简而言之,在我看来,这个图像也应该垂直镜像。

我错过了什么?


为了后代,代码复制如下:(MIT许可)

const regl = require('regl')()
const baboon = require('baboon-image')

regl({
  frag: `
  precision mediump float;
  uniform sampler2D texture;
  varying vec2 uv;
  void main () {
    gl_FragColor = texture2D(texture, uv);
  }`,

  vert: `
  precision mediump float;
  attribute vec2 position;
  varying vec2 uv;
  void main () {
    uv = position;
    gl_Position = vec4(1.0 - 2.0 * position, 0, 1);
  }`,

  attributes: {
    position: [
      -2, 0,
      0, -2,
      2, 2]
  },

  uniforms: {
    texture: regl.texture(baboon)
  },

  count: 3
})()
4

1 回答 1

4

WebGL 和您上面的示例中都没有“世界空间”之类的东西。WebGL 只关心剪辑空间或(标准化设备坐标)。世界空间是应用程序/框架/库处理并提供着色器以最终提供 WebGL 剪辑空间(或标准化设备坐标)的东西

正如 LJ 所指出的,上面的代码不是webgl它是regl,一些库。所以它要做的是取决于那个库而不是 webgl。例如,它可能会翻转它加载的所有纹理,我们怎么知道?也就是说,很容易猜到它会做什么。

对您的问题的简短回答是整个图像被翻转,因为

gl_Position = vec4(1.0 - 2.0 * position, 0, 1);

将其更改为

gl_Position = vec4(position, 0, 1);

你会看到它是颠倒的

它正在绘制一个巨大的三角形。输入值为

  position: [
      -2, 0,
      0, -2,
      2, 2]
  },

这条线

gl_Position = vec4(1.0 - 2.0 * position, 0, 1);

表示写入的值gl_Position

1 - 2 * -2, 1 - 2 *  0
1 - 2 *  0, 1 - 2 * -2
1 - 2 *  2, 1 - 2 *  2

哪个是

 5,  1
 1,  5
-3, -3

如果我们相对于画布/屏幕/帧缓冲区绘制它,我们会得到

三角图

蓝色区域是屏幕/画布

至于翻转,重要的是要注意纹理没有“向上”概念。更重要的是要记住纹理坐标 0,0 引用纹理中的第一个像素,而 1,1 引用纹理中的最后一个像素。

这是应用于该三角形的纹理坐标

在此处输入图像描述

其中纹理中的红点代表纹理坐标中的 0,0。

将 0,0 视为纹理的开始(而不是底部)的原因是,当您渲染到纹理(通过帧缓冲区)时,您不需要进行任何翻转。翻转仅在您最终渲染到屏幕时才起作用,因为 WebGL 在绘制到屏幕时碰巧将 -1、-1 放在左下角。

这有点难以解释,但如果你看一下这个例子,你会发现在屏幕外渲染到/从纹理时不需要翻转。仅在渲染到画布/屏幕时。

如果您想查看大三角形,请将着色器更改为此

gl_Position = vec4((1.0 - 2.0 * position) * 0.2, 0, 1);

为了验证纹理是否被翻转,这里是原始的

在此处输入图像描述

您可以在 regl 示例中看到它的渲染翻转

在此处输入图像描述

至于学习 WebGL 和剪辑空间,我推荐这些教程

于 2016-10-31T08:54:32.010 回答