Weston 纹理倒置(render-gl)

本文探讨了使用framebufferobject实现off-screen渲染时遇到的纹理倒置问题。详细分析了问题产生的原因在于原生窗口坐标系统与OpenGL坐标系统的不一致,并提出了两种解决方案:一是通过软件适配,二是修改VertexShader中的坐标顶点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

纹理倒置

背景

render-gl 接入 frame buffer object 实现 off-screen 渲染后,发现得到的渲染图发生了180°的倒置.

查阅了有关资料后,在 eglspec.1.5 中的 2.2.2.1 Native Surface Coordinate Systems 找到了答案:

The coordinate system for native windows and pixmaps in most platforms is in-
verted relative to the OpenGL, OpenGL ES, and OpenVG client API coordinate
systems. In such systems, native windows and pixmaps have (0, 0) in the upper
left of the pixmap, while the client APIs have (0, 0) in the lower left. To accomo-
date this, client API rendering to window and pixmap surfaces must invert their
own y coordinate when accessing the color buffer in the underlying native win-
dow or pixmap, so that the resulting images appear as intended by the application
when the final image is displayed by eglSwapBuffers or copied from a pixmap to
a visible window using native rendering APIs.

原生 render-gl 依赖于 native window system 实现 on-screen 渲染,其 frame buffer 的起始坐标为左下角; 而使用 frame buffer object 实现的 off-screen 渲染其坐标与 texture 保持一致,起始坐标为左上角,如下图所示:

请添加图片描述

weston 原生只支持基于 native window system 的渲染方式,故其已经做过 texture 顶点左上角至 default framebuffer 顶点左下角的适配了;而在引入 frame buffer object 之后, frmae buffer object 的顶点坐标重新变为左上角,而其逻辑却与之前保持一致,结果就是图像发生了180°倒置.

解决方案

解决这个问题的方案有很多种,因为归根结底是因为顶点坐标的 y 在最终渲染前没有进行一次正确的翻转;所以无论怎么样,只要能够完成一次正确的翻转,就能够解决问题; 大体上分为两大种解决方案:

  • 软件上进行适配
  • Vertex Shader 中修改顶点坐标

实际上第一次解决纹理倒置时使用的第一种方案,但是软件上的顶点倒置并没有那么简单,需要正确处理所有与之相关的业务逻辑;而有关与此的上下文又散落在各种零碎的代码片段,正确处理起来的难度实际上相当之大.

Vertex Shader 中修改坐标顶点实际上讲的就是修改 gl_Position, render-glVertex Shader 如下所示:

uniform mat4 proj;
attribute vec2 position;
attribute vec2 texcoord;
varying vec2 v_texcoord;

void main()
{
    gl_Position = proj * vec4(position, 0.0, 1.0);
    v_texcoord = texcoord;
}

要想正确地处理顶点坐标,就需要正确地处理 gl_Position, 有关于 gl_Postion 的描述可以参见 GLSLangSpec.4.60 :

The variable gl_Position is intended for writing the homogeneous vertex position. It can be written
at  any  time  during  shader  execution.  This  value  will  be  used  by  primitive  assembly,  clipping,
culling, and other fixed functionality operations, if present, that operate on primitives after vertex
processing  has  occurred.  Its  value  is  undefined  after  the  vertex  processing  stage  if  the  vertex
shader executable does not write gl_Position.

简单地将, gl_Position 是一个四元组,分别为 x、 y、 z 、w, 取值范围为 [-1, 1]; 对于上层用户而言,坐标应当是整数,比如我的屏幕尺寸是1080x1920,那么右下角的坐标就应当是 (1920, 1080),对应到 Vertex Shader 中即是 attribute position, 所以从 positiongl_Position 的过程中需要做一个归一化处理.

OpenGL 使用的坐标系并不是笛卡尔坐标系,即不是由 x, y, z 组成; 而是使用齐次坐标系,即由 x, y, z, w 组成; 当 w 恒为 1 时, 齐次坐标系等价于笛卡尔坐标系, 这里就是这种情况.

Vertex Shader 中, gL_Position 的结果由 proj 和由 position 组成的四元组相乘得到, 这里的相乘实际上一个矩阵运算,更具体一点是由 proj 这个 4x4 的矩阵与由 position 组成的 4x1 的矩阵得到 gl_Position 这个 4x1 且范围在 [-1, 1] 之间的矩阵.

proj 的全称为 projection, 在这里翻译成投影应该是比较合适的,它主要做了两件事:

  • 坐标映射 (Clamp)
  • 坐标旋转 (Rotate)

这两步可以通过 proj 来一起完成,用图示来表示如下:

请添加图片描述

所以实际上的解决办法就是修改 proj 这个矩阵的值,将其 (2,1) 位置的值由负修改为正,那么最终得到的顶点齐次坐标系的参考点就为左上角,或者也可以说是垂直翻转180°.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值