纹理倒置

背景

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°.

Weston 纹理倒置(render-gl)相关推荐

  1. 音视频开发之旅(38) -使用FBO实现渲染到纹理(Render to texture)

    目录 FBO基本知识 FBO实现渲染到纹理的流程 实践 遇到的问题 资料 收获 在之前的学习实践中我们把图片.视频.图形等渲染到屏幕时,采用的是直接屏幕上即默认的帧缓冲区,如果我们在渲染时不想直接渲染 ...

  2. 渲染到纹理(Render to texture):使用FrameBuffer

    弄了一天,找啊找,没找到什么例子,幸好irrlicht里有个使用FrameBuffer渲染到纹理的例子,看了下,一copy,哇,ok了啊. 主要代码: // generate color textur ...

  3. GL和DX中关于纹理操作(包括多重纹理)与混合的问题

    以前看OPENGL的时候就没有彻底搞懂纹理操作到底是怎么实现的.最近看龙书又看到纹理操作了.看来这个问题不解决不行啊.于是研究一番,略有心得,在此记下以备不时之需. 先搞清楚,目标像素就是已经存在帧缓 ...

  4. 什么是渲染目标(render target) 渲染到纹理(Render To Texture, RTT)详解

    渲染到纹理(Render To Texture, RTT)详解 RTT是现在很多特效里面都会用到的一项很基本的技术,实现起来很简单,也很重要.但是让人不解的是网上搜索了半天只找到很少的文章说这个事儿, ...

  5. CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)

    CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture) 渲染到纹理(Render To Texture)是实现很多OpenGL高级效果的一个基础.本文记录了如何用CShar ...

  6. php open gl,Open GL 资料 01

    publicclassMyGLSurfaceViewextendsGLSurfaceView { privatefinalfloatTOUCH_SCALE_FACTOR =180.0f /320; / ...

  7. Android 开发使用OpenGL ES绘制三棱锥并进行纹理贴图

    效果图: 直接上代码 MainActivity.java的代码 package com.zzu.shiyan3;import androidx.appcompat.app.AppCompatActiv ...

  8. [IG]交互图像-创建3D物体并可旋转、缩放,添加光源照明,凹凸纹理

    交互图形 任务一 任务二 任务三 任务四 任务五 任务六 任务七 HTML 完整实现代码 JavaScript 完整实现代码 HTML和JS代码已经贴出,其依赖代码文件Common以及相关资料均请在此 ...

  9. android openGl纹理的使用

    今天,简单讲讲android关于纹理的知识. 一.纹理的概念 纹理(texture) 在游戏制作里面指贴图,计算机图形学中的纹理既包括通常意义上物体表面的纹理即使物体表面呈现凹凸不平的沟纹,同时也包括 ...

最新文章

  1. WPF查找子控件和父控件方法
  2. Python使用matplotlib可视化安德鲁斯曲线、安德鲁斯曲线可以用来查看分类变量对于数据集是否具有判别性、区分性(Andrews Curve)
  3. VMware vSphere@cloudstack基本功能测试报告
  4. 机器学习算法基础——逻辑回归
  5. 跳转语句_C/C++中的goto语句
  6. ASP.NET2.0文件上传以及图片处理总结篇 [转]
  7. 如何去掉子窗体的关闭按钮.右上角的那个X
  8. CUDA精进之路(四):图像处理——Sobel算子边缘检测
  9. ORACLE检索数据一致性与事务恢复
  10. 数据结构严蔚敏清华大学pdf_2021年清华(清华大学)电子信息考研
  11. Github上优秀的开源项目
  12. Windows Server 2019 Datacenter OVF 模板 百度网盘 下载
  13. linux系统 中文定制版,我们的Ubuntu 中文定制版呢?
  14. 文件 或者 图片 与 base64 之间的转换
  15. K12在线教育行业和产品分析报告
  16. OLED显示图像和波形
  17. 前端例程20210510:新拟物风格(Neumorphism)设计与实现
  18. 单模光纤与多模光纤区别
  19. PostgreSQL16中pg_dump的LZ4和ZSTD压缩
  20. Echarts_1:水平柱体

热门文章

  1. THANK YOU FOR YOUR CONCERN, SIOBAN AND ANTHONY
  2. wxh play 组织结构图
  3. 聚类之层次聚类、基于划分的聚类(…
  4. 【Python_笔记】openpyxl中Workbook()和.load_workbook()区别
  5. 【表格合并与底纹】vue-elementul表格简单实现合并单元格,与列和行给底纹颜色
  6. 网络爬虫是干什么的呢?
  7. 如果获取token?
  8. SR触发器和JK触发器
  9. Latex写文章时插入单栏图片和双栏图片方法
  10. adb不是内部命令和sudo: adb: command not found