Golang的OpenGL情况(包括WebGL在内)
这是我在WebGL Advent Calendar上发布的帖子。关于Golang的Advent Calendar我会另外写。
最近,我在使用Golang编写OpenGL程序,但是关于Golang的OpenGL相关资料不太全,所以我想整理一下。
各种适用于Golang的OpenGL / WebGL库。
良好背景的go-gl库。
在Golang中,有一个名为go-gl的GitHub组织一直提供OpenGL的API。它是一个具有社区属性的组织。
很多早期的软件包都使用这个库。该库是以开源组织Khronos提供的OpenGL文件为基础生成绑定,因此是一个安全可靠、稳定的库。它支持2.1及以上版本的OpenGL / OpenGL ES。此外,作为基于OpenGL的跨平台应用程序的基础,它还提供了与glut相似的受欢迎库glfw的封装。
WebGL 是一种用于在网页浏览器中创建并呈现交互式3D图形的技术。
Go语言中有一个名为gopher.js的处理系统可以生成JavaScript代码。在这个gopher.js处理系统中,提供了WebGL的绑定功能。
看起来提供了大部分功能。当然,只能在网页上使用。
安卓/苹果
从1.4版本开始,Golang逐渐加速移动端的支持。其中与此同时发布的是golang.org/x/mobile包集合,其中包括OpenGL ES 2.0库。
前往xjs/gl
虽然Golang是一种非常灵活的语言,但是完全替换后端的机制(而且每个机制之间没有共享接口)是一项相对困难的工作。Golang没有像C语言那样可以通过细粒度的宏开关来切换ON/OFF,而只能通过粗粒度的文件条件编译来实现,因此吸收差异往往会变得非常复杂和庞大。
替代您执行此任务的是goxjs/gl提供的库。
在这里,我们提供OpenGL、GLFW和WebSocket的库。对于OpenGL,我们提供的功能是对go-gl 2.1版本的封装。2.1是go-gl支持的最旧版本,但它的API版本(包括GLSL版本)几乎与OpenGL ES 2.0和Web GL 1.0兼容,可以进行交叉编译。
在目前讨论的问题中,作者正在解释关于方针的内容。他们提供了可以与Android/iOS的OpenGL ES实现和API同步的代码,同时还可以进行跨平台编译到桌面的OpenGL和WebGL。作者希望将来能够将Android/iOS的mobile/gl与OpenGL ES进行合并。
另外,在除了移动设备的桌面和网络浏览器版本中,作者(美国人?)没有真正运行和验证的方法会导致程序崩溃。这使得使用起来有些不方便,因此我们可能会讨论修复方法,即在实现所有包装器的同时,在未经测试的API上输出日志。如果这样的策略发生了改变(当我的PR被合并时),如果使用实际结果没有问题的话,我们希望能够收到“它能正常工作”的报告,这样大家会感到高兴。
应该使用什么?
好吧,有四个选项,那么该如何进行选择呢?
我认为首先,并不需要经常使用由gopher.js提供的WebGL库。基本上,如果想要在浏览器中使用,那么goxjs/gl是唯一的选择。
要使移动OpenGL ES运行于Android/iOS,mobile/gl是一个经过验证且今后能期待的包。对于ARM架构的Linux/Darwin系统,建议配置环境(添加条件构建文件),使代码使用mobile/gl。对于其他情况,则建议使用goxjs/gl进行编译。幸运的是,API应该几乎相同,除了获取上下文这一步可能需要单独处理外,其他几乎可以直接复制粘贴。
但是,WebGL最终开始普及1.0版本,要等到更强大的Web GL 2.0成为常见环境还需要一段时间。由于goxjs/gl注重可移植性,所以选择使用OpenGL中已经成熟的版本(2.1)。当然,如果要充分利用高端API,就只能使用go-gl的4系列。
总结一下,大致的感觉如下。
goxjs/gl(+mobile/gl)
とにかく可搬性重視。ブラウザがWebGL 2.0になるまではOpenGL3も、ES3も使わない気持ちを持っている人向け。mobile/glと両立できるかどうかは今後調べます。
go-gl
ブラウザで実行することはなく、最新を使いたい人。
mobile/gl
モバイル端末向けの開発を主に行い、今絶賛開発中のmobile系パッケージとの連係が最優先の人。
当我尝试移植实际编写的示例代码和现有的OpenGL代码时,遇到了困难。
这是一个纯Go实现的OpenGL矢量图形库NanoVG,它是用C语言编写的。由于是直接移植,因此没有进行优化。原本根据gopher.js网站上的性能提示,应该仅使用float64和int这两种数值类型,以适应JavaScript中仅支持float64相当的数值类型。但为了优先实现运行,我们选择使用float32。
我正在使用Mac上进行编写,但是通过使用gopher.js,也能在浏览器上运行,并且当然也可以在Mac上运行,并且还能进行交叉编译,可以在Windows 10上运行。
因为速度没有进行优化,所以浏览器很慢。在2014年的 MacBook Pro(Core i7)上使用 Chrome 大约只有20fps。Mac的原生版本是200fps,而且在Mac上,如果不是使用外接Retina显示器,则能达到600fps至800fps,这让人意识到了过度高分辨率所带来的负面影响。Windows的配置使用了Core i7 6700和GeForce GTX 970,所以大约有2000fps。由于在相同价格情况下,3D性能相差悬殊,因此回归到Windows的用户数量正在增加。Mouse Computer的LITTLEGEAR很好。
嗯,目前我們在每一個幀中都固執地將貝茲曲線轉換為三角形多邊形,所以如果沒有變化的話,可以將轉換完成的坐標緩存起來,或者修改前面提到的float64變數,在WebGL中也可以保持60幀每秒的速度。
另外,由于性能限制或某些功能(如模板缓冲)默认被关闭,WebGL需要通过在获取canvas标签的context方法的第二个参数传递选项来启用。如果画面不符合预期,建议检查该选项。目前为止,在从OpenGL 2.1迁移时没有遇到其他问题。由于goxjs/glfw最初没有这个开启选项,所以我提交了PR以添加它。
使用Golang进行3D开发的吸引力是什么?
我觉得目前还没看到很多积极使用Gopher.js的例子。我认为这可能与还有几个几MB大小的JS文件等原因有关,但就个人而言,我认为基于Golang的Web开发将成为未来最主流的开发环境。
最大的原因是WebAssembly。尽管Gopher.js的目标语言是C语言,但Gopher.js的开发人员提到了WebAssembly。如果Gopher.js支持WebAssembly,那么使用WebGL的代码执行将变得更快(float32应该得到本地支持!),加载速度也会提高。此外,NanoVGo还使用自己的实现方式解析TrueType字体并将其烘烤成纹理,然后使用UV映射,在这种实现方式中,虽然可以访问WebGL,但对DOM的访问可能会受到限制(或许)。这对于WebAssembly的用例应该是合适的。
另外,Gopher.js的构建时间非常快。目前,NanoVGo的Mac/Windows版本使用cgo链接C库,因此构建时间很长。在上面的示例代码中,需要超过30秒(在电池供电时)。而Gopher.js完全采用Go语言实现(如果使用cgo,Gopher.js就会变得臃肿),只需要大约0.3秒。这使得我完全不再考虑使用其他JavaScript的转译器或各种工具,如jslint/eslint等。在日常开发中,如果要使用OpenGL,我认为最好使用Gopher.js构建和测试,甚至可以使用WebGL inspector。我希望Mac/Windows构建的速度问题会在1.5中通过一些新增功能(目前仅支持Linux)和-shared构建选项得到解决。期待明年的1.6版本。
WebGL+Golang的吸引力已经很大了,但更重要的是其在本地执行时具有高性能和高可移植性的优点。从速度上来看,与C语言版和Golang本地版相比没有差异(或许稍微快一些?),内存消耗也是9MB对33MB,而二进制文件大小也只有大约6MB(添加了缩小选项),所以虽然可能不及C语言,但比起其他流行的多平台开发工具要小得多。对于适用于移动平台如Android和iOS的应用,而且只需如此少的资源消耗,我想它甚至可以在Ras Pi Zero等设备上流畅运行(尽管我还没有尝试过,但我很想试试)。
目前,NanoVGo本身还比较简单,而且功能还不够完善,但是要追赶JavaScript的最新版本ES2015,还有Babel、WebPack、React、Flux等技术的发展需要花费很多时间,我会将这些事情交给其他人去做,我会把资源集中在Golang上。已婚者需要有选择性。
明天是emadurandal先生。