为什么这个图像不是垂直镜像的?
Why is this image not mirrored vertically?
我发现自己在 webGl 中使用的许多符号和域约定中有点迷失。查看 this regl example(显示狒狒测试图像)。这是我的理解:
- 未指定原语;它可能推断
GL_TRIANGLE
.
- 因此,它在 world-space 中创建了一个顶点为
(-2, 0)
、(0, -2)
、(2, 2)
的三角形曲面。将其绘制在纸上,似乎是专门选择的,因为它包含区域 [0,1] x [0,1]
.
uv
从世界 space 获取其值,包括这个 [0,1] x [0,1]
区域(这是 texture2d
的域)。如果我理解正确的话,惯例是+u
指向图像的右边缘,+v
指向顶部.
gl_Position
设置为1 - 2*uv
,这样图像在"clip space,"中占据[-1,1] x [-1,1], z=0
不管是什么。
- 更重要的是,也意味着
+{u,v}
方向对应-{x,y}
!
- 显示的图像,是,实际上是水平镜像!! (compare to this)但它不是垂直镜像。 最终转换 to/from 屏幕上的像素坐标必须有 其他东西 可以抵消 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
})()
WebGL 和您上面的示例中都没有 "world space" 这样的东西。 WebGL 只关心剪辑 space 或(规范化设备坐标)。 World space 是 app/framework/library 处理并提供着色器以最终提供 WebGL 剪辑 space(或规范化设备坐标)
正如 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 绘制它,我们得到
其中蓝色区域是screen/canvas
至于翻转,重要的是要注意纹理没有 "up" 概念。更重要的是要记住纹理坐标 0,0 引用纹理中的第一个像素,1,1 引用纹理中的最后一个像素。
这是应用于该三角形的纹理坐标
其中纹理中的红点代表纹理坐标中的0,0。
将 0,0 视为纹理的起点(而不是底部)的原因是,当您渲染到纹理(通过帧缓冲区)时,您不需要进行任何翻转。只有当你最终渲染到屏幕上时,翻转才会起作用,因为 WebGL 在绘制到屏幕时恰好将 -1,-1 放在左下角。
这有点难以解释,但如果您查看 this example,您会发现渲染离屏 to/from 纹理时不需要翻转。仅在渲染到 canvas/screen.
时
如果你想看到大三角形,把着色器改成这个
gl_Position = vec4((1.0 - 2.0 * position) * 0.2, 0, 1);
验证纹理是否翻转here's the original
并且您可以在 regl 示例中看到翻转的渲染
至于学习WebGL和剪辑spaceI'd recommend these tutorials
我发现自己在 webGl 中使用的许多符号和域约定中有点迷失。查看 this regl example(显示狒狒测试图像)。这是我的理解:
- 未指定原语;它可能推断
GL_TRIANGLE
. - 因此,它在 world-space 中创建了一个顶点为
(-2, 0)
、(0, -2)
、(2, 2)
的三角形曲面。将其绘制在纸上,似乎是专门选择的,因为它包含区域[0,1] x [0,1]
. uv
从世界 space 获取其值,包括这个[0,1] x [0,1]
区域(这是texture2d
的域)。如果我理解正确的话,惯例是+u
指向图像的右边缘,+v
指向顶部.gl_Position
设置为1 - 2*uv
,这样图像在"clip space,"中占据[-1,1] x [-1,1], z=0
不管是什么。- 更重要的是,也意味着
+{u,v}
方向对应-{x,y}
! - 显示的图像,是,实际上是水平镜像!! (compare to this)但它不是垂直镜像。 最终转换 to/from 屏幕上的像素坐标必须有 其他东西 可以抵消 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
})()
WebGL 和您上面的示例中都没有 "world space" 这样的东西。 WebGL 只关心剪辑 space 或(规范化设备坐标)。 World space 是 app/framework/library 处理并提供着色器以最终提供 WebGL 剪辑 space(或规范化设备坐标)
正如 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 绘制它,我们得到
其中蓝色区域是screen/canvas
至于翻转,重要的是要注意纹理没有 "up" 概念。更重要的是要记住纹理坐标 0,0 引用纹理中的第一个像素,1,1 引用纹理中的最后一个像素。
这是应用于该三角形的纹理坐标
其中纹理中的红点代表纹理坐标中的0,0。
将 0,0 视为纹理的起点(而不是底部)的原因是,当您渲染到纹理(通过帧缓冲区)时,您不需要进行任何翻转。只有当你最终渲染到屏幕上时,翻转才会起作用,因为 WebGL 在绘制到屏幕时恰好将 -1,-1 放在左下角。
这有点难以解释,但如果您查看 this example,您会发现渲染离屏 to/from 纹理时不需要翻转。仅在渲染到 canvas/screen.
时如果你想看到大三角形,把着色器改成这个
gl_Position = vec4((1.0 - 2.0 * position) * 0.2, 0, 1);
验证纹理是否翻转here's the original
并且您可以在 regl 示例中看到翻转的渲染
至于学习WebGL和剪辑spaceI'd recommend these tutorials