为什么这张图片没有垂直镜像?

时间:2016-10-30 16:55:56

标签: javascript webgl opengl-es-2.0 regl

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

  • 没有指定原语;它可能会推断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}对应!
  • 显示的图像 ,实际上是水平镜像的!! (compare to this)但是不是垂直镜像。 在屏幕像素坐标的最终转换中必须有其他,以消除y中的负面因素。
  • 但是,Google搜索没有提供相对于屏幕以任何方式镜像gl_Position的证据。我认为这是左撇子的讨论,但这仅仅是相对于世界坐标否定z(e.g. this question here)

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

我缺少什么?

对于后代,代码转载如下:(MIT licensed)

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
})()

1 个答案:

答案 0 :(得分:1)

没有"世界空间"在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

如果我们绘制相对于canvas / screen / framebuffer的图表

triangle-diagram

蓝色区域是屏幕/画布

至于重要的是要注意纹理没有" up"概念。要记住的更重要的是纹理坐标0,0引用纹理中的第一个像素,1,1引用纹理中的最后一个像素。

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

enter image description here

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

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

这很难解释,但是如果你看this example,你会看到在屏幕上渲染/从纹理渲染时不需要翻转。它只在渲染到画布/屏幕时才会显示。

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

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

验证纹理是否翻转here's the original

enter image description here

你可以看到它在regl示例中翻转的内容

enter image description here

学习WebGL和剪辑空间I'd recommend these tutorials