在LearnOpenGL CN和其他的一些教程中,教程的内容都是以desktop版本的OpenGL为准,而不是es版本。es版本和desktop有什么不同呢,大致可以分为这么几点:
- es版本是桌面版的子集,功能更少,只保留了最有用最高效的函数,但大致的语法,概念都是一样的;
- es只支持三角形面的片元,故在加载3d模型时要把模型转成三角形片元的,而桌面版支持三角形,四边形及其他片元;
- es多用于安卓,ios,和其他带图形显示的嵌入式设备上,在手机上多用于开发游戏。desktop目前在桌面端只能做一些杂七杂八的事情,原本的游戏份额被微软的directX抢的差不多了。目前手游王者荣耀就是基于es2.0,es3.0,metal,vulkan等不同标准开发的。其中metal是苹果的,之前苹果使用opengl es,后来自己做了metal。vulkan是制定opengl标准的组织用于取代opengl的新技术,目前各大游戏厂商及soc厂商如高通都在积极支持。
- 从opengl es中又分裂出了一支,叫webgl,将JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。
在Qt中,实现OpenGL主要使用QOpenGLWidget和QOpenGLFunctions(QOpenGLExtraFunctions),对于Desktop和es两个不同版本的区分有点模糊,主要区别在着色器方面。下面以几段代码来说明。
Desktop版本的vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 ourTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0f);
ourTexCoord = aTexCoord;
}
Desktop版本的fragment shader
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 ourTexCoord;
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;
void main(void)
{
FragColor = mix(texture2D(ourTexture1,ourTexCoord),texture2D(ourTexture2,ourTexCoord),0.2f);
}
这两段代码是LearnOpenGL CN中纹理Texture一章的着色器代码,很典型的Desktop版本的着色器代码。如果想将其转化成es2.0形式,需要区别glsl3.30和glsl1.x的区别,因为opengl 3.3和opengl es2.0不是一个时期的标准,这两个时期glsl(着色器编程语言)的语法是不一样的,opengl3.3和opengl es3.0才是同一个时期的东西。具体语法区别如下:
- glsl3.30版本中的in/out对应glsl1.x中的attribute/varying
- layout (location = x)可以删除,不指定具体位置
- 从顶点着色器传到片段着色器中的变量,如desktop代码中的OurTexCoord,前缀的in/out都要换成varying
- 片段着色器输出的值(FragColor)要改为gl_FragColor
- 将float类型的数值后的.f去掉,保留数字即可
下面是此代码的es2.0版本。
es2.0的vertex shader
attribute vec3 aPos;
attribute vec2 aTexCoord;
varying vec2 ourTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0);
ourTexCoord = aTexCoord;
}
es2.0的fragment shader
varying vec2 ourTexCoord;
uniform sampler2D ourTexture1;
uniform sampler2D ourTexture2;
void main(void)
{
gl_FragColor = mix(texture2D(ourTexture1,ourTexCoord),texture2D(ourTexture2,ourTexCoord),0.2);
}