探索 OpenGL、OpenGL ES、WebGL纹理坐标的差异

前言

前阵子再忙着调研第三方相机应用的滤镜实现,并将这些作为滤镜做成AE插件的形式供设计师使用,以便做出更唯美的滤镜效果。在开发AE 插件过程中,发现有的着色器代码,在AE环境中和vscode的 shader toy 中的输出完全不一致,通过一段时间的摸索最终得到的结论是OpenGL 与OpenGL ES 的纹理坐标系统不一致导致的问题。

WebGL与OpenGL的差异

在开发滤镜效果的时候,为了方便实时预览, 在 vscode中开发着色器,借助shader toy 插件实现实时预览。经过调研(面向百度和google的搜索引擎调研)得知 shader toy 是基于 WebGL (浏览器图形库),而 WebGL 是OpenGL ES 的web实现,下面详细说明一下 WebGL 和 OpenGL 之间的差异。

WebGL

WebGL 为web图形库的缩写。它主要用于渲染而为和交互式三维图形库。它是可以与HTML5一起使用的Javascript API。它支持跨平台,并且仅以英语提供。WebGL程序由用JavaScript编写的控制代码组成

  1. Web GL 是基于OpenGL ES 2.0 的javascript API,而不是纯OpenGL(ES代表嵌入式系统)
  2. WebGL 通过HTML5的Canvas来喝Dom打交道。因此也和OpenGL ES 2.0 一样,使用 GLSL作为Shading language作为着色器语言
  3. WebGL 2.0 基于 OpenGL ES3.0 确保了提供多选型的 Web GL 1.0 扩展,并引入新的 API。

OpenGL

  1. OpenGL ES 本质上是OpenGL的一个子集。
  2. OpenGL ES是Khronos协会从OpenGL裁剪定制而来的,转为手机,与其他等嵌入式设备而设计。他的接口其实和OpenGL 很类似。
  3. OpenGL ES相对OpenGL删减了一切定效能的操作方式,与高性能的绝不留低效能的,即只求效能不求兼容性。

主要区别

WebGL基于OpenGL ES,它缺少常规OpenGL具有的许多功能,例如仅支持顶点和片段着色器。

OpenGL具有WebGL所不具备的功能,例如几何体着色器,镶嵌细分着色器和计算着色器。

WebGL主要用于浏览器。OpenGL确实需要本机驱动程序,并且主要用于安装软件。

WebGL用于Web应用程序,而OpenGL用于许多视频游戏。

WebGL更易于学习和开发应用程序。如果您熟悉WebGL,则可以轻松学习OpenGL。

在WebGL中,它可以使用2D纹理来伪造3D纹理。在OpenGL中,不需要这样做,因为它具有很多功能,例如几何和着色器。

OpenGL、OpenGL ES、WebGL纹理坐标映射原理

OpenGL ES

摘录至《OpenGL ES 3.x 游戏开发(上卷)》第七章
启用纹理映射功能后,如果吧一幅纹理应用到相应的集合图源,就必须告知渲染系统如何惊醒纹理的映射。告知的方式就是为图源中的顶点指定恰当的纹理坐标,纹理坐标用浮点数来表示,范围一般从0.0 到1.0,下面的图7-1 就给出了纹理映射的基本原理。


FileSharing.png

左侧试衣服纹理图,其位于纹理坐标系中。纹理坐标系远点在左上侧,向右为S轴,向下为T轴,两个周的取值范围都是0.0~1.0.也就是说不论实际纹理图的尺寸如何,其横、纵坐标最大值都为1.
右侧为三角形的图元,其3个顶点 A、B、C都指定了纹理坐标,3组纹理坐标正好在右侧的纹理中确定了需要映射的三角形纹理区域。

WebGL

摘录至《WebGL3D开发实战详解第2版》第6章,第1节
启用纹理映射功能后,如果想把一幅纹理应用到相应的集合图元中,就必须告知渲染系统如何进行纹理映射。告知方式就是为图元中的顶点指定恰当的纹理坐标,纹理坐标用浮点数来表示,范围一般为0.0~1.0.图6-1中给出了纹理映射的基本原理。


FileSharing.png

纹理坐标的原点在左上侧,向右为S轴,向下为T,两个周的取值范围都是 0.0~1.0。也就是说其横向、纵向坐标的最大值都是1。右侧是一个三角形图元,其中3个顶点A、B、C都指定了纹理坐标,3组纹理坐标正好在右侧的纹理图中确定了需要映射的三角形区域。

OpenGL

摘录至 https://learnopengl-cn.github.io 入门->纹理
我们已经了解到,我们可以为每个顶点添加颜色来增加图形的细节,从而创建出有趣的图像。但是,如果想让图形看起来更真实,我们就必须有足够多的顶点,从而指定足够多的颜色。这将会产生很多额外开销,因为每个模型都会需求更多的顶点,每个顶点又需求一个颜色属性。
艺术家和程序员更喜欢使用纹理(Texture)。纹理是一个2D图片(甚至也有1D和3D的纹理),它可以用来添加物体的细节;你可以想象纹理是一张绘有砖块的纸,无缝折叠贴合到你的3D的房子上,这样你的房子看起来就像有砖墙外表了。因为我们可以在一张图片上插入非常多的细节,这样就可以让物体非常精细而不用指定额外的顶点。
下面你会看到之前教程的那个三角形贴上了一张砖墙图片。

FileSharing-1.png

为了能够把纹理映射(Map)到三角形上,我们需要指定三角形的每个顶点各自对应纹理的哪个部分。这样每个顶点就会关联着一个纹理坐标(Texture Coordinate),用来标明该从纹理图像的哪个部分采样(译注:采集片段颜色)。之后在图形的其它片段上进行片段插值(Fragment Interpolation)。
纹理坐标在x和y轴上,范围为0到1之间(注意我们使用的是2D纹理图像)。使用纹理坐标获取纹理颜色叫做采样(Sampling)。纹理坐标起始于(0, 0),也就是纹理图片的左下角,终始于(1, 1),即纹理图片的右上角。下面的图片展示了我们是如何把纹理坐标映射到三角形上的。
FileSharing-2.png

我们为三角形指定了3个纹理坐标点。如上图所示,我们希望三角形的左下角对应纹理的左下角,因此我们把三角形左下角顶点的纹理坐标设置为(0, 0);三角形的上顶点对应于图片的上中位置所以我们把它的纹理坐标设置为(0.5, 1.0);同理右下方的顶点设置为(1, 0)。我们只要给顶点着色器传递这三个纹理坐标就行了,接下来它们会被传片段着色器中,它会为每个片段进行纹理坐标的插值。

将OpenGL ES 着色器代码移植到OpenGL 着色器

因为shader toy是基于 WebGL,而WebGL是基于OpenGL ES的浏览器实现,所以我们要想清楚的了解shader toy 渲染与AE 插件渲染的区别,只需要了解OpenGL和OpenGL ES根本上的差异。下图为OpenGL和OpenGLES坐标空间和纹理空间的差异:


FileSharing-3.png

从上图中可以看出,OpenGL 和 OpenGL ES 两个环境的空间坐标系统完全一致;纹理坐标系系统的u方向一致,而v方向相反。

图像的点运算

因为OpenGL ES 空间坐标系统和OpenGL 空间坐标系统是一致的,虽然 纹理坐标系统并不一致,但是只要不对纹理坐标做运算,OpenGL ES 和 OpenGL 两个环境输出效果相同,示例图如下:


FileSharing-4.png

图像的几何运算

在做图形渲染的开发过程中,通常会用到一个颜色映射表这么一个东西,颜色映射表是一个固定尺寸的纹理图片。在片段着色器中具体使用步骤如下:

  1. 获取输入纹理的 rgba 原始色值。
  2. 通过 rgba 原始色值执行一系列运算最终得到一个 uv 坐标。
  3. 通过uv坐标去颜色映射表中去取出颜色。
  4. 将取得的颜色色值与原始色值进行混合得到最终输出片段色值。

运行流程图如下:


FileSharing-5.png

从上面的流程图中可以看出,在第三部通过uv坐标取颜色映射表中取颜色的时候,OpenGL 和OpenGL ES 环境取到了不同的颜色,从而直接导致了输出颜色的不一致。这儿有一个问题,在实际预览效果中,OpenGL 和OpenGL ES 预览效果跟理论恰好相反,希望大佬帮忙解决一下这个问题。
为使得OpenGL 纹理坐标中取出来的颜色与OpenGL ES 纹理坐标取出来的颜色一致,有如下两个方案:

  1. 颜色表保持不变,纹理的 UV.y = 1 - UV.y;这种变换是使得OpenGL 的纹理坐标与OpenGL ES 的纹理坐标一致。
  2. UV 坐标保持不变,在 OpenGL 环境中将颜色映射表进行上下翻转;这也能使得OpenGL 环境与OpenGL ES 环境纹理坐标在颜色映射表中取到同一块颜色。

总结

通过上面的描述,可以得知,导致同一着色器代码在 浏览器端(WebGL)、手机端(OpenGL ES)、电脑端(OpenGL)出现不同的效果。根本原因是纹理坐标系统的不一致,如果需要将一个端的着色器代码移植到另一个端,那么就需要考虑这种坐标系统的不一致性,一些简单的纹理坐标运算使用文中的方法即可,但是对于一些相对复杂空域变换的效果,需要做一些新的思考。有疑问可以评论区留言,大家相互学习交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容